1/* 2 * Copyright © 2016 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 <inttypes.h> /* for PRIx64 macro */ 25#include "ir.h" 26#include "ir_hierarchical_visitor.h" 27#include "ir_builder_print_visitor.h" 28#include "compiler/glsl_types.h" 29#include "glsl_parser_extras.h" 30#include "main/macros.h" 31#include "util/hash_table.h" 32#include "util/u_string.h" 33 34class ir_builder_print_visitor : public ir_hierarchical_visitor { 35public: 36 ir_builder_print_visitor(FILE *f); 37 virtual ~ir_builder_print_visitor(); 38 39 void indent(void); 40 41 virtual ir_visitor_status visit(class ir_variable *); 42 virtual ir_visitor_status visit(class ir_dereference_variable *); 43 virtual ir_visitor_status visit(class ir_constant *); 44 virtual ir_visitor_status visit(class ir_loop_jump *); 45 46 virtual ir_visitor_status visit_enter(class ir_if *); 47 48 virtual ir_visitor_status visit_enter(class ir_loop *); 49 virtual ir_visitor_status visit_leave(class ir_loop *); 50 51 virtual ir_visitor_status visit_enter(class ir_function_signature *); 52 virtual ir_visitor_status visit_leave(class ir_function_signature *); 53 54 virtual ir_visitor_status visit_enter(class ir_expression *); 55 56 virtual ir_visitor_status visit_enter(class ir_assignment *); 57 virtual ir_visitor_status visit_leave(class ir_assignment *); 58 59 virtual ir_visitor_status visit_leave(class ir_call *); 60 virtual ir_visitor_status visit_leave(class ir_swizzle *); 61 virtual ir_visitor_status visit_leave(class ir_return *); 62 63 virtual ir_visitor_status visit_enter(ir_texture *ir); 64 65private: 66 void print_with_indent(const char *fmt, ...); 67 void print_without_indent(const char *fmt, ...); 68 69 void print_without_declaration(const ir_rvalue *ir); 70 void print_without_declaration(const ir_constant *ir); 71 void print_without_declaration(const ir_dereference_variable *ir); 72 void print_without_declaration(const ir_swizzle *ir); 73 void print_without_declaration(const ir_expression *ir); 74 75 unsigned next_ir_index; 76 77 /** 78 * Mapping from ir_instruction * -> index used in the generated C code 79 * variable name. 80 */ 81 hash_table *index_map; 82 83 FILE *f; 84 85 int indentation; 86}; 87 88/* An operand is "simple" if it can be compactly printed on one line. 89 */ 90static bool 91is_simple_operand(const ir_rvalue *ir, unsigned depth = 1) 92{ 93 if (depth == 0) 94 return false; 95 96 switch (ir->ir_type) { 97 case ir_type_dereference_variable: 98 return true; 99 100 case ir_type_constant: { 101 if (ir->type == glsl_type::uint_type || 102 ir->type == glsl_type::int_type || 103 ir->type == glsl_type::float_type || 104 ir->type == glsl_type::bool_type) 105 return true; 106 107 const ir_constant *const c = (ir_constant *) ir; 108 ir_constant_data all_zero; 109 memset(&all_zero, 0, sizeof(all_zero)); 110 111 return memcmp(&c->value, &all_zero, sizeof(all_zero)) == 0; 112 } 113 114 case ir_type_swizzle: { 115 const ir_swizzle *swiz = (ir_swizzle *) ir; 116 return swiz->mask.num_components == 1 && 117 is_simple_operand(swiz->val, depth); 118 } 119 120 case ir_type_expression: { 121 const ir_expression *expr = (ir_expression *) ir; 122 123 for (unsigned i = 0; i < expr->num_operands; i++) { 124 if (!is_simple_operand(expr->operands[i], depth - 1)) 125 return false; 126 } 127 128 return true; 129 } 130 131 default: 132 return false; 133 } 134} 135 136void 137_mesa_print_builder_for_ir(FILE *f, exec_list *instructions) 138{ 139 ir_builder_print_visitor v(f); 140 v.run(instructions); 141} 142 143ir_builder_print_visitor::ir_builder_print_visitor(FILE *f) 144 : next_ir_index(1), f(f), indentation(0) 145{ 146 index_map = _mesa_pointer_hash_table_create(NULL); 147} 148 149ir_builder_print_visitor::~ir_builder_print_visitor() 150{ 151 _mesa_hash_table_destroy(index_map, NULL); 152} 153 154void ir_builder_print_visitor::indent(void) 155{ 156 for (int i = 0; i < indentation; i++) 157 fprintf(f, " "); 158} 159 160void 161ir_builder_print_visitor::print_with_indent(const char *fmt, ...) 162{ 163 va_list ap; 164 165 indent(); 166 167 va_start(ap, fmt); 168 vfprintf(f, fmt, ap); 169 va_end(ap); 170} 171 172void 173ir_builder_print_visitor::print_without_indent(const char *fmt, ...) 174{ 175 va_list ap; 176 177 va_start(ap, fmt); 178 vfprintf(f, fmt, ap); 179 va_end(ap); 180} 181 182void 183ir_builder_print_visitor::print_without_declaration(const ir_rvalue *ir) 184{ 185 switch (ir->ir_type) { 186 case ir_type_dereference_variable: 187 print_without_declaration((ir_dereference_variable *) ir); 188 break; 189 case ir_type_constant: 190 print_without_declaration((ir_constant *) ir); 191 break; 192 case ir_type_swizzle: 193 print_without_declaration((ir_swizzle *) ir); 194 break; 195 case ir_type_expression: 196 print_without_declaration((ir_expression *) ir); 197 break; 198 default: 199 unreachable("Invalid IR type."); 200 } 201} 202 203ir_visitor_status 204ir_builder_print_visitor::visit(ir_variable *ir) 205{ 206 const unsigned my_index = next_ir_index++; 207 208 _mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index); 209 210 const char *mode_str; 211 switch (ir->data.mode) { 212 case ir_var_auto: mode_str = "ir_var_auto"; break; 213 case ir_var_uniform: mode_str = "ir_var_uniform"; break; 214 case ir_var_shader_storage: mode_str = "ir_var_shader_storage"; break; 215 case ir_var_shader_shared: mode_str = "ir_var_shader_shared"; break; 216 case ir_var_shader_in: mode_str = "ir_var_shader_in"; break; 217 case ir_var_shader_out: mode_str = "ir_var_shader_out"; break; 218 case ir_var_function_in: mode_str = "ir_var_function_in"; break; 219 case ir_var_function_out: mode_str = "ir_var_function_out"; break; 220 case ir_var_function_inout: mode_str = "ir_var_function_inout"; break; 221 case ir_var_const_in: mode_str = "ir_var_const_in"; break; 222 case ir_var_system_value: mode_str = "ir_var_system_value"; break; 223 case ir_var_temporary: mode_str = "ir_var_temporary"; break; 224 default: 225 unreachable("Invalid variable mode"); 226 } 227 228 if (ir->data.mode == ir_var_temporary) { 229 print_with_indent("ir_variable *const r%04X = body.make_temp(glsl_type::%s_type, \"%s\");\n", 230 my_index, 231 ir->type->name, 232 ir->name); 233 } else { 234 print_with_indent("ir_variable *const r%04X = new(mem_ctx) ir_variable(glsl_type::%s_type, \"%s\", %s);\n", 235 my_index, 236 ir->type->name, 237 ir->name, 238 mode_str); 239 240 switch (ir->data.mode) { 241 case ir_var_function_in: 242 case ir_var_function_out: 243 case ir_var_function_inout: 244 case ir_var_const_in: 245 print_with_indent("sig_parameters.push_tail(r%04X);\n", my_index); 246 break; 247 default: 248 print_with_indent("body.emit(r%04X);\n", my_index); 249 break; 250 } 251 } 252 253 return visit_continue; 254} 255 256void 257ir_builder_print_visitor::print_without_declaration(const ir_dereference_variable *ir) 258{ 259 const struct hash_entry *const he = 260 _mesa_hash_table_search(index_map, ir->var); 261 262 print_without_indent("r%04X", (unsigned)(uintptr_t) he->data); 263} 264 265ir_visitor_status 266ir_builder_print_visitor::visit(ir_dereference_variable *ir) 267{ 268 const struct hash_entry *const he = 269 _mesa_hash_table_search(index_map, ir->var); 270 271 if (he != NULL) 272 _mesa_hash_table_insert(index_map, ir, he->data); 273 274 return visit_continue; 275} 276 277ir_visitor_status 278ir_builder_print_visitor::visit_enter(ir_function_signature *ir) 279{ 280 if (!ir->is_defined) 281 return visit_continue_with_parent; 282 283 print_with_indent("ir_function_signature *\n" 284 "%s(void *mem_ctx, builtin_available_predicate avail)\n" 285 "{\n", 286 ir->function_name()); 287 indentation++; 288 print_with_indent("ir_function_signature *const sig =\n"); 289 print_with_indent(" new(mem_ctx) ir_function_signature(glsl_type::%s_type, avail);\n", 290 ir->return_type->name); 291 292 print_with_indent("ir_factory body(&sig->body, mem_ctx);\n"); 293 print_with_indent("sig->is_defined = true;\n\n"); 294 295 if (!ir->parameters.is_empty()) 296 print_with_indent("exec_list sig_parameters;\n\n"); 297 298 return visit_continue; 299} 300 301ir_visitor_status 302ir_builder_print_visitor::visit_leave(ir_function_signature *ir) 303{ 304 if (!ir->parameters.is_empty()) 305 print_with_indent("sig->replace_parameters(&sig_parameters);\n"); 306 307 print_with_indent("return sig;\n"); 308 indentation--; 309 print_with_indent("}\n"); 310 return visit_continue; 311} 312 313void 314ir_builder_print_visitor::print_without_declaration(const ir_constant *ir) 315{ 316 if (ir->type->is_scalar()) { 317 switch (ir->type->base_type) { 318 case GLSL_TYPE_UINT: 319 print_without_indent("body.constant(%uu)", ir->value.u[0]); 320 return; 321 case GLSL_TYPE_INT: 322 print_without_indent("body.constant(int(%d))", ir->value.i[0]); 323 return; 324 case GLSL_TYPE_FLOAT: 325 print_without_indent("body.constant(%ff)", ir->value.f[0]); 326 return; 327 case GLSL_TYPE_BOOL: 328 print_without_indent("body.constant(%s)", 329 ir->value.i[0] != 0 ? "true" : "false"); 330 return; 331 default: 332 break; 333 } 334 } 335 336 ir_constant_data all_zero; 337 memset(&all_zero, 0, sizeof(all_zero)); 338 339 if (memcmp(&ir->value, &all_zero, sizeof(all_zero)) == 0) { 340 print_without_indent("ir_constant::zero(mem_ctx, glsl_type::%s_type)", 341 ir->type->name); 342 } 343} 344 345ir_visitor_status 346ir_builder_print_visitor::visit(ir_constant *ir) 347{ 348 const unsigned my_index = next_ir_index++; 349 350 _mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index); 351 352 if (ir->type == glsl_type::uint_type || 353 ir->type == glsl_type::int_type || 354 ir->type == glsl_type::float_type || 355 ir->type == glsl_type::bool_type) { 356 print_with_indent("ir_constant *const r%04X = ", my_index); 357 print_without_declaration(ir); 358 print_without_indent(";\n"); 359 return visit_continue; 360 } 361 362 ir_constant_data all_zero; 363 memset(&all_zero, 0, sizeof(all_zero)); 364 365 if (memcmp(&ir->value, &all_zero, sizeof(all_zero)) == 0) { 366 print_with_indent("ir_constant *const r%04X = ", my_index); 367 print_without_declaration(ir); 368 print_without_indent(";\n"); 369 } else { 370 print_with_indent("ir_constant_data r%04X_data;\n", my_index); 371 print_with_indent("memset(&r%04X_data, 0, sizeof(ir_constant_data));\n", 372 my_index); 373 for (unsigned i = 0; i < 16; i++) { 374 switch (ir->type->base_type) { 375 case GLSL_TYPE_UINT: 376 if (ir->value.u[i] != 0) 377 print_with_indent("r%04X_data.u[%u] = %u;\n", 378 my_index, i, ir->value.u[i]); 379 break; 380 case GLSL_TYPE_INT: 381 if (ir->value.i[i] != 0) 382 print_with_indent("r%04X_data.i[%u] = %i;\n", 383 my_index, i, ir->value.i[i]); 384 break; 385 case GLSL_TYPE_FLOAT: 386 if (ir->value.u[i] != 0) 387 print_with_indent("r%04X_data.u[%u] = 0x%08x; /* %f */\n", 388 my_index, 389 i, 390 ir->value.u[i], 391 ir->value.f[i]); 392 break; 393 case GLSL_TYPE_DOUBLE: { 394 uint64_t v; 395 396 STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); 397 398 memcpy(&v, &ir->value.d[i], sizeof(v)); 399 if (v != 0) 400 print_with_indent("r%04X_data.u64[%u] = 0x%016" PRIx64 "; /* %g */\n", 401 my_index, i, v, ir->value.d[i]); 402 break; 403 } 404 case GLSL_TYPE_UINT64: 405 if (ir->value.u64[i] != 0) 406 print_with_indent("r%04X_data.u64[%u] = %" PRIu64 ";\n", 407 my_index, 408 i, 409 ir->value.u64[i]); 410 break; 411 case GLSL_TYPE_INT64: 412 if (ir->value.i64[i] != 0) 413 print_with_indent("r%04X_data.i64[%u] = %" PRId64 ";\n", 414 my_index, 415 i, 416 ir->value.i64[i]); 417 break; 418 case GLSL_TYPE_BOOL: 419 if (ir->value.u[i] != 0) 420 print_with_indent("r%04X_data.u[%u] = 1;\n", my_index, i); 421 break; 422 default: 423 unreachable("Invalid constant type"); 424 } 425 } 426 427 print_with_indent("ir_constant *const r%04X = new(mem_ctx) ir_constant(glsl_type::%s_type, &r%04X_data);\n", 428 my_index, 429 ir->type->name, 430 my_index); 431 } 432 433 return visit_continue; 434} 435 436void 437ir_builder_print_visitor::print_without_declaration(const ir_swizzle *ir) 438{ 439 const struct hash_entry *const he = 440 _mesa_hash_table_search(index_map, ir->val); 441 442 if (ir->mask.num_components == 1) { 443 static const char swiz[4] = { 'x', 'y', 'z', 'w' }; 444 445 if (is_simple_operand(ir->val)) { 446 print_without_indent("swizzle_%c(", swiz[ir->mask.x]); 447 print_without_declaration(ir->val); 448 print_without_indent(")"); 449 } else { 450 assert(he); 451 print_without_indent("swizzle_%c(r%04X)", 452 swiz[ir->mask.x], 453 (unsigned)(uintptr_t) he->data); 454 } 455 } else { 456 static const char swiz[4] = { 'X', 'Y', 'Z', 'W' }; 457 458 assert(he); 459 print_without_indent("swizzle(r%04X, MAKE_SWIZZLE4(SWIZZLE_%c, SWIZZLE_%c, SWIZZLE_%c, SWIZZLE_%c), %u)", 460 (unsigned)(uintptr_t) he->data, 461 swiz[ir->mask.x], 462 swiz[ir->mask.y], 463 swiz[ir->mask.z], 464 swiz[ir->mask.w], 465 ir->mask.num_components); 466 } 467} 468 469ir_visitor_status 470ir_builder_print_visitor::visit_leave(ir_swizzle *ir) 471{ 472 const unsigned my_index = next_ir_index++; 473 474 _mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index); 475 476 print_with_indent("ir_swizzle *const r%04X = ", my_index); 477 print_without_declaration(ir); 478 print_without_indent(";\n"); 479 480 return visit_continue; 481} 482 483ir_visitor_status 484ir_builder_print_visitor::visit_enter(ir_assignment *ir) 485{ 486 ir_expression *const rhs_expr = ir->rhs->as_expression(); 487 488 if (!is_simple_operand(ir->rhs) && rhs_expr == NULL) 489 return visit_continue; 490 491 if (rhs_expr != NULL) { 492 const unsigned num_op = rhs_expr->num_operands; 493 494 for (unsigned i = 0; i < num_op; i++) { 495 if (is_simple_operand(rhs_expr->operands[i])) 496 continue; 497 498 rhs_expr->operands[i]->accept(this); 499 } 500 } 501 502 ir_visitor_status s; 503 504 this->in_assignee = true; 505 s = ir->lhs->accept(this); 506 this->in_assignee = false; 507 if (s != visit_continue) 508 return (s == visit_continue_with_parent) ? visit_continue : s; 509 510 assert(ir->condition == NULL); 511 512 const struct hash_entry *const he_lhs = 513 _mesa_hash_table_search(index_map, ir->lhs); 514 515 print_with_indent("body.emit(assign(r%04X, ", 516 (unsigned)(uintptr_t) he_lhs->data); 517 print_without_declaration(ir->rhs); 518 print_without_indent(", 0x%02x));\n\n", ir->write_mask); 519 520 return visit_continue_with_parent; 521} 522 523ir_visitor_status 524ir_builder_print_visitor::visit_leave(ir_assignment *ir) 525{ 526 const struct hash_entry *const he_lhs = 527 _mesa_hash_table_search(index_map, ir->lhs); 528 529 const struct hash_entry *const he_rhs = 530 _mesa_hash_table_search(index_map, ir->rhs); 531 532 assert(ir->condition == NULL); 533 assert(ir->lhs && ir->rhs); 534 535 print_with_indent("body.emit(assign(r%04X, r%04X, 0x%02x));\n\n", 536 (unsigned)(uintptr_t) he_lhs->data, 537 (unsigned)(uintptr_t) he_rhs->data, 538 ir->write_mask); 539 540 return visit_continue; 541} 542 543void 544ir_builder_print_visitor::print_without_declaration(const ir_expression *ir) 545{ 546 const unsigned num_op = ir->num_operands; 547 548 static const char *const arity[] = { 549 "", "unop", "binop", "triop", "quadop" 550 }; 551 552 switch (ir->operation) { 553 case ir_unop_neg: 554 case ir_binop_add: 555 case ir_binop_sub: 556 case ir_binop_mul: 557 case ir_binop_imul_high: 558 case ir_binop_less: 559 case ir_binop_gequal: 560 case ir_binop_equal: 561 case ir_binop_nequal: 562 case ir_binop_lshift: 563 case ir_binop_rshift: 564 case ir_binop_bit_and: 565 case ir_binop_bit_xor: 566 case ir_binop_bit_or: 567 case ir_binop_logic_and: 568 case ir_binop_logic_xor: 569 case ir_binop_logic_or: 570 print_without_indent("%s(", 571 ir_expression_operation_enum_strings[ir->operation]); 572 break; 573 default: 574 print_without_indent("expr(ir_%s_%s, ", 575 arity[num_op], 576 ir_expression_operation_enum_strings[ir->operation]); 577 break; 578 } 579 580 for (unsigned i = 0; i < num_op; i++) { 581 if (is_simple_operand(ir->operands[i])) 582 print_without_declaration(ir->operands[i]); 583 else { 584 const struct hash_entry *const he = 585 _mesa_hash_table_search(index_map, ir->operands[i]); 586 587 print_without_indent("r%04X", (unsigned)(uintptr_t) he->data); 588 } 589 590 if (i < num_op - 1) 591 print_without_indent(", "); 592 } 593 594 print_without_indent(")"); 595} 596 597ir_visitor_status 598ir_builder_print_visitor::visit_enter(ir_expression *ir) 599{ 600 const unsigned num_op = ir->num_operands; 601 602 for (unsigned i = 0; i < num_op; i++) { 603 if (is_simple_operand(ir->operands[i])) 604 continue; 605 606 ir->operands[i]->accept(this); 607 } 608 609 const unsigned my_index = next_ir_index++; 610 611 _mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index); 612 613 print_with_indent("ir_expression *const r%04X = ", my_index); 614 print_without_declaration(ir); 615 print_without_indent(";\n"); 616 617 return visit_continue_with_parent; 618} 619 620ir_visitor_status 621ir_builder_print_visitor::visit_enter(ir_if *ir) 622{ 623 const unsigned my_index = next_ir_index++; 624 625 print_with_indent("/* IF CONDITION */\n"); 626 627 ir_visitor_status s = ir->condition->accept(this); 628 if (s != visit_continue) 629 return (s == visit_continue_with_parent) ? visit_continue : s; 630 631 const struct hash_entry *const he = 632 _mesa_hash_table_search(index_map, ir->condition); 633 634 print_with_indent("ir_if *f%04X = new(mem_ctx) ir_if(operand(r%04X).val);\n", 635 my_index, 636 (unsigned)(uintptr_t) he->data); 637 print_with_indent("exec_list *const f%04X_parent_instructions = body.instructions;\n\n", 638 my_index); 639 640 indentation++; 641 print_with_indent("/* THEN INSTRUCTIONS */\n"); 642 print_with_indent("body.instructions = &f%04X->then_instructions;\n\n", 643 my_index); 644 645 if (s != visit_continue_with_parent) { 646 s = visit_list_elements(this, &ir->then_instructions); 647 if (s == visit_stop) 648 return s; 649 } 650 651 print_without_indent("\n"); 652 653 if (!ir->else_instructions.is_empty()) { 654 print_with_indent("/* ELSE INSTRUCTIONS */\n"); 655 print_with_indent("body.instructions = &f%04X->else_instructions;\n\n", 656 my_index); 657 658 if (s != visit_continue_with_parent) { 659 s = visit_list_elements(this, &ir->else_instructions); 660 if (s == visit_stop) 661 return s; 662 } 663 664 print_without_indent("\n"); 665 } 666 667 indentation--; 668 669 print_with_indent("body.instructions = f%04X_parent_instructions;\n", 670 my_index); 671 print_with_indent("body.emit(f%04X);\n\n", 672 my_index); 673 print_with_indent("/* END IF */\n\n"); 674 675 return visit_continue_with_parent; 676} 677 678ir_visitor_status 679ir_builder_print_visitor::visit_leave(ir_return *ir) 680{ 681 const struct hash_entry *const he = 682 _mesa_hash_table_search(index_map, ir->value); 683 684 print_with_indent("body.emit(ret(r%04X));\n\n", 685 (unsigned)(uintptr_t) he->data); 686 687 return visit_continue; 688} 689 690ir_visitor_status 691ir_builder_print_visitor::visit_enter(ir_texture *ir) 692{ 693 print_with_indent("\nUnsupported IR is encountered: texture functions are not supported. Exiting.\n"); 694 695 return visit_stop; 696} 697 698ir_visitor_status 699ir_builder_print_visitor::visit_leave(ir_call *ir) 700{ 701 const unsigned my_index = next_ir_index++; 702 703 print_without_indent("\n"); 704 print_with_indent("/* CALL %s */\n", ir->callee_name()); 705 print_with_indent("exec_list r%04X_parameters;\n", my_index); 706 707 foreach_in_list(ir_dereference_variable, param, &ir->actual_parameters) { 708 const struct hash_entry *const he = 709 _mesa_hash_table_search(index_map, param); 710 711 print_with_indent("r%04X_parameters.push_tail(operand(r%04X).val);\n", 712 my_index, 713 (unsigned)(uintptr_t) he->data); 714 } 715 716 char return_deref_string[32]; 717 if (ir->return_deref) { 718 const struct hash_entry *const he = 719 _mesa_hash_table_search(index_map, ir->return_deref); 720 721 snprintf(return_deref_string, sizeof(return_deref_string), 722 "operand(r%04X).val", (unsigned)(uintptr_t) he->data); 723 } else { 724 strcpy(return_deref_string, "NULL"); 725 } 726 727 print_with_indent("body.emit(new(mem_ctx) ir_call(shader->symbols->get_function(\"%s\"),\n", 728 ir->callee_name()); 729 print_with_indent(" %s, &r%04X_parameters);\n\n", 730 return_deref_string, 731 my_index); 732 return visit_continue; 733} 734 735ir_visitor_status 736ir_builder_print_visitor::visit_enter(ir_loop *ir) 737{ 738 const unsigned my_index = next_ir_index++; 739 740 _mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index); 741 742 print_with_indent("/* LOOP BEGIN */\n"); 743 print_with_indent("ir_loop *f%04X = new(mem_ctx) ir_loop();\n", my_index); 744 print_with_indent("exec_list *const f%04X_parent_instructions = body.instructions;\n\n", 745 my_index); 746 747 indentation++; 748 749 print_with_indent("body.instructions = &f%04X->body_instructions;\n\n", 750 my_index); 751 752 return visit_continue; 753} 754 755ir_visitor_status 756ir_builder_print_visitor::visit_leave(ir_loop *ir) 757{ 758 const struct hash_entry *const he = 759 _mesa_hash_table_search(index_map, ir); 760 761 indentation--; 762 763 print_with_indent("/* LOOP END */\n\n"); 764 print_with_indent("body.instructions = f%04X_parent_instructions;\n", 765 (unsigned)(uintptr_t) he->data); 766 print_with_indent("body.emit(f%04X);\n\n", 767 (unsigned)(uintptr_t) he->data); 768 769 return visit_continue; 770} 771 772ir_visitor_status 773ir_builder_print_visitor::visit(ir_loop_jump *ir) 774{ 775 print_with_indent("body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_%s));\n\n", 776 ir->is_break() ? "break" : "continue"); 777 return visit_continue; 778} 779