Use ir_print_visitor to dump IR tree
[mesa.git] / glsl_parser_extras.cpp
1 /*
2 * Copyright © 2008, 2009 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 #include <stdio.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33
34 #include "ast.h"
35 #include "glsl_parser_extras.h"
36 #include "glsl_parser.h"
37 #include "symbol_table.h"
38 #include "ir_print_visitor.h"
39
40 void
41 _mesa_glsl_error(YYLTYPE *locp, void *state, const char *fmt, ...)
42 {
43 char buf[1024];
44 int len;
45 va_list ap;
46
47 (void) state;
48 len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ",
49 locp->source, locp->first_line, locp->first_column);
50
51 va_start(ap, fmt);
52 vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
53 va_end(ap);
54
55 printf("%s\n", buf);
56 }
57
58
59 ast_node::~ast_node()
60 {
61 /* empty */
62 }
63
64
65 void
66 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
67 {
68 if (q->constant)
69 printf("const ");
70
71 if (q->invariant)
72 printf("invariant ");
73
74 if (q->attribute)
75 printf("attribute ");
76
77 if (q->varying)
78 printf("varying ");
79
80 if (q->in && q->out)
81 printf("inout ");
82 else {
83 if (q->in)
84 printf("in ");
85
86 if (q->out)
87 printf("out ");
88 }
89
90 if (q->centroid)
91 printf("centroid ");
92 if (q->uniform)
93 printf("uniform ");
94 if (q->smooth)
95 printf("smooth ");
96 if (q->flat)
97 printf("flat ");
98 if (q->noperspective)
99 printf("noperspective ");
100 }
101
102
103 void
104 ast_node::print(void) const
105 {
106 printf("node_%d ", type);
107 }
108
109
110 ast_node::ast_node(void)
111 {
112 make_empty_list(this);
113 }
114
115 void
116 ast_type_specifier::print(void) const
117 {
118 switch (type_specifier) {
119 case ast_void: printf("void "); break;
120 case ast_float: printf("float "); break;
121 case ast_int: printf("int "); break;
122 case ast_uint: printf("uint "); break;
123 case ast_bool: printf("bool "); break;
124 case ast_vec2: printf("vec2 "); break;
125 case ast_vec3: printf("vec3 "); break;
126 case ast_vec4: printf("vec4 "); break;
127 case ast_bvec2: printf("bvec2 "); break;
128 case ast_bvec3: printf("bvec3 "); break;
129 case ast_bvec4: printf("bvec4 "); break;
130 case ast_ivec2: printf("ivec2 "); break;
131 case ast_ivec3: printf("ivec3 "); break;
132 case ast_ivec4: printf("ivec4 "); break;
133 case ast_uvec2: printf("uvec2 "); break;
134 case ast_uvec3: printf("uvec3 "); break;
135 case ast_uvec4: printf("uvec4 "); break;
136 case ast_mat2: printf("mat2 "); break;
137 case ast_mat2x3: printf("mat2x3 "); break;
138 case ast_mat2x4: printf("mat2x4 "); break;
139 case ast_mat3x2: printf("mat3x2 "); break;
140 case ast_mat3: printf("mat3 "); break;
141 case ast_mat3x4: printf("mat3x4 "); break;
142 case ast_mat4x2: printf("mat4x2 "); break;
143 case ast_mat4x3: printf("mat4x3 "); break;
144 case ast_mat4: printf("mat4 "); break;
145 case ast_sampler1d: printf("sampler1d "); break;
146 case ast_sampler2d: printf("sampler2d "); break;
147 case ast_sampler3d: printf("sampler3d "); break;
148 case ast_samplercube: printf("samplercube "); break;
149 case ast_sampler1dshadow: printf("sampler1dshadow "); break;
150 case ast_sampler2dshadow: printf("sampler2dshadow "); break;
151 case ast_samplercubeshadow: printf("samplercubeshadow "); break;
152 case ast_sampler1darray: printf("sampler1darray "); break;
153 case ast_sampler2darray: printf("sampler2darray "); break;
154 case ast_sampler1darrayshadow: printf("sampler1darrayshadow "); break;
155 case ast_sampler2darrayshadow: printf("sampler2darrayshadow "); break;
156 case ast_isampler1d: printf("isampler1d "); break;
157 case ast_isampler2d: printf("isampler2d "); break;
158 case ast_isampler3d: printf("isampler3d "); break;
159 case ast_isamplercube: printf("isamplercube "); break;
160 case ast_isampler1darray: printf("isampler1darray "); break;
161 case ast_isampler2darray: printf("isampler2darray "); break;
162 case ast_usampler1d: printf("usampler1d "); break;
163 case ast_usampler2d: printf("usampler2d "); break;
164 case ast_usampler3d: printf("usampler3d "); break;
165 case ast_usamplercube: printf("usamplercube "); break;
166 case ast_usampler1darray: printf("usampler1darray "); break;
167 case ast_usampler2darray: printf("usampler2darray "); break;
168
169 case ast_struct:
170 structure->print();
171 break;
172
173 case ast_type_name: printf("%s ", type_name); break;
174 }
175
176 if (is_array) {
177 printf("[ ");
178
179 if (array_size) {
180 array_size->print();
181 }
182
183 printf("] ");
184 }
185 }
186
187 static void
188 ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
189 {
190 if (is_array) {
191 printf("[ ");
192
193 if (array_size)
194 array_size->print();
195
196 printf("] ");
197 }
198 }
199
200
201 ast_type_specifier::ast_type_specifier(int specifier)
202 {
203 type_specifier = ast_types(specifier);
204 }
205
206
207 void
208 ast_compound_statement::print(void) const
209 {
210 const struct simple_node *ptr;
211
212 printf("{\n");
213
214 foreach(ptr, & statements) {
215 ((ast_node *)ptr)->print();
216 }
217
218 printf("}\n");
219 }
220
221
222 ast_compound_statement::ast_compound_statement(int new_scope,
223 ast_node *statements)
224 {
225 this->new_scope = new_scope;
226 make_empty_list(& this->statements);
227
228 if (statements != NULL) {
229 /* This seems odd, but it works. The simple_list is,
230 * basically, a circular list. insert_at_tail adds
231 * the specified node to the list before the current
232 * head.
233 */
234 insert_at_tail((struct simple_node *) statements,
235 & this->statements);
236 }
237 }
238
239
240 void
241 ast_expression::print(void) const
242 {
243 switch (oper) {
244 case ast_assign:
245 case ast_mul_assign:
246 case ast_div_assign:
247 case ast_mod_assign:
248 case ast_add_assign:
249 case ast_sub_assign:
250 case ast_ls_assign:
251 case ast_rs_assign:
252 case ast_and_assign:
253 case ast_xor_assign:
254 case ast_or_assign:
255 subexpressions[0]->print();
256 printf("%s ", operator_string(oper));
257 subexpressions[1]->print();
258 break;
259
260 case ast_field_selection:
261 subexpressions[0]->print();
262 printf(". %s ", primary_expression.identifier);
263 break;
264
265 case ast_plus:
266 case ast_neg:
267 case ast_bit_not:
268 case ast_logic_not:
269 case ast_pre_inc:
270 case ast_pre_dec:
271 printf("%s ", operator_string(oper));
272 subexpressions[0]->print();
273 break;
274
275 case ast_post_inc:
276 case ast_post_dec:
277 subexpressions[0]->print();
278 printf("%s ", operator_string(oper));
279 break;
280
281 case ast_conditional:
282 subexpressions[0]->print();
283 printf("? ");
284 subexpressions[1]->print();
285 printf(": ");
286 subexpressions[1]->print();
287 break;
288
289 case ast_array_index:
290 subexpressions[0]->print();
291 printf("[ ");
292 subexpressions[1]->print();
293 printf("] ");
294 break;
295
296 case ast_function_call: {
297 ast_expression *parameters = subexpressions[1];
298
299 subexpressions[0]->print();
300 printf("( ");
301
302 if (parameters != NULL) {
303 struct simple_node *ptr;
304
305 parameters->print();
306 foreach (ptr, (struct simple_node *) parameters) {
307 printf(", ");
308 ((ast_node *)ptr)->print();
309 }
310 }
311
312 printf(") ");
313 break;
314 }
315
316 case ast_identifier:
317 printf("%s ", primary_expression.identifier);
318 break;
319
320 case ast_int_constant:
321 printf("%d ", primary_expression.int_constant);
322 break;
323
324 case ast_uint_constant:
325 printf("%u ", primary_expression.uint_constant);
326 break;
327
328 case ast_float_constant:
329 printf("%f ", primary_expression.float_constant);
330 break;
331
332 case ast_bool_constant:
333 printf("%s ",
334 primary_expression.bool_constant
335 ? "true" : "false");
336 break;
337
338 case ast_sequence: {
339 struct simple_node *ptr;
340 struct simple_node *const head = first_elem(& expressions);
341
342 printf("( ");
343 foreach (ptr, & expressions) {
344 if (ptr != head)
345 printf(", ");
346
347 ((ast_node *)ptr)->print();
348 }
349 printf(") ");
350 break;
351 }
352
353 default:
354 assert(0);
355 break;
356 }
357 }
358
359 ast_expression::ast_expression(int oper,
360 ast_expression *ex0,
361 ast_expression *ex1,
362 ast_expression *ex2)
363 {
364 this->oper = ast_operators(oper);
365 this->subexpressions[0] = ex0;
366 this->subexpressions[1] = ex1;
367 this->subexpressions[2] = ex2;
368 make_empty_list(& expressions);
369 }
370
371
372 void
373 ast_expression_statement::print(void) const
374 {
375 if (expression)
376 expression->print();
377
378 printf("; ");
379 }
380
381
382 ast_expression_statement::ast_expression_statement(ast_expression *ex) :
383 expression(ex)
384 {
385 /* empty */
386 }
387
388
389 void
390 ast_function::print(void) const
391 {
392 struct simple_node *ptr;
393
394 return_type->print();
395 printf(" %s (", identifier);
396
397 foreach(ptr, & parameters) {
398 ((ast_node *)ptr)->print();
399 }
400
401 printf(")");
402 }
403
404
405 ast_function::ast_function(void)
406 {
407 make_empty_list(& parameters);
408 }
409
410
411 void
412 ast_fully_specified_type::print(void) const
413 {
414 _mesa_ast_type_qualifier_print(& qualifier);
415 specifier->print();
416 }
417
418
419 void
420 ast_parameter_declarator::print(void) const
421 {
422 type->print();
423 if (identifier)
424 printf("%s ", identifier);
425 ast_opt_array_size_print(is_array, array_size);
426 }
427
428
429 void
430 ast_function_definition::print(void) const
431 {
432 prototype->print();
433 body->print();
434 }
435
436
437 void
438 ast_declaration::print(void) const
439 {
440 printf("%s ", identifier);
441 ast_opt_array_size_print(is_array, array_size);
442
443 if (initializer) {
444 printf("= ");
445 initializer->print();
446 }
447 }
448
449
450 ast_declaration::ast_declaration(char *identifier, int is_array,
451 ast_expression *array_size,
452 ast_expression *initializer)
453 {
454 this->identifier = identifier;
455 this->is_array = is_array;
456 this->array_size = array_size;
457 this->initializer = initializer;
458 }
459
460
461 void
462 ast_declarator_list::print(void) const
463 {
464 struct simple_node *head;
465 struct simple_node *ptr;
466
467 assert(type || invariant);
468
469 if (type)
470 type->print();
471 else
472 printf("invariant ");
473
474 head = first_elem(& declarations);
475 foreach (ptr, & declarations) {
476 if (ptr != head)
477 printf(", ");
478
479 ((ast_node *)ptr)->print();
480 }
481
482 printf("; ");
483 }
484
485
486 ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
487 {
488 this->type = type;
489 make_empty_list(& this->declarations);
490 }
491
492 void
493 ast_jump_statement::print(void) const
494 {
495 switch (mode) {
496 case ast_continue:
497 printf("continue; ");
498 break;
499 case ast_break:
500 printf("break; ");
501 break;
502 case ast_return:
503 printf("return ");
504 if (opt_return_value)
505 opt_return_value->print();
506
507 printf("; ");
508 break;
509 case ast_discard:
510 printf("discard; ");
511 break;
512 }
513 }
514
515
516 ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
517 {
518 this->mode = ast_jump_modes(mode);
519
520 if (mode == ast_return)
521 opt_return_value = return_value;
522 }
523
524
525 void
526 ast_selection_statement::print(void) const
527 {
528 printf("if ( ");
529 condition->print();
530 printf(") ");
531
532 then_statement->print();
533
534 if (else_statement) {
535 printf("else ");
536 else_statement->print();
537 }
538
539 }
540
541
542 ast_selection_statement::ast_selection_statement(ast_expression *condition,
543 ast_node *then_statement,
544 ast_node *else_statement)
545 {
546 this->condition = condition;
547 this->then_statement = then_statement;
548 this->else_statement = else_statement;
549 }
550
551
552 void
553 ast_iteration_statement::print(void) const
554 {
555 switch (mode) {
556 case ast_for:
557 printf("for( ");
558 if (init_statement)
559 init_statement->print();
560 printf("; ");
561
562 if (condition)
563 condition->print();
564 printf("; ");
565
566 if (rest_expression)
567 rest_expression->print();
568 printf(") ");
569
570 body->print();
571 break;
572
573 case ast_while:
574 printf("while ( ");
575 if (condition)
576 condition->print();
577 printf(") ");
578 body->print();
579 break;
580
581 case ast_do_while:
582 printf("do ");
583 body->print();
584 printf("while ( ");
585 if (condition)
586 condition->print();
587 printf("); ");
588 break;
589 }
590 }
591
592
593 ast_iteration_statement::ast_iteration_statement(int mode,
594 ast_node *init,
595 ast_node *condition,
596 ast_expression *rest_expression,
597 ast_node *body)
598 {
599 this->mode = ast_iteration_modes(mode);
600 this->init_statement = init;
601 this->condition = condition;
602 this->rest_expression = rest_expression;
603 this->body = body;
604 }
605
606
607 void
608 ast_struct_specifier::print(void) const
609 {
610 struct simple_node *ptr;
611
612 printf("struct %s { ", name);
613 foreach (ptr, & declarations) {
614 ((ast_node *)ptr)->print();
615 }
616 printf("} ");
617 }
618
619
620 ast_struct_specifier::ast_struct_specifier(char *identifier,
621 ast_node *declarator_list)
622 {
623 name = identifier;
624
625 /* This seems odd, but it works. The simple_list is,
626 * basically, a circular list. insert_at_tail adds
627 * the specified node to the list before the current
628 * head.
629 */
630 insert_at_tail((struct simple_node *) declarator_list,
631 & declarations);
632 }
633
634
635 static char *
636 load_text_file(const char *file_name, size_t *size)
637 {
638 char *text = NULL;
639 struct stat st;
640 ssize_t total_read = 0;
641 int fd = open(file_name, O_RDONLY);
642
643 *size = 0;
644 if (fd < 0) {
645 return NULL;
646 }
647
648 if (fstat(fd, & st) == 0) {
649 text = (char *) malloc(st.st_size + 1);
650 if (text != NULL) {
651 do {
652 ssize_t bytes = read(fd, text + total_read,
653 st.st_size - total_read);
654 if (bytes < 0) {
655 free(text);
656 text = NULL;
657 break;
658 }
659
660 if (bytes == 0) {
661 break;
662 }
663
664 total_read += bytes;
665 } while (total_read < st.st_size);
666
667 text[total_read] = '\0';
668 *size = total_read;
669 }
670 }
671
672 close(fd);
673
674 return text;
675 }
676
677
678 int
679 main(int argc, char **argv)
680 {
681 struct _mesa_glsl_parse_state state;
682 char *shader;
683 size_t shader_len;
684 struct simple_node *ptr;
685 exec_list instructions;
686
687 (void) argc;
688 shader = load_text_file(argv[1], & shader_len);
689
690 state.scanner = NULL;
691 make_empty_list(& state.translation_unit);
692 state.symbols = _mesa_symbol_table_ctor();
693
694 _mesa_glsl_lexer_ctor(& state, shader, shader_len);
695 _mesa_glsl_parse(& state);
696 _mesa_glsl_lexer_dtor(& state);
697
698 foreach (ptr, & state.translation_unit) {
699 ((ast_node *)ptr)->print();
700 }
701
702 foreach (ptr, & state.translation_unit) {
703 ((ast_node *)ptr)->hir(&instructions, &state);
704 }
705
706 printf("\n\n");
707 foreach_iter(exec_list_iterator, iter, instructions) {
708 ir_print_visitor v;
709
710 ((ir_instruction *)iter.get())->accept(& v);
711 }
712
713 _mesa_symbol_table_dtor(state.symbols);
714
715 return 0;
716 }