• 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 #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 
33 class ir_builder_print_visitor : public ir_hierarchical_visitor {
34 public:
35    ir_builder_print_visitor(FILE *f);
36    virtual ~ir_builder_print_visitor();
37 
38    void indent(void);
39 
40    virtual ir_visitor_status visit(class ir_variable *);
41    virtual ir_visitor_status visit(class ir_dereference_variable *);
42    virtual ir_visitor_status visit(class ir_constant *);
43    virtual ir_visitor_status visit(class ir_loop_jump *);
44 
45    virtual ir_visitor_status visit_enter(class ir_if *);
46 
47    virtual ir_visitor_status visit_enter(class ir_loop *);
48    virtual ir_visitor_status visit_leave(class ir_loop *);
49 
50    virtual ir_visitor_status visit_enter(class ir_function_signature *);
51    virtual ir_visitor_status visit_leave(class ir_function_signature *);
52 
53    virtual ir_visitor_status visit_enter(class ir_expression *);
54 
55    virtual ir_visitor_status visit_enter(class ir_assignment *);
56    virtual ir_visitor_status visit_leave(class ir_assignment *);
57 
58    virtual ir_visitor_status visit_leave(class ir_call *);
59    virtual ir_visitor_status visit_leave(class ir_swizzle *);
60    virtual ir_visitor_status visit_leave(class ir_return *);
61 
62 private:
63    void print_with_indent(const char *fmt, ...);
64    void print_without_indent(const char *fmt, ...);
65 
66    void print_without_declaration(const ir_rvalue *ir);
67    void print_without_declaration(const ir_constant *ir);
68    void print_without_declaration(const ir_dereference_variable *ir);
69    void print_without_declaration(const ir_swizzle *ir);
70    void print_without_declaration(const ir_expression *ir);
71 
72    unsigned next_ir_index;
73 
74    /**
75     * Mapping from ir_instruction * -> index used in the generated C code
76     * variable name.
77     */
78    hash_table *index_map;
79 
80    FILE *f;
81 
82    int indentation;
83 };
84 
85 /* An operand is "simple" if it can be compactly printed on one line.
86  */
87 static bool
is_simple_operand(const ir_rvalue * ir,unsigned depth=1)88 is_simple_operand(const ir_rvalue *ir, unsigned depth = 1)
89 {
90    if (depth == 0)
91       return false;
92 
93    switch (ir->ir_type) {
94    case ir_type_dereference_variable:
95       return true;
96 
97    case ir_type_constant: {
98       if (ir->type == glsl_type::uint_type ||
99           ir->type == glsl_type::int_type ||
100           ir->type == glsl_type::float_type ||
101           ir->type == glsl_type::bool_type)
102          return true;
103 
104       const ir_constant *const c = (ir_constant *) ir;
105       ir_constant_data all_zero;
106       memset(&all_zero, 0, sizeof(all_zero));
107 
108       return memcmp(&c->value, &all_zero, sizeof(all_zero)) == 0;
109    }
110 
111    case ir_type_swizzle: {
112       const ir_swizzle *swiz = (ir_swizzle *) ir;
113       return swiz->mask.num_components == 1 &&
114              is_simple_operand(swiz->val, depth);
115    }
116 
117    case ir_type_expression: {
118       const ir_expression *expr = (ir_expression *) ir;
119 
120       for (unsigned i = 0; i < expr->num_operands; i++) {
121          if (!is_simple_operand(expr->operands[i], depth - 1))
122             return false;
123       }
124 
125       return true;
126    }
127 
128    default:
129       return false;
130    }
131 }
132 
133 void
_mesa_print_builder_for_ir(FILE * f,exec_list * instructions)134 _mesa_print_builder_for_ir(FILE *f, exec_list *instructions)
135 {
136    ir_builder_print_visitor v(f);
137    v.run(instructions);
138 }
139 
ir_builder_print_visitor(FILE * f)140 ir_builder_print_visitor::ir_builder_print_visitor(FILE *f)
141    : next_ir_index(1), f(f), indentation(0)
142 {
143    index_map =
144       _mesa_hash_table_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal);
145 }
146 
~ir_builder_print_visitor()147 ir_builder_print_visitor::~ir_builder_print_visitor()
148 {
149    _mesa_hash_table_destroy(index_map, NULL);
150 }
151 
indent(void)152 void ir_builder_print_visitor::indent(void)
153 {
154    for (int i = 0; i < indentation; i++)
155       fprintf(f, "   ");
156 }
157 
158 void
print_with_indent(const char * fmt,...)159 ir_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 
170 void
print_without_indent(const char * fmt,...)171 ir_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 
180 void
print_without_declaration(const ir_rvalue * ir)181 ir_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 
201 ir_visitor_status
visit(ir_variable * ir)202 ir_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 
254 void
print_without_declaration(const ir_dereference_variable * ir)255 ir_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 
263 ir_visitor_status
visit(ir_dereference_variable * ir)264 ir_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 
275 ir_visitor_status
visit_enter(ir_function_signature * ir)276 ir_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 
299 ir_visitor_status
visit_leave(ir_function_signature * ir)300 ir_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 
311 void
print_without_declaration(const ir_constant * ir)312 ir_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 
343 ir_visitor_status
visit(ir_constant * ir)344 ir_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 
434 void
print_without_declaration(const ir_swizzle * ir)435 ir_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 
465 ir_visitor_status
visit_leave(ir_swizzle * ir)466 ir_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 
479 ir_visitor_status
visit_enter(ir_assignment * ir)480 ir_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 
519 ir_visitor_status
visit_leave(ir_assignment * ir)520 ir_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 
538 void
print_without_declaration(const ir_expression * ir)539 ir_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 
592 ir_visitor_status
visit_enter(ir_expression * ir)593 ir_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 
615 ir_visitor_status
visit_enter(ir_if * ir)616 ir_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 
673 ir_visitor_status
visit_leave(ir_return * ir)674 ir_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 
685 ir_visitor_status
visit_leave(ir_call * ir)686 ir_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       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 
723 ir_visitor_status
visit_enter(ir_loop * ir)724 ir_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 
743 ir_visitor_status
visit_leave(ir_loop * ir)744 ir_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 
760 ir_visitor_status
visit(ir_loop_jump * ir)761 ir_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