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 virtual ir_visitor_status visit_leave(ir_swizzle *ir); 71 72 virtual ir_visitor_status visit_enter(ir_assignment *ir); 73 74 static void validate_ir(ir_instruction *ir, void *data); 75 76 ir_function *current_function; 77 78 struct hash_table *ht; 79}; 80 81 82ir_visitor_status 83ir_validate::visit(ir_dereference_variable *ir) 84{ 85 if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) { 86 printf("ir_dereference_variable @ %p does not specify a variable %p\n", 87 (void *) ir, (void *) ir->var); 88 abort(); 89 } 90 91 if (hash_table_find(ht, ir->var) == NULL) { 92 printf("ir_dereference_variable @ %p specifies undeclared variable " 93 "`%s' @ %p\n", 94 (void *) ir, ir->var->name, (void *) ir->var); 95 abort(); 96 } 97 98 this->validate_ir(ir, this->data); 99 100 return visit_continue; 101} 102 103ir_visitor_status 104ir_validate::visit(ir_if *ir) 105{ 106 if (ir->condition->type != glsl_type::bool_type) { 107 printf("ir_if condition %s type instead of bool.\n", 108 ir->condition->type->name); 109 ir->print(); 110 printf("\n"); 111 abort(); 112 } 113 114 return visit_continue; 115} 116 117 118ir_visitor_status 119ir_validate::visit_leave(ir_loop *ir) 120{ 121 if (ir->counter != NULL) { 122 if ((ir->from == NULL) || (ir->from == NULL) || (ir->increment == NULL)) { 123 printf("ir_loop has invalid loop controls:\n" 124 " counter: %p\n" 125 " from: %p\n" 126 " to: %p\n" 127 " increment: %p\n", 128 (void *) ir->counter, (void *) ir->from, (void *) ir->to, 129 (void *) ir->increment); 130 abort(); 131 } 132 133 if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) { 134 printf("ir_loop has invalid comparitor %d\n", ir->cmp); 135 abort(); 136 } 137 } else { 138 if ((ir->from != NULL) || (ir->from != NULL) || (ir->increment != NULL)) { 139 printf("ir_loop has invalid loop controls:\n" 140 " counter: %p\n" 141 " from: %p\n" 142 " to: %p\n" 143 " increment: %p\n", 144 (void *) ir->counter, (void *) ir->from, (void *) ir->to, 145 (void *) ir->increment); 146 abort(); 147 } 148 } 149 150 return visit_continue; 151} 152 153 154ir_visitor_status 155ir_validate::visit_enter(ir_function *ir) 156{ 157 /* Function definitions cannot be nested. 158 */ 159 if (this->current_function != NULL) { 160 printf("Function definition nested inside another function " 161 "definition:\n"); 162 printf("%s %p inside %s %p\n", 163 ir->name, (void *) ir, 164 this->current_function->name, (void *) this->current_function); 165 abort(); 166 } 167 168 /* Store the current function hierarchy being traversed. This is used 169 * by the function signature visitor to ensure that the signatures are 170 * linked with the correct functions. 171 */ 172 this->current_function = ir; 173 174 this->validate_ir(ir, this->data); 175 176 return visit_continue; 177} 178 179ir_visitor_status 180ir_validate::visit_leave(ir_function *ir) 181{ 182 assert(hieralloc_parent(ir->name) == ir); 183 184 this->current_function = NULL; 185 return visit_continue; 186} 187 188ir_visitor_status 189ir_validate::visit_enter(ir_function_signature *ir) 190{ 191 if (this->current_function != ir->function()) { 192 printf("Function signature nested inside wrong function " 193 "definition:\n"); 194 printf("%p inside %s %p instead of %s %p\n", 195 (void *) ir, 196 this->current_function->name, (void *) this->current_function, 197 ir->function_name(), (void *) ir->function()); 198 abort(); 199 } 200 201 this->validate_ir(ir, this->data); 202 203 return visit_continue; 204} 205 206ir_visitor_status 207ir_validate::visit_leave(ir_expression *ir) 208{ 209 switch (ir->operation) { 210 case ir_unop_bit_not: 211 assert(ir->operands[0]->type == ir->type); 212 break; 213 case ir_unop_logic_not: 214 assert(ir->type->base_type == GLSL_TYPE_BOOL); 215 assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); 216 break; 217 218 case ir_unop_neg: 219 case ir_unop_abs: 220 case ir_unop_sign: 221 case ir_unop_rcp: 222 case ir_unop_rsq: 223 case ir_unop_sqrt: 224 assert(ir->type == ir->operands[0]->type); 225 break; 226 227 case ir_unop_exp: 228 case ir_unop_log: 229 case ir_unop_exp2: 230 case ir_unop_log2: 231 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 232 assert(ir->type == ir->operands[0]->type); 233 break; 234 235 case ir_unop_f2i: 236 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 237 assert(ir->type->base_type == GLSL_TYPE_INT); 238 break; 239 case ir_unop_i2f: 240 assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); 241 assert(ir->type->base_type == GLSL_TYPE_FLOAT); 242 break; 243 case ir_unop_f2b: 244 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 245 assert(ir->type->base_type == GLSL_TYPE_BOOL); 246 break; 247 case ir_unop_b2f: 248 assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); 249 assert(ir->type->base_type == GLSL_TYPE_FLOAT); 250 break; 251 case ir_unop_i2b: 252 assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); 253 assert(ir->type->base_type == GLSL_TYPE_BOOL); 254 break; 255 case ir_unop_b2i: 256 assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); 257 assert(ir->type->base_type == GLSL_TYPE_INT); 258 break; 259 case ir_unop_u2f: 260 assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT); 261 assert(ir->type->base_type == GLSL_TYPE_FLOAT); 262 break; 263 264 case ir_unop_any: 265 assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); 266 assert(ir->type == glsl_type::bool_type); 267 break; 268 269 case ir_unop_trunc: 270 case ir_unop_round_even: 271 case ir_unop_ceil: 272 case ir_unop_floor: 273 case ir_unop_fract: 274 case ir_unop_sin: 275 case ir_unop_cos: 276 case ir_unop_sin_reduced: 277 case ir_unop_cos_reduced: 278 case ir_unop_dFdx: 279 case ir_unop_dFdy: 280 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 281 assert(ir->operands[0]->type == ir->type); 282 break; 283 284 case ir_unop_noise: 285 /* XXX what can we assert here? */ 286 break; 287 288 case ir_binop_add: 289 case ir_binop_sub: 290 case ir_binop_mul: 291 case ir_binop_div: 292 case ir_binop_mod: 293 case ir_binop_min: 294 case ir_binop_max: 295 case ir_binop_pow: 296 if (ir->operands[0]->type->is_scalar()) 297 assert(ir->operands[1]->type == ir->type); 298 else if (ir->operands[1]->type->is_scalar()) 299 assert(ir->operands[0]->type == ir->type); 300 else if (ir->operands[0]->type->is_vector() && 301 ir->operands[1]->type->is_vector()) { 302 assert(ir->operands[0]->type == ir->operands[1]->type); 303 assert(ir->operands[0]->type == ir->type); 304 } 305 break; 306 307 case ir_binop_less: 308 case ir_binop_greater: 309 case ir_binop_lequal: 310 case ir_binop_gequal: 311 case ir_binop_equal: 312 case ir_binop_nequal: 313 /* The semantics of the IR operators differ from the GLSL <, >, <=, >=, 314 * ==, and != operators. The IR operators perform a component-wise 315 * comparison on scalar or vector types and return a boolean scalar or 316 * vector type of the same size. 317 */ 318 assert(ir->type->base_type == GLSL_TYPE_BOOL); 319 assert(ir->operands[0]->type == ir->operands[1]->type); 320 assert(ir->operands[0]->type->is_vector() 321 || ir->operands[0]->type->is_scalar()); 322 assert(ir->operands[0]->type->vector_elements 323 == ir->type->vector_elements); 324 break; 325 326 case ir_binop_all_equal: 327 case ir_binop_any_nequal: 328 /* GLSL == and != operate on scalars, vectors, matrices and arrays, and 329 * return a scalar boolean. The IR matches that. 330 */ 331 assert(ir->type == glsl_type::bool_type); 332 assert(ir->operands[0]->type == ir->operands[1]->type); 333 break; 334 335 case ir_binop_lshift: 336 case ir_binop_rshift: 337 assert(ir->operands[0]->type->is_integer() && 338 ir->operands[1]->type->is_integer()); 339 if (ir->operands[0]->type->is_scalar()) { 340 assert(ir->operands[1]->type->is_scalar()); 341 } 342 if (ir->operands[0]->type->is_vector() && 343 ir->operands[1]->type->is_vector()) { 344 assert(ir->operands[0]->type->components() == 345 ir->operands[1]->type->components()); 346 } 347 assert(ir->type == ir->operands[0]->type); 348 break; 349 350 case ir_binop_bit_and: 351 case ir_binop_bit_xor: 352 case ir_binop_bit_or: 353 assert(ir->operands[0]->type->base_type == 354 ir->operands[1]->type->base_type); 355 assert(ir->type->is_integer()); 356 if (ir->operands[0]->type->is_vector() && 357 ir->operands[1]->type->is_vector()) { 358 assert(ir->operands[0]->type->vector_elements == 359 ir->operands[1]->type->vector_elements); 360 } 361 break; 362 363 case ir_binop_logic_and: 364 case ir_binop_logic_xor: 365 case ir_binop_logic_or: 366 assert(ir->type == glsl_type::bool_type); 367 assert(ir->operands[0]->type == glsl_type::bool_type); 368 assert(ir->operands[1]->type == glsl_type::bool_type); 369 break; 370 371 case ir_binop_dot: 372 assert(ir->type == glsl_type::float_type); 373 assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); 374 assert(ir->operands[0]->type->is_vector()); 375 assert(ir->operands[0]->type == ir->operands[1]->type); 376 break; 377 378 case ir_quadop_vector: 379 /* The vector operator collects some number of scalars and generates a 380 * vector from them. 381 * 382 * - All of the operands must be scalar. 383 * - Number of operands must matche the size of the resulting vector. 384 * - Base type of the operands must match the base type of the result. 385 */ 386 assert(ir->type->is_vector()); 387 switch (ir->type->vector_elements) { 388 case 2: 389 assert(ir->operands[0]->type->is_scalar()); 390 assert(ir->operands[0]->type->base_type == ir->type->base_type); 391 assert(ir->operands[1]->type->is_scalar()); 392 assert(ir->operands[1]->type->base_type == ir->type->base_type); 393 assert(ir->operands[2] == NULL); 394 assert(ir->operands[3] == NULL); 395 break; 396 case 3: 397 assert(ir->operands[0]->type->is_scalar()); 398 assert(ir->operands[0]->type->base_type == ir->type->base_type); 399 assert(ir->operands[1]->type->is_scalar()); 400 assert(ir->operands[1]->type->base_type == ir->type->base_type); 401 assert(ir->operands[2]->type->is_scalar()); 402 assert(ir->operands[2]->type->base_type == ir->type->base_type); 403 assert(ir->operands[3] == NULL); 404 break; 405 case 4: 406 assert(ir->operands[0]->type->is_scalar()); 407 assert(ir->operands[0]->type->base_type == ir->type->base_type); 408 assert(ir->operands[1]->type->is_scalar()); 409 assert(ir->operands[1]->type->base_type == ir->type->base_type); 410 assert(ir->operands[2]->type->is_scalar()); 411 assert(ir->operands[2]->type->base_type == ir->type->base_type); 412 assert(ir->operands[3]->type->is_scalar()); 413 assert(ir->operands[3]->type->base_type == ir->type->base_type); 414 break; 415 default: 416 /* The is_vector assertion above should prevent execution from ever 417 * getting here. 418 */ 419 assert(!"Should not get here."); 420 break; 421 } 422 } 423 424 return visit_continue; 425} 426 427ir_visitor_status 428ir_validate::visit_leave(ir_swizzle *ir) 429{ 430 int chans[4] = {ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w}; 431 432 for (unsigned int i = 0; i < ir->type->vector_elements; i++) { 433 if (chans[i] >= ir->val->type->vector_elements) { 434 printf("ir_swizzle @ %p specifies a channel not present " 435 "in the value.\n", (void *) ir); 436 ir->print(); 437 abort(); 438 } 439 } 440 441 return visit_continue; 442} 443 444ir_visitor_status 445ir_validate::visit(ir_variable *ir) 446{ 447 /* An ir_variable is the one thing that can (and will) appear multiple times 448 * in an IR tree. It is added to the hashtable so that it can be used 449 * in the ir_dereference_variable handler to ensure that a variable is 450 * declared before it is dereferenced. 451 */ 452 if (ir->name) 453 assert(hieralloc_parent(ir->name) == ir); 454 455 hash_table_insert(ht, ir, ir); 456 return visit_continue; 457} 458 459ir_visitor_status 460ir_validate::visit_enter(ir_assignment *ir) 461{ 462 const ir_dereference *const lhs = ir->lhs; 463 if (lhs->type->is_scalar() || lhs->type->is_vector()) { 464 if (ir->write_mask == 0) { 465 printf("Assignment LHS is %s, but write mask is 0:\n", 466 lhs->type->is_scalar() ? "scalar" : "vector"); 467 ir->print(); 468 abort(); 469 } 470 471 int lhs_components = 0; 472 for (int i = 0; i < 4; i++) { 473 if (ir->write_mask & (1 << i)) 474 lhs_components++; 475 } 476 477 if (lhs_components != ir->rhs->type->vector_elements) { 478 printf("Assignment count of LHS write mask channels enabled not\n" 479 "matching RHS vector size (%d LHS, %d RHS).\n", 480 lhs_components, ir->rhs->type->vector_elements); 481 ir->print(); 482 abort(); 483 } 484 } 485 486 this->validate_ir(ir, this->data); 487 488 return visit_continue; 489} 490 491void 492ir_validate::validate_ir(ir_instruction *ir, void *data) 493{ 494 struct hash_table *ht = (struct hash_table *) data; 495 496 if (hash_table_find(ht, ir)) { 497 printf("Instruction node present twice in ir tree:\n"); 498 ir->print(); 499 printf("\n"); 500 abort(); 501 } 502 hash_table_insert(ht, ir, ir); 503} 504 505void 506check_node_type(ir_instruction *ir, void *data) 507{ 508 (void) data; 509 510 if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) { 511 printf("Instruction node with unset type\n"); 512 ir->print(); printf("\n"); 513 } 514 assert(ir->type != glsl_type::error_type); 515} 516 517void 518validate_ir_tree(exec_list *instructions) 519{ 520 ir_validate v; 521 522 v.run(instructions); 523 524 foreach_iter(exec_list_iterator, iter, *instructions) { 525 ir_instruction *ir = (ir_instruction *)iter.get(); 526 527 visit_tree(ir, check_node_type, NULL); 528 } 529} 530