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