Detect and process constant record constructors
authorIan Romanick <ian.d.romanick@intel.com>
Thu, 10 Jun 2010 00:26:20 +0000 (17:26 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 11 Jun 2010 20:51:42 +0000 (13:51 -0700)
ast_function.cpp

index 889a239..f0c1f04 100644 (file)
@@ -290,6 +290,50 @@ process_array_constructor(exec_list *instructions,
 }
 
 
+/**
+ * Try to convert a record constructor to a constant expression
+ */
+static ir_constant *
+constant_record_constructor(const glsl_type *constructor_type,
+                           YYLTYPE *loc, exec_list *parameters,
+                           struct _mesa_glsl_parse_state *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_sentinal()) {
+        _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);
+        return NULL;
+      }
+
+      if (ir->as_constant() == NULL)
+        all_parameters_are_constant = false;
+
+      node = node->next;
+   }
+
+   if (!all_parameters_are_constant)
+      return NULL;
+
+   return new ir_constant(constructor_type, parameters);
+}
+
+
 ir_rvalue *
 ast_function_expression::hir(exec_list *instructions,
                             struct _mesa_glsl_parse_state *state)
@@ -528,6 +572,17 @@ ast_function_expression::hir(exec_list *instructions,
       process_parameters(instructions, &actual_parameters, &this->expressions,
                         state);
 
+      const glsl_type *const type =
+        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);
+
+        if (constant != NULL)
+           return constant;
+      }
+
       return match_function_by_name(instructions, 
                                    id->primary_expression.identifier, & loc,
                                    &actual_parameters, state);