gtest: Update to 1.7.0.
[mesa.git] / src / glsl / ir_print_visitor.cpp
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 "ir_print_visitor.h"
25 #include "glsl_types.h"
26 #include "glsl_parser_extras.h"
27 #include "main/macros.h"
28 #include "program/hash_table.h"
29
30 static void print_type(FILE *f, const glsl_type *t);
31
32 void
33 ir_instruction::print(void) const
34 {
35 this->fprint(stdout);
36 }
37
38 void
39 ir_instruction::fprint(FILE *f) const
40 {
41 ir_instruction *deconsted = const_cast<ir_instruction *>(this);
42
43 ir_print_visitor v(f);
44 deconsted->accept(&v);
45 }
46
47 extern "C" {
48 void
49 _mesa_print_ir(FILE *f, exec_list *instructions,
50 struct _mesa_glsl_parse_state *state)
51 {
52 if (state) {
53 for (unsigned i = 0; i < state->num_user_structures; i++) {
54 const glsl_type *const s = state->user_structures[i];
55
56 fprintf(f, "(structure (%s) (%s@%p) (%u) (\n",
57 s->name, s->name, (void *) s, s->length);
58
59 for (unsigned j = 0; j < s->length; j++) {
60 fprintf(f, "\t((");
61 print_type(f, s->fields.structure[j].type);
62 fprintf(f, ")(%s))\n", s->fields.structure[j].name);
63 }
64
65 fprintf(f, ")\n");
66 }
67 }
68
69 fprintf(f, "(\n");
70 foreach_list(n, instructions) {
71 ir_instruction *ir = (ir_instruction *) n;
72 ir->fprint(f);
73 if (ir->ir_type != ir_type_function)
74 fprintf(f, "\n");
75 }
76 fprintf(f, "\n)");
77 }
78
79 } /* extern "C" */
80
81 ir_print_visitor::ir_print_visitor(FILE *f)
82 : f(f)
83 {
84 indentation = 0;
85 printable_names =
86 hash_table_ctor(32, hash_table_pointer_hash, hash_table_pointer_compare);
87 symbols = _mesa_symbol_table_ctor();
88 mem_ctx = ralloc_context(NULL);
89 }
90
91 ir_print_visitor::~ir_print_visitor()
92 {
93 hash_table_dtor(printable_names);
94 _mesa_symbol_table_dtor(symbols);
95 ralloc_free(mem_ctx);
96 }
97
98 void ir_print_visitor::indent(void)
99 {
100 for (int i = 0; i < indentation; i++)
101 fprintf(f, " ");
102 }
103
104 const char *
105 ir_print_visitor::unique_name(ir_variable *var)
106 {
107 /* var->name can be NULL in function prototypes when a type is given for a
108 * parameter but no name is given. In that case, just return an empty
109 * string. Don't worry about tracking the generated name in the printable
110 * names hash because this is the only scope where it can ever appear.
111 */
112 if (var->name == NULL) {
113 static unsigned arg = 1;
114 return ralloc_asprintf(this->mem_ctx, "parameter@%u", arg++);
115 }
116
117 /* Do we already have a name for this variable? */
118 const char *name = (const char *) hash_table_find(this->printable_names, var);
119 if (name != NULL)
120 return name;
121
122 /* If there's no conflict, just use the original name */
123 if (_mesa_symbol_table_find_symbol(this->symbols, -1, var->name) == NULL) {
124 name = var->name;
125 } else {
126 static unsigned i = 1;
127 name = ralloc_asprintf(this->mem_ctx, "%s@%u", var->name, ++i);
128 }
129 hash_table_insert(this->printable_names, (void *) name, var);
130 _mesa_symbol_table_add_symbol(this->symbols, -1, name, var);
131 return name;
132 }
133
134 static void
135 print_type(FILE *f, const glsl_type *t)
136 {
137 if (t->base_type == GLSL_TYPE_ARRAY) {
138 fprintf(f, "(array ");
139 print_type(f, t->fields.array);
140 fprintf(f, " %u)", t->length);
141 } else if ((t->base_type == GLSL_TYPE_STRUCT)
142 && (strncmp("gl_", t->name, 3) != 0)) {
143 fprintf(f, "%s@%p", t->name, (void *) t);
144 } else {
145 fprintf(f, "%s", t->name);
146 }
147 }
148
149 void ir_print_visitor::visit(ir_rvalue *)
150 {
151 fprintf(f, "error");
152 }
153
154 void ir_print_visitor::visit(ir_variable *ir)
155 {
156 fprintf(f, "(declare ");
157
158 const char *const cent = (ir->data.centroid) ? "centroid " : "";
159 const char *const samp = (ir->data.sample) ? "sample " : "";
160 const char *const inv = (ir->data.invariant) ? "invariant " : "";
161 const char *const mode[] = { "", "uniform ", "shader_in ", "shader_out ",
162 "in ", "out ", "inout ",
163 "const_in ", "sys ", "temporary " };
164 STATIC_ASSERT(ARRAY_SIZE(mode) == ir_var_mode_count);
165 const char *const interp[] = { "", "smooth", "flat", "noperspective" };
166 STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT);
167
168 fprintf(f, "(%s%s%s%s%s) ",
169 cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]);
170
171 print_type(f, ir->type);
172 fprintf(f, " %s)", unique_name(ir));
173 }
174
175
176 void ir_print_visitor::visit(ir_function_signature *ir)
177 {
178 _mesa_symbol_table_push_scope(symbols);
179 fprintf(f, "(signature ");
180 indentation++;
181
182 print_type(f, ir->return_type);
183 fprintf(f, "\n");
184 indent();
185
186 fprintf(f, "(parameters\n");
187 indentation++;
188
189 foreach_list(n, &ir->parameters) {
190 ir_variable *const inst = (ir_variable *) n;
191
192 indent();
193 inst->accept(this);
194 fprintf(f, "\n");
195 }
196 indentation--;
197
198 indent();
199 fprintf(f, ")\n");
200
201 indent();
202
203 fprintf(f, "(\n");
204 indentation++;
205
206 foreach_list(n, &ir->body) {
207 ir_instruction *const inst = (ir_instruction *) n;
208
209 indent();
210 inst->accept(this);
211 fprintf(f, "\n");
212 }
213 indentation--;
214 indent();
215 fprintf(f, "))\n");
216 indentation--;
217 _mesa_symbol_table_pop_scope(symbols);
218 }
219
220
221 void ir_print_visitor::visit(ir_function *ir)
222 {
223 fprintf(f, "(function %s\n", ir->name);
224 indentation++;
225 foreach_list(n, &ir->signatures) {
226 ir_function_signature *const sig = (ir_function_signature *) n;
227 indent();
228 sig->accept(this);
229 fprintf(f, "\n");
230 }
231 indentation--;
232 indent();
233 fprintf(f, ")\n\n");
234 }
235
236
237 void ir_print_visitor::visit(ir_expression *ir)
238 {
239 fprintf(f, "(expression ");
240
241 print_type(f, ir->type);
242
243 fprintf(f, " %s ", ir->operator_string());
244
245 for (unsigned i = 0; i < ir->get_num_operands(); i++) {
246 ir->operands[i]->accept(this);
247 }
248
249 fprintf(f, ") ");
250 }
251
252
253 void ir_print_visitor::visit(ir_texture *ir)
254 {
255 fprintf(f, "(%s ", ir->opcode_string());
256
257 print_type(f, ir->type);
258 fprintf(f, " ");
259
260 ir->sampler->accept(this);
261 fprintf(f, " ");
262
263 if (ir->op != ir_txs && ir->op != ir_query_levels) {
264 ir->coordinate->accept(this);
265
266 fprintf(f, " ");
267
268 if (ir->offset != NULL) {
269 ir->offset->accept(this);
270 } else {
271 fprintf(f, "0");
272 }
273
274 fprintf(f, " ");
275 }
276
277 if (ir->op != ir_txf && ir->op != ir_txf_ms &&
278 ir->op != ir_txs && ir->op != ir_tg4 &&
279 ir->op != ir_query_levels) {
280 if (ir->projector)
281 ir->projector->accept(this);
282 else
283 fprintf(f, "1");
284
285 if (ir->shadow_comparitor) {
286 fprintf(f, " ");
287 ir->shadow_comparitor->accept(this);
288 } else {
289 fprintf(f, " ()");
290 }
291 }
292
293 fprintf(f, " ");
294 switch (ir->op)
295 {
296 case ir_tex:
297 case ir_lod:
298 case ir_query_levels:
299 break;
300 case ir_txb:
301 ir->lod_info.bias->accept(this);
302 break;
303 case ir_txl:
304 case ir_txf:
305 case ir_txs:
306 ir->lod_info.lod->accept(this);
307 break;
308 case ir_txf_ms:
309 ir->lod_info.sample_index->accept(this);
310 break;
311 case ir_txd:
312 fprintf(f, "(");
313 ir->lod_info.grad.dPdx->accept(this);
314 fprintf(f, " ");
315 ir->lod_info.grad.dPdy->accept(this);
316 fprintf(f, ")");
317 break;
318 case ir_tg4:
319 ir->lod_info.component->accept(this);
320 break;
321 };
322 fprintf(f, ")");
323 }
324
325
326 void ir_print_visitor::visit(ir_swizzle *ir)
327 {
328 const unsigned swiz[4] = {
329 ir->mask.x,
330 ir->mask.y,
331 ir->mask.z,
332 ir->mask.w,
333 };
334
335 fprintf(f, "(swiz ");
336 for (unsigned i = 0; i < ir->mask.num_components; i++) {
337 fprintf(f, "%c", "xyzw"[swiz[i]]);
338 }
339 fprintf(f, " ");
340 ir->val->accept(this);
341 fprintf(f, ")");
342 }
343
344
345 void ir_print_visitor::visit(ir_dereference_variable *ir)
346 {
347 ir_variable *var = ir->variable_referenced();
348 fprintf(f, "(var_ref %s) ", unique_name(var));
349 }
350
351
352 void ir_print_visitor::visit(ir_dereference_array *ir)
353 {
354 fprintf(f, "(array_ref ");
355 ir->array->accept(this);
356 ir->array_index->accept(this);
357 fprintf(f, ") ");
358 }
359
360
361 void ir_print_visitor::visit(ir_dereference_record *ir)
362 {
363 fprintf(f, "(record_ref ");
364 ir->record->accept(this);
365 fprintf(f, " %s) ", ir->field);
366 }
367
368
369 void ir_print_visitor::visit(ir_assignment *ir)
370 {
371 fprintf(f, "(assign ");
372
373 if (ir->condition)
374 ir->condition->accept(this);
375
376 char mask[5];
377 unsigned j = 0;
378
379 for (unsigned i = 0; i < 4; i++) {
380 if ((ir->write_mask & (1 << i)) != 0) {
381 mask[j] = "xyzw"[i];
382 j++;
383 }
384 }
385 mask[j] = '\0';
386
387 fprintf(f, " (%s) ", mask);
388
389 ir->lhs->accept(this);
390
391 fprintf(f, " ");
392
393 ir->rhs->accept(this);
394 fprintf(f, ") ");
395 }
396
397
398 void ir_print_visitor::visit(ir_constant *ir)
399 {
400 fprintf(f, "(constant ");
401 print_type(f, ir->type);
402 fprintf(f, " (");
403
404 if (ir->type->is_array()) {
405 for (unsigned i = 0; i < ir->type->length; i++)
406 ir->get_array_element(i)->accept(this);
407 } else if (ir->type->is_record()) {
408 ir_constant *value = (ir_constant *) ir->components.get_head();
409 for (unsigned i = 0; i < ir->type->length; i++) {
410 fprintf(f, "(%s ", ir->type->fields.structure[i].name);
411 value->accept(this);
412 fprintf(f, ")");
413
414 value = (ir_constant *) value->next;
415 }
416 } else {
417 for (unsigned i = 0; i < ir->type->components(); i++) {
418 if (i != 0)
419 fprintf(f, " ");
420 switch (ir->type->base_type) {
421 case GLSL_TYPE_UINT: fprintf(f, "%u", ir->value.u[i]); break;
422 case GLSL_TYPE_INT: fprintf(f, "%d", ir->value.i[i]); break;
423 case GLSL_TYPE_FLOAT:
424 if (ir->value.f[i] == 0.0f)
425 /* 0.0 == -0.0, so print with %f to get the proper sign. */
426 fprintf(f, "%.1f", ir->value.f[i]);
427 else if (fabs(ir->value.f[i]) < 0.000001f)
428 fprintf(f, "%a", ir->value.f[i]);
429 else if (fabs(ir->value.f[i]) > 1000000.0f)
430 fprintf(f, "%e", ir->value.f[i]);
431 else
432 fprintf(f, "%f", ir->value.f[i]);
433 break;
434 case GLSL_TYPE_BOOL: fprintf(f, "%d", ir->value.b[i]); break;
435 default: assert(0);
436 }
437 }
438 }
439 fprintf(f, ")) ");
440 }
441
442
443 void
444 ir_print_visitor::visit(ir_call *ir)
445 {
446 fprintf(f, "(call %s ", ir->callee_name());
447 if (ir->return_deref)
448 ir->return_deref->accept(this);
449 fprintf(f, " (");
450 foreach_list(n, &ir->actual_parameters) {
451 ir_rvalue *const param = (ir_rvalue *) n;
452
453 param->accept(this);
454 }
455 fprintf(f, "))\n");
456 }
457
458
459 void
460 ir_print_visitor::visit(ir_return *ir)
461 {
462 fprintf(f, "(return");
463
464 ir_rvalue *const value = ir->get_value();
465 if (value) {
466 fprintf(f, " ");
467 value->accept(this);
468 }
469
470 fprintf(f, ")");
471 }
472
473
474 void
475 ir_print_visitor::visit(ir_discard *ir)
476 {
477 fprintf(f, "(discard ");
478
479 if (ir->condition != NULL) {
480 fprintf(f, " ");
481 ir->condition->accept(this);
482 }
483
484 fprintf(f, ")");
485 }
486
487
488 void
489 ir_print_visitor::visit(ir_if *ir)
490 {
491 fprintf(f, "(if ");
492 ir->condition->accept(this);
493
494 fprintf(f, "(\n");
495 indentation++;
496
497 foreach_list(n, &ir->then_instructions) {
498 ir_instruction *const inst = (ir_instruction *) n;
499
500 indent();
501 inst->accept(this);
502 fprintf(f, "\n");
503 }
504
505 indentation--;
506 indent();
507 fprintf(f, ")\n");
508
509 indent();
510 if (!ir->else_instructions.is_empty()) {
511 fprintf(f, "(\n");
512 indentation++;
513
514 foreach_list(n, &ir->else_instructions) {
515 ir_instruction *const inst = (ir_instruction *) n;
516
517 indent();
518 inst->accept(this);
519 fprintf(f, "\n");
520 }
521 indentation--;
522 indent();
523 fprintf(f, "))\n");
524 } else {
525 fprintf(f, "())\n");
526 }
527 }
528
529
530 void
531 ir_print_visitor::visit(ir_loop *ir)
532 {
533 fprintf(f, "(loop (\n");
534 indentation++;
535
536 foreach_list(n, &ir->body_instructions) {
537 ir_instruction *const inst = (ir_instruction *) n;
538
539 indent();
540 inst->accept(this);
541 fprintf(f, "\n");
542 }
543 indentation--;
544 indent();
545 fprintf(f, "))\n");
546 }
547
548
549 void
550 ir_print_visitor::visit(ir_loop_jump *ir)
551 {
552 fprintf(f, "%s", ir->is_break() ? "break" : "continue");
553 }
554
555 void
556 ir_print_visitor::visit(ir_emit_vertex *)
557 {
558 fprintf(f, "(emit-vertex)");
559 }
560
561 void
562 ir_print_visitor::visit(ir_end_primitive *)
563 {
564 fprintf(f, "(end-primitive)");
565 }