It seems like this would be much more compact as a ir_hierarchical_visitor that only implements visit_leave(ir_dereference_array *). Is there a reason that doesn't work that I'm not seeing?
On 07/15/2018 01:04 AM, Timothy Arceri wrote: > Fixes new piglit test: > tests/spec/glsl-1.20/execution/qualifiers/vs-out-conversion-int-to-float-vec4-index.shader_test > --- > src/compiler/glsl/ast_function.cpp | 94 ++++++++++++++++++++++++++++++ > 1 file changed, 94 insertions(+) > > diff --git a/src/compiler/glsl/ast_function.cpp > b/src/compiler/glsl/ast_function.cpp > index 127aa1f91c4..97e78f99ea7 100644 > --- a/src/compiler/glsl/ast_function.cpp > +++ b/src/compiler/glsl/ast_function.cpp > @@ -348,6 +348,93 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, > return true; > } > > +static void > +copy_index_derefs_to_temps(void *mem_ctx, ir_rvalue *param, > + exec_list *before_instructions) > +{ > + /* Loop through the IR copying array indices until we find a swizzle, > + * costant or variable ref. > + */ > + ir_rvalue *ir = param; > + while (ir != NULL) { > + switch (ir->ir_type) { > + case ir_type_dereference_record: { > + ir_dereference_record *r = (ir_dereference_record *) ir; > + ir = r->record->as_dereference(); > + break; > + } > + > + case ir_type_swizzle: { > + ir_swizzle *s = (ir_swizzle *) ir; > + ir = s->val->as_dereference(); > + break; > + } > + > + case ir_type_expression: { > + ir_expression *expr = (ir_expression* ) ir; > + for (unsigned int i = 0; i < expr->num_operands; i++) { > + copy_index_derefs_to_temps(mem_ctx, expr->operands[i], > + before_instructions); > + } > + > + ir = NULL; > + break; > + } > + > + case ir_type_dereference_array: { > + ir_dereference_array *a = (ir_dereference_array *) ir; > + ir = a->array->as_dereference(); > + > + ir_rvalue *idx = a->array_index; > + copy_index_derefs_to_temps(mem_ctx, idx, before_instructions); > + > + if (idx->as_dereference_variable()) { > + ir_variable *var = idx->variable_referenced(); > + > + /* If the index is read only it cannot change so there is no need > + * to copy it. > + */ > + if (var->data.read_only || var->data.memory_read_only) > + break; > + } > + > + ir_variable *tmp = new(mem_ctx) ir_variable(idx->type, "idx_tmp", > + ir_var_temporary); > + before_instructions->push_tail(tmp); > + > + ir_dereference_variable *const deref_tmp_1 = > + new(mem_ctx) ir_dereference_variable(tmp); > + ir_assignment *const assignment = > + new(mem_ctx) ir_assignment(deref_tmp_1, > + idx->clone(mem_ctx, NULL)); > + before_instructions->push_tail(assignment); > + > + /* Replace the array index with a dereference of the new temporary. > + */ > + ir_dereference_variable *const deref_tmp_2 = > + new(mem_ctx) ir_dereference_variable(tmp); > + a->array_index = deref_tmp_2; > + break; > + } > + > + case ir_type_dereference_variable: { > + ir = NULL; > + break; > + } > + > + case ir_type_constant: { > + /* Nothing to do for constants */ > + ir = NULL; > + break; > + } > + > + default: > + unreachable("Unexpected deref type"); > + break; > + } > + } > +} > + > static void > fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type, > exec_list *before_instructions, exec_list *after_instructions, > @@ -362,6 +449,13 @@ fix_parameter(void *mem_ctx, ir_rvalue *actual, const > glsl_type *formal_type, > && (expr == NULL || expr->operation != ir_binop_vector_extract)) > return; > > + /* An array index could also be an out variable so we need to make a copy > + * of them before the function is called. > + */ > + if (!actual->as_dereference_variable()) { > + copy_index_derefs_to_temps(mem_ctx, actual, before_instructions); > + } > + > /* To convert an out parameter, we need to create a temporary variable to > * hold the value before conversion, and then perform the conversion after > * the function call returns. > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev