summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2008-08-04 15:21:25 -0600
committerBrian Paul <brian.paul@tungstengraphics.com>2008-08-04 17:14:49 -0600
commitf70f6e076c9f1a2c06ec433ce93da5913eef457a (patch)
treee0c71753eb691266f7546ed4c5d8ead35c773962 /src
parente194c457fdabd7474da3b277245d7761311dd758 (diff)
mesa: glsl: additional type checking for ?: and = operators
Diffstat (limited to 'src')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c75
1 files changed, 69 insertions, 6 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index a9bd6369dc..86db53c6ac 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -2459,16 +2459,36 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
{
slang_ir_node *cond, *ifNode, *trueExpr, *falseExpr, *trueNode, *falseNode;
slang_ir_node *tmpDecl, *tmpVar, *tree;
- slang_typeinfo type;
- int size;
+ slang_typeinfo type0, type1, type2;
+ int size, isBool, isEqual;
assert(oper->type == SLANG_OPER_SELECT);
assert(oper->num_children == 3);
+ /* type of children[0] must be boolean */
+ slang_typeinfo_construct(&type0);
+ _slang_typeof_operation(A, &oper->children[0], &type0);
+ isBool = (type0.spec.type == SLANG_SPEC_BOOL);
+ slang_typeinfo_destruct(&type0);
+ if (!isBool) {
+ slang_info_log_error(A->log, "selector type is not boolean");
+ return NULL;
+ }
+
+ slang_typeinfo_construct(&type1);
+ slang_typeinfo_construct(&type2);
+ _slang_typeof_operation(A, &oper->children[1], &type1);
+ _slang_typeof_operation(A, &oper->children[2], &type2);
+ isEqual = slang_type_specifier_equal(&type1.spec, &type2.spec);
+ slang_typeinfo_destruct(&type1);
+ slang_typeinfo_destruct(&type2);
+ if (!isEqual) {
+ slang_info_log_error(A->log, "incompatible types for ?: operator");
+ return NULL;
+ }
+
/* size of x or y's type */
- slang_typeinfo_construct(&type);
- _slang_typeof_operation(A, &oper->children[1], &type);
- size = _slang_sizeof_type_specifier(&type.spec);
+ size = _slang_sizeof_type_specifier(&type1.spec);
assert(size > 0);
/* temporary var */
@@ -2801,6 +2821,32 @@ _slang_gen_swizzle(slang_ir_node *child, GLuint swizzle)
/**
+ * Check if an assignment of type t1 to t0 is legal.
+ * XXX more cases needed.
+ */
+static GLboolean
+_slang_assignment_compatible(const slang_typeinfo *t0,
+ const slang_typeinfo *t1)
+
+{
+#if 01 /* not used just yet - causes problems elsewhere */
+ if (t0->spec.type == SLANG_SPEC_INT &&
+ t1->spec.type == SLANG_SPEC_FLOAT)
+ return GL_FALSE;
+
+ if (t0->spec.type == SLANG_SPEC_BOOL &&
+ t1->spec.type == SLANG_SPEC_FLOAT)
+ return GL_FALSE;
+
+ if (t0->spec.type == SLANG_SPEC_BOOL &&
+ t1->spec.type == SLANG_SPEC_INT)
+ return GL_FALSE;
+#endif
+ return GL_TRUE;
+}
+
+
+/**
* Generate IR tree for an assignment (=).
*/
static slang_ir_node *
@@ -2845,8 +2891,25 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
}
else {
slang_ir_node *n, *lhs, *rhs;
- lhs = _slang_gen_operation(A, &oper->children[0]);
+ /* lhs and rhs type checking */
+ {
+ slang_typeinfo t0, t1;
+
+ slang_typeinfo_construct(&t0);
+ _slang_typeof_operation(A, &oper->children[0], &t0);
+
+ slang_typeinfo_construct(&t1);
+ _slang_typeof_operation(A, &oper->children[1], &t1);
+
+ if (!_slang_assignment_compatible(&t0, &t1)) {
+ slang_info_log_error(A->log,
+ "illegal types in assignment");
+ return NULL;
+ }
+ }
+
+ lhs = _slang_gen_operation(A, &oper->children[0]);
if (lhs) {
if (!lhs->Store) {
slang_info_log_error(A->log,