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