aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ast_function.cpp74
1 files changed, 73 insertions, 1 deletions
diff --git a/ast_function.cpp b/ast_function.cpp
index 340873ae418..91d4f15a3b7 100644
--- a/ast_function.cpp
+++ b/ast_function.cpp
@@ -188,6 +188,77 @@ dereference_component(ir_rvalue *src, unsigned component)
}
+static ir_rvalue *
+process_array_constructor(exec_list *instructions,
+ const glsl_type *constructor_type,
+ YYLTYPE *loc, simple_node *parameters,
+ struct _mesa_glsl_parse_state *state)
+{
+ /* Array constructors come in two forms: sized and unsized. Sized array
+ * constructors look like 'vec4[2](a, b)', where 'a' and 'b' are vec4
+ * variables. In this case the number of parameters must exactly match the
+ * specified size of the array.
+ *
+ * Unsized array constructors look like 'vec4[](a, b)', where 'a' and 'b'
+ * are vec4 variables. In this case the size of the array being constructed
+ * is determined by the number of parameters.
+ *
+ * From page 52 (page 58 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "There must be exactly the same number of arguments as the size of
+ * the array being constructed. If no size is present in the
+ * constructor, then the array is explicitly sized to the number of
+ * arguments provided. The arguments are assigned in order, starting at
+ * element 0, to the elements of the constructed array. Each argument
+ * must be the same type as the element type of the array, or be a type
+ * that can be converted to the element type of the array according to
+ * Section 4.1.10 "Implicit Conversions.""
+ */
+ exec_list actual_parameters;
+ const unsigned parameter_count =
+ process_parameters(instructions, &actual_parameters, parameters, state);
+
+ if ((parameter_count == 0)
+ || ((constructor_type->length != 0)
+ && (constructor_type->length != parameter_count))) {
+ const unsigned min_param = (constructor_type->length == 0)
+ ? 1 : constructor_type->length;
+
+ _mesa_glsl_error(loc, state, "array constructor must have %s %u "
+ "parameter%s",
+ (constructor_type->length != 0) ? "at least" : "exactly",
+ min_param, (min_param <= 1) ? "" : "s");
+ return ir_call::get_error_instruction();
+ }
+
+ if (constructor_type->length == 0) {
+ constructor_type =
+ glsl_type::get_array_instance(constructor_type->get_base_type(),
+ parameter_count);
+ assert(constructor_type != NULL);
+ assert(constructor_type->length == parameter_count);
+ }
+
+ ir_function *f = state->symbols->get_function(constructor_type->name);
+
+ /* If the constructor for this type of array does not exist, generate the
+ * prototype and add it to the symbol table. The code will be generated
+ * later.
+ */
+ if (f == NULL) {
+ f = constructor_type->generate_constructor_prototype(state->symbols);
+ }
+
+ ir_rvalue *const r =
+ process_call(instructions, f, loc, &actual_parameters, state);
+
+ assert(r != NULL);
+ assert(r->type->is_error() || (r->type == constructor_type));
+
+ return r;
+}
+
+
ir_rvalue *
ast_function_expression::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
@@ -224,7 +295,8 @@ ast_function_expression::hir(exec_list *instructions,
return ir_call::get_error_instruction();
}
- return ir_call::get_error_instruction();
+ return process_array_constructor(instructions, constructor_type,
+ & loc, subexpressions[1], state);
}
/* There are two kinds of constructor call. Constructors for built-in