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