formal_iter.next();
}
- return new(ctx) ir_call(sig, actual_parameters);
+ /* Always insert the call in the instruction stream, and return a deref
+ * of its return val if it returns a value, since we don't know if
+ * the rvalue is going to be assigned to anything or not.
+ */
+ ir_call *call = new(ctx) ir_call(sig, actual_parameters);
+ if (!sig->return_type->is_void()) {
+ ir_variable *var;
+ ir_dereference_variable *deref;
+
+ var = new(ctx) ir_variable(sig->return_type,
+ talloc_asprintf(ctx, "%s_retval",
+ sig->function_name()),
+ ir_var_temporary);
+ instructions->push_tail(var);
+
+ deref = new(ctx) ir_dereference_variable(var);
+ ir_assignment *assign = new(ctx) ir_assignment(deref, call, NULL);
+ instructions->push_tail(assign);
+
+ deref = new(ctx) ir_dereference_variable(var);
+ return deref;
+ } else {
+ instructions->push_tail(call);
+ return NULL;
+ }
} else {
/* FINISHME: Log a better error message here. G++ will show the types
* FINISHME: of the actual parameters and the set of candidate
/**
* 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;
+
+ /* 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;
- /* 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);
+ /* 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);
}
- ir_rvalue *const r =
- process_call(instructions, f, loc, &actual_parameters, state);
+ if (all_parameters_are_constant) {
+ /* FINISHME: Add support for generating constant arrays. */
+ }
+
+ 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);
}
assert(!parameters->is_empty());
ir_variable *var = new(ctx) ir_variable(type,
- talloc_strdup(ctx, "vec_ctor"));
+ talloc_strdup(ctx, "vec_ctor"),
+ ir_var_temporary);
instructions->push_tail(var);
/* There are two kinds of vector constructors.
assert(!parameters->is_empty());
ir_variable *var = new(ctx) ir_variable(type,
- talloc_strdup(ctx, "mat_ctor"));
+ talloc_strdup(ctx, "mat_ctor"),
+ ir_var_temporary);
instructions->push_tail(var);
/* There are three kinds of matrix constructors.
*/
ir_variable *rhs_var =
new(ctx) ir_variable(glsl_type::vec4_type,
- talloc_strdup(ctx, "mat_ctor_vec"));
+ talloc_strdup(ctx, "mat_ctor_vec"),
+ ir_var_temporary);
instructions->push_tail(rhs_var);
ir_constant_data zero;
*/
ir_variable *const rhs_var =
new(ctx) ir_variable(first_param->type,
- talloc_strdup(ctx, "mat_ctor_mat"));
+ talloc_strdup(ctx, "mat_ctor_mat"),
+ ir_var_temporary);
instructions->push_tail(rhs_var);
ir_dereference *const rhs_var_ref =
*/
ir_variable *rhs_var =
new(ctx) ir_variable(rhs->type,
- talloc_strdup(ctx, "mat_ctor_vec"));
+ talloc_strdup(ctx, "mat_ctor_vec"),
+ ir_var_temporary);
instructions->push_tail(rhs_var);
ir_dereference *rhs_var_ref =
continue;
/* Create a temporary containing the matrix. */
- ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp");
+ ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp",
+ ir_var_temporary);
instructions->push_tail(var);
instructions->push_tail(new(ctx) ir_assignment(new(ctx)
ir_dereference_variable(var), matrix, NULL));
all_parameters_are_constant = false;
if (result != ir) {
- ir->insert_before(result);
- ir->remove();
+ ir->replace_with(result);
}
}