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