/**
* Perform automatic type conversion of constructor parameters
+ *
+ * This implements the rules in the "Conversion and Scalar Constructors"
+ * section (GLSL 1.10 section 5.4.1), not the "Implicit Conversions" rules.
*/
static ir_rvalue *
convert_component(ir_rvalue *src, const glsl_type *desired_type)
assert(result != NULL);
+ /* Try constant folding; it may fold in the conversion we just added. */
ir_constant *const constant = result->constant_expression_value();
return (constant != NULL) ? (ir_rvalue *) constant : (ir_rvalue *) result;
}
-
/**
* Dereference a specific component from a scalar, vector, or matrix
*/
if (constructor_type->length == 0) {
constructor_type =
- glsl_type::get_array_instance(state,
- constructor_type->element_type(),
+ glsl_type::get_array_instance(constructor_type->element_type(),
parameter_count);
assert(constructor_type != NULL);
assert(constructor_type->length == parameter_count);
}
- ir_function *f = state->symbols->get_function(constructor_type->name);
+ bool all_parameters_are_constant = true;
- /* If the constructor for this type of array does not exist, generate the
- * prototype and add it to the symbol table.
- */
- if (f == NULL) {
- f = constructor_type->generate_constructor(state->symbols);
+ /* Type cast each parameter and, if possible, fold constants. */
+ foreach_list_safe(n, &actual_parameters) {
+ ir_rvalue *ir = (ir_rvalue *) n;
+ ir_rvalue *result = ir;
+
+ /* Apply implicit conversions (not the scalar constructor rules!) */
+ if (constructor_type->element_type()->is_float()) {
+ const glsl_type *desired_type =
+ glsl_type::get_instance(GLSL_TYPE_FLOAT,
+ ir->type->vector_elements,
+ ir->type->matrix_columns);
+ result = convert_component(ir, desired_type);
+ }
+
+ if (result->type != constructor_type->element_type()) {
+ _mesa_glsl_error(loc, state, "type error in array constructor: "
+ "expected: %s, found %s",
+ constructor_type->element_type()->name,
+ result->type->name);
+ }
+
+ /* Attempt to convert the parameter to a constant valued expression.
+ * After doing so, track whether or not all the parameters to the
+ * constructor are trivially constant valued expressions.
+ */
+ ir_rvalue *const constant = result->constant_expression_value();
+
+ if (constant != NULL)
+ result = constant;
+ else
+ all_parameters_are_constant = false;
+
+ ir->replace_with(result);
+ }
+
+ if (all_parameters_are_constant) {
+ /* FINISHME: Add support for generating constant arrays. */
}
- ir_rvalue *const r =
- process_call(instructions, f, loc, &actual_parameters, state);
+ ir_variable *var = new(ctx) ir_variable(constructor_type, "array_ctor",
+ ir_var_temporary);
+ instructions->push_tail(var);
+
+ int i = 0;
+ foreach_list(node, &actual_parameters) {
+ ir_rvalue *rhs = (ir_rvalue *) node;
+ ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
+ new(ctx) ir_constant(i));
- assert(r != NULL);
- assert(r->type->is_error() || (r->type == constructor_type));
+ ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
+ instructions->push_tail(assignment);
- return r;
+ i++;
+ }
+
+ return new(ctx) ir_dereference_variable(var);
}
all_parameters_are_constant = false;
if (result != ir) {
- ir->insert_before(result);
- ir->remove();
+ ir->replace_with(result);
}
}