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