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