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