ir_validate.cpp revision 4dfb89904c0a3d2166e9a3fc0253a254680e91bc
1/* 2 * Copyright © 2010 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24/** 25 * \file ir_validate.cpp 26 * 27 * Attempts to verify that various invariants of the IR tree are true. 28 * 29 * In particular, at the moment it makes sure that no single 30 * ir_instruction node except for ir_variable appears multiple times 31 * in the ir tree. ir_variable does appear multiple times: Once as a 32 * declaration in an exec_list, and multiple times as the endpoint of 33 * a dereference chain. 34 */ 35 36#include <inttypes.h> 37#include "ir.h" 38#include "ir_hierarchical_visitor.h" 39#include "program/hash_table.h" 40#include "glsl_types.h" 41 42class ir_validate : public ir_hierarchical_visitor { 43public: 44 ir_validate() 45 { 46 this->ht = hash_table_ctor(0, hash_table_pointer_hash, 47 hash_table_pointer_compare); 48 49 this->current_function = NULL; 50 51 this->callback = ir_validate::validate_ir; 52 this->data = ht; 53 } 54 55 ~ir_validate() 56 { 57 hash_table_dtor(this->ht); 58 } 59 60 virtual ir_visitor_status visit(ir_variable *v); 61 virtual ir_visitor_status visit(ir_dereference_variable *ir); 62 virtual ir_visitor_status visit(ir_if *ir); 63 64 virtual ir_visitor_status visit_leave(ir_loop *ir); 65 virtual ir_visitor_status visit_enter(ir_function *ir); 66 virtual ir_visitor_status visit_leave(ir_function *ir); 67 virtual ir_visitor_status visit_enter(ir_function_signature *ir); 68 69 virtual ir_visitor_status visit_leave(ir_expression *ir); 70 71 virtual ir_visitor_status visit_enter(ir_assignment *ir); 72 73 static void validate_ir(ir_instruction *ir, void *data); 74 75 ir_function *current_function; 76 77 struct hash_table *ht; 78}; 79 80 81ir_visitor_status 82ir_validate::visit(ir_dereference_variable *ir) 83{ 84 if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) { 85 printf("ir_dereference_variable @ %p does not specify a variable %p\n", 86 (void *) ir, (void *) ir->var); 87 abort(); 88 } 89 90 if (hash_table_find(ht, ir->var) == NULL) { 91 printf("ir_dereference_variable @ %p specifies undeclared variable " 92 "`%s' @ %p\n", 93 (void *) ir, ir->var->name, (void *) ir->var); 94 abort(); 95 } 96 97 this->validate_ir(ir, this->data); 98 99 return visit_continue; 100} 101 102ir_visitor_status 103ir_validate::visit(ir_if *ir) 104{ 105 if (ir->condition->type != glsl_type::bool_type) { 106 printf("ir_if condition %s type instead of bool.\n", 107 ir->condition->type->name); 108 ir->print(); 109 printf("\n"); 110 abort(); 111 } 112 113 return visit_continue; 114} 115 116 117ir_visitor_status 118ir_validate::visit_leave(ir_loop *ir) 119{ 120 if (ir->counter != NULL) { 121 if ((ir->from == NULL) || (ir->from == NULL) || (ir->increment == NULL)) { 122 printf("ir_loop has invalid loop controls:\n" 123 " counter: %p\n" 124 " from: %p\n" 125 " to: %p\n" 126 " increment: %p\n", 127 ir->counter, ir->from, ir->to, ir->increment); 128 abort(); 129 } 130 131 if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) { 132 printf("ir_loop has invalid comparitor %d\n", ir->cmp); 133 abort(); 134 } 135 } else { 136 if ((ir->from != NULL) || (ir->from != NULL) || (ir->increment != NULL)) { 137 printf("ir_loop has invalid loop controls:\n" 138 " counter: %p\n" 139 " from: %p\n" 140 " to: %p\n" 141 " increment: %p\n", 142 ir->counter, ir->from, ir->to, ir->increment); 143 abort(); 144 } 145 } 146 147 return visit_continue; 148} 149 150 151ir_visitor_status 152ir_validate::visit_enter(ir_function *ir) 153{ 154 /* Function definitions cannot be nested. 155 */ 156 if (this->current_function != NULL) { 157 printf("Function definition nested inside another function " 158 "definition:\n"); 159 printf("%s %p inside %s %p\n", 160 ir->name, (void *) ir, 161 this->current_function->name, (void *) this->current_function); 162 abort(); 163 } 164 165 /* Store the current function hierarchy being traversed. This is used 166 * by the function signature visitor to ensure that the signatures are 167 * linked with the correct functions. 168 */ 169 this->current_function = ir; 170 171 this->validate_ir(ir, this->data); 172 173 return visit_continue; 174} 175 176ir_visitor_status 177ir_validate::visit_leave(ir_function *ir) 178{ 179 assert(talloc_parent(ir->name) == ir); 180 181 this->current_function = NULL; 182 return visit_continue; 183} 184 185ir_visitor_status 186ir_validate::visit_enter(ir_function_signature *ir) 187{ 188 if (this->current_function != ir->function()) { 189 printf("Function signature nested inside wrong function " 190 "definition:\n"); 191 printf("%p inside %s %p instead of %s %p\n", 192 (void *) ir, 193 this->current_function->name, (void *) this->current_function, 194 ir->function_name(), (void *) ir->function()); 195 abort(); 196 } 197 198 this->validate_ir(ir, this->data); 199 200 return visit_continue; 201} 202 203ir_visitor_status 204ir_validate::visit_leave(ir_expression *ir) 205{ 206 switch (ir->operation) { 207 case ir_unop_bit_not: 208 assert(ir->operands[0]->type == ir->type); 209 break; 210 case ir_unop_logic_not: 211 assert(ir->type->base_type == GLSL_TYPE_BOOL); 212 assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); 213 break; 214 215 case ir_unop_neg: 216 case ir_unop_abs: 217 case ir_unop_sign: 218 case ir_unop_rcp: 219 case ir_unop_rsq: 220 case ir_unop_sqrt: 221 assert(ir->type == ir->operands[0]->type); 222 break; 223 224 case ir_unop_exp: 225 case ir_unop_log: 226 case ir_unop_exp2: 227 case ir_unop_log2: 228 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 229 assert(ir->type == ir->operands[0]->type); 230 break; 231 232 case ir_unop_f2i: 233 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 234 assert(ir->type->base_type == GLSL_TYPE_INT); 235 break; 236 case ir_unop_i2f: 237 assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); 238 assert(ir->type->base_type == GLSL_TYPE_FLOAT); 239 break; 240 case ir_unop_f2b: 241 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 242 assert(ir->type->base_type == GLSL_TYPE_BOOL); 243 break; 244 case ir_unop_b2f: 245 assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); 246 assert(ir->type->base_type == GLSL_TYPE_FLOAT); 247 break; 248 case ir_unop_i2b: 249 assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); 250 assert(ir->type->base_type == GLSL_TYPE_BOOL); 251 break; 252 case ir_unop_b2i: 253 assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); 254 assert(ir->type->base_type == GLSL_TYPE_INT); 255 break; 256 case ir_unop_u2f: 257 assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT); 258 assert(ir->type->base_type == GLSL_TYPE_FLOAT); 259 break; 260 261 case ir_unop_any: 262 assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); 263 assert(ir->type == glsl_type::bool_type); 264 break; 265 266 case ir_unop_trunc: 267 case ir_unop_ceil: 268 case ir_unop_floor: 269 case ir_unop_fract: 270 case ir_unop_sin: 271 case ir_unop_cos: 272 case ir_unop_dFdx: 273 case ir_unop_dFdy: 274 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 275 assert(ir->operands[0]->type == ir->type); 276 break; 277 278 case ir_binop_add: 279 case ir_binop_sub: 280 case ir_binop_mul: 281 case ir_binop_div: 282 case ir_binop_mod: 283 case ir_binop_min: 284 case ir_binop_max: 285 case ir_binop_pow: 286 if (ir->operands[0]->type->is_scalar()) 287 assert(ir->operands[1]->type == ir->type); 288 else if (ir->operands[1]->type->is_scalar()) 289 assert(ir->operands[0]->type == ir->type); 290 else if (ir->operands[0]->type->is_vector() && 291 ir->operands[1]->type->is_vector()) { 292 assert(ir->operands[0]->type == ir->operands[1]->type); 293 assert(ir->operands[0]->type == ir->type); 294 } 295 break; 296 297 case ir_binop_less: 298 case ir_binop_greater: 299 case ir_binop_lequal: 300 case ir_binop_gequal: 301 case ir_binop_equal: 302 case ir_binop_nequal: 303 /* The semantics of the IR operators differ from the GLSL <, >, <=, >=, 304 * ==, and != operators. The IR operators perform a component-wise 305 * comparison on scalar or vector types and return a boolean scalar or 306 * vector type of the same size. 307 */ 308 assert(ir->type->base_type == GLSL_TYPE_BOOL); 309 assert(ir->operands[0]->type == ir->operands[1]->type); 310 assert(ir->operands[0]->type->is_vector() 311 || ir->operands[0]->type->is_scalar()); 312 assert(ir->operands[0]->type->vector_elements 313 == ir->type->vector_elements); 314 break; 315 316 case ir_binop_all_equal: 317 case ir_binop_any_nequal: 318 /* GLSL == and != operate on scalars, vectors, matrices and arrays, and 319 * return a scalar boolean. The IR matches that. 320 */ 321 assert(ir->type == glsl_type::bool_type); 322 assert(ir->operands[0]->type == ir->operands[1]->type); 323 break; 324 325 case ir_binop_lshift: 326 case ir_binop_rshift: 327 case ir_binop_bit_and: 328 case ir_binop_bit_xor: 329 case ir_binop_bit_or: 330 assert(ir->operands[0]->type == ir->operands[1]->type); 331 assert(ir->type == ir->operands[0]->type); 332 assert(ir->type->base_type == GLSL_TYPE_INT || 333 ir->type->base_type == GLSL_TYPE_UINT); 334 break; 335 336 case ir_binop_logic_and: 337 case ir_binop_logic_xor: 338 case ir_binop_logic_or: 339 assert(ir->type == glsl_type::bool_type); 340 assert(ir->operands[0]->type == glsl_type::bool_type); 341 assert(ir->operands[1]->type == glsl_type::bool_type); 342 break; 343 344 case ir_binop_dot: 345 assert(ir->type == glsl_type::float_type); 346 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 347 assert(ir->operands[0]->type->is_vector()); 348 assert(ir->operands[0]->type == ir->operands[1]->type); 349 break; 350 351 case ir_binop_cross: 352 assert(ir->operands[0]->type == glsl_type::vec3_type); 353 assert(ir->operands[1]->type == glsl_type::vec3_type); 354 assert(ir->type == glsl_type::vec3_type); 355 break; 356 } 357 358 return visit_continue; 359} 360 361ir_visitor_status 362ir_validate::visit(ir_variable *ir) 363{ 364 /* An ir_variable is the one thing that can (and will) appear multiple times 365 * in an IR tree. It is added to the hashtable so that it can be used 366 * in the ir_dereference_variable handler to ensure that a variable is 367 * declared before it is dereferenced. 368 */ 369 if (ir->name) 370 assert(talloc_parent(ir->name) == ir); 371 372 hash_table_insert(ht, ir, ir); 373 return visit_continue; 374} 375 376ir_visitor_status 377ir_validate::visit_enter(ir_assignment *ir) 378{ 379 const ir_dereference *const lhs = ir->lhs; 380 if (lhs->type->is_scalar() || lhs->type->is_vector()) { 381 if (ir->write_mask == 0) { 382 printf("Assignment LHS is %s, but write mask is 0:\n", 383 lhs->type->is_scalar() ? "scalar" : "vector"); 384 ir->print(); 385 abort(); 386 } 387 388 /* Mask of fields that do not exist in the destination. These should 389 * not be written by the assignment. 390 */ 391 const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1); 392 393 if ((invalid_mask & ir->write_mask) != 0) { 394 printf("Assignment write mask enables invalid components for " 395 "type %s:\n", lhs->type->name); 396 ir->print(); 397 abort(); 398 } 399 } 400 401 this->validate_ir(ir, this->data); 402 403 return visit_continue; 404} 405 406void 407ir_validate::validate_ir(ir_instruction *ir, void *data) 408{ 409 struct hash_table *ht = (struct hash_table *) data; 410 411 if (hash_table_find(ht, ir)) { 412 printf("Instruction node present twice in ir tree:\n"); 413 ir->print(); 414 printf("\n"); 415 abort(); 416 } 417 hash_table_insert(ht, ir, ir); 418} 419 420void 421check_node_type(ir_instruction *ir, void *data) 422{ 423 (void) data; 424 425 if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) { 426 printf("Instruction node with unset type\n"); 427 ir->print(); printf("\n"); 428 } 429 assert(ir->type != glsl_type::error_type); 430} 431 432void 433validate_ir_tree(exec_list *instructions) 434{ 435 ir_validate v; 436 437 v.run(instructions); 438 439 foreach_iter(exec_list_iterator, iter, *instructions) { 440 ir_instruction *ir = (ir_instruction *)iter.get(); 441 442 visit_tree(ir, check_node_type, NULL); 443 } 444} 445