glsl: Add methods to copy parts of one ir_constant into another.
authorOlivier Galibert <galibert@pobox.com>
Wed, 2 May 2012 21:11:40 +0000 (23:11 +0200)
committerKenneth Graunke <kenneth@whitecape.org>
Tue, 8 May 2012 19:55:50 +0000 (12:55 -0700)
- copy_masked_offset copies part of a constant into another,
  assign-like.

- copy_offset copies a constant into (a subset of) another,
  funcall-return like.

These methods are to be used to trace through assignments and function
calls when computing a constant expression.

Signed-off-by: Olivier Galibert <galibert@pobox.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net> [v1]
src/glsl/ir.cpp
src/glsl/ir.h

index d0a6d09ebe082ae8bbe5fdc2103c62994b11fdf4..839d5b3fdb46323bed7e69744b584534dd7afe9b 100644 (file)
@@ -856,6 +856,95 @@ ir_constant::get_record_field(const char *name)
    return (ir_constant *) node;
 }
 
+void
+ir_constant::copy_offset(ir_constant *src, int offset)
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL: {
+      unsigned int size = src->type->components();
+      assert (size <= this->type->components() - offset);
+      for (unsigned int i=0; i<size; i++) {
+        switch (this->type->base_type) {
+        case GLSL_TYPE_UINT:
+           value.u[i+offset] = src->get_uint_component(i);
+           break;
+        case GLSL_TYPE_INT:
+           value.i[i+offset] = src->get_int_component(i);
+           break;
+        case GLSL_TYPE_FLOAT:
+           value.f[i+offset] = src->get_float_component(i);
+           break;
+        case GLSL_TYPE_BOOL:
+           value.b[i+offset] = src->get_bool_component(i);
+           break;
+        default: // Shut up the compiler
+           break;
+        }
+      }
+      break;
+   }
+
+   case GLSL_TYPE_STRUCT: {
+      assert (src->type == this->type);
+      this->components.make_empty();
+      foreach_list(node, &src->components) {
+        ir_constant *const orig = (ir_constant *) node;
+
+        this->components.push_tail(orig->clone(this, NULL));
+      }
+      break;
+   }
+
+   case GLSL_TYPE_ARRAY: {
+      assert (src->type == this->type);
+      for (unsigned i = 0; i < this->type->length; i++) {
+        this->array_elements[i] = src->array_elements[i]->clone(this, NULL);
+      }
+      break;
+   }
+
+   default:
+      assert(!"Should not get here.");
+      break;
+   }
+}
+
+void
+ir_constant::copy_masked_offset(ir_constant *src, int offset, unsigned int mask)
+{
+   assert (!type->is_array() && !type->is_record());
+
+   if (!type->is_vector() && !type->is_matrix()) {
+      offset = 0;
+      mask = 1;
+   }
+
+   int id = 0;
+   for (int i=0; i<4; i++) {
+      if (mask & (1 << i)) {
+        switch (this->type->base_type) {
+        case GLSL_TYPE_UINT:
+           value.u[i+offset] = src->get_uint_component(id++);
+           break;
+        case GLSL_TYPE_INT:
+           value.i[i+offset] = src->get_int_component(id++);
+           break;
+        case GLSL_TYPE_FLOAT:
+           value.f[i+offset] = src->get_float_component(id++);
+           break;
+        case GLSL_TYPE_BOOL:
+           value.b[i+offset] = src->get_bool_component(id++);
+           break;
+        default:
+           assert(!"Should not get here.");
+           return;
+        }
+      }
+   }
+}
 
 bool
 ir_constant::has_value(const ir_constant *c) const
index dc96e1fe9edf56c632ceec2f52bd0525cb3345ed..fe950861620f419550ad226b2255a7371ea21afe 100644 (file)
@@ -1682,6 +1682,31 @@ public:
 
    ir_constant *get_record_field(const char *name);
 
+   /**
+    * Copy the values on another constant at a given offset.
+    *
+    * The offset is ignored for array or struct copies, it's only for
+    * scalars or vectors into vectors or matrices.
+    *
+    * With identical types on both sides and zero offset it's clone()
+    * without creating a new object.
+    */
+
+   void copy_offset(ir_constant *src, int offset);
+
+   /**
+    * Copy the values on another constant at a given offset and
+    * following an assign-like mask.
+    *
+    * The mask is ignored for scalars.
+    *
+    * Note that this function only handles what assign can handle,
+    * i.e. at most a vector as source and a column of a matrix as
+    * destination.
+    */
+
+   void copy_masked_offset(ir_constant *src, int offset, unsigned int mask);
+
    /**
     * Determine whether a constant has the same value as another constant
     *