These should work well even in a non-flat IR hierarchy.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
/* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
loc = this->subexpressions[0]->get_location();
- if (op[0]->mode != ir_op_dereference) {
+ const ir_dereference *const ref = op[0]->as_dereference();
+ if (ref == NULL) {
_mesa_glsl_error(& loc, state, "invalid lvalue in assignment");
error_emitted = true;
type = glsl_error_type;
} else {
- const struct ir_dereference *const ref =
- (struct ir_dereference *) op[0];
- const struct ir_variable *const var =
- (struct ir_variable *) ref->var;
-
- if ((var != NULL)
- && (var->mode == ir_op_var_decl)
- && (var->read_only)) {
+ const ir_variable *const var = (ir_variable *) ref->var;
+
+ if (var != NULL && var->read_only) {
_mesa_glsl_error(& loc, state, "cannot assign to read-only "
"variable `%s'", var->name);
error_emitted = true;
/* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
loc = this->subexpressions[0]->get_location();
- if (op[0]->mode != ir_op_dereference) {
+ const ir_dereference *const ref = op[0]->as_dereference();
+ if (ref == NULL) {
_mesa_glsl_error(& loc, state, "invalid lvalue in assignment");
error_emitted = true;
type = glsl_error_type;
} else {
- const struct ir_dereference *const ref =
- (struct ir_dereference *) op[0];
- const struct ir_variable *const var =
- (struct ir_variable *) ref->var;
-
- if ((var != NULL)
- && (var->mode == ir_op_var_decl)
- && (var->read_only)) {
+ const ir_variable *const var = (ir_variable *) ref->var;
+
+ if (var != NULL && var->read_only) {
_mesa_glsl_error(& loc, state, "cannot assign to read-only "
"variable `%s'", var->name);
error_emitted = true;
* either include invalid parameter names or may not have names at all.
*/
foreach_iter(exec_list_iterator, iter, signature->parameters) {
- assert(((struct ir_instruction *)iter.get())->mode == ir_op_var_decl);
+ assert(((ir_instruction *) iter.get())->as_variable() != NULL);
iter.remove();
delete iter.get();
foreach_iter(exec_list_iterator, iter, parameters) {
ir_variable *const var = (ir_variable *) iter.get();
- assert(((ir_instruction *)var)->mode == ir_op_var_decl);
+ assert(((ir_instruction *) var)->as_variable() != NULL);
iter.remove();
instructions->push_tail(var);
ir_assignment::ir_assignment(ir_instruction *lhs, ir_instruction *rhs,
ir_expression *condition)
- : ir_instruction(ir_op_assign)
+ : ir_instruction()
{
this->lhs = (ir_dereference *) lhs;
this->rhs = rhs;
ir_expression::ir_expression(int op, const struct glsl_type *type,
ir_instruction *op0, ir_instruction *op1)
- : ir_instruction(ir_op_expression)
+ : ir_instruction()
{
this->type = type;
this->operation = ir_expression_operation(op);
ir_label::ir_label(const char *label)
- : ir_instruction(ir_op_label), label(label)
+ : ir_instruction(), label(label)
{
/* empty */
}
ir_constant::ir_constant(const struct glsl_type *type, const void *data)
- : ir_instruction(ir_op_constant)
+ : ir_instruction()
{
const unsigned elements =
((type->vector_elements == 0) ? 1 : type->vector_elements)
ir_dereference::ir_dereference(ir_instruction *var)
- : ir_instruction(ir_op_dereference)
+ : ir_instruction()
{
this->mode = ir_reference_variable;
this->var = var;
ir_dereference::ir_dereference(ir_instruction *var,
ir_instruction *array_index)
- : ir_instruction(ir_op_dereference), mode(ir_reference_array),
+ : ir_instruction(), mode(ir_reference_array),
var(var)
{
this->type = (var != NULL) ? var->type : glsl_error_type;
ir_variable::ir_variable(const struct glsl_type *type, const char *name)
- : ir_instruction(ir_op_var_decl), read_only(false), centroid(false),
- invariant(false), mode(ir_var_auto), interpolation(ir_var_smooth)
+ : ir_instruction(), read_only(false), centroid(false), invariant(false),
+ mode(ir_var_auto), interpolation(ir_var_smooth)
{
this->type = type;
this->name = name;
ir_function_signature::ir_function_signature(const glsl_type *return_type)
- : ir_instruction(ir_op_func_sig), return_type(return_type), definition(NULL)
+ : ir_instruction(), return_type(return_type), definition(NULL)
{
/* empty */
}
ir_function::ir_function(const char *name)
- : ir_instruction(ir_op_func), name(name)
+ : ir_instruction(), name(name)
{
/* empty */
}
void *bong_hits;
};
-
-enum ir_opcodes {
- ir_op_var_decl,
- ir_op_assign,
- ir_op_expression,
- ir_op_dereference,
- ir_op_jump,
- ir_op_label,
- ir_op_constant,
- ir_op_func_sig,
- ir_op_func,
- ir_op_call,
-};
-
/**
* Base class of all IR instructions
*/
class ir_instruction : public exec_node {
public:
- unsigned mode;
const struct glsl_type *type;
virtual void accept(ir_visitor *) = 0;
+ /**
+ * \name IR instruction downcast functions
+ *
+ * These functions either cast the object to a derived class or return
+ * \c NULL if the object's type does not match the specified derived class.
+ * Additional downcast functions will be added as needed.
+ */
+ /*@{*/
+ virtual class ir_variable * as_variable() { return NULL; }
+ virtual class ir_dereference * as_dereference() { return NULL; }
+ /*@}*/
+
protected:
- ir_instruction(int mode)
- : mode(mode)
+ ir_instruction()
{
/* empty */
}
-
-private:
- /**
- * Dummy constructor to catch bad constructors in derived classes.
- *
- * Every derived must use the constructor that sets the instructions
- * mode. Having the \c void constructor private prevents derived classes
- * from accidentally doing the wrong thing.
- */
- ir_instruction(void);
};
public:
ir_variable(const struct glsl_type *, const char *);
+ virtual ir_variable *as_variable()
+ {
+ return this;
+ }
+
virtual void accept(ir_visitor *v)
{
v->visit(this);
};
/*@}*/
-class ir_expression;
-class ir_dereference;
class ir_assignment : public ir_instruction {
public:
class ir_call : public ir_instruction {
public:
ir_call(const ir_function_signature *callee, exec_list *actual_parameters)
- : ir_instruction(ir_op_call), callee(callee)
+ : ir_instruction(), callee(callee)
{
assert(callee->return_type != NULL);
type = callee->return_type;
private:
ir_call()
- : ir_instruction(ir_op_call), callee(NULL)
+ : ir_instruction(), callee(NULL)
{
/* empty */
}
class ir_jump : public ir_instruction {
protected:
ir_jump()
- : ir_instruction(ir_op_jump)
+ : ir_instruction()
{
/* empty */
}
ir_dereference(ir_instruction *variable, ir_instruction *array_index);
+ virtual ir_dereference *as_dereference()
+ {
+ return this;
+ }
+
virtual void accept(ir_visitor *v)
{
v->visit(this);