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