diff options
-rw-r--r-- | ast_function.cpp | 33 | ||||
-rw-r--r-- | ast_to_hir.cpp | 58 | ||||
-rw-r--r-- | glsl_parser_extras.cpp | 3 | ||||
-rw-r--r-- | glsl_types.cpp | 17 | ||||
-rw-r--r-- | glsl_types.h | 34 | ||||
-rw-r--r-- | ir.cpp | 4 | ||||
-rw-r--r-- | ir.h | 2 | ||||
-rw-r--r-- | tests/constructor-02.glsl | 7 | ||||
-rw-r--r-- | tests/function-04.glsl | 15 |
9 files changed, 151 insertions, 22 deletions
diff --git a/ast_function.cpp b/ast_function.cpp index a120eb8dd6..7082ed3c14 100644 --- a/ast_function.cpp +++ b/ast_function.cpp @@ -88,18 +88,35 @@ ast_function_expression::hir(exec_list *instructions, * 2. methods - Only the .length() method of array types. * 3. functions - Calls to regular old functions. * - * There are two kinds of constructor call. Constructors for built-in - * language types, such as mat4 and vec2, are free form. The only - * requirement is that the parameters must provide enough values of the - * correct scalar type. Constructors for arrays and structures must have - * the exact number of parameters with matching types in the correct order. - * These constructors follow essentially the same type matching rules as - * functions. - * * Method calls are actually detected when the ast_field_selection * expression is handled. */ if (is_constructor()) { + const ast_type_specifier *type = (ast_type_specifier *) subexpressions[0]; + YYLTYPE loc = type->get_location(); + + const glsl_type *const constructor_type = + state->symbols->get_type(type->type_name); + + + /* Constructors for samplers are illegal. + */ + if (constructor_type->is_sampler()) { + _mesa_glsl_error(& loc, state, "cannot construct sampler type `%s'", + constructor_type->name); + return ir_call::get_error_instruction(); + } + + + /* There are two kinds of constructor call. Constructors for built-in + * language types, such as mat4 and vec2, are free form. The only + * requirement is that the parameters must provide enough values of the + * correct scalar type. Constructors for arrays and structures must + * have the exact number of parameters with matching types in the + * correct order. These constructors follow essentially the same type + * matching rules as functions. + */ + return ir_call::get_error_instruction(); } else { const ast_expression *id = subexpressions[0]; 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); } diff --git a/glsl_parser_extras.cpp b/glsl_parser_extras.cpp index 3a2038a153..b774d8b5f4 100644 --- a/glsl_parser_extras.cpp +++ b/glsl_parser_extras.cpp @@ -44,8 +44,7 @@ _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state, int len; va_list ap; - if (state) - state->error = true; + state->error = true; len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ", locp->source, locp->first_line, locp->first_column); diff --git a/glsl_types.cpp b/glsl_types.cpp index af6a40800b..2b06a33553 100644 --- a/glsl_types.cpp +++ b/glsl_types.cpp @@ -142,3 +142,20 @@ _mesa_glsl_get_vector_type(unsigned base_type, unsigned vector_length) return glsl_error_type; } } + + +const glsl_type *glsl_type::get_base_type() const +{ + switch (base_type) { + case GLSL_TYPE_UINT: + return glsl_uint_type; + case GLSL_TYPE_INT: + return glsl_int_type; + case GLSL_TYPE_FLOAT: + return glsl_float_type; + case GLSL_TYPE_BOOL: + return glsl_bool_type; + default: + return glsl_error_type; + } +} diff --git a/glsl_types.h b/glsl_types.h index 57f339a9a6..97d8390e60 100644 --- a/glsl_types.h +++ b/glsl_types.h @@ -138,6 +138,16 @@ struct glsl_type { } /** + * For numeric and boolean derrived types returns the basic scalar type + * + * If the type is a numeric or boolean scalar, vector, or matrix type, + * this function gets the scalar type of the individual components. For + * all other types, including arrays of numeric or boolean types, the + * error type is returned. + */ + const glsl_type *get_base_type() const; + + /** * Query whether or not a type is a scalar (non-vector and non-matrix). */ bool is_scalar() const @@ -168,6 +178,30 @@ struct glsl_type { } /** + * Query whether or not a type is a non-array numeric type + */ + bool is_numeric() const + { + return (base_type >= GLSL_TYPE_UINT) && (base_type <= GLSL_TYPE_FLOAT); + } + + /** + * Query whether or not a type is a non-array boolean type + */ + bool is_boolean() const + { + return base_type == GLSL_TYPE_BOOL; + } + + /** + * Query whether or not a type is a sampler + */ + bool is_sampler() const + { + return base_type == GLSL_TYPE_SAMPLER; + } + + /** * Query whether or not a type is the void type singleton. */ bool is_void() const @@ -103,8 +103,8 @@ ir_function_signature::ir_function_signature(const glsl_type *return_type) } -ir_function::ir_function(void) - : ir_instruction(ir_op_func) +ir_function::ir_function(const char *name) + : ir_instruction(ir_op_func), name(name) { /* empty */ } @@ -157,7 +157,7 @@ public: */ class ir_function : public ir_instruction { public: - ir_function(void); + ir_function(const char *name); virtual void accept(ir_visitor *v) { diff --git a/tests/constructor-02.glsl b/tests/constructor-02.glsl new file mode 100644 index 0000000000..47acbe9db1 --- /dev/null +++ b/tests/constructor-02.glsl @@ -0,0 +1,7 @@ +/* FAIL - cannot construct samplers */ +void main() +{ + int i; + + i = sampler2D(0); +} diff --git a/tests/function-04.glsl b/tests/function-04.glsl new file mode 100644 index 0000000000..dfc0d2b7a6 --- /dev/null +++ b/tests/function-04.glsl @@ -0,0 +1,15 @@ +/* FAIL - type mismatch in assignment */ + +vec3 foo(float x, float y, float z) +{ + vec3 v; + v.x = x; + v.y = y; + v.z = z; + return v; +} + +void main() +{ + gl_Position = foo(1.0, 1.0, 1.0); +} |