+ if (result->type->is_matrix())
+ matrix_parameters++;
+ else
+ nonmatrix_parameters++;
+
+ actual_parameters.push_tail(result);
+ components_used += result->type->components();
+ }
+
+ /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "It is an error to construct matrices from other matrices. This
+ * is reserved for future use."
+ */
+ if (state->language_version == 110 && matrix_parameters > 0
+ && constructor_type->is_matrix()) {
+ _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
+ "matrix in GLSL 1.10",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "If a matrix argument is given to a matrix constructor, it is
+ * an error to have any other arguments."
+ */
+ if ((matrix_parameters > 0)
+ && ((matrix_parameters + nonmatrix_parameters) > 1)
+ && constructor_type->is_matrix()) {
+ _mesa_glsl_error(& loc, state, "for matrix `%s' constructor, "
+ "matrix must be only parameter",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "In these cases, there must be enough components provided in the
+ * arguments to provide an initializer for every component in the
+ * constructed value."
+ */
+ if (components_used < type_components && components_used != 1
+ && matrix_parameters == 0) {
+ _mesa_glsl_error(& loc, state, "too few components to construct "
+ "`%s'",
+ constructor_type->name);
+ return ir_call::get_error_instruction(ctx);
+ }
+
+ /* Later, we cast each parameter to the same base type as the
+ * constructor. Since there are no non-floating point matrices, we
+ * need to break them up into a series of column vectors.
+ */
+ if (constructor_type->base_type != GLSL_TYPE_FLOAT) {
+ foreach_list_safe(n, &actual_parameters) {
+ ir_rvalue *matrix = (ir_rvalue *) n;
+
+ if (!matrix->type->is_matrix())
+ continue;
+
+ /* Create a temporary containing the matrix. */
+ 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));
+ var->constant_value = matrix->constant_expression_value();
+
+ /* Replace the matrix with dereferences of its columns. */
+ for (int i = 0; i < matrix->type->matrix_columns; i++) {
+ matrix->insert_before(new (ctx) ir_dereference_array(var,
+ new(ctx) ir_constant(i)));
+ }
+ matrix->remove();