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