X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fglsl%2Fir_validate.cpp;h=44d7549ea285bda27b48cbf88b3fd012d565d241;hb=0292ffb85c03e9fa15b9395e3875109dd8979292;hp=f9f781b36ab7af08752c49d0a98d0164a90df833;hpb=ee7666b5ac2fc7de64baf60835271e15baf89474;p=mesa.git diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index f9f781b36ab..44d7549ea28 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -61,11 +61,15 @@ public: virtual ir_visitor_status visit(ir_dereference_variable *ir); virtual ir_visitor_status visit(ir_if *ir); + virtual ir_visitor_status visit_leave(ir_loop *ir); virtual ir_visitor_status visit_enter(ir_function *ir); virtual ir_visitor_status visit_leave(ir_function *ir); virtual ir_visitor_status visit_enter(ir_function_signature *ir); virtual ir_visitor_status visit_leave(ir_expression *ir); + virtual ir_visitor_status visit_leave(ir_swizzle *ir); + + virtual ir_visitor_status visit_enter(ir_assignment *ir); static void validate_ir(ir_instruction *ir, void *data); @@ -80,14 +84,14 @@ ir_validate::visit(ir_dereference_variable *ir) { if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) { printf("ir_dereference_variable @ %p does not specify a variable %p\n", - ir, ir->var); + (void *) ir, (void *) ir->var); abort(); } if (hash_table_find(ht, ir->var) == NULL) { printf("ir_dereference_variable @ %p specifies undeclared variable " "`%s' @ %p\n", - ir, ir->var->name, ir->var); + (void *) ir, ir->var->name, (void *) ir->var); abort(); } @@ -111,6 +115,42 @@ ir_validate::visit(ir_if *ir) } +ir_visitor_status +ir_validate::visit_leave(ir_loop *ir) +{ + if (ir->counter != NULL) { + if ((ir->from == NULL) || (ir->from == NULL) || (ir->increment == NULL)) { + printf("ir_loop has invalid loop controls:\n" + " counter: %p\n" + " from: %p\n" + " to: %p\n" + " increment: %p\n", + (void *) ir->counter, (void *) ir->from, (void *) ir->to, + (void *) ir->increment); + abort(); + } + + if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) { + printf("ir_loop has invalid comparitor %d\n", ir->cmp); + abort(); + } + } else { + if ((ir->from != NULL) || (ir->from != NULL) || (ir->increment != NULL)) { + printf("ir_loop has invalid loop controls:\n" + " counter: %p\n" + " from: %p\n" + " to: %p\n" + " increment: %p\n", + (void *) ir->counter, (void *) ir->from, (void *) ir->to, + (void *) ir->increment); + abort(); + } + } + + return visit_continue; +} + + ir_visitor_status ir_validate::visit_enter(ir_function *ir) { @@ -120,8 +160,8 @@ ir_validate::visit_enter(ir_function *ir) printf("Function definition nested inside another function " "definition:\n"); printf("%s %p inside %s %p\n", - ir->name, ir, - this->current_function->name, this->current_function); + ir->name, (void *) ir, + this->current_function->name, (void *) this->current_function); abort(); } @@ -139,7 +179,7 @@ ir_validate::visit_enter(ir_function *ir) ir_visitor_status ir_validate::visit_leave(ir_function *ir) { - assert(talloc_parent(ir->name) == ir); + assert(ralloc_parent(ir->name) == ir); this->current_function = NULL; return visit_continue; @@ -152,9 +192,9 @@ ir_validate::visit_enter(ir_function_signature *ir) printf("Function signature nested inside wrong function " "definition:\n"); printf("%p inside %s %p instead of %s %p\n", - ir, - this->current_function->name, this->current_function, - ir->function_name(), ir->function()); + (void *) ir, + this->current_function->name, (void *) this->current_function, + ir->function_name(), (void *) ir->function()); abort(); } @@ -181,10 +221,14 @@ ir_validate::visit_leave(ir_expression *ir) case ir_unop_rcp: case ir_unop_rsq: case ir_unop_sqrt: + assert(ir->type == ir->operands[0]->type); + break; + case ir_unop_exp: case ir_unop_log: case ir_unop_exp2: case ir_unop_log2: + assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); assert(ir->type == ir->operands[0]->type); break; @@ -217,18 +261,30 @@ ir_validate::visit_leave(ir_expression *ir) assert(ir->type->base_type == GLSL_TYPE_FLOAT); break; + case ir_unop_any: + assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); + assert(ir->type == glsl_type::bool_type); + break; + case ir_unop_trunc: + case ir_unop_round_even: case ir_unop_ceil: case ir_unop_floor: case ir_unop_fract: case ir_unop_sin: case ir_unop_cos: + case ir_unop_sin_reduced: + case ir_unop_cos_reduced: case ir_unop_dFdx: case ir_unop_dFdy: assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); assert(ir->operands[0]->type == ir->type); break; + case ir_unop_noise: + /* XXX what can we assert here? */ + break; + case ir_binop_add: case ir_binop_sub: case ir_binop_mul: @@ -247,24 +303,30 @@ ir_validate::visit_leave(ir_expression *ir) assert(ir->operands[0]->type == ir->type); } break; + case ir_binop_less: case ir_binop_greater: case ir_binop_lequal: case ir_binop_gequal: - /* GLSL < > <= >= operators take scalar floats/ints, but in the - * IR we may want to do them for vectors instead to support the - * lessEqual() and friends builtins. + case ir_binop_equal: + case ir_binop_nequal: + /* The semantics of the IR operators differ from the GLSL <, >, <=, >=, + * ==, and != operators. The IR operators perform a component-wise + * comparison on scalar or vector types and return a boolean scalar or + * vector type of the same size. */ - assert(ir->type == glsl_type::bool_type); + assert(ir->type->base_type == GLSL_TYPE_BOOL); assert(ir->operands[0]->type == ir->operands[1]->type); + assert(ir->operands[0]->type->is_vector() + || ir->operands[0]->type->is_scalar()); + assert(ir->operands[0]->type->vector_elements + == ir->type->vector_elements); break; - case ir_binop_equal: - case ir_binop_nequal: - /* GLSL == and != operate on vectors and return a bool, and the - * IR matches that. We may want to switch up the IR to work on - * vectors and return a bvec and make the operators break down - * to ANDing/ORing the results of the vector comparison. + case ir_binop_all_equal: + case ir_binop_any_nequal: + /* GLSL == and != operate on scalars, vectors, matrices and arrays, and + * return a scalar boolean. The IR matches that. */ assert(ir->type == glsl_type::bool_type); assert(ir->operands[0]->type == ir->operands[1]->type); @@ -272,14 +334,31 @@ ir_validate::visit_leave(ir_expression *ir) case ir_binop_lshift: case ir_binop_rshift: + assert(ir->operands[0]->type->is_integer() && + ir->operands[1]->type->is_integer()); + if (ir->operands[0]->type->is_scalar()) { + assert(ir->operands[1]->type->is_scalar()); + } + if (ir->operands[0]->type->is_vector() && + ir->operands[1]->type->is_vector()) { + assert(ir->operands[0]->type->components() == + ir->operands[1]->type->components()); + } + assert(ir->type == ir->operands[0]->type); + break; + case ir_binop_bit_and: case ir_binop_bit_xor: case ir_binop_bit_or: - assert(ir->operands[0]->type == ir->operands[1]->type); - assert(ir->type == ir->operands[0]->type); - assert(ir->type->base_type == GLSL_TYPE_INT || - ir->type->base_type == GLSL_TYPE_UINT); - break; + assert(ir->operands[0]->type->base_type == + ir->operands[1]->type->base_type); + assert(ir->type->is_integer()); + if (ir->operands[0]->type->is_vector() && + ir->operands[1]->type->is_vector()) { + assert(ir->operands[0]->type->vector_elements == + ir->operands[1]->type->vector_elements); + } + break; case ir_binop_logic_and: case ir_binop_logic_xor: @@ -292,14 +371,71 @@ ir_validate::visit_leave(ir_expression *ir) case ir_binop_dot: assert(ir->type == glsl_type::float_type); assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); + assert(ir->operands[0]->type->is_vector()); assert(ir->operands[0]->type == ir->operands[1]->type); break; - case ir_binop_cross: - assert(ir->operands[0]->type == glsl_type::vec3_type); - assert(ir->operands[1]->type == glsl_type::vec3_type); - assert(ir->type == glsl_type::vec3_type); - break; + case ir_quadop_vector: + /* The vector operator collects some number of scalars and generates a + * vector from them. + * + * - All of the operands must be scalar. + * - Number of operands must matche the size of the resulting vector. + * - Base type of the operands must match the base type of the result. + */ + assert(ir->type->is_vector()); + switch (ir->type->vector_elements) { + case 2: + assert(ir->operands[0]->type->is_scalar()); + assert(ir->operands[0]->type->base_type == ir->type->base_type); + assert(ir->operands[1]->type->is_scalar()); + assert(ir->operands[1]->type->base_type == ir->type->base_type); + assert(ir->operands[2] == NULL); + assert(ir->operands[3] == NULL); + break; + case 3: + assert(ir->operands[0]->type->is_scalar()); + assert(ir->operands[0]->type->base_type == ir->type->base_type); + assert(ir->operands[1]->type->is_scalar()); + assert(ir->operands[1]->type->base_type == ir->type->base_type); + assert(ir->operands[2]->type->is_scalar()); + assert(ir->operands[2]->type->base_type == ir->type->base_type); + assert(ir->operands[3] == NULL); + break; + case 4: + assert(ir->operands[0]->type->is_scalar()); + assert(ir->operands[0]->type->base_type == ir->type->base_type); + assert(ir->operands[1]->type->is_scalar()); + assert(ir->operands[1]->type->base_type == ir->type->base_type); + assert(ir->operands[2]->type->is_scalar()); + assert(ir->operands[2]->type->base_type == ir->type->base_type); + assert(ir->operands[3]->type->is_scalar()); + assert(ir->operands[3]->type->base_type == ir->type->base_type); + break; + default: + /* The is_vector assertion above should prevent execution from ever + * getting here. + */ + assert(!"Should not get here."); + break; + } + } + + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_leave(ir_swizzle *ir) +{ + int chans[4] = {ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w}; + + for (unsigned int i = 0; i < ir->type->vector_elements; i++) { + if (chans[i] >= ir->val->type->vector_elements) { + printf("ir_swizzle @ %p specifies a channel not present " + "in the value.\n", (void *) ir); + ir->print(); + abort(); + } } return visit_continue; @@ -313,12 +449,45 @@ ir_validate::visit(ir_variable *ir) * in the ir_dereference_variable handler to ensure that a variable is * declared before it is dereferenced. */ - assert(talloc_parent(ir->name) == ir); + if (ir->name) + assert(ralloc_parent(ir->name) == ir); hash_table_insert(ht, ir, ir); return visit_continue; } +ir_visitor_status +ir_validate::visit_enter(ir_assignment *ir) +{ + const ir_dereference *const lhs = ir->lhs; + if (lhs->type->is_scalar() || lhs->type->is_vector()) { + if (ir->write_mask == 0) { + printf("Assignment LHS is %s, but write mask is 0:\n", + lhs->type->is_scalar() ? "scalar" : "vector"); + ir->print(); + abort(); + } + + int lhs_components = 0; + for (int i = 0; i < 4; i++) { + if (ir->write_mask & (1 << i)) + lhs_components++; + } + + if (lhs_components != ir->rhs->type->vector_elements) { + printf("Assignment count of LHS write mask channels enabled not\n" + "matching RHS vector size (%d LHS, %d RHS).\n", + lhs_components, ir->rhs->type->vector_elements); + ir->print(); + abort(); + } + } + + this->validate_ir(ir, this->data); + + return visit_continue; +} + void ir_validate::validate_ir(ir_instruction *ir, void *data) { @@ -336,6 +505,8 @@ ir_validate::validate_ir(ir_instruction *ir, void *data) void check_node_type(ir_instruction *ir, void *data) { + (void) data; + if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) { printf("Instruction node with unset type\n"); ir->print(); printf("\n");