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.
This commit is contained in:
Ian Romanick
2010-05-19 11:37:35 +02:00
parent 461c294ac5
commit 70fe8b6663
9 changed files with 179 additions and 144 deletions

View File

@@ -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();

View File

@@ -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

View File

@@ -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);

View File

@@ -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 "

107
ir.cpp
View File

@@ -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_dereference_array::ir_dereference_array(ir_rvalue *value,
ir_rvalue *array_index)
: mode(ir_reference_array), var(var)
: ir_dereference(ir_reference_array)
{
type = glsl_type::error_type;
this->selector.array_index = array_index;
this->set_array(value);
}
if (var != NULL) {
const glsl_type *const vt = var->type;
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 (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::ir_dereference(ir_instruction *variable, const char *field)
: mode(ir_reference_record), var(variable)
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 = (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;
}
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 = (this->var != NULL)
? this->var->type->field_type(field) : glsl_type::error_type;
}
bool
ir_dereference::is_lvalue()
{
if (var == NULL)
ir_variable *var = this->variable_referenced();
/* Every l-value derference chain eventually ends in a variable.
*/
if ((var == NULL) || var->read_only)
return false;
ir_variable *const as_var = var->as_variable();
if (mode == ir_reference_variable) {
if (as_var == NULL)
if (this->type->is_array() && !var->array_lvalue)
return false;
if (as_var->type->is_array() && !as_var->array_lvalue)
return false;
}
if (as_var != NULL)
return !as_var->read_only;
/* Walk up the dereference chain and figure out if the variable is read-only.
*/
return this->var->as_rvalue()->is_lvalue();
}
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;
}
}
assert(!"Should not get here.");
return NULL;
return true;
}

67
ir.h
View File

@@ -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();
}
};

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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 *