2 * Copyright © 2016 Intel Corporation
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:
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
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.
24 #include <inttypes.h> /* for PRIx64 macro */
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"
34 class ir_builder_print_visitor
: public ir_hierarchical_visitor
{
36 ir_builder_print_visitor(FILE *f
);
37 virtual ~ir_builder_print_visitor();
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
*);
46 virtual ir_visitor_status
visit_enter(class ir_if
*);
48 virtual ir_visitor_status
visit_enter(class ir_loop
*);
49 virtual ir_visitor_status
visit_leave(class ir_loop
*);
51 virtual ir_visitor_status
visit_enter(class ir_function_signature
*);
52 virtual ir_visitor_status
visit_leave(class ir_function_signature
*);
54 virtual ir_visitor_status
visit_enter(class ir_expression
*);
56 virtual ir_visitor_status
visit_enter(class ir_assignment
*);
57 virtual ir_visitor_status
visit_leave(class ir_assignment
*);
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
*);
63 virtual ir_visitor_status
visit_enter(ir_texture
*ir
);
66 void print_with_indent(const char *fmt
, ...);
67 void print_without_indent(const char *fmt
, ...);
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
);
75 unsigned next_ir_index
;
78 * Mapping from ir_instruction * -> index used in the generated C code
81 hash_table
*index_map
;
88 /* An operand is "simple" if it can be compactly printed on one line.
91 is_simple_operand(const ir_rvalue
*ir
, unsigned depth
= 1)
96 switch (ir
->ir_type
) {
97 case ir_type_dereference_variable
:
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
)
107 const ir_constant
*const c
= (ir_constant
*) ir
;
108 ir_constant_data all_zero
;
109 memset(&all_zero
, 0, sizeof(all_zero
));
111 return memcmp(&c
->value
, &all_zero
, sizeof(all_zero
)) == 0;
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
);
120 case ir_type_expression
: {
121 const ir_expression
*expr
= (ir_expression
*) ir
;
123 for (unsigned i
= 0; i
< expr
->num_operands
; i
++) {
124 if (!is_simple_operand(expr
->operands
[i
], depth
- 1))
137 _mesa_print_builder_for_ir(FILE *f
, exec_list
*instructions
)
139 ir_builder_print_visitor
v(f
);
143 ir_builder_print_visitor::ir_builder_print_visitor(FILE *f
)
144 : next_ir_index(1), f(f
), indentation(0)
146 index_map
= _mesa_pointer_hash_table_create(NULL
);
149 ir_builder_print_visitor::~ir_builder_print_visitor()
151 _mesa_hash_table_destroy(index_map
, NULL
);
154 void ir_builder_print_visitor::indent(void)
156 for (int i
= 0; i
< indentation
; i
++)
161 ir_builder_print_visitor::print_with_indent(const char *fmt
, ...)
168 vfprintf(f
, fmt
, ap
);
173 ir_builder_print_visitor::print_without_indent(const char *fmt
, ...)
178 vfprintf(f
, fmt
, ap
);
183 ir_builder_print_visitor::print_without_declaration(const ir_rvalue
*ir
)
185 switch (ir
->ir_type
) {
186 case ir_type_dereference_variable
:
187 print_without_declaration((ir_dereference_variable
*) ir
);
189 case ir_type_constant
:
190 print_without_declaration((ir_constant
*) ir
);
192 case ir_type_swizzle
:
193 print_without_declaration((ir_swizzle
*) ir
);
195 case ir_type_expression
:
196 print_without_declaration((ir_expression
*) ir
);
199 unreachable("Invalid IR type.");
204 ir_builder_print_visitor::visit(ir_variable
*ir
)
206 const unsigned my_index
= next_ir_index
++;
208 _mesa_hash_table_insert(index_map
, ir
, (void *)(uintptr_t) my_index
);
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;
225 unreachable("Invalid variable mode");
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",
234 print_with_indent("ir_variable *const r%04X = new(mem_ctx) ir_variable(glsl_type::%s_type, \"%s\", %s);\n",
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
);
248 print_with_indent("body.emit(r%04X);\n", my_index
);
253 return visit_continue
;
257 ir_builder_print_visitor::print_without_declaration(const ir_dereference_variable
*ir
)
259 const struct hash_entry
*const he
=
260 _mesa_hash_table_search(index_map
, ir
->var
);
262 print_without_indent("r%04X", (unsigned)(uintptr_t) he
->data
);
266 ir_builder_print_visitor::visit(ir_dereference_variable
*ir
)
268 const struct hash_entry
*const he
=
269 _mesa_hash_table_search(index_map
, ir
->var
);
272 _mesa_hash_table_insert(index_map
, ir
, he
->data
);
274 return visit_continue
;
278 ir_builder_print_visitor::visit_enter(ir_function_signature
*ir
)
281 return visit_continue_with_parent
;
283 print_with_indent("ir_function_signature *\n"
284 "%s(void *mem_ctx, builtin_available_predicate avail)\n"
286 ir
->function_name());
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
);
292 print_with_indent("ir_factory body(&sig->body, mem_ctx);\n");
293 print_with_indent("sig->is_defined = true;\n\n");
295 if (!ir
->parameters
.is_empty())
296 print_with_indent("exec_list sig_parameters;\n\n");
298 return visit_continue
;
302 ir_builder_print_visitor::visit_leave(ir_function_signature
*ir
)
304 if (!ir
->parameters
.is_empty())
305 print_with_indent("sig->replace_parameters(&sig_parameters);\n");
307 print_with_indent("return sig;\n");
309 print_with_indent("}\n");
310 return visit_continue
;
314 ir_builder_print_visitor::print_without_declaration(const ir_constant
*ir
)
316 if (ir
->type
->is_scalar()) {
317 switch (ir
->type
->base_type
) {
319 print_without_indent("body.constant(%uu)", ir
->value
.u
[0]);
322 print_without_indent("body.constant(int(%d))", ir
->value
.i
[0]);
324 case GLSL_TYPE_FLOAT
:
325 print_without_indent("body.constant(%ff)", ir
->value
.f
[0]);
328 print_without_indent("body.constant(%s)",
329 ir
->value
.i
[0] != 0 ? "true" : "false");
336 ir_constant_data all_zero
;
337 memset(&all_zero
, 0, sizeof(all_zero
));
339 if (memcmp(&ir
->value
, &all_zero
, sizeof(all_zero
)) == 0) {
340 print_without_indent("ir_constant::zero(mem_ctx, glsl_type::%s_type)",
346 ir_builder_print_visitor::visit(ir_constant
*ir
)
348 const unsigned my_index
= next_ir_index
++;
350 _mesa_hash_table_insert(index_map
, ir
, (void *)(uintptr_t) my_index
);
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
;
362 ir_constant_data all_zero
;
363 memset(&all_zero
, 0, sizeof(all_zero
));
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");
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",
373 for (unsigned i
= 0; i
< 16; i
++) {
374 switch (ir
->type
->base_type
) {
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
]);
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
]);
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",
393 case GLSL_TYPE_DOUBLE
: {
396 STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
398 memcpy(&v
, &ir
->value
.d
[i
], sizeof(v
));
400 print_with_indent("r%04X_data.u64[%u] = 0x%016" PRIx64
"; /* %g */\n",
401 my_index
, i
, v
, ir
->value
.d
[i
]);
404 case GLSL_TYPE_UINT64
:
405 if (ir
->value
.u64
[i
] != 0)
406 print_with_indent("r%04X_data.u64[%u] = %" PRIu64
";\n",
411 case GLSL_TYPE_INT64
:
412 if (ir
->value
.i64
[i
] != 0)
413 print_with_indent("r%04X_data.i64[%u] = %" PRId64
";\n",
419 if (ir
->value
.u
[i
] != 0)
420 print_with_indent("r%04X_data.u[%u] = 1;\n", my_index
, i
);
423 unreachable("Invalid constant type");
427 print_with_indent("ir_constant *const r%04X = new(mem_ctx) ir_constant(glsl_type::%s_type, &r%04X_data);\n",
433 return visit_continue
;
437 ir_builder_print_visitor::print_without_declaration(const ir_swizzle
*ir
)
439 const struct hash_entry
*const he
=
440 _mesa_hash_table_search(index_map
, ir
->val
);
442 if (ir
->mask
.num_components
== 1) {
443 static const char swiz
[4] = { 'x', 'y', 'z', 'w' };
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(")");
451 print_without_indent("swizzle_%c(r%04X)",
453 (unsigned)(uintptr_t) he
->data
);
456 static const char swiz
[4] = { 'X', 'Y', 'Z', 'W' };
459 print_without_indent("swizzle(r%04X, MAKE_SWIZZLE4(SWIZZLE_%c, SWIZZLE_%c, SWIZZLE_%c, SWIZZLE_%c), %u)",
460 (unsigned)(uintptr_t) he
->data
,
465 ir
->mask
.num_components
);
470 ir_builder_print_visitor::visit_leave(ir_swizzle
*ir
)
472 const unsigned my_index
= next_ir_index
++;
474 _mesa_hash_table_insert(index_map
, ir
, (void *)(uintptr_t) my_index
);
476 print_with_indent("ir_swizzle *const r%04X = ", my_index
);
477 print_without_declaration(ir
);
478 print_without_indent(";\n");
480 return visit_continue
;
484 ir_builder_print_visitor::visit_enter(ir_assignment
*ir
)
486 ir_expression
*const rhs_expr
= ir
->rhs
->as_expression();
488 if (!is_simple_operand(ir
->rhs
) && rhs_expr
== NULL
)
489 return visit_continue
;
491 if (rhs_expr
!= NULL
) {
492 const unsigned num_op
= rhs_expr
->num_operands
;
494 for (unsigned i
= 0; i
< num_op
; i
++) {
495 if (is_simple_operand(rhs_expr
->operands
[i
]))
498 rhs_expr
->operands
[i
]->accept(this);
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
;
510 assert(ir
->condition
== NULL
);
512 const struct hash_entry
*const he_lhs
=
513 _mesa_hash_table_search(index_map
, ir
->lhs
);
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
);
520 return visit_continue_with_parent
;
524 ir_builder_print_visitor::visit_leave(ir_assignment
*ir
)
526 const struct hash_entry
*const he_lhs
=
527 _mesa_hash_table_search(index_map
, ir
->lhs
);
529 const struct hash_entry
*const he_rhs
=
530 _mesa_hash_table_search(index_map
, ir
->rhs
);
532 assert(ir
->condition
== NULL
);
533 assert(ir
->lhs
&& ir
->rhs
);
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
,
540 return visit_continue
;
544 ir_builder_print_visitor::print_without_declaration(const ir_expression
*ir
)
546 const unsigned num_op
= ir
->num_operands
;
548 static const char *const arity
[] = {
549 "", "unop", "binop", "triop", "quadop"
552 switch (ir
->operation
) {
557 case ir_binop_imul_high
:
559 case ir_binop_gequal
:
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
]);
574 print_without_indent("expr(ir_%s_%s, ",
576 ir_expression_operation_enum_strings
[ir
->operation
]);
580 for (unsigned i
= 0; i
< num_op
; i
++) {
581 if (is_simple_operand(ir
->operands
[i
]))
582 print_without_declaration(ir
->operands
[i
]);
584 const struct hash_entry
*const he
=
585 _mesa_hash_table_search(index_map
, ir
->operands
[i
]);
587 print_without_indent("r%04X", (unsigned)(uintptr_t) he
->data
);
591 print_without_indent(", ");
594 print_without_indent(")");
598 ir_builder_print_visitor::visit_enter(ir_expression
*ir
)
600 const unsigned num_op
= ir
->num_operands
;
602 for (unsigned i
= 0; i
< num_op
; i
++) {
603 if (is_simple_operand(ir
->operands
[i
]))
606 ir
->operands
[i
]->accept(this);
609 const unsigned my_index
= next_ir_index
++;
611 _mesa_hash_table_insert(index_map
, ir
, (void *)(uintptr_t) my_index
);
613 print_with_indent("ir_expression *const r%04X = ", my_index
);
614 print_without_declaration(ir
);
615 print_without_indent(";\n");
617 return visit_continue_with_parent
;
621 ir_builder_print_visitor::visit_enter(ir_if
*ir
)
623 const unsigned my_index
= next_ir_index
++;
625 print_with_indent("/* IF CONDITION */\n");
627 ir_visitor_status s
= ir
->condition
->accept(this);
628 if (s
!= visit_continue
)
629 return (s
== visit_continue_with_parent
) ? visit_continue
: s
;
631 const struct hash_entry
*const he
=
632 _mesa_hash_table_search(index_map
, ir
->condition
);
634 print_with_indent("ir_if *f%04X = new(mem_ctx) ir_if(operand(r%04X).val);\n",
636 (unsigned)(uintptr_t) he
->data
);
637 print_with_indent("exec_list *const f%04X_parent_instructions = body.instructions;\n\n",
641 print_with_indent("/* THEN INSTRUCTIONS */\n");
642 print_with_indent("body.instructions = &f%04X->then_instructions;\n\n",
645 if (s
!= visit_continue_with_parent
) {
646 s
= visit_list_elements(this, &ir
->then_instructions
);
651 print_without_indent("\n");
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",
658 if (s
!= visit_continue_with_parent
) {
659 s
= visit_list_elements(this, &ir
->else_instructions
);
664 print_without_indent("\n");
669 print_with_indent("body.instructions = f%04X_parent_instructions;\n",
671 print_with_indent("body.emit(f%04X);\n\n",
673 print_with_indent("/* END IF */\n\n");
675 return visit_continue_with_parent
;
679 ir_builder_print_visitor::visit_leave(ir_return
*ir
)
681 const struct hash_entry
*const he
=
682 _mesa_hash_table_search(index_map
, ir
->value
);
684 print_with_indent("body.emit(ret(r%04X));\n\n",
685 (unsigned)(uintptr_t) he
->data
);
687 return visit_continue
;
691 ir_builder_print_visitor::visit_enter(ir_texture
*ir
)
693 print_with_indent("\nUnsupported IR is encountered: texture functions are not supported. Exiting.\n");
699 ir_builder_print_visitor::visit_leave(ir_call
*ir
)
701 const unsigned my_index
= next_ir_index
++;
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
);
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
);
711 print_with_indent("r%04X_parameters.push_tail(operand(r%04X).val);\n",
713 (unsigned)(uintptr_t) he
->data
);
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
);
721 snprintf(return_deref_string
, sizeof(return_deref_string
),
722 "operand(r%04X).val", (unsigned)(uintptr_t) he
->data
);
724 strcpy(return_deref_string
, "NULL");
727 print_with_indent("body.emit(new(mem_ctx) ir_call(shader->symbols->get_function(\"%s\"),\n",
729 print_with_indent(" %s, &r%04X_parameters);\n\n",
732 return visit_continue
;
736 ir_builder_print_visitor::visit_enter(ir_loop
*ir
)
738 const unsigned my_index
= next_ir_index
++;
740 _mesa_hash_table_insert(index_map
, ir
, (void *)(uintptr_t) my_index
);
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",
749 print_with_indent("body.instructions = &f%04X->body_instructions;\n\n",
752 return visit_continue
;
756 ir_builder_print_visitor::visit_leave(ir_loop
*ir
)
758 const struct hash_entry
*const he
=
759 _mesa_hash_table_search(index_map
, ir
);
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
);
769 return visit_continue
;
773 ir_builder_print_visitor::visit(ir_loop_jump
*ir
)
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
;