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