From 70fe8b66632f4afd87ebb12a450b1e639428e88f Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 19 May 2010 11:37:35 +0200 Subject: [PATCH] Begin refactoring ir_dereference Create separate subclasses of ir_dereference for variable, array, and record dereferences. As a side effect, array and record dereferences no longer point to ir_variable objects directly. Instead they each point to an ir_dereference_variable object. This is the first of several steps in the refactoring process. The intention is that ir_dereference will eventually become an abstract base class. --- ast_function.cpp | 2 +- ast_to_hir.cpp | 37 +++++------- glsl_types.cpp | 42 +++++++------- hir_field_selection.cpp | 3 +- ir.cpp | 107 +++++++++++++++++------------------ ir.h | 67 +++++++++++++++++++--- ir_expression_flattening.cpp | 4 +- ir_function_inlining.cpp | 38 ++++++------- ir_reader.cpp | 19 ++----- 9 files changed, 177 insertions(+), 142 deletions(-) diff --git a/ast_function.cpp b/ast_function.cpp index 7931633c5a1..300108cb73e 100644 --- a/ast_function.cpp +++ b/ast_function.cpp @@ -200,7 +200,7 @@ dereference_component(ir_rvalue *src, unsigned component) const int c = component / src->type->column_type()->vector_elements; const int r = component % src->type->column_type()->vector_elements; ir_constant *const col_index = new ir_constant(glsl_type::int_type, &c); - ir_dereference *const col = new ir_dereference(src, col_index); + ir_dereference *const col = new ir_dereference_array(src, col_index); col->type = src->type->column_type(); diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp index 2243d644032..b8128fa8a77 100644 --- a/ast_to_hir.cpp +++ b/ast_to_hir.cpp @@ -535,7 +535,7 @@ get_lvalue_copy(exec_list *instructions, struct _mesa_glsl_parse_state *state, var = new ir_variable(lvalue->type, "_internal_tmp"); var->mode = ir_var_auto; - var_deref = new ir_dereference(var); + var_deref = new ir_dereference_variable(var); do_assignment(instructions, state, var_deref, lvalue, loc); /* Once we've created this temporary, mark it read only so it's no @@ -803,17 +803,17 @@ ast_expression::hir(exec_list *instructions, ir_variable *const tmp = generate_temporary(glsl_type::bool_type, instructions, state); - ir_dereference *const then_deref = new ir_dereference(tmp); + ir_dereference *const then_deref = new ir_dereference_variable(tmp); ir_assignment *const then_assign = new ir_assignment(then_deref, op[1], NULL); stmt->then_instructions.push_tail(then_assign); - ir_dereference *const else_deref = new ir_dereference(tmp); + ir_dereference *const else_deref = new ir_dereference_variable(tmp); ir_assignment *const else_assign = new ir_assignment(else_deref, new ir_constant(false), NULL); stmt->else_instructions.push_tail(else_assign); - result = new ir_dereference(tmp); + result = new ir_dereference_variable(tmp); type = tmp->type; } break; @@ -865,17 +865,17 @@ ast_expression::hir(exec_list *instructions, error_emitted = true; } - ir_dereference *const then_deref = new ir_dereference(tmp); + ir_dereference *const then_deref = new ir_dereference_variable(tmp); ir_assignment *const then_assign = new ir_assignment(then_deref, new ir_constant(true), NULL); stmt->then_instructions.push_tail(then_assign); - ir_dereference *const else_deref = new ir_dereference(tmp); + ir_dereference *const else_deref = new ir_dereference_variable(tmp); ir_assignment *const else_assign = new ir_assignment(else_deref, op[1], NULL); stmt->else_instructions.push_tail(else_assign); - result = new ir_dereference(tmp); + result = new ir_dereference_variable(tmp); type = tmp->type; } break; @@ -996,13 +996,13 @@ ast_expression::hir(exec_list *instructions, instructions->push_tail(stmt); op[1] = this->subexpressions[1]->hir(& stmt->then_instructions, state); - ir_dereference *const then_deref = new ir_dereference(tmp); + ir_dereference *const then_deref = new ir_dereference_variable(tmp); ir_assignment *const then_assign = new ir_assignment(then_deref, op[1], NULL); stmt->then_instructions.push_tail(then_assign); op[2] = this->subexpressions[2]->hir(& stmt->else_instructions, state); - ir_dereference *const else_deref = new ir_dereference(tmp); + ir_dereference *const else_deref = new ir_dereference_variable(tmp); ir_assignment *const else_assign = new ir_assignment(else_deref, op[2], NULL); stmt->else_instructions.push_tail(else_assign); @@ -1028,7 +1028,7 @@ ast_expression::hir(exec_list *instructions, tmp->type = op[1]->type; } - result = new ir_dereference(tmp); + result = new ir_dereference_variable(tmp); type = tmp->type; break; } @@ -1097,18 +1097,9 @@ ast_expression::hir(exec_list *instructions, error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); - ir_dereference *const lhs = op[0]->as_dereference(); - ir_instruction *array; - if ((lhs != NULL) - && (lhs->mode == ir_dereference::ir_reference_variable)) { - result = new ir_dereference(lhs->var, op[1]); + ir_instruction *const array = op[0]; - delete op[0]; - array = lhs->var; - } else { - result = new ir_dereference(op[0], op[1]); - array = op[0]; - } + result = new ir_dereference_array(op[0], op[1]); /* Do not use op[0] after this point. Use array. */ @@ -1218,7 +1209,7 @@ ast_expression::hir(exec_list *instructions, ir_variable *var = state->symbols->get_variable(this->primary_expression.identifier); - result = new ir_dereference(var); + result = new ir_dereference_variable(var); if (var != NULL) { type = result->type; @@ -1722,7 +1713,7 @@ ast_declarator_list::hir(exec_list *instructions, ? "attribute" : "varying"); } - ir_dereference *const lhs = new ir_dereference(var); + ir_dereference *const lhs = new ir_dereference_variable(var); ir_rvalue *rhs = decl->initializer->hir(instructions, state); /* Calculate the constant value if this is a const diff --git a/glsl_types.cpp b/glsl_types.cpp index a293ce72860..e1beeefe891 100644 --- a/glsl_types.cpp +++ b/glsl_types.cpp @@ -171,10 +171,10 @@ glsl_type::generate_constructor(glsl_symbol_table *symtab) const for (unsigned i = 0; i < length; i++) { ir_dereference *const lhs = (this->base_type == GLSL_TYPE_ARRAY) - ? new ir_dereference(retval, new ir_constant(i)) - : new ir_dereference(retval, fields.structure[i].name); + ? (ir_dereference *) new ir_dereference_array(retval, new ir_constant(i)) + : (ir_dereference *) new ir_dereference_record(retval, fields.structure[i].name); - ir_dereference *const rhs = new ir_dereference(declarations[i]); + ir_dereference *const rhs = new ir_dereference_variable(declarations[i]); ir_instruction *const assign = new ir_assignment(lhs, rhs, NULL); sig->body.push_tail(assign); @@ -182,7 +182,7 @@ glsl_type::generate_constructor(glsl_symbol_table *symtab) const free(declarations); - ir_dereference *const retref = new ir_dereference(retval); + ir_dereference *const retref = new ir_dereference_variable(retval); ir_instruction *const inst = new ir_return(retref); sig->body.push_tail(inst); @@ -250,15 +250,16 @@ generate_vec_body_from_scalar(exec_list *instructions, /* Generate a single assignment of the parameter to __retval.x and return * __retval.xxxx for however many vector components there are. */ - ir_dereference *const lhs_ref = new ir_dereference(declarations[16]); - ir_dereference *const rhs = new ir_dereference(declarations[0]); + ir_dereference *const lhs_ref = + new ir_dereference_variable(declarations[16]); + ir_dereference *const rhs = new ir_dereference_variable(declarations[0]); ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1); inst = new ir_assignment(lhs, rhs, NULL); instructions->push_tail(inst); - ir_dereference *const retref = new ir_dereference(declarations[16]); + ir_dereference *const retref = new ir_dereference_variable(declarations[16]); ir_swizzle *retval = new ir_swizzle(retref, 0, 0, 0, 0, declarations[16]->type->vector_elements); @@ -283,8 +284,9 @@ generate_vec_body_from_N_scalars(exec_list *instructions, * __retval.x and return __retval. */ for (unsigned i = 0; i < vec_type->vector_elements; i++) { - ir_dereference *const lhs_ref = new ir_dereference(declarations[16]); - ir_dereference *const rhs = new ir_dereference(declarations[i]); + ir_dereference *const lhs_ref = + new ir_dereference_variable(declarations[16]); + ir_dereference *const rhs = new ir_dereference_variable(declarations[i]); ir_swizzle *lhs = new ir_swizzle(lhs_ref, i, 0, 0, 0, 1); @@ -292,7 +294,7 @@ generate_vec_body_from_N_scalars(exec_list *instructions, instructions->push_tail(inst); } - ir_dereference *retval = new ir_dereference(declarations[16]); + ir_dereference *retval = new ir_dereference_variable(declarations[16]); inst = new ir_return(retval); instructions->push_tail(inst); @@ -334,8 +336,8 @@ generate_mat_body_from_scalar(exec_list *instructions, instructions->push_tail(column); - ir_dereference *const lhs_ref = new ir_dereference(column); - ir_dereference *const rhs = new ir_dereference(declarations[0]); + ir_dereference *const lhs_ref = new ir_dereference_variable(column); + ir_dereference *const rhs = new ir_dereference_variable(declarations[0]); ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1); @@ -346,7 +348,7 @@ generate_mat_body_from_scalar(exec_list *instructions, ir_constant *const zero = new ir_constant(glsl_type::float_type, &z); for (unsigned i = 1; i < column_type->vector_elements; i++) { - ir_dereference *const lhs_ref = new ir_dereference(column); + ir_dereference *const lhs_ref = new ir_dereference_variable(column); ir_swizzle *lhs = new ir_swizzle(lhs_ref, i, 0, 0, 0, 1); @@ -357,7 +359,7 @@ generate_mat_body_from_scalar(exec_list *instructions, for (unsigned i = 0; i < row_type->vector_elements; i++) { static const unsigned swiz[] = { 1, 1, 1, 0, 1, 1, 1 }; - ir_dereference *const rhs_ref = new ir_dereference(column); + ir_dereference *const rhs_ref = new ir_dereference_variable(column); /* This will be .xyyy when i=0, .yxyy when i=1, etc. */ @@ -366,13 +368,14 @@ generate_mat_body_from_scalar(exec_list *instructions, column_type->vector_elements); ir_constant *const idx = new ir_constant(glsl_type::int_type, &i); - ir_dereference *const lhs = new ir_dereference(declarations[16], idx); + ir_dereference *const lhs = + new ir_dereference_array(declarations[16], idx); inst = new ir_assignment(lhs, rhs, NULL); instructions->push_tail(inst); } - ir_dereference *const retval = new ir_dereference(declarations[16]); + ir_dereference *const retval = new ir_dereference_variable(declarations[16]); inst = new ir_return(retval); instructions->push_tail(inst); } @@ -397,20 +400,21 @@ generate_mat_body_from_N_scalars(exec_list *instructions, for (unsigned j = 0; j < row_type->vector_elements; j++) { ir_constant *row_index = new ir_constant(glsl_type::int_type, &i); ir_dereference *const row_access = - new ir_dereference(declarations[16], row_index); + new ir_dereference_array(declarations[16], row_index); ir_swizzle *component_access = new ir_swizzle(row_access, j, 0, 0, 0, 1); const unsigned param = (i * row_type->vector_elements) + j; - ir_dereference *const rhs = new ir_dereference(declarations[param]); + ir_dereference *const rhs = + new ir_dereference_variable(declarations[param]); inst = new ir_assignment(component_access, rhs, NULL); instructions->push_tail(inst); } } - ir_dereference *retval = new ir_dereference(declarations[16]); + ir_dereference *retval = new ir_dereference_variable(declarations[16]); inst = new ir_return(retval); instructions->push_tail(inst); diff --git a/hir_field_selection.cpp b/hir_field_selection.cpp index 685cf75dcf0..f0be84dab4c 100644 --- a/hir_field_selection.cpp +++ b/hir_field_selection.cpp @@ -62,7 +62,8 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, expr->primary_expression.identifier); } } else if (op->type->base_type == GLSL_TYPE_STRUCT) { - result = new ir_dereference(op, expr->primary_expression.identifier); + result = new ir_dereference_record(op, + expr->primary_expression.identifier); if (result->type->is_error()) { _mesa_glsl_error(& loc, state, "Cannot access field `%s' of " diff --git a/ir.cpp b/ir.cpp index 696feb23f6f..f6f2558bc06 100644 --- a/ir.cpp +++ b/ir.cpp @@ -223,22 +223,40 @@ ir_constant::ir_constant(bool b) } -ir_dereference::ir_dereference(ir_instruction *var) +ir_dereference_variable::ir_dereference_variable(ir_variable *var) + : ir_dereference(ir_reference_variable) { - this->mode = ir_reference_variable; this->var = var; this->type = (var != NULL) ? var->type : glsl_type::error_type; } -ir_dereference::ir_dereference(ir_instruction *var, - ir_rvalue *array_index) - : mode(ir_reference_array), var(var) +ir_dereference_array::ir_dereference_array(ir_rvalue *value, + ir_rvalue *array_index) + : ir_dereference(ir_reference_array) { - type = glsl_type::error_type; + this->selector.array_index = array_index; + this->set_array(value); +} + + +ir_dereference_array::ir_dereference_array(ir_variable *var, + ir_rvalue *array_index) + : ir_dereference(ir_reference_array) +{ + this->selector.array_index = array_index; + this->set_array(new ir_dereference_variable(var)); +} + + +void +ir_dereference_array::set_array(ir_rvalue *value) +{ + this->var = value; + this->type = glsl_type::error_type; - if (var != NULL) { - const glsl_type *const vt = var->type; + if (this->var != NULL) { + const glsl_type *const vt = this->var->type; if (vt->is_array()) { type = vt->element_type(); @@ -248,68 +266,45 @@ ir_dereference::ir_dereference(ir_instruction *var, type = vt->get_base_type(); } } +} - this->selector.array_index = array_index; + +ir_dereference_record::ir_dereference_record(ir_rvalue *value, + const char *field) + : ir_dereference(ir_reference_record) +{ + this->var = value; + this->selector.field = field; + this->type = (this->var != NULL) + ? this->var->type->field_type(field) : glsl_type::error_type; } -ir_dereference::ir_dereference(ir_instruction *variable, const char *field) - : mode(ir_reference_record), var(variable) + +ir_dereference_record::ir_dereference_record(ir_variable *var, + const char *field) + : ir_dereference(ir_reference_record) { + this->var = new ir_dereference_variable(var); this->selector.field = field; - this->type = (var != NULL) - ? var->type->field_type(field) : glsl_type::error_type; + this->type = (this->var != NULL) + ? this->var->type->field_type(field) : glsl_type::error_type; } + bool ir_dereference::is_lvalue() { - if (var == NULL) - return false; - - ir_variable *const as_var = var->as_variable(); - if (mode == ir_reference_variable) { - if (as_var == NULL) - return false; - - if (as_var->type->is_array() && !as_var->array_lvalue) - return false; - } - - if (as_var != NULL) - return !as_var->read_only; + ir_variable *var = this->variable_referenced(); - /* Walk up the dereference chain and figure out if the variable is read-only. + /* Every l-value derference chain eventually ends in a variable. */ - return this->var->as_rvalue()->is_lvalue(); -} - + if ((var == NULL) || var->read_only) + return false; -ir_variable * -ir_dereference::variable_referenced() -{ - /* Walk down the dereference chain to find the variable at the end. - * - * This could be implemented recurrsively, but it would still need to call - * as_variable and as_rvalue, so the code wouldn't be any cleaner. - */ - for (ir_instruction *current = this->var; current != NULL; /* empty */ ) { - ir_dereference *deref; - ir_variable *v; - - if ((deref = current->as_dereference())) { - current = deref->var; - } else if ((v = current->as_variable())) { - return v; - } else { - /* This is the case of, for example, an array dereference of the - * value returned by a function call. - */ - return NULL; - } - } + if (this->type->is_array() && !var->array_lvalue) + return false; - assert(!"Should not get here."); - return NULL; + return true; } diff --git a/ir.h b/ir.h index 93b4c2b66ab..70fe9f9db6f 100644 --- a/ir.h +++ b/ir.h @@ -788,12 +788,6 @@ public: class ir_dereference : public ir_rvalue { public: - ir_dereference(struct ir_instruction *); - - ir_dereference(ir_instruction *variable, ir_rvalue *array_index); - - ir_dereference(ir_instruction *variable, const char *field); - virtual ir_dereference *as_dereference() { return this; @@ -811,9 +805,9 @@ public: /** * Get the variable that is ultimately referenced by an r-value */ - virtual ir_variable *variable_referenced(); + virtual ir_variable *variable_referenced() = 0; - enum { + enum ir_deref_mode { ir_reference_variable, ir_reference_array, ir_reference_record @@ -830,6 +824,63 @@ public: ir_rvalue *array_index; const char *field; } selector; + +protected: + ir_dereference(ir_deref_mode mode) + : mode(mode) + { + /* empty */ + } +}; + + +class ir_dereference_variable : public ir_dereference { +public: + ir_dereference_variable(ir_variable *var); + + /** + * Get the variable that is ultimately referenced by an r-value + */ + virtual ir_variable *variable_referenced() + { + return (ir_variable *) this->var; + } +}; + + +class ir_dereference_array : public ir_dereference { +public: + ir_dereference_array(ir_rvalue *value, ir_rvalue *array_index); + + ir_dereference_array(ir_variable *var, ir_rvalue *array_index); + + /** + * Get the variable that is ultimately referenced by an r-value + */ + virtual ir_variable *variable_referenced() + { + return ((ir_rvalue *) this->var)->variable_referenced(); + } + + +private: + void set_array(ir_rvalue *value); +}; + + +class ir_dereference_record : public ir_dereference { +public: + ir_dereference_record(ir_rvalue *value, const char *field); + + ir_dereference_record(ir_variable *var, const char *field); + + /** + * Get the variable that is ultimately referenced by an r-value + */ + virtual ir_variable *variable_referenced() + { + return ((ir_rvalue *) this->var)->variable_referenced(); + } }; diff --git a/ir_expression_flattening.cpp b/ir_expression_flattening.cpp index 28c96a787de..9494786d4e4 100644 --- a/ir_expression_flattening.cpp +++ b/ir_expression_flattening.cpp @@ -143,12 +143,12 @@ ir_expression_flattening_visitor::visit(ir_expression *ir) var = new ir_variable(ir->operands[operand]->type, "flattening_tmp"); this->base_ir->insert_before(var); - assign = new ir_assignment(new ir_dereference(var), + assign = new ir_assignment(new ir_dereference_variable(var), ir->operands[operand], NULL); this->base_ir->insert_before(assign); - ir->operands[operand] = new ir_dereference(var); + ir->operands[operand] = new ir_dereference_variable(var); } } } diff --git a/ir_function_inlining.cpp b/ir_function_inlining.cpp index 09604c04df9..499ce5f1dc2 100644 --- a/ir_function_inlining.cpp +++ b/ir_function_inlining.cpp @@ -220,28 +220,27 @@ ir_function_cloning_visitor::visit(ir_swizzle *ir) void ir_function_cloning_visitor::visit(ir_dereference *ir) { - ir_variable *old_var = ir->var->as_variable(); - ir_instruction *var; - - if (old_var) - var = this->get_remapped_variable(old_var); - else { - ir->var->accept(this); - var = this->result; - } - if (ir->mode == ir_dereference::ir_reference_variable) { - this->result = new ir_dereference(var); + ir_variable *var = this->get_remapped_variable(ir->variable_referenced()); + this->result = new ir_dereference_variable(var); } else if (ir->mode == ir_dereference::ir_reference_array) { - ir_rvalue *index; + ir->var->accept(this); + + ir_rvalue *var = this->result->as_rvalue(); ir->selector.array_index->accept(this); - index = this->result->as_rvalue(); - this->result = new ir_dereference(var, index); + ir_rvalue *index = this->result->as_rvalue(); + + this->result = new ir_dereference_array(var, index); } else { assert(ir->mode == ir_dereference::ir_reference_record); - this->result = new ir_dereference(var, strdup(ir->selector.field)); + + ir->var->accept(this); + + ir_rvalue *var = this->result->as_rvalue(); + + this->result = new ir_dereference_record(var, strdup(ir->selector.field)); } } @@ -300,7 +299,8 @@ ir_function_cloning_visitor::visit(ir_return *ir) rval = this->result->as_rvalue(); assert(rval); - result = new ir_assignment(new ir_dereference(this->retval), rval, NULL); + result = new ir_assignment(new ir_dereference_variable(this->retval), rval, + NULL); } @@ -406,7 +406,7 @@ ir_call::generate_inline(ir_instruction *next_ir) parameters[i]->mode == ir_var_inout) { ir_assignment *assign; - assign = new ir_assignment(new ir_dereference(parameters[i]), + assign = new ir_assignment(new ir_dereference_variable(parameters[i]), param, NULL); next_ir->insert_before(assign); } @@ -438,7 +438,7 @@ ir_call::generate_inline(ir_instruction *next_ir) ir_assignment *assign; assign = new ir_assignment(param->as_rvalue(), - new ir_dereference(parameters[i]), + new ir_dereference_variable(parameters[i]), NULL); next_ir->insert_before(assign); } @@ -449,7 +449,7 @@ ir_call::generate_inline(ir_instruction *next_ir) delete(parameters); if (retval) - return new ir_dereference(retval); + return new ir_dereference_variable(retval); else return NULL; } diff --git a/ir_reader.cpp b/ir_reader.cpp index 1bf5363f52a..744606d4f2c 100644 --- a/ir_reader.cpp +++ b/ir_reader.cpp @@ -817,7 +817,7 @@ read_constant(_mesa_glsl_parse_state *st, s_list *list) return NULL; // should not be reached } -static ir_instruction * +static ir_variable * read_dereferencable(_mesa_glsl_parse_state *st, s_expression *expr) { // Read the subject of a dereference - either a variable name or a swizzle @@ -828,15 +828,8 @@ read_dereferencable(_mesa_glsl_parse_state *st, s_expression *expr) ir_read_error(st, expr, "undeclared variable: %s", var_name->value()); } return var; - } else { - // Hopefully a (swiz ...) - s_list *list = SX_AS_LIST(expr); - if (list != NULL && !list->subexpressions.is_empty()) { - s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.head); - if (tag != NULL && strcmp(tag->value(), "swiz") == 0) - return read_swizzle(st, list); - } } + ir_read_error(st, expr, "expected variable name or (swiz ...)"); return NULL; } @@ -849,10 +842,10 @@ read_var_ref(_mesa_glsl_parse_state *st, s_list *list) return NULL; } s_expression *subj_expr = (s_expression*) list->subexpressions.head->next; - ir_instruction *subject = read_dereferencable(st, subj_expr); + ir_variable *subject = read_dereferencable(st, subj_expr); if (subject == NULL) return NULL; - return new ir_dereference(subject); + return new ir_dereference_variable(subject); } static ir_dereference * @@ -865,13 +858,13 @@ read_array_ref(_mesa_glsl_parse_state *st, s_list *list) } s_expression *subj_expr = (s_expression*) list->subexpressions.head->next; - ir_instruction *subject = read_dereferencable(st, subj_expr); + ir_variable *subject = read_dereferencable(st, subj_expr); if (subject == NULL) return NULL; s_expression *idx_expr = (s_expression*) subj_expr->next; ir_rvalue *idx = read_rvalue(st, idx_expr); - return new ir_dereference(subject, idx); + return new ir_dereference_array(subject, idx); } static ir_dereference * -- 2.30.2