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