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