glsl/standalone: Enable ARB_gpu_shader_int64
[mesa.git] / src / compiler / glsl / ir_builder_print_visitor.cpp
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
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
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
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
148 ir_builder_print_visitor::~ir_builder_print_visitor()
149 {
150 _mesa_hash_table_destroy(index_map, NULL);
151 }
152
153 void ir_builder_print_visitor::indent(void)
154 {
155 for (int i = 0; i < indentation; i++)
156 fprintf(f, " ");
157 }
158
159 void
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
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
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
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
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
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
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
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
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
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 print_without_indent("r%04X_data.u64[%u] = 0x%016" PRIx64 "; /* %g */\n",
400 my_index, i, v, ir->value.d[i]);
401 break;
402 }
403 case GLSL_TYPE_UINT64:
404 if (ir->value.u64[i] != 0)
405 print_without_indent("r%04X_data.u64[%u] = %" PRIu64 ";\n",
406 my_index,
407 i,
408 ir->value.u64[i]);
409 break;
410 case GLSL_TYPE_INT64:
411 if (ir->value.i64[i] != 0)
412 print_without_indent("r%04X_data.i64[%u] = %" PRId64 ";\n",
413 my_index,
414 i,
415 ir->value.i64[i]);
416 break;
417 case GLSL_TYPE_BOOL:
418 if (ir->value.u[i] != 0)
419 print_without_indent("r%04X_data.u[%u] = 1;\n", my_index, i);
420 break;
421 default:
422 unreachable("Invalid constant type");
423 }
424 }
425
426 print_with_indent("ir_constant *const r%04X = new(mem_ctx) ir_constant(glsl_type::%s_type, &r%04X_data);\n",
427 my_index,
428 ir->type->name,
429 my_index);
430 }
431
432 return visit_continue;
433 }
434
435 void
436 ir_builder_print_visitor::print_without_declaration(const ir_swizzle *ir)
437 {
438 const struct hash_entry *const he =
439 _mesa_hash_table_search(index_map, ir->val);
440
441 if (ir->mask.num_components == 1) {
442 static const char swiz[4] = { 'x', 'y', 'z', 'w' };
443
444 if (is_simple_operand(ir->val)) {
445 print_without_indent("swizzle_%c(", swiz[ir->mask.x]);
446 print_without_declaration(ir->val);
447 print_without_indent(")");
448 } else {
449 print_without_indent("swizzle_%c(r%04X)",
450 swiz[ir->mask.x],
451 (unsigned)(uintptr_t) he->data);
452 }
453 } else {
454 static const char swiz[4] = { 'X', 'Y', 'Z', 'W' };
455
456 print_without_indent("swizzle(r%04X, MAKE_SWIZZLE4(SWIZZLE_%c, SWIZZLE_%c, SWIZZLE_%c, SWIZZLE_%c), %u)",
457 (unsigned)(uintptr_t) he->data,
458 swiz[ir->mask.x],
459 swiz[ir->mask.y],
460 swiz[ir->mask.z],
461 swiz[ir->mask.w],
462 ir->mask.num_components);
463 }
464 }
465
466 ir_visitor_status
467 ir_builder_print_visitor::visit_leave(ir_swizzle *ir)
468 {
469 const unsigned my_index = next_ir_index++;
470
471 _mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index);
472
473 print_with_indent("ir_swizzle *const r%04X = ", my_index);
474 print_without_declaration(ir);
475 print_without_indent(";\n");
476
477 return visit_continue;
478 }
479
480 ir_visitor_status
481 ir_builder_print_visitor::visit_enter(ir_assignment *ir)
482 {
483 ir_expression *const rhs_expr = ir->rhs->as_expression();
484
485 if (!is_simple_operand(ir->rhs) && rhs_expr == NULL)
486 return visit_continue;
487
488 if (rhs_expr != NULL) {
489 const unsigned num_op = rhs_expr->get_num_operands();
490
491 for (unsigned i = 0; i < num_op; i++) {
492 if (is_simple_operand(rhs_expr->operands[i]))
493 continue;
494
495 rhs_expr->operands[i]->accept(this);
496 }
497 }
498
499 ir_visitor_status s;
500
501 this->in_assignee = true;
502 s = ir->lhs->accept(this);
503 this->in_assignee = false;
504 if (s != visit_continue)
505 return (s == visit_continue_with_parent) ? visit_continue : s;
506
507 assert(ir->condition == NULL);
508
509 const struct hash_entry *const he_lhs =
510 _mesa_hash_table_search(index_map, ir->lhs);
511
512 print_with_indent("body.emit(assign(r%04X, ",
513 (unsigned)(uintptr_t) he_lhs->data);
514 print_without_declaration(ir->rhs);
515 print_without_indent(", 0x%02x));\n\n", ir->write_mask);
516
517 return visit_continue_with_parent;
518 }
519
520 ir_visitor_status
521 ir_builder_print_visitor::visit_leave(ir_assignment *ir)
522 {
523 const struct hash_entry *const he_lhs =
524 _mesa_hash_table_search(index_map, ir->lhs);
525
526 const struct hash_entry *const he_rhs =
527 _mesa_hash_table_search(index_map, ir->rhs);
528
529 assert(ir->condition == NULL);
530
531 print_with_indent("body.emit(assign(r%04X, r%04X, 0x%02x));\n\n",
532 (unsigned)(uintptr_t) he_lhs->data,
533 (unsigned)(uintptr_t) he_rhs->data,
534 ir->write_mask);
535
536 return visit_continue;
537 }
538
539 void
540 ir_builder_print_visitor::print_without_declaration(const ir_expression *ir)
541 {
542 const unsigned num_op = ir->get_num_operands();
543
544 static const char *const arity[] = {
545 "", "unop", "binop", "triop", "quadop"
546 };
547
548 switch (ir->operation) {
549 case ir_unop_neg:
550 case ir_binop_add:
551 case ir_binop_sub:
552 case ir_binop_mul:
553 case ir_binop_imul_high:
554 case ir_binop_less:
555 case ir_binop_greater:
556 case ir_binop_lequal:
557 case ir_binop_gequal:
558 case ir_binop_equal:
559 case ir_binop_nequal:
560 case ir_binop_lshift:
561 case ir_binop_rshift:
562 case ir_binop_bit_and:
563 case ir_binop_bit_xor:
564 case ir_binop_bit_or:
565 case ir_binop_logic_and:
566 case ir_binop_logic_xor:
567 case ir_binop_logic_or:
568 print_without_indent("%s(",
569 ir_expression_operation_enum_strings[ir->operation]);
570 break;
571 default:
572 print_without_indent("expr(ir_%s_%s, ",
573 arity[num_op],
574 ir_expression_operation_enum_strings[ir->operation]);
575 break;
576 }
577
578 for (unsigned i = 0; i < num_op; i++) {
579 if (is_simple_operand(ir->operands[i]))
580 print_without_declaration(ir->operands[i]);
581 else {
582 const struct hash_entry *const he =
583 _mesa_hash_table_search(index_map, ir->operands[i]);
584
585 print_without_indent("r%04X", (unsigned)(uintptr_t) he->data);
586 }
587
588 if (i < num_op - 1)
589 print_without_indent(", ");
590 }
591
592 print_without_indent(")");
593 }
594
595 ir_visitor_status
596 ir_builder_print_visitor::visit_enter(ir_expression *ir)
597 {
598 const unsigned num_op = ir->get_num_operands();
599
600 for (unsigned i = 0; i < num_op; i++) {
601 if (is_simple_operand(ir->operands[i]))
602 continue;
603
604 ir->operands[i]->accept(this);
605 }
606
607 const unsigned my_index = next_ir_index++;
608
609 _mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index);
610
611 print_with_indent("ir_expression *const r%04X = ", my_index);
612 print_without_declaration(ir);
613 print_without_indent(";\n");
614
615 return visit_continue_with_parent;
616 }
617
618 ir_visitor_status
619 ir_builder_print_visitor::visit_enter(ir_if *ir)
620 {
621 const unsigned my_index = next_ir_index++;
622
623 print_with_indent("/* IF CONDITION */\n");
624
625 ir_visitor_status s = ir->condition->accept(this);
626 if (s != visit_continue)
627 return (s == visit_continue_with_parent) ? visit_continue : s;
628
629 const struct hash_entry *const he =
630 _mesa_hash_table_search(index_map, ir->condition);
631
632 print_with_indent("ir_if *f%04X = new(mem_ctx) ir_if(operand(r%04X).val);\n",
633 my_index,
634 (unsigned)(uintptr_t) he->data);
635 print_with_indent("exec_list *const f%04X_parent_instructions = body.instructions;\n\n",
636 my_index);
637
638 indentation++;
639 print_with_indent("/* THEN INSTRUCTIONS */\n");
640 print_with_indent("body.instructions = &f%04X->then_instructions;\n\n",
641 my_index);
642
643 if (s != visit_continue_with_parent) {
644 s = visit_list_elements(this, &ir->then_instructions);
645 if (s == visit_stop)
646 return s;
647 }
648
649 print_without_indent("\n");
650
651 if (!ir->else_instructions.is_empty()) {
652 print_with_indent("/* ELSE INSTRUCTIONS */\n");
653 print_with_indent("body.instructions = &f%04X->else_instructions;\n\n",
654 my_index);
655
656 if (s != visit_continue_with_parent) {
657 s = visit_list_elements(this, &ir->else_instructions);
658 if (s == visit_stop)
659 return s;
660 }
661
662 print_without_indent("\n");
663 }
664
665 indentation--;
666
667 print_with_indent("body.instructions = f%04X_parent_instructions;\n",
668 my_index);
669 print_with_indent("body.emit(f%04X);\n\n",
670 my_index);
671 print_with_indent("/* END IF */\n\n");
672
673 return visit_continue_with_parent;
674 }
675
676 ir_visitor_status
677 ir_builder_print_visitor::visit_leave(ir_return *ir)
678 {
679 const struct hash_entry *const he =
680 _mesa_hash_table_search(index_map, ir->value);
681
682 print_with_indent("body.emit(ret(r%04X));\n\n",
683 (unsigned)(uintptr_t) he->data);
684
685 return visit_continue;
686 }
687
688 ir_visitor_status
689 ir_builder_print_visitor::visit_leave(ir_call *ir)
690 {
691 const unsigned my_index = next_ir_index++;
692
693 print_without_indent("\n");
694 print_with_indent("/* CALL %s */\n", ir->callee_name());
695 print_with_indent("exec_list r%04X_parameters;\n", my_index);
696
697 foreach_in_list(ir_dereference_variable, param, &ir->actual_parameters) {
698 const struct hash_entry *const he =
699 _mesa_hash_table_search(index_map, param);
700
701 print_with_indent("r%04X_parameters.push_tail(operand(r%04X).val);\n",
702 my_index,
703 (unsigned)(uintptr_t) he->data);
704 }
705
706 char return_deref_string[32];
707 if (ir->return_deref) {
708 const struct hash_entry *const he =
709 _mesa_hash_table_search(index_map, ir->return_deref);
710
711 snprintf(return_deref_string, sizeof(return_deref_string),
712 "operand(r%04X).val",
713 (unsigned)(uintptr_t) he->data);
714 } else {
715 strcpy(return_deref_string, "NULL");
716 }
717
718 print_with_indent("body.emit(new(mem_ctx) ir_call(shader->symbols->get_function(\"%s\"),\n",
719 ir->callee_name());
720 print_with_indent(" %s, &r%04X_parameters);\n\n",
721 return_deref_string,
722 my_index);
723 return visit_continue;
724 }
725
726 ir_visitor_status
727 ir_builder_print_visitor::visit_enter(ir_loop *ir)
728 {
729 const unsigned my_index = next_ir_index++;
730
731 _mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index);
732
733 print_with_indent("/* LOOP BEGIN */\n");
734 print_with_indent("ir_loop *f%04X = new(mem_ctx) ir_loop();\n", my_index);
735 print_with_indent("exec_list *const f%04X_parent_instructions = body.instructions;\n\n",
736 my_index);
737
738 indentation++;
739
740 print_with_indent("body.instructions = &f%04X->body_instructions;\n\n",
741 my_index);
742
743 return visit_continue;
744 }
745
746 ir_visitor_status
747 ir_builder_print_visitor::visit_leave(ir_loop *ir)
748 {
749 const struct hash_entry *const he =
750 _mesa_hash_table_search(index_map, ir);
751
752 indentation--;
753
754 print_with_indent("/* LOOP END */\n\n");
755 print_with_indent("body.instructions = f%04X_parent_instructions;\n",
756 (unsigned)(uintptr_t) he->data);
757 print_with_indent("body.emit(f%04X);\n\n",
758 (unsigned)(uintptr_t) he->data);
759
760 return visit_continue;
761 }
762
763 ir_visitor_status
764 ir_builder_print_visitor::visit(ir_loop_jump *ir)
765 {
766 print_with_indent("body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_%s));\n\n",
767 ir->is_break() ? "break" : "continue");
768 return visit_continue;
769 }