summaryrefslogtreecommitdiffstats
path: root/src/compiler/nir/nir_print.c
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2018-03-14 21:45:38 -0700
committerJason Ekstrand <[email protected]>2018-06-22 20:15:53 -0700
commit19a4662a540a8c940310a75f19bc8cd75be651e0 (patch)
treebe24fd16f6a4b55529b015442f709971938d44a8 /src/compiler/nir/nir_print.c
parent5fbbbda37a09e6d253532fd83097b21cd289c16b (diff)
nir: Add a deref instruction type
This commit adds a new instruction type to NIR for handling derefs. Nothing uses it yet but this adds the data structure as well as all of the code to validate, print, clone, and [de]serialize them. Reviewed-by: Caio Marcelo de Oliveira Filho <[email protected]> Acked-by: Rob Clark <[email protected]> Acked-by: Bas Nieuwenhuizen <[email protected]> Acked-by: Dave Airlie <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/compiler/nir/nir_print.c')
-rw-r--r--src/compiler/nir/nir_print.c132
1 files changed, 130 insertions, 2 deletions
diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c
index 7c3e93eb82a..90d865fe950 100644
--- a/src/compiler/nir/nir_print.c
+++ b/src/compiler/nir/nir_print.c
@@ -393,7 +393,7 @@ print_constant(nir_constant *c, const struct glsl_type *type, print_state *state
}
static const char *
-get_variable_mode_str(nir_variable_mode mode)
+get_variable_mode_str(nir_variable_mode mode, bool want_local_global_mode)
{
switch (mode) {
case nir_var_shader_in:
@@ -410,7 +410,9 @@ get_variable_mode_str(nir_variable_mode mode)
return "shared";
case nir_var_param:
case nir_var_global:
+ return want_local_global_mode ? "global" : "";
case nir_var_local:
+ return want_local_global_mode ? "local" : "";
default:
return "";
}
@@ -428,7 +430,7 @@ print_var_decl(nir_variable *var, print_state *state)
const char *const patch = (var->data.patch) ? "patch " : "";
const char *const inv = (var->data.invariant) ? "invariant " : "";
fprintf(fp, "%s%s%s%s%s %s ",
- cent, samp, patch, inv, get_variable_mode_str(var->data.mode),
+ cent, samp, patch, inv, get_variable_mode_str(var->data.mode, false),
glsl_interp_mode_name(var->data.interpolation));
const char *const coher = (var->data.image.coherent) ? "coherent " : "";
@@ -518,6 +520,128 @@ print_var_decl(nir_variable *var, print_state *state)
}
static void
+print_deref_link(nir_deref_instr *instr, bool whole_chain, print_state *state)
+{
+ FILE *fp = state->fp;
+
+ if (instr->deref_type == nir_deref_type_var) {
+ fprintf(fp, "%s", get_var_name(instr->var, state));
+ return;
+ } else if (instr->deref_type == nir_deref_type_cast) {
+ fprintf(fp, "(%s *)", glsl_get_type_name(instr->type));
+ print_src(&instr->parent, state);
+ return;
+ }
+
+ assert(instr->parent.is_ssa);
+ nir_deref_instr *parent =
+ nir_instr_as_deref(instr->parent.ssa->parent_instr);
+
+ /* Is the parent we're going to print a bare cast? */
+ const bool is_parent_cast =
+ whole_chain && parent->deref_type == nir_deref_type_cast;
+
+ /* If we're not printing the whole chain, the parent we print will be a SSA
+ * value that represents a pointer. The only deref type that naturally
+ * gives a pointer is a cast.
+ */
+ const bool is_parent_pointer =
+ !whole_chain || parent->deref_type == nir_deref_type_cast;
+
+ /* Struct derefs have a nice syntax that works on pointers, arrays derefs
+ * do not.
+ */
+ const bool need_deref =
+ is_parent_pointer && instr->deref_type != nir_deref_type_struct;
+
+ /* Cast need extra parens and so * dereferences */
+ if (is_parent_cast || need_deref)
+ fprintf(fp, "(");
+
+ if (need_deref)
+ fprintf(fp, "*");
+
+ if (whole_chain) {
+ print_deref_link(parent, whole_chain, state);
+ } else {
+ print_src(&instr->parent, state);
+ }
+
+ if (is_parent_cast || need_deref)
+ fprintf(fp, ")");
+
+ switch (instr->deref_type) {
+ case nir_deref_type_struct:
+ fprintf(fp, "%s%s", is_parent_pointer ? "->" : ".",
+ glsl_get_struct_elem_name(parent->type, instr->strct.index));
+ break;
+
+ case nir_deref_type_array: {
+ nir_const_value *const_index = nir_src_as_const_value(instr->arr.index);
+ if (const_index) {
+ fprintf(fp, "[%u]", const_index->u32[0]);
+ } else {
+ fprintf(fp, "[");
+ print_src(&instr->arr.index, state);
+ fprintf(fp, "]");
+ }
+ break;
+ }
+
+ case nir_deref_type_array_wildcard:
+ fprintf(fp, "[*]");
+ break;
+
+ default:
+ unreachable("Invalid deref instruction type");
+ }
+}
+
+static void
+print_deref_instr(nir_deref_instr *instr, print_state *state)
+{
+ FILE *fp = state->fp;
+
+ print_dest(&instr->dest, state);
+
+ switch (instr->deref_type) {
+ case nir_deref_type_var:
+ fprintf(fp, " = deref_var ");
+ break;
+ case nir_deref_type_array:
+ case nir_deref_type_array_wildcard:
+ fprintf(fp, " = deref_array ");
+ break;
+ case nir_deref_type_struct:
+ fprintf(fp, " = deref_struct ");
+ break;
+ case nir_deref_type_cast:
+ fprintf(fp, " = deref_cast ");
+ break;
+ default:
+ unreachable("Invalid deref instruction type");
+ }
+
+ /* Only casts naturally return a pointer type */
+ if (instr->deref_type != nir_deref_type_cast)
+ fprintf(fp, "&");
+
+ print_deref_link(instr, false, state);
+
+ fprintf(fp, " (%s %s) ",
+ get_variable_mode_str(instr->mode, true),
+ glsl_get_type_name(instr->type));
+
+ if (instr->deref_type != nir_deref_type_var &&
+ instr->deref_type != nir_deref_type_cast) {
+ /* Print the entire chain as a comment */
+ fprintf(fp, "/* &");
+ print_deref_link(instr, true, state);
+ fprintf(fp, " */");
+ }
+}
+
+static void
print_var(nir_variable *var, print_state *state)
{
FILE *fp = state->fp;
@@ -965,6 +1089,10 @@ print_instr(const nir_instr *instr, print_state *state, unsigned tabs)
print_alu_instr(nir_instr_as_alu(instr), state);
break;
+ case nir_instr_type_deref:
+ print_deref_instr(nir_instr_as_deref(instr), state);
+ break;
+
case nir_instr_type_call:
print_call_instr(nir_instr_as_call(instr), state);
break;