blob: e7f34864d53099513aab2035838e38ff9fb38efc [file] [log] [blame]
Ian Romanicka87ac252010-02-22 13:19:34 -08001/*
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"
Ian Romanickd59673c2010-02-25 17:17:23 -080036#include "glsl_parser.h"
Ian Romanicka87ac252010-02-22 13:19:34 -080037#include "symbol_table.h"
Ian Romanick1c4156f2010-03-10 09:27:03 -080038#include "ir_print_visitor.h"
Ian Romanicka87ac252010-02-22 13:19:34 -080039
40void
Ian Romanick1f585182010-03-11 14:08:33 -080041_mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
42 const char *fmt, ...)
Ian Romanicka87ac252010-02-22 13:19:34 -080043{
44 char buf[1024];
45 int len;
46 va_list ap;
47
Ian Romanick1f585182010-03-11 14:08:33 -080048 if (state)
49 state->error = true;
50
Ian Romanicka87ac252010-02-22 13:19:34 -080051 len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ",
52 locp->source, locp->first_line, locp->first_column);
53
54 va_start(ap, fmt);
55 vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
56 va_end(ap);
57
58 printf("%s\n", buf);
59}
60
61
62ast_node::~ast_node()
63{
64 /* empty */
65}
66
67
68void
69_mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
70{
71 if (q->constant)
72 printf("const ");
73
74 if (q->invariant)
75 printf("invariant ");
76
77 if (q->attribute)
78 printf("attribute ");
79
80 if (q->varying)
81 printf("varying ");
82
83 if (q->in && q->out)
84 printf("inout ");
85 else {
86 if (q->in)
87 printf("in ");
88
89 if (q->out)
90 printf("out ");
91 }
92
93 if (q->centroid)
94 printf("centroid ");
95 if (q->uniform)
96 printf("uniform ");
97 if (q->smooth)
98 printf("smooth ");
99 if (q->flat)
100 printf("flat ");
101 if (q->noperspective)
102 printf("noperspective ");
103}
104
105
106void
107ast_node::print(void) const
108{
109 printf("node_%d ", type);
110}
111
112
113ast_node::ast_node(void)
114{
Ian Romanick53d27742010-02-22 13:22:10 -0800115 make_empty_list(this);
Ian Romanicka87ac252010-02-22 13:19:34 -0800116}
117
Ian Romanicka87ac252010-02-22 13:19:34 -0800118
119static void
120ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
121{
122 if (is_array) {
123 printf("[ ");
124
125 if (array_size)
126 array_size->print();
127
128 printf("] ");
129 }
130}
131
132
Ian Romanicka87ac252010-02-22 13:19:34 -0800133void
134ast_compound_statement::print(void) const
135{
136 const struct simple_node *ptr;
137
138 printf("{\n");
139
140 foreach(ptr, & statements) {
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800141 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800142 }
143
144 printf("}\n");
145}
146
147
148ast_compound_statement::ast_compound_statement(int new_scope,
149 ast_node *statements)
150{
151 this->new_scope = new_scope;
152 make_empty_list(& this->statements);
153
154 if (statements != NULL) {
155 /* This seems odd, but it works. The simple_list is,
156 * basically, a circular list. insert_at_tail adds
157 * the specified node to the list before the current
158 * head.
159 */
160 insert_at_tail((struct simple_node *) statements,
161 & this->statements);
162 }
163}
164
165
166void
167ast_expression::print(void) const
168{
Ian Romanicka87ac252010-02-22 13:19:34 -0800169 switch (oper) {
170 case ast_assign:
Ian Romanicka87ac252010-02-22 13:19:34 -0800171 case ast_mul_assign:
172 case ast_div_assign:
173 case ast_mod_assign:
174 case ast_add_assign:
175 case ast_sub_assign:
176 case ast_ls_assign:
177 case ast_rs_assign:
178 case ast_and_assign:
179 case ast_xor_assign:
180 case ast_or_assign:
181 subexpressions[0]->print();
Ian Romanick88349b22010-02-22 19:10:25 -0800182 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800183 subexpressions[1]->print();
184 break;
185
186 case ast_field_selection:
187 subexpressions[0]->print();
188 printf(". %s ", primary_expression.identifier);
189 break;
190
191 case ast_plus:
192 case ast_neg:
193 case ast_bit_not:
194 case ast_logic_not:
195 case ast_pre_inc:
196 case ast_pre_dec:
Ian Romanick88349b22010-02-22 19:10:25 -0800197 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800198 subexpressions[0]->print();
199 break;
200
201 case ast_post_inc:
202 case ast_post_dec:
203 subexpressions[0]->print();
Ian Romanick88349b22010-02-22 19:10:25 -0800204 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800205 break;
206
207 case ast_conditional:
208 subexpressions[0]->print();
209 printf("? ");
210 subexpressions[1]->print();
211 printf(": ");
212 subexpressions[1]->print();
213 break;
214
215 case ast_array_index:
216 subexpressions[0]->print();
217 printf("[ ");
218 subexpressions[1]->print();
219 printf("] ");
220 break;
221
222 case ast_function_call: {
223 ast_expression *parameters = subexpressions[1];
224
225 subexpressions[0]->print();
226 printf("( ");
227
228 if (parameters != NULL) {
229 struct simple_node *ptr;
230
231 parameters->print();
232 foreach (ptr, (struct simple_node *) parameters) {
233 printf(", ");
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800234 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800235 }
236 }
237
238 printf(") ");
239 break;
240 }
241
242 case ast_identifier:
243 printf("%s ", primary_expression.identifier);
244 break;
245
246 case ast_int_constant:
247 printf("%d ", primary_expression.int_constant);
248 break;
249
250 case ast_uint_constant:
251 printf("%u ", primary_expression.uint_constant);
252 break;
253
254 case ast_float_constant:
255 printf("%f ", primary_expression.float_constant);
256 break;
257
258 case ast_bool_constant:
259 printf("%s ",
260 primary_expression.bool_constant
261 ? "true" : "false");
262 break;
263
264 case ast_sequence: {
265 struct simple_node *ptr;
266 struct simple_node *const head = first_elem(& expressions);
267
268 printf("( ");
269 foreach (ptr, & expressions) {
270 if (ptr != head)
271 printf(", ");
272
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800273 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800274 }
275 printf(") ");
276 break;
277 }
Ian Romanick88349b22010-02-22 19:10:25 -0800278
279 default:
280 assert(0);
281 break;
Ian Romanicka87ac252010-02-22 13:19:34 -0800282 }
283}
284
285ast_expression::ast_expression(int oper,
286 ast_expression *ex0,
287 ast_expression *ex1,
288 ast_expression *ex2)
289{
290 this->oper = ast_operators(oper);
291 this->subexpressions[0] = ex0;
292 this->subexpressions[1] = ex1;
293 this->subexpressions[2] = ex2;
294 make_empty_list(& expressions);
295}
296
297
298void
299ast_expression_statement::print(void) const
300{
301 if (expression)
302 expression->print();
303
304 printf("; ");
305}
306
307
308ast_expression_statement::ast_expression_statement(ast_expression *ex) :
309 expression(ex)
310{
311 /* empty */
312}
313
314
315void
316ast_function::print(void) const
317{
318 struct simple_node *ptr;
319
320 return_type->print();
321 printf(" %s (", identifier);
322
323 foreach(ptr, & parameters) {
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800324 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800325 }
326
327 printf(")");
328}
329
330
331ast_function::ast_function(void)
332{
333 make_empty_list(& parameters);
334}
335
336
337void
338ast_fully_specified_type::print(void) const
339{
340 _mesa_ast_type_qualifier_print(& qualifier);
341 specifier->print();
342}
343
344
345void
346ast_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
355void
356ast_function_definition::print(void) const
357{
358 prototype->print();
359 body->print();
360}
361
362
363void
364ast_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
376ast_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
387void
388ast_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
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800405 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800406 }
407
408 printf("; ");
409}
410
411
412ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
413{
414 this->type = type;
415 make_empty_list(& this->declarations);
416}
417
418void
419ast_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
442ast_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
451void
452ast_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
468ast_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
478void
479ast_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
519ast_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
533void
534ast_struct_specifier::print(void) const
535{
536 struct simple_node *ptr;
537
538 printf("struct %s { ", name);
539 foreach (ptr, & declarations) {
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800540 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800541 }
542 printf("} ");
543}
544
545
546ast_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
561static char *
562load_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
604int
605main(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;
Ian Romanick0044e7e2010-03-08 23:44:00 -0800611 exec_list instructions;
Ian Romanicka87ac252010-02-22 13:19:34 -0800612
Ian Romanick8e6cd3b2010-03-10 09:31:30 -0800613 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);
Ian Romanicka87ac252010-02-22 13:19:34 -0800634
635 state.scanner = NULL;
636 make_empty_list(& state.translation_unit);
637 state.symbols = _mesa_symbol_table_ctor();
Ian Romanick1f585182010-03-11 14:08:33 -0800638 state.error = false;
Ian Romanicka87ac252010-02-22 13:19:34 -0800639
640 _mesa_glsl_lexer_ctor(& state, shader, shader_len);
641 _mesa_glsl_parse(& state);
642 _mesa_glsl_lexer_dtor(& state);
643
644 foreach (ptr, & state.translation_unit) {
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800645 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800646 }
647
Ian Romanickd949a9a2010-03-10 09:55:22 -0800648 _mesa_ast_to_hir(&instructions, &state);
Ian Romanicka87ac252010-02-22 13:19:34 -0800649
Ian Romanick1c4156f2010-03-10 09:27:03 -0800650 printf("\n\n");
Ian Romanick1c4156f2010-03-10 09:27:03 -0800651
Ian Romanick1f585182010-03-11 14:08:33 -0800652 if (!state.error) {
653 foreach_iter(exec_list_iterator, iter, instructions) {
654 ir_print_visitor v;
655
656 ((ir_instruction *)iter.get())->accept(& v);
657 }
Ian Romanick1c4156f2010-03-10 09:27:03 -0800658 }
659
Ian Romanicka87ac252010-02-22 13:19:34 -0800660 _mesa_symbol_table_dtor(state.symbols);
661
662 return 0;
663}