diff options
Diffstat (limited to 'ast_to_hir.cpp')
-rw-r--r-- | ast_to_hir.cpp | 58 |
1 files changed, 49 insertions, 9 deletions
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp index 62f2068b3a..f7c82fab4b 100644 --- a/ast_to_hir.cpp +++ b/ast_to_hir.cpp @@ -331,6 +331,45 @@ relational_result_type(const struct glsl_type *type_a, } +/** + * Validates that a value can be assigned to a location with a specified type + * + * Validates that \c rhs can be assigned to some location. If the types are + * not an exact match but an automatic conversion is possible, \c rhs will be + * converted. + * + * \return + * \c NULL if \c rhs cannot be assigned to a location with type \c lhs_type. + * Otherwise the actual RHS to be assigned will be returned. This may be + * \c rhs, or it may be \c rhs after some type conversion. + * + * \note + * In addition to being used for assignments, this function is used to + * type-check return values. + */ +ir_instruction * +validate_assignment(const glsl_type *lhs_type, ir_instruction *rhs) +{ + const glsl_type *const rhs_type = rhs->type; + + /* If there is already some error in the RHS, just return it. Anything + * else will lead to an avalanche of error message back to the user. + */ + if (rhs_type->is_error()) + return rhs; + + /* FINISHME: For GLSL 1.10, check that the types are not arrays. */ + + /* If the types are identical, the assignment can trivially proceed. + */ + if (rhs_type == lhs_type) + return rhs; + + /* FINISHME: Check for and apply automatic conversions. */ + return NULL; +} + + ir_instruction * ast_node::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -448,8 +487,11 @@ ast_expression::hir(exec_list *instructions, } } - /* FINISHME: Check that the LHS and RHS have matching types. */ - /* FINISHME: For GLSL 1.10, check that the types are not arrays. */ + ir_instruction *rhs = validate_assignment(op[0]->type, op[1]); + if (rhs == NULL) { + type = glsl_error_type; + rhs = op[1]; + } ir_instruction *tmp = new ir_assignment(op[0], op[1], NULL); instructions->push_tail(tmp); @@ -650,7 +692,7 @@ ast_expression::hir(exec_list *instructions, if (var != NULL) { type = result->type; } else { - _mesa_glsl_error(& loc, NULL, "`%s' undeclared", + _mesa_glsl_error(& loc, state, "`%s' undeclared", this->primary_expression.identifier); error_emitted = true; @@ -704,7 +746,7 @@ ast_expression::hir(exec_list *instructions, } if (is_error_type(type) && !error_emitted) - _mesa_glsl_error(& loc, NULL, "type mismatch"); + _mesa_glsl_error(& loc, state, "type mismatch"); return result; } @@ -769,7 +811,7 @@ type_specifier_to_glsl_type(const struct ast_type_specifier *spec, *name = spec->type_name; /* FINISHME: Handle array declarations. Note that this requires complete - * FINSIHME: handling of constant expressions. + * FINISHME: handling of constant expressions. */ } @@ -869,7 +911,7 @@ ast_declarator_list::hir(exec_list *instructions, var = new ir_variable(var_type, decl->identifier); - /* FINSIHME: Variables that are attribute, uniform, varying, in, or + /* FINISHME: Variables that are attribute, uniform, varying, in, or * FINISHME: out varibles must be declared either at global scope or * FINISHME: in a parameter list (in and out only). */ @@ -1053,9 +1095,7 @@ ast_function_definition::hir(exec_list *instructions, "non-function", name); signature = NULL; } else { - f = new ir_function(); - f->name = name; - + f = new ir_function(name); state->symbols->add_function(f->name, f); } |