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