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();
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
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;
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;
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);
tmp->type = op[1]->type;
}
- result = new ir_dereference(tmp);
+ result = new ir_dereference_variable(tmp);
type = tmp->type;
break;
}
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.
*/
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;
? "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
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);
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);
/* 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);
* __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);
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);
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);
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);
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.
*/
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);
}
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);
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 "
}
-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();
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;
}
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;
/**
* 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
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();
+ }
};
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);
}
}
}
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));
}
}
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);
}
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);
}
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);
}
delete(parameters);
if (retval)
- return new ir_dereference(retval);
+ return new ir_dereference_variable(retval);
else
return NULL;
}
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
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;
}
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 *
}
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 *