Replace "mode" type tag with virtual as_foo() downcasting functions.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 26 Mar 2010 06:30:28 +0000 (23:30 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 26 Mar 2010 19:50:40 +0000 (12:50 -0700)
These should work well even in a non-flat IR hierarchy.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
ast_to_hir.cpp
ir.cpp
ir.h

index cdbf2c1e46b8c5d7e05ee8f9a09ab5ea52fe8995..5b577d1f56d432eca36370c267e5dbb5d32bfe57 100644 (file)
@@ -455,20 +455,16 @@ ast_expression::hir(exec_list *instructions,
 
         /* 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;
@@ -620,20 +616,16 @@ ast_expression::hir(exec_list *instructions,
 
         /* 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;
@@ -1126,7 +1118,7 @@ ast_function_definition::hir(exec_list *instructions,
        * 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();
@@ -1157,7 +1149,7 @@ ast_function_definition::hir(exec_list *instructions,
    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);
diff --git a/ir.cpp b/ir.cpp
index 1b5947a4704d5a8de2f0d845ded2167135b6ec51..0e98f0c8d99b4a8fe8a37f41074eab18b3a25edb 100644 (file)
--- a/ir.cpp
+++ b/ir.cpp
@@ -28,7 +28,7 @@
 
 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;
@@ -38,7 +38,7 @@ ir_assignment::ir_assignment(ir_instruction *lhs, ir_instruction *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);
@@ -48,14 +48,14 @@ ir_expression::ir_expression(int op, const struct glsl_type *type,
 
 
 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)
@@ -79,7 +79,7 @@ ir_constant::ir_constant(const struct glsl_type *type, const void *data)
 
 
 ir_dereference::ir_dereference(ir_instruction *var)
-   : ir_instruction(ir_op_dereference)
+   : ir_instruction()
 {
    this->mode = ir_reference_variable;
    this->var = var;
@@ -89,7 +89,7 @@ ir_dereference::ir_dereference(ir_instruction *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;
@@ -124,8 +124,8 @@ ir_dereference::set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w,
 
 
 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;
@@ -133,14 +133,14 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *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 */
 }
diff --git a/ir.h b/ir.h
index 22b46c971e84848c17e96742699ef5aae6b8fb64..c21b26a460e8946cc06c8e0ad861c0649a9b74bb 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -33,46 +33,32 @@ struct ir_program {
    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);
 };
 
 
@@ -94,6 +80,11 @@ class ir_variable : public ir_instruction {
 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);
@@ -181,8 +172,6 @@ public:
 };
 /*@}*/
 
-class ir_expression;
-class ir_dereference;
 
 class ir_assignment : public ir_instruction {
 public:
@@ -296,7 +285,7 @@ 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;
@@ -315,7 +304,7 @@ public:
 
 private:
    ir_call()
-      : ir_instruction(ir_op_call), callee(NULL)
+      : ir_instruction(), callee(NULL)
    {
       /* empty */
    }
@@ -334,7 +323,7 @@ private:
 class ir_jump : public ir_instruction {
 protected:
    ir_jump()
-      : ir_instruction(ir_op_jump)
+      : ir_instruction()
    {
       /* empty */
    }
@@ -395,6 +384,11 @@ public:
 
    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);