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 #include "ir_print_visitor.h" 25 #include "glsl_types.h" 26 #include "glsl_parser_extras.h" 27 #include "program/hash_table.h" 28 29 static void print_type(const glsl_type *t); 30 31 void 32 ir_instruction::print(void) const 33 { 34 ir_instruction *deconsted = const_cast<ir_instruction *>(this); 35 36 ir_print_visitor v; 37 deconsted->accept(&v); 38 } 39 40 void 41 _mesa_print_ir(exec_list *instructions, 42 struct _mesa_glsl_parse_state *state) 43 { 44 if (state) { 45 for (unsigned i = 0; i < state->num_user_structures; i++) { 46 const glsl_type *const s = state->user_structures[i]; 47 48 printf("(structure (%s) (%s@%p) (%u) (\n", 49 s->name, s->name, (void *) s, s->length); 50 51 for (unsigned j = 0; j < s->length; j++) { 52 printf("\t(("); 53 print_type(s->fields.structure[j].type); 54 printf(")(%s))\n", s->fields.structure[j].name); 55 } 56 57 printf(")\n"); 58 } 59 } 60 61 printf("(\n"); 62 foreach_iter(exec_list_iterator, iter, *instructions) { 63 ir_instruction *ir = (ir_instruction *)iter.get(); 64 ir->print(); 65 if (ir->ir_type != ir_type_function) 66 printf("\n"); 67 } 68 printf("\n)"); 69 } 70 71 ir_print_visitor::ir_print_visitor() 72 { 73 indentation = 0; 74 printable_names = 75 hash_table_ctor(32, hash_table_pointer_hash, hash_table_pointer_compare); 76 symbols = _mesa_symbol_table_ctor(); 77 mem_ctx = ralloc_context(NULL); 78 } 79 80 ir_print_visitor::~ir_print_visitor() 81 { 82 hash_table_dtor(printable_names); 83 _mesa_symbol_table_dtor(symbols); 84 ralloc_free(mem_ctx); 85 } 86 87 void ir_print_visitor::indent(void) 88 { 89 for (int i = 0; i < indentation; i++) 90 printf(" "); 91 } 92 93 const char * 94 ir_print_visitor::unique_name(ir_variable *var) 95 { 96 /* var->name can be NULL in function prototypes when a type is given for a 97 * parameter but no name is given. In that case, just return an empty 98 * string. Don't worry about tracking the generated name in the printable 99 * names hash because this is the only scope where it can ever appear. 100 */ 101 if (var->name == NULL) { 102 static unsigned arg = 1; 103 return ralloc_asprintf(this->mem_ctx, "parameter@%u", arg++); 104 } 105 106 /* Do we already have a name for this variable? */ 107 const char *name = (const char *) hash_table_find(this->printable_names, var); 108 if (name != NULL) 109 return name; 110 111 /* If there's no conflict, just use the original name */ 112 if (_mesa_symbol_table_find_symbol(this->symbols, -1, var->name) == NULL) { 113 name = var->name; 114 } else { 115 static unsigned i = 1; 116 name = ralloc_asprintf(this->mem_ctx, "%s@%u", var->name, ++i); 117 } 118 hash_table_insert(this->printable_names, (void *) name, var); 119 _mesa_symbol_table_add_symbol(this->symbols, -1, name, var); 120 return name; 121 } 122 123 static void 124 print_type(const glsl_type *t) 125 { 126 if (t->base_type == GLSL_TYPE_ARRAY) { 127 printf("(array "); 128 print_type(t->fields.array); 129 printf(" %u)", t->length); 130 } else if ((t->base_type == GLSL_TYPE_STRUCT) 131 && (strncmp("gl_", t->name, 3) != 0)) { 132 printf("%s@%p", t->name, (void *) t); 133 } else { 134 printf("%s", t->name); 135 } 136 } 137 138 void ir_print_visitor::visit(ir_rvalue *ir) 139 { 140 printf("error"); 141 } 142 143 void ir_print_visitor::visit(ir_variable *ir) 144 { 145 printf("(declare "); 146 147 const char *const cent = (ir->centroid) ? "centroid " : ""; 148 const char *const inv = (ir->invariant) ? "invariant " : ""; 149 const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ", 150 "const_in ", "sys ", "temporary " }; 151 const char *const interp[] = { "", "flat", "noperspective" }; 152 153 printf("(%s%s%s%s) ", 154 cent, inv, mode[ir->mode], interp[ir->interpolation]); 155 156 print_type(ir->type); 157 printf(" %s)", unique_name(ir)); 158 } 159 160 161 void ir_print_visitor::visit(ir_function_signature *ir) 162 { 163 _mesa_symbol_table_push_scope(symbols); 164 printf("(signature "); 165 indentation++; 166 167 print_type(ir->return_type); 168 printf("\n"); 169 indent(); 170 171 printf("(parameters\n"); 172 indentation++; 173 174 foreach_iter(exec_list_iterator, iter, ir->parameters) { 175 ir_variable *const inst = (ir_variable *) iter.get(); 176 177 indent(); 178 inst->accept(this); 179 printf("\n"); 180 } 181 indentation--; 182 183 indent(); 184 printf(")\n"); 185 186 indent(); 187 188 printf("(\n"); 189 indentation++; 190 191 foreach_iter(exec_list_iterator, iter, ir->body) { 192 ir_instruction *const inst = (ir_instruction *) iter.get(); 193 194 indent(); 195 inst->accept(this); 196 printf("\n"); 197 } 198 indentation--; 199 indent(); 200 printf("))\n"); 201 indentation--; 202 _mesa_symbol_table_pop_scope(symbols); 203 } 204 205 206 void ir_print_visitor::visit(ir_function *ir) 207 { 208 printf("(function %s\n", ir->name); 209 indentation++; 210 foreach_iter(exec_list_iterator, iter, *ir) { 211 ir_function_signature *const sig = (ir_function_signature *) iter.get(); 212 indent(); 213 sig->accept(this); 214 printf("\n"); 215 } 216 indentation--; 217 indent(); 218 printf(")\n\n"); 219 } 220 221 222 void ir_print_visitor::visit(ir_expression *ir) 223 { 224 printf("(expression "); 225 226 print_type(ir->type); 227 228 printf(" %s ", ir->operator_string()); 229 230 for (unsigned i = 0; i < ir->get_num_operands(); i++) { 231 ir->operands[i]->accept(this); 232 } 233 234 printf(") "); 235 } 236 237 238 void ir_print_visitor::visit(ir_texture *ir) 239 { 240 printf("(%s ", ir->opcode_string()); 241 242 print_type(ir->type); 243 printf(" "); 244 245 ir->sampler->accept(this); 246 printf(" "); 247 248 if (ir->op != ir_txs) { 249 ir->coordinate->accept(this); 250 251 printf(" "); 252 253 if (ir->offset != NULL) { 254 ir->offset->accept(this); 255 } else { 256 printf("0"); 257 } 258 259 printf(" "); 260 } 261 262 if (ir->op != ir_txf && ir->op != ir_txs) { 263 if (ir->projector) 264 ir->projector->accept(this); 265 else 266 printf("1"); 267 268 if (ir->shadow_comparitor) { 269 printf(" "); 270 ir->shadow_comparitor->accept(this); 271 } else { 272 printf(" ()"); 273 } 274 } 275 276 printf(" "); 277 switch (ir->op) 278 { 279 case ir_tex: 280 break; 281 case ir_txb: 282 ir->lod_info.bias->accept(this); 283 break; 284 case ir_txl: 285 case ir_txf: 286 case ir_txs: 287 ir->lod_info.lod->accept(this); 288 break; 289 case ir_txd: 290 printf("("); 291 ir->lod_info.grad.dPdx->accept(this); 292 printf(" "); 293 ir->lod_info.grad.dPdy->accept(this); 294 printf(")"); 295 break; 296 }; 297 printf(")"); 298 } 299 300 301 void ir_print_visitor::visit(ir_swizzle *ir) 302 { 303 const unsigned swiz[4] = { 304 ir->mask.x, 305 ir->mask.y, 306 ir->mask.z, 307 ir->mask.w, 308 }; 309 310 printf("(swiz "); 311 for (unsigned i = 0; i < ir->mask.num_components; i++) { 312 printf("%c", "xyzw"[swiz[i]]); 313 } 314 printf(" "); 315 ir->val->accept(this); 316 printf(")"); 317 } 318 319 320 void ir_print_visitor::visit(ir_dereference_variable *ir) 321 { 322 ir_variable *var = ir->variable_referenced(); 323 printf("(var_ref %s) ", unique_name(var)); 324 } 325 326 327 void ir_print_visitor::visit(ir_dereference_array *ir) 328 { 329 printf("(array_ref "); 330 ir->array->accept(this); 331 ir->array_index->accept(this); 332 printf(") "); 333 } 334 335 336 void ir_print_visitor::visit(ir_dereference_record *ir) 337 { 338 printf("(record_ref "); 339 ir->record->accept(this); 340 printf(" %s) ", ir->field); 341 } 342 343 344 void ir_print_visitor::visit(ir_assignment *ir) 345 { 346 printf("(assign "); 347 348 if (ir->condition) 349 ir->condition->accept(this); 350 351 char mask[5]; 352 unsigned j = 0; 353 354 for (unsigned i = 0; i < 4; i++) { 355 if ((ir->write_mask & (1 << i)) != 0) { 356 mask[j] = "xyzw"[i]; 357 j++; 358 } 359 } 360 mask[j] = '\0'; 361 362 printf(" (%s) ", mask); 363 364 ir->lhs->accept(this); 365 366 printf(" "); 367 368 ir->rhs->accept(this); 369 printf(") "); 370 } 371 372 373 void ir_print_visitor::visit(ir_constant *ir) 374 { 375 printf("(constant "); 376 print_type(ir->type); 377 printf(" ("); 378 379 if (ir->type->is_array()) { 380 for (unsigned i = 0; i < ir->type->length; i++) 381 ir->get_array_element(i)->accept(this); 382 } else if (ir->type->is_record()) { 383 ir_constant *value = (ir_constant *) ir->components.get_head(); 384 for (unsigned i = 0; i < ir->type->length; i++) { 385 printf("(%s ", ir->type->fields.structure[i].name); 386 value->accept(this); 387 printf(")"); 388 389 value = (ir_constant *) value->next; 390 } 391 } else { 392 for (unsigned i = 0; i < ir->type->components(); i++) { 393 if (i != 0) 394 printf(" "); 395 switch (ir->type->base_type) { 396 case GLSL_TYPE_UINT: printf("%u", ir->value.u[i]); break; 397 case GLSL_TYPE_INT: printf("%d", ir->value.i[i]); break; 398 case GLSL_TYPE_FLOAT: printf("%f", ir->value.f[i]); break; 399 case GLSL_TYPE_BOOL: printf("%d", ir->value.b[i]); break; 400 default: assert(0); 401 } 402 } 403 } 404 printf(")) "); 405 } 406 407 408 void 409 ir_print_visitor::visit(ir_call *ir) 410 { 411 printf("(call %s ", ir->callee_name()); 412 if (ir->return_deref) 413 ir->return_deref->accept(this); 414 printf(" ("); 415 foreach_iter(exec_list_iterator, iter, *ir) { 416 ir_instruction *const inst = (ir_instruction *) iter.get(); 417 418 inst->accept(this); 419 } 420 printf("))\n"); 421 } 422 423 424 void 425 ir_print_visitor::visit(ir_return *ir) 426 { 427 printf("(return"); 428 429 ir_rvalue *const value = ir->get_value(); 430 if (value) { 431 printf(" "); 432 value->accept(this); 433 } 434 435 printf(")"); 436 } 437 438 439 void 440 ir_print_visitor::visit(ir_discard *ir) 441 { 442 printf("(discard "); 443 444 if (ir->condition != NULL) { 445 printf(" "); 446 ir->condition->accept(this); 447 } 448 449 printf(")"); 450 } 451 452 453 void 454 ir_print_visitor::visit(ir_if *ir) 455 { 456 printf("(if "); 457 ir->condition->accept(this); 458 459 printf("(\n"); 460 indentation++; 461 462 foreach_iter(exec_list_iterator, iter, ir->then_instructions) { 463 ir_instruction *const inst = (ir_instruction *) iter.get(); 464 465 indent(); 466 inst->accept(this); 467 printf("\n"); 468 } 469 470 indentation--; 471 indent(); 472 printf(")\n"); 473 474 indent(); 475 if (!ir->else_instructions.is_empty()) { 476 printf("(\n"); 477 indentation++; 478 479 foreach_iter(exec_list_iterator, iter, ir->else_instructions) { 480 ir_instruction *const inst = (ir_instruction *) iter.get(); 481 482 indent(); 483 inst->accept(this); 484 printf("\n"); 485 } 486 indentation--; 487 indent(); 488 printf("))\n"); 489 } else { 490 printf("())\n"); 491 } 492 } 493 494 495 void 496 ir_print_visitor::visit(ir_loop *ir) 497 { 498 printf("(loop ("); 499 if (ir->counter != NULL) 500 ir->counter->accept(this); 501 printf(") ("); 502 if (ir->from != NULL) 503 ir->from->accept(this); 504 printf(") ("); 505 if (ir->to != NULL) 506 ir->to->accept(this); 507 printf(") ("); 508 if (ir->increment != NULL) 509 ir->increment->accept(this); 510 printf(") (\n"); 511 indentation++; 512 513 foreach_iter(exec_list_iterator, iter, ir->body_instructions) { 514 ir_instruction *const inst = (ir_instruction *) iter.get(); 515 516 indent(); 517 inst->accept(this); 518 printf("\n"); 519 } 520 indentation--; 521 indent(); 522 printf("))\n"); 523 } 524 525 526 void 527 ir_print_visitor::visit(ir_loop_jump *ir) 528 { 529 printf("%s", ir->is_break() ? "break" : "continue"); 530 } 531