blob: 265782ebdabf8ac971e555c4f786d2ca8ee34412 [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 Romanick1c4156f2010-03-10 09:27:03 -080037#include "ir_print_visitor.h"
Ian Romanicka87ac252010-02-22 13:19:34 -080038
39void
Ian Romanick1f585182010-03-11 14:08:33 -080040_mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
41 const char *fmt, ...)
Ian Romanicka87ac252010-02-22 13:19:34 -080042{
43 char buf[1024];
44 int len;
45 va_list ap;
46
Ian Romanick71d0bbf2010-03-23 13:21:19 -070047 state->error = true;
Ian Romanick1f585182010-03-11 14:08:33 -080048
Ian Romanicka87ac252010-02-22 13:19:34 -080049 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
60ast_node::~ast_node()
61{
62 /* empty */
63}
64
65
66void
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
104void
105ast_node::print(void) const
106{
107 printf("node_%d ", type);
108}
109
110
111ast_node::ast_node(void)
112{
Ian Romanick53d27742010-02-22 13:22:10 -0800113 make_empty_list(this);
Ian Romanicka87ac252010-02-22 13:19:34 -0800114}
115
Ian Romanicka87ac252010-02-22 13:19:34 -0800116
117static void
118ast_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
Ian Romanicka87ac252010-02-22 13:19:34 -0800131void
132ast_compound_statement::print(void) const
133{
134 const struct simple_node *ptr;
135
136 printf("{\n");
137
138 foreach(ptr, & statements) {
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800139 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800140 }
141
142 printf("}\n");
143}
144
145
146ast_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
164void
165ast_expression::print(void) const
166{
Ian Romanicka87ac252010-02-22 13:19:34 -0800167 switch (oper) {
168 case ast_assign:
Ian Romanicka87ac252010-02-22 13:19:34 -0800169 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();
Ian Romanick88349b22010-02-22 19:10:25 -0800180 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800181 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:
Ian Romanick88349b22010-02-22 19:10:25 -0800195 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800196 subexpressions[0]->print();
197 break;
198
199 case ast_post_inc:
200 case ast_post_dec:
201 subexpressions[0]->print();
Ian Romanick88349b22010-02-22 19:10:25 -0800202 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800203 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(", ");
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800232 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800233 }
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
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800271 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800272 }
273 printf(") ");
274 break;
275 }
Ian Romanick88349b22010-02-22 19:10:25 -0800276
277 default:
278 assert(0);
279 break;
Ian Romanicka87ac252010-02-22 13:19:34 -0800280 }
281}
282
283ast_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
296void
297ast_expression_statement::print(void) const
298{
299 if (expression)
300 expression->print();
301
302 printf("; ");
303}
304
305
306ast_expression_statement::ast_expression_statement(ast_expression *ex) :
307 expression(ex)
308{
309 /* empty */
310}
311
312
313void
314ast_function::print(void) const
315{
316 struct simple_node *ptr;
317
318 return_type->print();
319 printf(" %s (", identifier);
320
321 foreach(ptr, & parameters) {
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800322 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800323 }
324
325 printf(")");
326}
327
328
329ast_function::ast_function(void)
Ian Romanick92318a92010-03-31 18:23:21 -0700330 : is_definition(false), signature(NULL)
Ian Romanicka87ac252010-02-22 13:19:34 -0800331{
332 make_empty_list(& parameters);
333}
334
335
336void
337ast_fully_specified_type::print(void) const
338{
339 _mesa_ast_type_qualifier_print(& qualifier);
340 specifier->print();
341}
342
343
344void
345ast_parameter_declarator::print(void) const
346{
347 type->print();
348 if (identifier)
349 printf("%s ", identifier);
350 ast_opt_array_size_print(is_array, array_size);
351}
352
353
354void
355ast_function_definition::print(void) const
356{
357 prototype->print();
358 body->print();
359}
360
361
362void
363ast_declaration::print(void) const
364{
365 printf("%s ", identifier);
366 ast_opt_array_size_print(is_array, array_size);
367
368 if (initializer) {
369 printf("= ");
370 initializer->print();
371 }
372}
373
374
375ast_declaration::ast_declaration(char *identifier, int is_array,
376 ast_expression *array_size,
377 ast_expression *initializer)
378{
379 this->identifier = identifier;
380 this->is_array = is_array;
381 this->array_size = array_size;
382 this->initializer = initializer;
383}
384
385
386void
387ast_declarator_list::print(void) const
388{
389 struct simple_node *head;
390 struct simple_node *ptr;
391
392 assert(type || invariant);
393
394 if (type)
395 type->print();
396 else
397 printf("invariant ");
398
399 head = first_elem(& declarations);
400 foreach (ptr, & declarations) {
401 if (ptr != head)
402 printf(", ");
403
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800404 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800405 }
406
407 printf("; ");
408}
409
410
411ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
412{
413 this->type = type;
414 make_empty_list(& this->declarations);
415}
416
417void
418ast_jump_statement::print(void) const
419{
420 switch (mode) {
421 case ast_continue:
422 printf("continue; ");
423 break;
424 case ast_break:
425 printf("break; ");
426 break;
427 case ast_return:
428 printf("return ");
429 if (opt_return_value)
430 opt_return_value->print();
431
432 printf("; ");
433 break;
434 case ast_discard:
435 printf("discard; ");
436 break;
437 }
438}
439
440
441ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
442{
443 this->mode = ast_jump_modes(mode);
444
445 if (mode == ast_return)
446 opt_return_value = return_value;
447}
448
449
450void
451ast_selection_statement::print(void) const
452{
453 printf("if ( ");
454 condition->print();
455 printf(") ");
456
457 then_statement->print();
458
459 if (else_statement) {
460 printf("else ");
461 else_statement->print();
462 }
463
464}
465
466
467ast_selection_statement::ast_selection_statement(ast_expression *condition,
468 ast_node *then_statement,
469 ast_node *else_statement)
470{
471 this->condition = condition;
472 this->then_statement = then_statement;
473 this->else_statement = else_statement;
474}
475
476
477void
478ast_iteration_statement::print(void) const
479{
480 switch (mode) {
481 case ast_for:
482 printf("for( ");
483 if (init_statement)
484 init_statement->print();
485 printf("; ");
486
487 if (condition)
488 condition->print();
489 printf("; ");
490
491 if (rest_expression)
492 rest_expression->print();
493 printf(") ");
494
495 body->print();
496 break;
497
498 case ast_while:
499 printf("while ( ");
500 if (condition)
501 condition->print();
502 printf(") ");
503 body->print();
504 break;
505
506 case ast_do_while:
507 printf("do ");
508 body->print();
509 printf("while ( ");
510 if (condition)
511 condition->print();
512 printf("); ");
513 break;
514 }
515}
516
517
518ast_iteration_statement::ast_iteration_statement(int mode,
519 ast_node *init,
520 ast_node *condition,
521 ast_expression *rest_expression,
522 ast_node *body)
523{
524 this->mode = ast_iteration_modes(mode);
525 this->init_statement = init;
526 this->condition = condition;
527 this->rest_expression = rest_expression;
528 this->body = body;
529}
530
531
532void
533ast_struct_specifier::print(void) const
534{
535 struct simple_node *ptr;
536
537 printf("struct %s { ", name);
538 foreach (ptr, & declarations) {
Ian Romanicke41a1cd2010-02-25 12:49:55 -0800539 ((ast_node *)ptr)->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800540 }
541 printf("} ");
542}
543
544
545ast_struct_specifier::ast_struct_specifier(char *identifier,
546 ast_node *declarator_list)
547{
548 name = identifier;
549
550 /* This seems odd, but it works. The simple_list is,
551 * basically, a circular list. insert_at_tail adds
552 * the specified node to the list before the current
553 * head.
554 */
555 insert_at_tail((struct simple_node *) declarator_list,
556 & declarations);
557}
558
559
560static char *
561load_text_file(const char *file_name, size_t *size)
562{
563 char *text = NULL;
564 struct stat st;
565 ssize_t total_read = 0;
566 int fd = open(file_name, O_RDONLY);
567
568 *size = 0;
569 if (fd < 0) {
570 return NULL;
571 }
572
573 if (fstat(fd, & st) == 0) {
574 text = (char *) malloc(st.st_size + 1);
575 if (text != NULL) {
576 do {
577 ssize_t bytes = read(fd, text + total_read,
578 st.st_size - total_read);
579 if (bytes < 0) {
580 free(text);
581 text = NULL;
582 break;
583 }
584
585 if (bytes == 0) {
586 break;
587 }
588
589 total_read += bytes;
590 } while (total_read < st.st_size);
591
592 text[total_read] = '\0';
593 *size = total_read;
594 }
595 }
596
597 close(fd);
598
599 return text;
600}
601
602
603int
604main(int argc, char **argv)
605{
606 struct _mesa_glsl_parse_state state;
607 char *shader;
608 size_t shader_len;
609 struct simple_node *ptr;
Ian Romanick0044e7e2010-03-08 23:44:00 -0800610 exec_list instructions;
Ian Romanicka87ac252010-02-22 13:19:34 -0800611
Ian Romanick8e6cd3b2010-03-10 09:31:30 -0800612 if (argc < 3) {
613 printf("Usage: %s [v|g|f] <shader_file>\n", argv[0]);
614 return EXIT_FAILURE;
615 }
616
617 switch (argv[1][0]) {
618 case 'v':
619 state.target = vertex_shader;
620 break;
621 case 'g':
622 state.target = geometry_shader;
623 break;
624 case 'f':
625 state.target = fragment_shader;
626 break;
627 default:
628 printf("Usage: %s [v|g|f] <shader_file>\n", argv[0]);
629 return EXIT_FAILURE;
630 }
631
632 shader = load_text_file(argv[2], & shader_len);
Ian Romanicka87ac252010-02-22 13:19:34 -0800633
634 state.scanner = NULL;
635 make_empty_list(& state.translation_unit);
Ian Romanick8bde4ce2010-03-19 11:57:24 -0700636 state.symbols = new glsl_symbol_table;
Ian Romanick1f585182010-03-11 14:08:33 -0800637 state.error = false;
Ian Romanick5185a5f2010-03-29 15:20:42 -0700638 state.temp_index = 0;
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);
Ian Romanickd1464272010-03-25 18:29:25 -0700657 printf("\n");
Ian Romanick1f585182010-03-11 14:08:33 -0800658 }
Ian Romanick1c4156f2010-03-10 09:27:03 -0800659 }
660
Ian Romanick8bde4ce2010-03-19 11:57:24 -0700661 delete state.symbols;
Ian Romanicka87ac252010-02-22 13:19:34 -0800662
Eric Anholt7c15bb22010-03-25 14:37:25 -0700663 return state.error != 0;
Ian Romanicka87ac252010-02-22 13:19:34 -0800664}