static ir_rvalue *
-process_call(exec_list *instructions, ir_function *f,
- YYLTYPE *loc, exec_list *actual_parameters,
- struct _mesa_glsl_parse_state *state)
+match_function_by_name(exec_list *instructions, const char *name,
+ YYLTYPE *loc, exec_list *actual_parameters,
+ struct _mesa_glsl_parse_state *state)
{
void *ctx = state;
+ ir_function *f = state->symbols->get_function(name);
+ ir_function_signature *sig;
+
+ sig = f ? f->matching_signature(actual_parameters) : NULL;
- ir_function_signature *sig = f->matching_signature(actual_parameters);
+ /* FINISHME: This doesn't handle the case where shader X contains a
+ * FINISHME: matching signature but shader X + N contains an _exact_
+ * FINISHME: matching signature.
+ */
+ if (sig == NULL && (f == NULL || state->es_shader || !f->has_user_signature()) && state->symbols->get_type(name) == NULL && (state->language_version == 110 || state->symbols->get_variable(name) == NULL)) {
+ /* The current shader doesn't contain a matching function or signature.
+ * Before giving up, look for the prototype in the built-in functions.
+ */
+ for (unsigned i = 0; i < state->num_builtins_to_link; i++) {
+ ir_function *builtin;
+ builtin = state->builtins_to_link[i]->symbols->get_function(name);
+ sig = builtin ? builtin->matching_signature(actual_parameters) : NULL;
+ if (sig != NULL) {
+ if (f == NULL) {
+ f = new(ctx) ir_function(name);
+ state->symbols->add_global_function(f);
+ emit_function(state, instructions, f);
+ }
- /* The instructions param will be used when the FINISHMEs below are done */
- (void) instructions;
+ f->add_signature(sig->clone_prototype(f, NULL));
+ break;
+ }
+ }
+ }
if (sig != NULL) {
/* Verify that 'out' and 'inout' actual parameters are lvalues. This
return NULL;
}
} else {
- char *str = prototype_string(NULL, f->name, actual_parameters);
+ char *str = prototype_string(NULL, name, actual_parameters);
_mesa_glsl_error(loc, state, "no matching function for call to `%s'",
str);
talloc_free(str);
const char *prefix = "candidates are: ";
- foreach_list (node, &f->signatures) {
- ir_function_signature *sig = (ir_function_signature *) node;
- str = prototype_string(sig->return_type, f->name, &sig->parameters);
- _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
- talloc_free(str);
+ for (int i = -1; i < state->num_builtins_to_link; i++) {
+ glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols
+ : state->symbols;
+ f = syms->get_function(name);
+ if (f == NULL)
+ continue;
- prefix = " ";
- }
+ foreach_list (node, &f->signatures) {
+ ir_function_signature *sig = (ir_function_signature *) node;
- return ir_call::get_error_instruction(ctx);
- }
-}
+ str = prototype_string(sig->return_type, f->name, &sig->parameters);
+ _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
+ talloc_free(str);
+ prefix = " ";
+ }
-static ir_rvalue *
-match_function_by_name(exec_list *instructions, const char *name,
- YYLTYPE *loc, exec_list *actual_parameters,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
- ir_function *f = state->symbols->get_function(name);
+ }
- if (f == NULL) {
- _mesa_glsl_error(loc, state, "function `%s' undeclared", name);
return ir_call::get_error_instruction(ctx);
}
-
- /* Once we've determined that the function being called might exist, try
- * to find an overload of the function that matches the parameters.
- */
- return process_call(instructions, f, loc, actual_parameters, state);
}
instructions->push_tail(inst);
} else {
unsigned base_component = 0;
+ unsigned base_lhs_component = 0;
ir_constant_data data;
- unsigned constant_mask = 0;
+ unsigned constant_mask = 0, constant_components = 0;
memset(&data, 0, sizeof(data));
/* Do not try to assign more components to the vector than it has!
*/
- if ((rhs_components + base_component) > lhs_components) {
- rhs_components = lhs_components - base_component;
+ if ((rhs_components + base_lhs_component) > lhs_components) {
+ rhs_components = lhs_components - base_lhs_component;
}
const ir_constant *const c = param->as_constant();
/* Mask of fields to be written in the assignment.
*/
- constant_mask |= ((1U << rhs_components) - 1) << base_component;
- }
+ constant_mask |= ((1U << rhs_components) - 1) << base_lhs_component;
+ constant_components += rhs_components;
- /* Advance the component index by the number of components that were
- * just assigned.
+ base_component += rhs_components;
+ }
+ /* Advance the component index by the number of components
+ * that were just assigned.
*/
- base_component += rhs_components;
+ base_lhs_component += rhs_components;
}
if (constant_mask != 0) {
ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
- ir_rvalue *rhs = new(ctx) ir_constant(var->type, &data);
+ const glsl_type *rhs_type = glsl_type::get_instance(var->type->base_type,
+ constant_components,
+ 1);
+ ir_rvalue *rhs = new(ctx) ir_constant(rhs_type, &data);
ir_instruction *inst =
new(ctx) ir_assignment(lhs, rhs, NULL, constant_mask);
const ir_constant *const c = param->as_constant();
if (c == NULL) {
- /* Generate a swizzle that puts the first element of the source at
- * the location of the first element of the destination.
- */
- unsigned swiz[4] = { 0, 0, 0, 0 };
- for (unsigned i = 0; i < rhs_components; i++)
- swiz[i + base_component] = i;
-
/* Mask of fields to be written in the assignment.
*/
const unsigned write_mask = ((1U << rhs_components) - 1)
<< base_component;
ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
- ir_rvalue *rhs = new(ctx) ir_swizzle(param, swiz, lhs_components);
+
+ /* Generate a swizzle so that LHS and RHS sizes match.
+ */
+ ir_rvalue *rhs =
+ new(ctx) ir_swizzle(param, 0, 1, 2, 3, rhs_components);
ir_instruction *inst =
new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
assert(column_ref->type->components() >= (row_base + count));
assert(src->type->components() >= (src_base + count));
- /* Generate a swizzle that puts the first element of the source at the
- * location of the first element of the destination.
+ /* Generate a swizzle that extracts the number of components from the source
+ * that are to be assigned to the column of the matrix.
*/
- unsigned swiz[4] = { src_base, src_base, src_base, src_base };
- for (unsigned i = 0; i < count; i++)
- swiz[i + row_base] = src_base + i;
-
- ir_rvalue *const rhs =
- new(mem_ctx) ir_swizzle(src, swiz, column_ref->type->components());
+ if (count < src->type->vector_elements) {
+ src = new(mem_ctx) ir_swizzle(src,
+ src_base + 0, src_base + 1,
+ src_base + 2, src_base + 3,
+ count);
+ }
/* Mask of fields to be written in the assignment.
*/
const unsigned write_mask = ((1U << count) - 1) << row_base;
- return new(mem_ctx) ir_assignment(column_ref, rhs, NULL, write_mask);
+ return new(mem_ctx) ir_assignment(column_ref, src, NULL, write_mask);
}
var->type->matrix_columns);
unsigned swiz[4] = { 0, 0, 0, 0 };
- for (unsigned i = 1; i < src_matrix->type->vector_elements; i++)
+ for (unsigned i = 1; i < last_row; i++)
swiz[i] = i;
const unsigned write_mask = (1U << last_row) - 1;
*/
ir_rvalue *rhs;
if (lhs->type->vector_elements != rhs_col->type->vector_elements) {
- rhs = new(ctx) ir_swizzle(rhs_col, swiz,
- lhs->type->vector_elements);
+ rhs = new(ctx) ir_swizzle(rhs_col, swiz, last_row);
} else {
rhs = rhs_col;
}
- assert(lhs->type == rhs->type);
-
ir_instruction *inst =
new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
instructions->push_tail(inst);
* "It is an error to construct matrices from other matrices. This
* is reserved for future use."
*/
- if ((state->language_version <= 110) && (matrix_parameters > 0)
+ 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",