summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ast_function.cpp33
-rw-r--r--ast_to_hir.cpp58
-rw-r--r--glsl_parser_extras.cpp3
-rw-r--r--glsl_types.cpp17
-rw-r--r--glsl_types.h34
-rw-r--r--ir.cpp4
-rw-r--r--ir.h2
-rw-r--r--tests/constructor-02.glsl7
-rw-r--r--tests/function-04.glsl15
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
diff --git a/ir.cpp b/ir.cpp
index 4f7ea1bf1a..26e7394305 100644
--- a/ir.cpp
+++ b/ir.cpp
@@ -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 */
}
diff --git a/ir.h b/ir.h
index 997a37c079..7db617d65b 100644
--- a/ir.h
+++ b/ir.h
@@ -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);
+}