summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-06-09 17:26:20 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-06-11 13:51:42 -0700
commitab92d0e53eab9030742e5e6d938a5739e549f16c (patch)
treee85c3d9f2ed15a68835832bd46241d8107fb69ff
parentc077131c0f4692b46afb06ab236288a24f2cfa14 (diff)
Detect and process constant record constructors
-rw-r--r--ast_function.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/ast_function.cpp b/ast_function.cpp
index 889a239c6e..f0c1f0409a 100644
--- a/ast_function.cpp
+++ b/ast_function.cpp
@@ -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);