bool needs_lowering(ir_dereference_array *deref) const { if (deref == NULL || deref->array_index->as_constant() || !is_array_or_matrix(deref->array)) return false; return this->storage_type_needs_lowering(deref); }
virtual ir_visitor_status visit_enter(ir_dereference_array *ir) { if (is_array_or_matrix(ir->array) && (ir->array_index->as_constant() == NULL)) { this->deref = ir; return visit_stop; } return visit_continue; }
ir_variable *convert_dereference_array(ir_dereference_array *orig_deref, ir_assignment* orig_assign, ir_dereference *orig_base) { assert(is_array_or_matrix(orig_deref->array)); const unsigned length = (orig_deref->array->type->is_array()) ? orig_deref->array->type->length : orig_deref->array->type->matrix_columns; void *const mem_ctx = ralloc_parent(base_ir); /* Temporary storage for either the result of the dereference of * the array, or the RHS that's being assigned into the * dereference of the array. */ ir_variable *var; if (orig_assign) { var = new(mem_ctx) ir_variable(orig_assign->rhs->type, "dereference_array_value", ir_var_temporary); base_ir->insert_before(var); ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(var); ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, orig_assign->rhs, NULL); base_ir->insert_before(assign); } else { var = new(mem_ctx) ir_variable(orig_deref->type, "dereference_array_value", ir_var_temporary); base_ir->insert_before(var); } /* Store the index to a temporary to avoid reusing its tree. */ ir_variable *index = new(mem_ctx) ir_variable(orig_deref->array_index->type, "dereference_array_index", ir_var_temporary); base_ir->insert_before(index); ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(index); ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, orig_deref->array_index, NULL); base_ir->insert_before(assign); orig_deref->array_index = lhs->clone(mem_ctx, NULL); assignment_generator ag; ag.rvalue = orig_base; ag.base_ir = base_ir; ag.old_index = index; ag.var = var; if (orig_assign) { ag.is_write = true; ag.write_mask = orig_assign->write_mask; } else { ag.is_write = false; } switch_generator sg(ag, index, 4, 4); /* If the original assignment has a condition, respect that original * condition! This is acomplished by wrapping the new conditional * assignments in an if-statement that uses the original condition. */ if ((orig_assign != NULL) && (orig_assign->condition != NULL)) { /* No need to clone the condition because the IR that it hangs on is * going to be removed from the instruction sequence. */ ir_if *if_stmt = new(mem_ctx) ir_if(orig_assign->condition); sg.generate(0, length, &if_stmt->then_instructions); base_ir->insert_before(if_stmt); } else { exec_list list; sg.generate(0, length, &list); base_ir->insert_before(&list); } return var; }