Mesa (master): glsl2: Emit structure constructors inline

Kenneth Graunke kwg at kemper.freedesktop.org
Thu Sep 2 03:40:07 UTC 2010


Module: Mesa
Branch: master
Commit: 37200d83d3e61aa480e6dbb350e522bd0388644c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=37200d83d3e61aa480e6dbb350e522bd0388644c

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Wed Sep  1 13:46:04 2010 -0700

glsl2: Emit structure constructors inline

Fixes piglit test cases glsl-[fv]s-all-0[12].

---

 src/glsl/ast_function.cpp |  107 +++++++++++++++++++++++++++++---------------
 1 files changed, 70 insertions(+), 37 deletions(-)

diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 1fa2fab..1cd300c 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -429,43 +429,14 @@ process_array_constructor(exec_list *instructions,
  */
 static ir_constant *
 constant_record_constructor(const glsl_type *constructor_type,
-			    YYLTYPE *loc, exec_list *parameters,
-			    struct _mesa_glsl_parse_state *state)
+			    exec_list *parameters, void *mem_ctx)
 {
-   void *ctx = state;
-   bool all_parameters_are_constant = true;
-
-   exec_node *node = parameters->head;
-   for (unsigned i = 0; i < constructor_type->length; i++) {
-      ir_instruction *ir = (ir_instruction *) node;
-
-      if (node->is_tail_sentinel()) {
-	 _mesa_glsl_error(loc, state,
-			  "insufficient parameters to constructor for `%s'",
-			  constructor_type->name);
-	 return NULL;
-      }
-
-      if (ir->type != constructor_type->fields.structure[i].type) {
-	 _mesa_glsl_error(loc, state,
-			  "parameter type mismatch in constructor for `%s' "
-			  " (%s vs %s)",
-			  constructor_type->name,
-			  ir->type->name,
-			  constructor_type->fields.structure[i].type->name);
+   foreach_list(node, parameters) {
+      if (((ir_instruction *) node)->as_constant() == NULL)
 	 return NULL;
-      }
-
-      if (ir->as_constant() == NULL)
-	 all_parameters_are_constant = false;
-
-      node = node->next;
    }
 
-   if (!all_parameters_are_constant)
-      return NULL;
-
-   return new(ctx) ir_constant(constructor_type, parameters);
+   return new(mem_ctx) ir_constant(constructor_type, parameters);
 }
 
 
@@ -949,6 +920,39 @@ emit_inline_matrix_constructor(const glsl_type *type,
 
 
 ir_rvalue *
+emit_inline_record_constructor(const glsl_type *type,
+			       exec_list *instructions,
+			       exec_list *parameters,
+			       void *mem_ctx)
+{
+   ir_variable *const var =
+      new(mem_ctx) ir_variable(type, "record_ctor", ir_var_temporary);
+   ir_dereference_variable *const d = new(mem_ctx) ir_dereference_variable(var);
+
+   instructions->push_tail(var);
+
+   exec_node *node = parameters->head;
+   for (unsigned i = 0; i < type->length; i++) {
+      assert(!node->is_tail_sentinel());
+
+      ir_dereference *const lhs =
+	 new(mem_ctx) ir_dereference_record(d->clone(mem_ctx, NULL),
+					    type->fields.structure[i].name);
+
+      ir_rvalue *const rhs = ((ir_instruction *) node)->as_rvalue();
+      assert(rhs != NULL);
+
+      ir_instruction *const assign = new(mem_ctx) ir_assignment(lhs, rhs, NULL);
+
+      instructions->push_tail(assign);
+      node = node->next;
+   }
+
+   return d;
+}
+
+
+ir_rvalue *
 ast_function_expression::hir(exec_list *instructions,
 			     struct _mesa_glsl_parse_state *state)
 {
@@ -989,6 +993,7 @@ ast_function_expression::hir(exec_list *instructions,
 					  & loc, &this->expressions, state);
       }
 
+
       /* There are two kinds of constructor call.  Constructors for built-in
        * language types, such as mat4 and vec2, are free form.  The only
        * requirement is that the parameters must provide enough values of the
@@ -1176,11 +1181,39 @@ ast_function_expression::hir(exec_list *instructions,
 	 state->symbols->get_type(id->primary_expression.identifier);
 
       if ((type != NULL) && type->is_record()) {
-	 ir_constant *constant =
-	    constant_record_constructor(type, &loc, &actual_parameters, state);
+	 exec_node *node = actual_parameters.head;
+	 for (unsigned i = 0; i < type->length; i++) {
+	    ir_instruction *ir = (ir_instruction *) node;
+
+	    if (node->is_tail_sentinel()) {
+	       _mesa_glsl_error(&loc, state,
+				"insufficient parameters to constructor "
+				"for `%s'",
+				type->name);
+	       return ir_call::get_error_instruction(ctx);
+	    }
 
-	 if (constant != NULL)
-	    return constant;
+	    if (ir->type != type->fields.structure[i].type) {
+	       _mesa_glsl_error(&loc, state,
+				"parameter type mismatch in constructor "
+				"for `%s.%s' (%s vs %s)",
+				type->name,
+				type->fields.structure[i].name,
+				ir->type->name,
+				type->fields.structure[i].type->name);
+	       return ir_call::get_error_instruction(ctx);;
+	    }
+
+	    node = node->next;
+	 }
+
+	 ir_rvalue *const constant =
+	    constant_record_constructor(type, &actual_parameters, state);
+
+	 return (constant != NULL)
+	    ? constant
+	    : emit_inline_record_constructor(type, instructions,
+					     &actual_parameters, state);
       }
 
       return match_function_by_name(instructions, 




More information about the mesa-commit mailing list