Move swizzles out of ir_dereference and into their own class.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 26 Mar 2010 08:20:08 +0000 (01:20 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 26 Mar 2010 21:00:59 +0000 (14:00 -0700)
Also turn generate_swizzle into a static "create" method of the new
class; we'll want to use it for the IR reader as well.

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

index 2fd2e53fda307e4a9a20011b44220eb9b1fb4709..c7e73b663046d9a3c03d14cab66046f3801a2e6c 100644 (file)
@@ -454,23 +454,10 @@ ast_expression::hir(exec_list *instructions,
         YYLTYPE loc;
 
         /* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
-        loc = this->subexpressions[0]->get_location();
-        const ir_dereference *const ref = op[0]->as_dereference();
-        if (ref == NULL) {
-           _mesa_glsl_error(& loc, state, "invalid lvalue in assignment");
+        if (!op[0]->is_lvalue()) {
+           _mesa_glsl_error(& loc, state, "non-lvalue in assignment");
            error_emitted = true;
-
            type = glsl_error_type;
-        } else {
-           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;
-
-              type = glsl_error_type;
-           }
         }
       }
 
@@ -612,24 +599,10 @@ ast_expression::hir(exec_list *instructions,
       if (!error_emitted) {
         YYLTYPE loc;
 
-        /* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */
-        loc = this->subexpressions[0]->get_location();
-        const ir_dereference *const ref = op[0]->as_dereference();
-        if (ref == NULL) {
-           _mesa_glsl_error(& loc, state, "invalid lvalue in assignment");
+        if (!op[0]->is_lvalue()) {
+           _mesa_glsl_error(& loc, state, "non-lvalue in assignment");
            error_emitted = true;
-
            type = glsl_error_type;
-        } else {
-           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;
-
-              type = glsl_error_type;
-           }
         }
       }
 
index 846761fff678c467f98ae7cfd909bc0ca18b5433..bcaa69825c010c2fa39780a270b70b75448e9482 100644 (file)
@@ -178,17 +178,18 @@ 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 = new ir_dereference(declarations[16]);
+   ir_dereference *const lhs_ref = new ir_dereference(declarations[16]);
    ir_dereference *const rhs = new ir_dereference(declarations[0]);
 
-   lhs->set_swizzle(0, 0, 0, 0, 1);
+   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 retval = new ir_dereference(declarations[16]);
+   ir_dereference *const retref = new ir_dereference(declarations[16]);
 
-   retval->set_swizzle(0, 0, 0, 0, declarations[16]->type->vector_elements);
+   ir_swizzle *retval = new ir_swizzle(retref, 0, 0, 0, 0,
+                                       declarations[16]->type->vector_elements);
 
    inst = new ir_return(retval);
    instructions->push_tail(inst);
@@ -210,11 +211,10 @@ 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 = new ir_dereference(declarations[16]);
+      ir_dereference *const lhs_ref = new ir_dereference(declarations[16]);
       ir_dereference *const rhs = new ir_dereference(declarations[i]);
 
-      lhs->selector.swizzle.x = i;
-      lhs->selector.swizzle.num_components = 1;
+      ir_swizzle *lhs = new ir_swizzle(lhs_ref, 1, 0, 0, 0, 1);
 
       inst = new ir_assignment(lhs, rhs, NULL);
       instructions->push_tail(inst);
@@ -262,10 +262,10 @@ generate_mat_body_from_scalar(exec_list *instructions,
 
    instructions->push_tail(column);
 
-   ir_dereference *const lhs = new ir_dereference(column);
+   ir_dereference *const lhs_ref = new ir_dereference(column);
    ir_dereference *const rhs = new ir_dereference(declarations[0]);
 
-   lhs->set_swizzle(0, 0, 0, 0, 1);
+   ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1);
 
    inst = new ir_assignment(lhs, rhs, NULL);
    instructions->push_tail(inst);
@@ -274,9 +274,9 @@ generate_mat_body_from_scalar(exec_list *instructions,
    ir_constant *const zero = new ir_constant(glsl_float_type, &z);
 
    for (unsigned i = 1; i < column_type->vector_elements; i++) {
-      ir_dereference *const lhs = new ir_dereference(column);
+      ir_dereference *const lhs_ref = new ir_dereference(column);
 
-      lhs->set_swizzle(i, 0, 0, 0, 1);
+      ir_swizzle *lhs = new ir_swizzle(lhs_ref, i, 0, 0, 0, 1);
 
       inst = new ir_assignment(lhs, zero, NULL);
       instructions->push_tail(inst);
@@ -285,12 +285,13 @@ 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 = new ir_dereference(column);
+      ir_dereference *const rhs_ref = new ir_dereference(column);
 
       /* This will be .xyyy when i=0, .yxyy when i=1, etc.
        */
-      rhs->set_swizzle(swiz[3 - i], swiz[4 - i], swiz[5 - i], swiz[6 - i],
-                      column_type->vector_elements);
+      ir_swizzle *rhs = new ir_swizzle(rhs_ref, swiz[3 - i], swiz[4 - i],
+                                       swiz[5 - i], swiz[6 - i],
+                                      column_type->vector_elements);
 
       ir_constant *const idx = new ir_constant(glsl_int_type, &i);
       ir_dereference *const lhs = new ir_dereference(declarations[16], idx);
@@ -326,11 +327,11 @@ generate_mat_body_from_N_scalars(exec_list *instructions,
         ir_dereference *const row_access =
            new ir_dereference(declarations[16], row_index);
 
-        ir_dereference *const component_access =
+        ir_dereference *const component_access_ref =
            new ir_dereference(row_access);
 
-        component_access->selector.swizzle.x = j;
-        component_access->selector.swizzle.num_components = 1;
+        ir_swizzle *component_access = new ir_swizzle(component_access_ref,
+                                                      j, 0, 0, 0, 1);
 
         const unsigned param = (i * row_type->vector_elements) + j;
         ir_dereference *const rhs = new ir_dereference(declarations[param]);
index 41dbd42d3bf21f7552b60ac44c5b25f6aeec0130..76c48683619f93bc7b81ec3c606a49fab37dd757 100644 (file)
 #include "glsl_types.h"
 #include "ir.h"
 
-#define X 1
-#define R 5
-#define S 9
-#define I 13
-
-static bool
-generate_swizzle(const char *str, ir_dereference *deref,
-                unsigned vector_length)
-{
-   /* For each possible swizzle character, this table encodes the value in
-    * \c idx_map that represents the 0th element of the vector.  For invalid
-    * swizzle characters (e.g., 'k'), a special value is used that will allow
-    * detection of errors.
-    */
-   static const unsigned char base_idx[26] = {
-   /* a  b  c  d  e  f  g  h  i  j  k  l  m */
-      R, R, I, I, I, I, R, I, I, I, I, I, I,
-   /* n  o  p  q  r  s  t  u  v  w  x  y  z */
-      I, I, S, S, R, S, S, I, I, X, X, X, X
-   };
-
-   /* Each valid swizzle character has an entry in the previous table.  This
-    * table encodes the base index encoded in the previous table plus the actual
-    * index of the swizzle character.  When processing swizzles, the first
-    * character in the string is indexed in the previous table.  Each character
-    * in the string is indexed in this table, and the value found there has the
-    * value form the first table subtracted.  The result must be on the range
-    * [0,3].
-    *
-    * For example, the string "wzyx" will get X from the first table.  Each of
-    * the charcaters will get X+3, X+2, X+1, and X+0 from this table.  After
-    * subtraction, the swizzle values are { 3, 2, 1, 0 }.
-    *
-    * The string "wzrg" will get X from the first table.  Each of the characters
-    * will get X+3, X+2, R+0, and R+1 from this table.  After subtraction, the
-    * swizzle values are { 3, 2, 4, 5 }.  Since 4 and 5 are outside the range
-    * [0,3], the error is detected.
-    */
-   static const unsigned char idx_map[26] = {
-   /* a    b    c    d    e    f    g    h    i    j    k    l    m */
-      R+3, R+2, 0,   0,   0,   0,   R+1, 0,   0,   0,   0,   0,   0,
-   /* n    o    p    q    r    s    t    u    v    w    x    y    z */
-      0,   0,   S+2, S+3, R+0, S+0, S+1, 0,   0,   X+3, X+0, X+1, X+2
-   };
-
-   int swiz_idx[4] = { 0, 0, 0, 0 };
-   unsigned i;
-
-
-   /* Validate the first character in the swizzle string and look up the base
-    * index value as described above.
-    */
-   if ((str[0] < 'a') || (str[0] > 'z'))
-      return false;
-
-   const unsigned base = base_idx[str[0] - 'a'];
-
-
-   for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
-      /* Validate the next character, and, as described above, convert it to a
-       * swizzle index.
-       */
-      if ((str[i] < 'a') || (str[i] > 'z'))
-        return false;
-
-      swiz_idx[i] = idx_map[str[i] - 'a'] - base;
-      if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
-        return false;
-   }
-
-   if (str[i] != '\0')
-        return false;
-
-   deref->set_swizzle(swiz_idx[0], swiz_idx[1], swiz_idx[2], swiz_idx[3], i);
-   return true;
-}
-
-
 struct ir_rvalue *
 _mesa_ast_field_selection_to_hir(const ast_expression *expr,
                                 exec_list *instructions,
                                 struct _mesa_glsl_parse_state *state)
 {
+   ir_rvalue *result = NULL;
    ir_rvalue *op;
-   ir_dereference *deref;
-   YYLTYPE loc;
-
 
    op = expr->subexpressions[0]->hir(instructions, state);
-   deref = new ir_dereference(op);
-
-   /* Initially assume that the resulting type of the field selection is an
-    * error.  This make the error paths below a bit easier to follow.
-    */
-   deref->type = glsl_error_type;
-
-   /* If processing the thing being dereferenced generated an error, bail out
-    * now.  Doing so prevents spurious error messages from being logged below.
-    */
-   if (is_error_type(op->type))
-      return deref;
 
    /* There are two kinds of field selection.  There is the selection of a
     * specific field from a structure, and there is the selection of a
@@ -136,21 +44,18 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr,
     * by the base type of the thing to which the field selection operator is
     * being applied.
     */
-   loc = expr->get_location();
-   if (op->type->is_vector()) {
-      if (generate_swizzle(expr->primary_expression.identifier, 
-                          deref, op->type->vector_elements)) {
-        /* Based on the number of elements in the swizzle and the base type
-         * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
-         * generate the type of the resulting value.
-         */
-        deref->type =
-           glsl_type::get_instance(op->type->base_type,
-                                   deref->selector.swizzle.num_components,
-                                   1);
+   YYLTYPE loc = expr->get_location();
+   if (op->type == glsl_error_type) {
+      /* silently propagate the error */
+   } else if (op->type->is_vector()) {
+      ir_swizzle *swiz = ir_swizzle::create(op,
+                                           expr->primary_expression.identifier,
+                                           op->type->vector_elements);
+      if (swiz != NULL) {
+        result = swiz;
       } else {
         /* FINISHME: Logging of error messages should be moved into
-         * FINISHME: generate_swizzle.  This allows the generation of more
+         * FINISHME: ir_swizzle::create.  This allows the generation of more
          * FINISHME: specific error messages.
          */
         _mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'",
@@ -164,5 +69,5 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr,
                       expr->primary_expression.identifier);
    }
 
-   return deref;
+   return result ? result : ir_call::get_error_instruction();
 }
diff --git a/ir.cpp b/ir.cpp
index 8051fb41330e91a7db60bc3c81af2156b7895f0a..58c459ed5db7cc72b6e6f6d3690aa0722b790b1b 100644 (file)
--- a/ir.cpp
+++ b/ir.cpp
@@ -97,9 +97,9 @@ ir_dereference::ir_dereference(ir_instruction *var,
 }
 
 
-void
-ir_dereference::set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w,
-                           unsigned count)
+ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
+                      unsigned w, unsigned count)
+   : val(val)
 {
    assert((count >= 1) && (count <= 4));
 
@@ -113,14 +113,100 @@ ir_dereference::set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w,
    assert(z <= 3);
    assert(w <= 3);
 
-   selector.swizzle.x = x;
-   selector.swizzle.y = y;
-   selector.swizzle.z = z;
-   selector.swizzle.w = w;
-   selector.swizzle.num_components = count;
-   selector.swizzle.has_duplicates = dup_mask != 0;
+   mask.x = x;
+   mask.y = y;
+   mask.z = z;
+   mask.w = w;
+   mask.num_components = count;
+   mask.has_duplicates = dup_mask != 0;
+
+   /* Based on the number of elements in the swizzle and the base type
+    * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
+    * generate the type of the resulting value.
+    */
+   type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
 }
 
+#define X 1
+#define R 5
+#define S 9
+#define I 13
+
+ir_swizzle *
+ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
+{
+   /* For each possible swizzle character, this table encodes the value in
+    * \c idx_map that represents the 0th element of the vector.  For invalid
+    * swizzle characters (e.g., 'k'), a special value is used that will allow
+    * detection of errors.
+    */
+   static const unsigned char base_idx[26] = {
+   /* a  b  c  d  e  f  g  h  i  j  k  l  m */
+      R, R, I, I, I, I, R, I, I, I, I, I, I,
+   /* n  o  p  q  r  s  t  u  v  w  x  y  z */
+      I, I, S, S, R, S, S, I, I, X, X, X, X
+   };
+
+   /* Each valid swizzle character has an entry in the previous table.  This
+    * table encodes the base index encoded in the previous table plus the actual
+    * index of the swizzle character.  When processing swizzles, the first
+    * character in the string is indexed in the previous table.  Each character
+    * in the string is indexed in this table, and the value found there has the
+    * value form the first table subtracted.  The result must be on the range
+    * [0,3].
+    *
+    * For example, the string "wzyx" will get X from the first table.  Each of
+    * the charcaters will get X+3, X+2, X+1, and X+0 from this table.  After
+    * subtraction, the swizzle values are { 3, 2, 1, 0 }.
+    *
+    * The string "wzrg" will get X from the first table.  Each of the characters
+    * will get X+3, X+2, R+0, and R+1 from this table.  After subtraction, the
+    * swizzle values are { 3, 2, 4, 5 }.  Since 4 and 5 are outside the range
+    * [0,3], the error is detected.
+    */
+   static const unsigned char idx_map[26] = {
+   /* a    b    c    d    e    f    g    h    i    j    k    l    m */
+      R+3, R+2, 0,   0,   0,   0,   R+1, 0,   0,   0,   0,   0,   0,
+   /* n    o    p    q    r    s    t    u    v    w    x    y    z */
+      0,   0,   S+2, S+3, R+0, S+0, S+1, 0,   0,   X+3, X+0, X+1, X+2
+   };
+
+   int swiz_idx[4] = { 0, 0, 0, 0 };
+   unsigned i;
+
+
+   /* Validate the first character in the swizzle string and look up the base
+    * index value as described above.
+    */
+   if ((str[0] < 'a') || (str[0] > 'z'))
+      return NULL;
+
+   const unsigned base = base_idx[str[0] - 'a'];
+
+
+   for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
+      /* Validate the next character, and, as described above, convert it to a
+       * swizzle index.
+       */
+      if ((str[i] < 'a') || (str[i] > 'z'))
+        return NULL;
+
+      swiz_idx[i] = idx_map[str[i] - 'a'] - base;
+      if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
+        return NULL;
+   }
+
+   if (str[i] != '\0')
+        return NULL;
+
+   return new ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
+                         swiz_idx[3], i);
+}
+
+#undef X
+#undef R
+#undef S
+#undef I
 
 
 ir_variable::ir_variable(const struct glsl_type *type, const char *name)
diff --git a/ir.h b/ir.h
index 29bc055dd7ab2485ac817ac791b9276df949afc1..63ae0bc3b696ee777bea59ab51673d2b036702d2 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -394,6 +394,31 @@ struct ir_swizzle_mask {
    unsigned has_duplicates:1;
 };
 
+
+class ir_swizzle : public ir_rvalue {
+public:
+   ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
+              unsigned count);
+   /**
+    * Construct an ir_swizzle from the textual representation.  Can fail.
+    */
+   static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   bool is_lvalue()
+   {
+      return val->is_lvalue();
+   }
+
+   ir_rvalue *val;
+   ir_swizzle_mask mask;
+};
+
+
 class ir_dereference : public ir_rvalue {
 public:
    ir_dereference(struct ir_instruction *);
@@ -415,13 +440,6 @@ public:
       return var != NULL;
    }
 
-   /**
-    * Setting the swizzle of a derefernce
-    */
-   void set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w,
-                   unsigned count);
-
-
    enum {
       ir_reference_variable,
       ir_reference_array,
@@ -438,7 +456,6 @@ public:
    union {
       ir_rvalue *array_index;
       const char *field;
-      struct ir_swizzle_mask swizzle;
    } selector;
 };
 
index 8941d3c7b9fa694842d97217368de14e2304eeab..1696be69b55d859e19bbe03058f4303f84acf162 100644 (file)
@@ -102,26 +102,34 @@ void ir_print_visitor::visit(ir_expression *ir)
 }
 
 
+void ir_print_visitor::visit(ir_swizzle *ir)
+{
+   const unsigned swiz[4] = {
+      ir->mask.x,
+      ir->mask.y,
+      ir->mask.z,
+      ir->mask.w,
+   };
+
+   printf("(swiz ");
+   for (unsigned i = 0; i < ir->mask.num_components; i++) {
+      printf("%c", "xyzw"[swiz[i]]);
+   }
+   printf(" ");
+   ir->val->accept(this);
+   printf(")");
+}
+
+
 void ir_print_visitor::visit(ir_dereference *ir)
 {
    deref_depth++;
 
    switch (ir->mode) {
    case ir_dereference::ir_reference_variable: {
-      const unsigned swiz[4] = {
-        ir->selector.swizzle.x,
-        ir->selector.swizzle.y,
-        ir->selector.swizzle.z,
-        ir->selector.swizzle.w,
-      };
-
       printf("(var_ref ");
       ir->var->accept(this);
-      printf("(");
-      for (unsigned i = 0; i < ir->selector.swizzle.num_components; i++) {
-        printf("%c", "xyzw"[swiz[i]]);
-      }
-      printf(")) ");
+      printf(") ");
       break;
    }
    case ir_dereference::ir_reference_array:
index a4309c4f2a4f0adc6c724247807981247afd558e..8fd684eb92a7342631621194a97a423ca5a578b3 100644 (file)
@@ -58,6 +58,7 @@ public:
    virtual void visit(ir_function_signature *);
    virtual void visit(ir_function *);
    virtual void visit(ir_expression *);
+   virtual void visit(ir_swizzle *);
    virtual void visit(ir_dereference *);
    virtual void visit(ir_assignment *);
    virtual void visit(ir_constant *);
index 8ea416eb9f20f7c6e179796583181f034bb99c1f..76981f7afc1737a8aa0fb367157bbcea7cc2e3b5 100644 (file)
@@ -49,6 +49,7 @@ public:
    virtual void visit(class ir_function_signature *) = 0;
    virtual void visit(class ir_function *) = 0;
    virtual void visit(class ir_expression *) = 0;
+   virtual void visit(class ir_swizzle *) = 0;
    virtual void visit(class ir_dereference *) = 0;
    virtual void visit(class ir_assignment *) = 0;
    virtual void visit(class ir_constant *) = 0;