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    virtual ir_visitor_status visit_enter(ir_texture *ir);
64 
65 private:
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  */
90 static bool
is_simple_operand(const ir_rvalue * ir,unsigned depth=1)91 is_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 
136 void
_mesa_print_builder_for_ir(FILE * f,exec_list * instructions)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 
ir_builder_print_visitor(FILE * f)143 ir_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 
~ir_builder_print_visitor()149 ir_builder_print_visitor::~ir_builder_print_visitor()
150 {
151    _mesa_hash_table_destroy(index_map, NULL);
152 }
153 
indent(void)154 void ir_builder_print_visitor::indent(void)
155 {
156    for (int i = 0; i < indentation; i++)
157       fprintf(f, "   ");
158 }
159 
160 void
print_with_indent(const char * fmt,...)161 ir_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 
172 void
print_without_indent(const char * fmt,...)173 ir_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 
182 void
print_without_declaration(const ir_rvalue * ir)183 ir_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 
203 ir_visitor_status
visit(ir_variable * ir)204 ir_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 
256 void
print_without_declaration(const ir_dereference_variable * ir)257 ir_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 
265 ir_visitor_status
visit(ir_dereference_variable * ir)266 ir_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 
277 ir_visitor_status
visit_enter(ir_function_signature * ir)278 ir_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 
301 ir_visitor_status
visit_leave(ir_function_signature * ir)302 ir_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 
313 void
print_without_declaration(const ir_constant * ir)314 ir_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 
345 ir_visitor_status
visit(ir_constant * ir)346 ir_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 
436 void
print_without_declaration(const ir_swizzle * ir)437 ir_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 
469 ir_visitor_status
visit_leave(ir_swizzle * ir)470 ir_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 
483 ir_visitor_status
visit_enter(ir_assignment * ir)484 ir_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 
523 ir_visitor_status
visit_leave(ir_assignment * ir)524 ir_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 
543 void
print_without_declaration(const ir_expression * ir)544 ir_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 
597 ir_visitor_status
visit_enter(ir_expression * ir)598 ir_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 
620 ir_visitor_status
visit_enter(ir_if * ir)621 ir_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 
678 ir_visitor_status
visit_leave(ir_return * ir)679 ir_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 
690 ir_visitor_status
visit_enter(ir_texture * ir)691 ir_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 
698 ir_visitor_status
visit_leave(ir_call * ir)699 ir_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 
735 ir_visitor_status
visit_enter(ir_loop * ir)736 ir_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 
755 ir_visitor_status
visit_leave(ir_loop * ir)756 ir_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 
772 ir_visitor_status
visit(ir_loop_jump * ir)773 ir_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