xref: /aosp_15_r20/external/mesa3d/src/compiler/glsl/ir_print_visitor.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2010 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_print_visitor.h"
26 #include "linker_util.h"
27 #include "compiler/glsl_types.h"
28 #include "glsl_parser_extras.h"
29 #include "main/macros.h"
30 #include "util/hash_table.h"
31 #include "util/u_string.h"
32 #include "util/half_float.h"
33 
34 void
print(void) const35 ir_instruction::print(void) const
36 {
37    this->fprint(stdout);
38 }
39 
40 void
fprint(FILE * f) const41 ir_instruction::fprint(FILE *f) const
42 {
43    ir_instruction *deconsted = const_cast<ir_instruction *>(this);
44 
45    ir_print_visitor v(f);
46    deconsted->accept(&v);
47 }
48 
49 static void
glsl_print_type(FILE * f,const glsl_type * t)50 glsl_print_type(FILE *f, const glsl_type *t)
51 {
52    if (glsl_type_is_array(t)) {
53       fprintf(f, "(array ");
54       glsl_print_type(f, t->fields.array);
55       fprintf(f, " %u)", t->length);
56    } else if (glsl_type_is_struct(t) && !is_gl_identifier(glsl_get_type_name(t))) {
57       fprintf(f, "%s@%p", glsl_get_type_name(t), (void *) t);
58    } else {
59       fprintf(f, "%s", glsl_get_type_name(t));
60    }
61 }
62 
63 extern "C" {
64 void
_mesa_print_ir(FILE * f,exec_list * instructions,struct _mesa_glsl_parse_state * state)65 _mesa_print_ir(FILE *f, exec_list *instructions,
66 	       struct _mesa_glsl_parse_state *state)
67 {
68    if (state) {
69       for (unsigned i = 0; i < state->num_user_structures; i++) {
70 	 const glsl_type *const s = state->user_structures[i];
71 
72 	 fprintf(f, "(structure (%s) (%s@%p) (%u) (\n",
73                  glsl_get_type_name(s), glsl_get_type_name(s), (void *) s, s->length);
74 
75 	 for (unsigned j = 0; j < s->length; j++) {
76 	    fprintf(f, "\t((");
77 	    glsl_print_type(f, s->fields.structure[j].type);
78 	    fprintf(f, ")(%s))\n", s->fields.structure[j].name);
79 	 }
80 
81 	 fprintf(f, ")\n");
82       }
83    }
84 
85    fprintf(f, "(\n");
86    foreach_in_list(ir_instruction, ir, instructions) {
87       ir->fprint(f);
88       if (ir->ir_type != ir_type_function)
89 	 fprintf(f, "\n");
90    }
91    fprintf(f, ")\n");
92 }
93 
94 void
fprint_ir(FILE * f,const void * instruction)95 fprint_ir(FILE *f, const void *instruction)
96 {
97    const ir_instruction *ir = (const ir_instruction *)instruction;
98    ir->fprint(f);
99 }
100 
101 } /* extern "C" */
102 
ir_print_visitor(FILE * f)103 ir_print_visitor::ir_print_visitor(FILE *f)
104    : f(f)
105 {
106    indentation = 0;
107    printable_names = _mesa_pointer_hash_table_create(NULL);
108    symbols = _mesa_symbol_table_ctor();
109    mem_ctx = ralloc_context(NULL);
110 }
111 
~ir_print_visitor()112 ir_print_visitor::~ir_print_visitor()
113 {
114    _mesa_hash_table_destroy(printable_names, NULL);
115    _mesa_symbol_table_dtor(symbols);
116    ralloc_free(mem_ctx);
117 }
118 
indent(void)119 void ir_print_visitor::indent(void)
120 {
121    for (int i = 0; i < indentation; i++)
122       fprintf(f, "  ");
123 }
124 
125 const char *
unique_name(ir_variable * var)126 ir_print_visitor::unique_name(ir_variable *var)
127 {
128    /* var->name can be NULL in function prototypes when a type is given for a
129     * parameter but no name is given.  In that case, just return an empty
130     * string.  Don't worry about tracking the generated name in the printable
131     * names hash because this is the only scope where it can ever appear.
132     */
133    if (var->name == NULL) {
134       static unsigned arg = 1;
135       return ralloc_asprintf(this->mem_ctx, "parameter@%u", arg++);
136    }
137 
138    /* Do we already have a name for this variable? */
139    struct hash_entry * entry =
140       _mesa_hash_table_search(this->printable_names, var);
141 
142    if (entry != NULL) {
143       return (const char *) entry->data;
144    }
145 
146    /* If there's no conflict, just use the original name */
147    const char* name = NULL;
148    if (_mesa_symbol_table_find_symbol(this->symbols, var->name) == NULL) {
149       name = var->name;
150    } else {
151       static unsigned i = 1;
152       name = ralloc_asprintf(this->mem_ctx, "%s@%u", var->name, ++i);
153    }
154    _mesa_hash_table_insert(this->printable_names, var, (void *) name);
155    _mesa_symbol_table_add_symbol(this->symbols, name, var);
156    return name;
157 }
158 
visit(ir_rvalue *)159 void ir_print_visitor::visit(ir_rvalue *)
160 {
161    fprintf(f, "error");
162 }
163 
visit(ir_variable * ir)164 void ir_print_visitor::visit(ir_variable *ir)
165 {
166    fprintf(f, "(declare ");
167 
168    char binding[32] = {0};
169    if (ir->data.binding)
170       snprintf(binding, sizeof(binding), "binding=%i ", ir->data.binding);
171 
172    char loc[32] = {0};
173    if (ir->data.location != -1)
174       snprintf(loc, sizeof(loc), "location=%i ", ir->data.location);
175 
176    char component[32] = {0};
177    if (ir->data.explicit_component || ir->data.location_frac != 0)
178       snprintf(component, sizeof(component), "component=%i ",
179                     ir->data.location_frac);
180 
181    char stream[32] = {0};
182    if (ir->data.stream & (1u << 31)) {
183       if (ir->data.stream & ~(1u << 31)) {
184          snprintf(stream, sizeof(stream), "stream(%u,%u,%u,%u) ",
185                   ir->data.stream & 3, (ir->data.stream >> 2) & 3,
186                   (ir->data.stream >> 4) & 3, (ir->data.stream >> 6) & 3);
187       }
188    } else if (ir->data.stream) {
189       snprintf(stream, sizeof(stream), "stream%u ", ir->data.stream);
190    }
191 
192    char image_format[32] = {0};
193    if (ir->data.image_format) {
194       snprintf(image_format, sizeof(image_format), "format=%x ",
195                     ir->data.image_format);
196    }
197 
198    const char *const cent = (ir->data.centroid) ? "centroid " : "";
199    const char *const samp = (ir->data.sample) ? "sample " : "";
200    const char *const patc = (ir->data.patch) ? "patch " : "";
201    const char *const inv = (ir->data.invariant) ? "invariant " : "";
202    const char *const explicit_inv = (ir->data.explicit_invariant) ? "explicit_invariant " : "";
203    const char *const prec = (ir->data.precise) ? "precise " : "";
204    const char *const bindless = (ir->data.bindless) ? "bindless " : "";
205    const char *const bound = (ir->data.bound) ? "bound " : "";
206    const char *const memory_read_only = (ir->data.memory_read_only) ? "readonly " : "";
207    const char *const memory_write_only = (ir->data.memory_write_only) ? "writeonly " : "";
208    const char *const memory_coherent = (ir->data.memory_coherent) ? "coherent " : "";
209    const char *const memory_volatile = (ir->data.memory_volatile) ? "volatile " : "";
210    const char *const memory_restrict = (ir->data.memory_restrict) ? "restrict " : "";
211    const char *const mode[] = { "", "uniform ", "shader_storage ",
212                                 "shader_shared ", "shader_in ", "shader_out ",
213                                 "in ", "out ", "inout ",
214 			        "const_in ", "sys ", "temporary " };
215    STATIC_ASSERT(ARRAY_SIZE(mode) == ir_var_mode_count);
216    const char *const interp[] = { "", "smooth", "flat", "noperspective", "explicit" };
217    STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_MODE_COUNT);
218    const char *const precision[] = { "", "highp ", "mediump ", "lowp "};
219 
220    fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s) ",
221            binding, loc, component, cent, bindless, bound,
222            image_format, memory_read_only, memory_write_only,
223            memory_coherent, memory_volatile, memory_restrict,
224            samp, patc, inv, explicit_inv, prec, mode[ir->data.mode],
225            stream,
226            interp[ir->data.interpolation], precision[ir->data.precision]);
227 
228    glsl_print_type(f, ir->type);
229    fprintf(f, " %s)", unique_name(ir));
230 
231    if (ir->constant_initializer) {
232       fprintf(f, " ");
233       visit(ir->constant_initializer);
234    }
235 
236    if (ir->constant_value) {
237       fprintf(f, " ");
238       visit(ir->constant_value);
239    }
240 }
241 
242 
visit(ir_function_signature * ir)243 void ir_print_visitor::visit(ir_function_signature *ir)
244 {
245    _mesa_symbol_table_push_scope(symbols);
246    fprintf(f, "(signature ");
247    indentation++;
248 
249    glsl_print_type(f, ir->return_type);
250    fprintf(f, "\n");
251    indent();
252 
253    fprintf(f, "(parameters\n");
254    indentation++;
255 
256    foreach_in_list(ir_variable, inst, &ir->parameters) {
257       indent();
258       inst->accept(this);
259       fprintf(f, "\n");
260    }
261    indentation--;
262 
263    indent();
264    fprintf(f, ")\n");
265 
266    indent();
267 
268    fprintf(f, "(\n");
269    indentation++;
270 
271    foreach_in_list(ir_instruction, inst, &ir->body) {
272       indent();
273       inst->accept(this);
274       fprintf(f, "\n");
275    }
276    indentation--;
277    indent();
278    fprintf(f, "))\n");
279    indentation--;
280    _mesa_symbol_table_pop_scope(symbols);
281 }
282 
283 
visit(ir_function * ir)284 void ir_print_visitor::visit(ir_function *ir)
285 {
286    fprintf(f, "(%s function %s\n", ir->is_subroutine ? "subroutine" : "", ir->name);
287    indentation++;
288    foreach_in_list(ir_function_signature, sig, &ir->signatures) {
289       indent();
290       sig->accept(this);
291       fprintf(f, "\n");
292    }
293    indentation--;
294    indent();
295    fprintf(f, ")\n\n");
296 }
297 
298 
visit(ir_expression * ir)299 void ir_print_visitor::visit(ir_expression *ir)
300 {
301    fprintf(f, "(expression ");
302 
303    glsl_print_type(f, ir->type);
304 
305    fprintf(f, " %s ", ir_expression_operation_strings[ir->operation]);
306 
307    for (unsigned i = 0; i < ir->num_operands; i++) {
308       ir->operands[i]->accept(this);
309    }
310 
311    fprintf(f, ") ");
312 }
313 
314 
visit(ir_texture * ir)315 void ir_print_visitor::visit(ir_texture *ir)
316 {
317    fprintf(f, "(%s ", ir->opcode_string());
318 
319    if (ir->op == ir_samples_identical) {
320       ir->sampler->accept(this);
321       fprintf(f, " ");
322       ir->coordinate->accept(this);
323       fprintf(f, ")");
324       return;
325    }
326 
327    glsl_print_type(f, ir->type);
328    fprintf(f, " ");
329 
330    ir->sampler->accept(this);
331    fprintf(f, " ");
332 
333    if (ir->op != ir_txs && ir->op != ir_query_levels &&
334        ir->op != ir_texture_samples) {
335       ir->coordinate->accept(this);
336 
337       fprintf(f, " ");
338 
339       if (ir->op != ir_lod && ir->op != ir_samples_identical)
340          fprintf(f, "%d ", ir->is_sparse);
341 
342       if (ir->offset != NULL) {
343 	 ir->offset->accept(this);
344       } else {
345 	 fprintf(f, "0");
346       }
347 
348       fprintf(f, " ");
349    }
350 
351    if (ir->op != ir_txf && ir->op != ir_txf_ms &&
352        ir->op != ir_txs && ir->op != ir_tg4 &&
353        ir->op != ir_query_levels && ir->op != ir_texture_samples) {
354       if (ir->projector)
355 	 ir->projector->accept(this);
356       else
357 	 fprintf(f, "1");
358 
359       if (ir->shadow_comparator) {
360 	 fprintf(f, " ");
361 	 ir->shadow_comparator->accept(this);
362       } else {
363 	 fprintf(f, " ()");
364       }
365    }
366 
367    if (ir->op == ir_tex || ir->op == ir_txb || ir->op == ir_txd) {
368       if (ir->clamp) {
369          fprintf(f, " ");
370          ir->clamp->accept(this);
371       } else {
372          fprintf(f, " ()");
373       }
374    }
375 
376    fprintf(f, " ");
377    switch (ir->op)
378    {
379    case ir_tex:
380    case ir_lod:
381    case ir_query_levels:
382    case ir_texture_samples:
383       break;
384    case ir_txb:
385       ir->lod_info.bias->accept(this);
386       break;
387    case ir_txl:
388    case ir_txf:
389    case ir_txs:
390       ir->lod_info.lod->accept(this);
391       break;
392    case ir_txf_ms:
393       ir->lod_info.sample_index->accept(this);
394       break;
395    case ir_txd:
396       fprintf(f, "(");
397       ir->lod_info.grad.dPdx->accept(this);
398       fprintf(f, " ");
399       ir->lod_info.grad.dPdy->accept(this);
400       fprintf(f, ")");
401       break;
402    case ir_tg4:
403       ir->lod_info.component->accept(this);
404       break;
405    case ir_samples_identical:
406       unreachable("ir_samples_identical was already handled");
407    };
408    fprintf(f, ")");
409 }
410 
411 
visit(ir_swizzle * ir)412 void ir_print_visitor::visit(ir_swizzle *ir)
413 {
414    const unsigned swiz[4] = {
415       ir->mask.x,
416       ir->mask.y,
417       ir->mask.z,
418       ir->mask.w,
419    };
420 
421    fprintf(f, "(swiz ");
422    for (unsigned i = 0; i < ir->mask.num_components; i++) {
423       fprintf(f, "%c", "xyzw"[swiz[i]]);
424    }
425    fprintf(f, " ");
426    ir->val->accept(this);
427    fprintf(f, ")");
428 }
429 
430 
visit(ir_dereference_variable * ir)431 void ir_print_visitor::visit(ir_dereference_variable *ir)
432 {
433    ir_variable *var = ir->variable_referenced();
434    fprintf(f, "(var_ref %s) ", unique_name(var));
435 }
436 
437 
visit(ir_dereference_array * ir)438 void ir_print_visitor::visit(ir_dereference_array *ir)
439 {
440    fprintf(f, "(array_ref ");
441    ir->array->accept(this);
442    ir->array_index->accept(this);
443    fprintf(f, ") ");
444 }
445 
446 
visit(ir_dereference_record * ir)447 void ir_print_visitor::visit(ir_dereference_record *ir)
448 {
449    fprintf(f, "(record_ref ");
450    ir->record->accept(this);
451 
452    const char *field_name =
453       ir->record->type->fields.structure[ir->field_idx].name;
454    fprintf(f, " %s) ", field_name);
455 }
456 
457 
visit(ir_assignment * ir)458 void ir_print_visitor::visit(ir_assignment *ir)
459 {
460    fprintf(f, "(assign ");
461 
462    char mask[5];
463    unsigned j = 0;
464 
465    for (unsigned i = 0; i < 4; i++) {
466       if ((ir->write_mask & (1 << i)) != 0) {
467 	 mask[j] = "xyzw"[i];
468 	 j++;
469       }
470    }
471    mask[j] = '\0';
472 
473    fprintf(f, " (%s) ", mask);
474 
475    ir->lhs->accept(this);
476 
477    fprintf(f, " ");
478 
479    ir->rhs->accept(this);
480    fprintf(f, ") ");
481 }
482 
483 static void
print_float_constant(FILE * f,float val)484 print_float_constant(FILE *f, float val)
485 {
486    if (val == 0.0f)
487       /* 0.0 == -0.0, so print with %f to get the proper sign. */
488       fprintf(f, "%f", val);
489    else if (fabs(val) < 0.000001f)
490       fprintf(f, "%a", val);
491    else if (fabs(val) > 1000000.0f)
492       fprintf(f, "%e", val);
493    else
494       fprintf(f, "%f", val);
495 }
496 
visit(ir_constant * ir)497 void ir_print_visitor::visit(ir_constant *ir)
498 {
499    fprintf(f, "(constant ");
500    glsl_print_type(f, ir->type);
501    fprintf(f, " (");
502 
503    if (glsl_type_is_array(ir->type)) {
504       for (unsigned i = 0; i < ir->type->length; i++)
505 	 ir->get_array_element(i)->accept(this);
506    } else if (glsl_type_is_struct(ir->type)) {
507       for (unsigned i = 0; i < ir->type->length; i++) {
508 	 fprintf(f, "(%s ", ir->type->fields.structure[i].name);
509          ir->get_record_field(i)->accept(this);
510 	 fprintf(f, ")");
511       }
512    } else {
513       for (unsigned i = 0; i < glsl_get_components(ir->type); i++) {
514 	 if (i != 0)
515 	    fprintf(f, " ");
516 	 switch (ir->type->base_type) {
517          case GLSL_TYPE_UINT16:fprintf(f, "%u", ir->value.u16[i]); break;
518 	 case GLSL_TYPE_INT16: fprintf(f, "%d", ir->value.i16[i]); break;
519 	 case GLSL_TYPE_UINT:  fprintf(f, "%u", ir->value.u[i]); break;
520 	 case GLSL_TYPE_INT:   fprintf(f, "%d", ir->value.i[i]); break;
521 	 case GLSL_TYPE_FLOAT:
522             print_float_constant(f, ir->value.f[i]);
523             break;
524 	 case GLSL_TYPE_FLOAT16:
525             print_float_constant(f, _mesa_half_to_float(ir->value.f16[i]));
526             break;
527 	 case GLSL_TYPE_SAMPLER:
528 	 case GLSL_TYPE_IMAGE:
529 	 case GLSL_TYPE_UINT64:
530             fprintf(f, "%" PRIu64, ir->value.u64[i]);
531             break;
532 	 case GLSL_TYPE_INT64: fprintf(f, "%" PRIi64, ir->value.i64[i]); break;
533 	 case GLSL_TYPE_BOOL:  fprintf(f, "%d", ir->value.b[i]); break;
534 	 case GLSL_TYPE_DOUBLE:
535             if (ir->value.d[i] == 0.0)
536                /* 0.0 == -0.0, so print with %f to get the proper sign. */
537                fprintf(f, "%.1f", ir->value.d[i]);
538             else if (fabs(ir->value.d[i]) < 0.000001)
539                fprintf(f, "%a", ir->value.d[i]);
540             else if (fabs(ir->value.d[i]) > 1000000.0)
541                fprintf(f, "%e", ir->value.d[i]);
542             else
543                fprintf(f, "%f", ir->value.d[i]);
544             break;
545 	 default:
546             unreachable("Invalid constant type");
547 	 }
548       }
549    }
550    fprintf(f, ")) ");
551 }
552 
553 
554 void
visit(ir_call * ir)555 ir_print_visitor::visit(ir_call *ir)
556 {
557    fprintf(f, "(call %s ", ir->callee_name());
558    if (ir->return_deref)
559       ir->return_deref->accept(this);
560    fprintf(f, " (");
561    foreach_in_list(ir_rvalue, param, &ir->actual_parameters) {
562       param->accept(this);
563    }
564    fprintf(f, "))\n");
565 }
566 
567 
568 void
visit(ir_return * ir)569 ir_print_visitor::visit(ir_return *ir)
570 {
571    fprintf(f, "(return");
572 
573    ir_rvalue *const value = ir->get_value();
574    if (value) {
575       fprintf(f, " ");
576       value->accept(this);
577    }
578 
579    fprintf(f, ")");
580 }
581 
582 
583 void
visit(ir_discard * ir)584 ir_print_visitor::visit(ir_discard *ir)
585 {
586    fprintf(f, "(discard ");
587 
588    if (ir->condition != NULL) {
589       fprintf(f, " ");
590       ir->condition->accept(this);
591    }
592 
593    fprintf(f, ")");
594 }
595 
596 
597 void
visit(ir_demote * ir)598 ir_print_visitor::visit(ir_demote *ir)
599 {
600    fprintf(f, "(demote)");
601 }
602 
603 
604 void
visit(ir_if * ir)605 ir_print_visitor::visit(ir_if *ir)
606 {
607    fprintf(f, "(if ");
608    ir->condition->accept(this);
609 
610    fprintf(f, "(\n");
611    indentation++;
612 
613    foreach_in_list(ir_instruction, inst, &ir->then_instructions) {
614       indent();
615       inst->accept(this);
616       fprintf(f, "\n");
617    }
618 
619    indentation--;
620    indent();
621    fprintf(f, ")\n");
622 
623    indent();
624    if (!ir->else_instructions.is_empty()) {
625       fprintf(f, "(\n");
626       indentation++;
627 
628       foreach_in_list(ir_instruction, inst, &ir->else_instructions) {
629 	 indent();
630 	 inst->accept(this);
631 	 fprintf(f, "\n");
632       }
633       indentation--;
634       indent();
635       fprintf(f, "))\n");
636    } else {
637       fprintf(f, "())\n");
638    }
639 }
640 
641 
642 void
visit(ir_loop * ir)643 ir_print_visitor::visit(ir_loop *ir)
644 {
645    fprintf(f, "(loop (\n");
646    indentation++;
647 
648    foreach_in_list(ir_instruction, inst, &ir->body_instructions) {
649       indent();
650       inst->accept(this);
651       fprintf(f, "\n");
652    }
653    indentation--;
654    indent();
655    fprintf(f, "))\n");
656 }
657 
658 
659 void
visit(ir_loop_jump * ir)660 ir_print_visitor::visit(ir_loop_jump *ir)
661 {
662    fprintf(f, "%s", ir->is_break() ? "break" : "continue");
663 }
664 
665 void
visit(ir_emit_vertex * ir)666 ir_print_visitor::visit(ir_emit_vertex *ir)
667 {
668    fprintf(f, "(emit-vertex ");
669    ir->stream->accept(this);
670    fprintf(f, ")\n");
671 }
672 
673 void
visit(ir_end_primitive * ir)674 ir_print_visitor::visit(ir_end_primitive *ir)
675 {
676    fprintf(f, "(end-primitive ");
677    ir->stream->accept(this);
678    fprintf(f, ")\n");
679 }
680 
681 void
visit(ir_barrier *)682 ir_print_visitor::visit(ir_barrier *)
683 {
684    fprintf(f, "(barrier)\n");
685 }
686