glsl: Refactor variable declaration handling.
[mesa.git] / src / glsl / 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 <string.h>
26 #include <assert.h>
27
28 extern "C" {
29 #include <talloc.h>
30 #include "main/core.h" /* for struct __GLcontextRec */
31 }
32
33 #include "ast.h"
34 #include "glsl_parser_extras.h"
35 #include "glsl_parser.h"
36 #include "ir_optimization.h"
37
38 _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct __GLcontextRec *ctx,
39 GLenum target, void *mem_ctx)
40 {
41 switch (target) {
42 case GL_VERTEX_SHADER: this->target = vertex_shader; break;
43 case GL_FRAGMENT_SHADER: this->target = fragment_shader; break;
44 case GL_GEOMETRY_SHADER: this->target = geometry_shader; break;
45 }
46
47 this->scanner = NULL;
48 this->translation_unit.make_empty();
49 this->symbols = new(mem_ctx) glsl_symbol_table;
50 this->info_log = talloc_strdup(mem_ctx, "");
51 this->error = false;
52 this->loop_or_switch_nesting = NULL;
53 this->ARB_texture_rectangle_enable = true;
54
55 if (ctx != NULL) {
56 this->extensions = &ctx->Extensions;
57
58 this->Const.MaxLights = ctx->Const.MaxLights;
59 this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes;
60 this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits;
61 this->Const.MaxTextureCoords = ctx->Const.MaxTextureCoordUnits;
62 this->Const.MaxVertexAttribs = ctx->Const.VertexProgram.MaxAttribs;
63 this->Const.MaxVertexUniformComponents = ctx->Const.VertexProgram.MaxUniformComponents;
64 this->Const.MaxVaryingFloats = ctx->Const.MaxVarying * 4;
65 this->Const.MaxVertexTextureImageUnits = ctx->Const.MaxVertexTextureImageUnits;
66 this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits;
67 this->Const.MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
68 this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
69
70 this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
71 } else {
72 /* If there is no GL context (standalone compiler), fill in constants
73 * with the minimum required values.
74 */
75 static struct gl_extensions null_extensions;
76
77 memset(&null_extensions, 0, sizeof(null_extensions));
78 null_extensions.ARB_draw_buffers = GL_TRUE;
79 null_extensions.ARB_fragment_coord_conventions = GL_TRUE;
80 null_extensions.EXT_texture_array = GL_TRUE;
81 null_extensions.NV_texture_rectangle = GL_TRUE;
82
83 this->extensions = &null_extensions;
84
85 /* 1.10 minimums. */
86 this->Const.MaxLights = 8;
87 this->Const.MaxClipPlanes = 8;
88 this->Const.MaxTextureUnits = 2;
89
90 /* More than the 1.10 minimum to appease parser tests taken from
91 * apps that (hopefully) already checked the number of coords.
92 */
93 this->Const.MaxTextureCoords = 4;
94
95 this->Const.MaxVertexAttribs = 16;
96 this->Const.MaxVertexUniformComponents = 512;
97 this->Const.MaxVaryingFloats = 32;
98 this->Const.MaxVertexTextureImageUnits = 0;
99 this->Const.MaxCombinedTextureImageUnits = 2;
100 this->Const.MaxTextureImageUnits = 2;
101 this->Const.MaxFragmentUniformComponents = 64;
102
103 this->Const.MaxDrawBuffers = 2;
104 }
105 }
106
107 const char *
108 _mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
109 {
110 switch (target) {
111 case vertex_shader: return "vertex";
112 case fragment_shader: return "fragment";
113 case geometry_shader: return "geometry";
114 case ir_shader: break;
115 }
116
117 assert(!"Should not get here.");
118 return "unknown";
119 }
120
121
122 void
123 _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
124 const char *fmt, ...)
125 {
126 va_list ap;
127
128 state->error = true;
129
130 assert(state->info_log != NULL);
131 state->info_log = talloc_asprintf_append(state->info_log,
132 "%u:%u(%u): error: ",
133 locp->source,
134 locp->first_line,
135 locp->first_column);
136 va_start(ap, fmt);
137 state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
138 va_end(ap);
139 state->info_log = talloc_strdup_append(state->info_log, "\n");
140 }
141
142
143 void
144 _mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
145 const char *fmt, ...)
146 {
147 va_list ap;
148
149 assert(state->info_log != NULL);
150 state->info_log = talloc_asprintf_append(state->info_log,
151 "%u:%u(%u): warning: ",
152 locp->source,
153 locp->first_line,
154 locp->first_column);
155 va_start(ap, fmt);
156 state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
157 va_end(ap);
158 state->info_log = talloc_strdup_append(state->info_log, "\n");
159 }
160
161
162 bool
163 _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
164 const char *behavior, YYLTYPE *behavior_locp,
165 _mesa_glsl_parse_state *state)
166 {
167 enum {
168 extension_disable,
169 extension_enable,
170 extension_require,
171 extension_warn
172 } ext_mode;
173
174 if (strcmp(behavior, "warn") == 0) {
175 ext_mode = extension_warn;
176 } else if (strcmp(behavior, "require") == 0) {
177 ext_mode = extension_require;
178 } else if (strcmp(behavior, "enable") == 0) {
179 ext_mode = extension_enable;
180 } else if (strcmp(behavior, "disable") == 0) {
181 ext_mode = extension_disable;
182 } else {
183 _mesa_glsl_error(behavior_locp, state,
184 "Unknown extension behavior `%s'",
185 behavior);
186 return false;
187 }
188
189 bool unsupported = false;
190
191 if (strcmp(name, "all") == 0) {
192 if ((ext_mode == extension_enable) || (ext_mode == extension_require)) {
193 _mesa_glsl_error(name_locp, state, "Cannot %s all extensions",
194 (ext_mode == extension_enable)
195 ? "enable" : "require");
196 return false;
197 }
198 } else if (strcmp(name, "GL_ARB_draw_buffers") == 0) {
199 /* This extension is only supported in fragment shaders.
200 */
201 if (state->target != fragment_shader) {
202 unsupported = true;
203 } else {
204 state->ARB_draw_buffers_enable = (ext_mode != extension_disable);
205 state->ARB_draw_buffers_warn = (ext_mode == extension_warn);
206 }
207 } else if (strcmp(name, "GL_ARB_fragment_coord_conventions") == 0) {
208 state->ARB_fragment_coord_conventions_enable =
209 (ext_mode != extension_disable);
210 state->ARB_fragment_coord_conventions_warn =
211 (ext_mode == extension_warn);
212
213 unsupported = !state->extensions->ARB_fragment_coord_conventions;
214 } else if (strcmp(name, "GL_ARB_texture_rectangle") == 0) {
215 state->ARB_texture_rectangle_enable = (ext_mode != extension_disable);
216 state->ARB_texture_rectangle_warn = (ext_mode == extension_warn);
217 } else if (strcmp(name, "GL_EXT_texture_array") == 0) {
218 state->EXT_texture_array_enable = (ext_mode != extension_disable);
219 state->EXT_texture_array_warn = (ext_mode == extension_warn);
220
221 unsupported = !state->extensions->EXT_texture_array;
222 } else {
223 unsupported = true;
224 }
225
226 if (unsupported) {
227 static const char *const fmt = "extension `%s' unsupported in %s shader";
228
229 if (ext_mode == extension_require) {
230 _mesa_glsl_error(name_locp, state, fmt,
231 name, _mesa_glsl_shader_target_name(state->target));
232 return false;
233 } else {
234 _mesa_glsl_warning(name_locp, state, fmt,
235 name, _mesa_glsl_shader_target_name(state->target));
236 }
237 }
238
239 return true;
240 }
241
242 void
243 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
244 {
245 if (q->constant)
246 printf("const ");
247
248 if (q->invariant)
249 printf("invariant ");
250
251 if (q->attribute)
252 printf("attribute ");
253
254 if (q->varying)
255 printf("varying ");
256
257 if (q->in && q->out)
258 printf("inout ");
259 else {
260 if (q->in)
261 printf("in ");
262
263 if (q->out)
264 printf("out ");
265 }
266
267 if (q->centroid)
268 printf("centroid ");
269 if (q->uniform)
270 printf("uniform ");
271 if (q->smooth)
272 printf("smooth ");
273 if (q->flat)
274 printf("flat ");
275 if (q->noperspective)
276 printf("noperspective ");
277 }
278
279
280 void
281 ast_node::print(void) const
282 {
283 printf("unhandled node ");
284 }
285
286
287 ast_node::ast_node(void)
288 {
289 this->location.source = 0;
290 this->location.line = 0;
291 this->location.column = 0;
292 }
293
294
295 static void
296 ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
297 {
298 if (is_array) {
299 printf("[ ");
300
301 if (array_size)
302 array_size->print();
303
304 printf("] ");
305 }
306 }
307
308
309 void
310 ast_compound_statement::print(void) const
311 {
312 printf("{\n");
313
314 foreach_list_const(n, &this->statements) {
315 ast_node *ast = exec_node_data(ast_node, n, link);
316 ast->print();
317 }
318
319 printf("}\n");
320 }
321
322
323 ast_compound_statement::ast_compound_statement(int new_scope,
324 ast_node *statements)
325 {
326 this->new_scope = new_scope;
327
328 if (statements != NULL) {
329 this->statements.push_degenerate_list_at_head(&statements->link);
330 }
331 }
332
333
334 void
335 ast_expression::print(void) const
336 {
337 switch (oper) {
338 case ast_assign:
339 case ast_mul_assign:
340 case ast_div_assign:
341 case ast_mod_assign:
342 case ast_add_assign:
343 case ast_sub_assign:
344 case ast_ls_assign:
345 case ast_rs_assign:
346 case ast_and_assign:
347 case ast_xor_assign:
348 case ast_or_assign:
349 subexpressions[0]->print();
350 printf("%s ", operator_string(oper));
351 subexpressions[1]->print();
352 break;
353
354 case ast_field_selection:
355 subexpressions[0]->print();
356 printf(". %s ", primary_expression.identifier);
357 break;
358
359 case ast_plus:
360 case ast_neg:
361 case ast_bit_not:
362 case ast_logic_not:
363 case ast_pre_inc:
364 case ast_pre_dec:
365 printf("%s ", operator_string(oper));
366 subexpressions[0]->print();
367 break;
368
369 case ast_post_inc:
370 case ast_post_dec:
371 subexpressions[0]->print();
372 printf("%s ", operator_string(oper));
373 break;
374
375 case ast_conditional:
376 subexpressions[0]->print();
377 printf("? ");
378 subexpressions[1]->print();
379 printf(": ");
380 subexpressions[1]->print();
381 break;
382
383 case ast_array_index:
384 subexpressions[0]->print();
385 printf("[ ");
386 subexpressions[1]->print();
387 printf("] ");
388 break;
389
390 case ast_function_call: {
391 subexpressions[0]->print();
392 printf("( ");
393
394 foreach_list_const (n, &this->expressions) {
395 if (n != this->expressions.get_head())
396 printf(", ");
397
398 ast_node *ast = exec_node_data(ast_node, n, link);
399 ast->print();
400 }
401
402 printf(") ");
403 break;
404 }
405
406 case ast_identifier:
407 printf("%s ", primary_expression.identifier);
408 break;
409
410 case ast_int_constant:
411 printf("%d ", primary_expression.int_constant);
412 break;
413
414 case ast_uint_constant:
415 printf("%u ", primary_expression.uint_constant);
416 break;
417
418 case ast_float_constant:
419 printf("%f ", primary_expression.float_constant);
420 break;
421
422 case ast_bool_constant:
423 printf("%s ",
424 primary_expression.bool_constant
425 ? "true" : "false");
426 break;
427
428 case ast_sequence: {
429 printf("( ");
430 foreach_list_const(n, & this->expressions) {
431 if (n != this->expressions.get_head())
432 printf(", ");
433
434 ast_node *ast = exec_node_data(ast_node, n, link);
435 ast->print();
436 }
437 printf(") ");
438 break;
439 }
440
441 default:
442 assert(0);
443 break;
444 }
445 }
446
447 ast_expression::ast_expression(int oper,
448 ast_expression *ex0,
449 ast_expression *ex1,
450 ast_expression *ex2)
451 {
452 this->oper = ast_operators(oper);
453 this->subexpressions[0] = ex0;
454 this->subexpressions[1] = ex1;
455 this->subexpressions[2] = ex2;
456 }
457
458
459 void
460 ast_expression_statement::print(void) const
461 {
462 if (expression)
463 expression->print();
464
465 printf("; ");
466 }
467
468
469 ast_expression_statement::ast_expression_statement(ast_expression *ex) :
470 expression(ex)
471 {
472 /* empty */
473 }
474
475
476 void
477 ast_function::print(void) const
478 {
479 return_type->print();
480 printf(" %s (", identifier);
481
482 foreach_list_const(n, & this->parameters) {
483 ast_node *ast = exec_node_data(ast_node, n, link);
484 ast->print();
485 }
486
487 printf(")");
488 }
489
490
491 ast_function::ast_function(void)
492 : is_definition(false), signature(NULL)
493 {
494 /* empty */
495 }
496
497
498 void
499 ast_fully_specified_type::print(void) const
500 {
501 _mesa_ast_type_qualifier_print(& qualifier);
502 specifier->print();
503 }
504
505
506 void
507 ast_parameter_declarator::print(void) const
508 {
509 type->print();
510 if (identifier)
511 printf("%s ", identifier);
512 ast_opt_array_size_print(is_array, array_size);
513 }
514
515
516 void
517 ast_function_definition::print(void) const
518 {
519 prototype->print();
520 body->print();
521 }
522
523
524 void
525 ast_declaration::print(void) const
526 {
527 printf("%s ", identifier);
528 ast_opt_array_size_print(is_array, array_size);
529
530 if (initializer) {
531 printf("= ");
532 initializer->print();
533 }
534 }
535
536
537 ast_declaration::ast_declaration(char *identifier, int is_array,
538 ast_expression *array_size,
539 ast_expression *initializer)
540 {
541 this->identifier = identifier;
542 this->is_array = is_array;
543 this->array_size = array_size;
544 this->initializer = initializer;
545 }
546
547
548 void
549 ast_declarator_list::print(void) const
550 {
551 assert(type || invariant);
552
553 if (type)
554 type->print();
555 else
556 printf("invariant ");
557
558 foreach_list_const (ptr, & this->declarations) {
559 if (ptr != this->declarations.get_head())
560 printf(", ");
561
562 ast_node *ast = exec_node_data(ast_node, ptr, link);
563 ast->print();
564 }
565
566 printf("; ");
567 }
568
569
570 ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
571 {
572 this->type = type;
573 this->invariant = false;
574 }
575
576 void
577 ast_jump_statement::print(void) const
578 {
579 switch (mode) {
580 case ast_continue:
581 printf("continue; ");
582 break;
583 case ast_break:
584 printf("break; ");
585 break;
586 case ast_return:
587 printf("return ");
588 if (opt_return_value)
589 opt_return_value->print();
590
591 printf("; ");
592 break;
593 case ast_discard:
594 printf("discard; ");
595 break;
596 }
597 }
598
599
600 ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
601 {
602 this->mode = ast_jump_modes(mode);
603
604 if (mode == ast_return)
605 opt_return_value = return_value;
606 }
607
608
609 void
610 ast_selection_statement::print(void) const
611 {
612 printf("if ( ");
613 condition->print();
614 printf(") ");
615
616 then_statement->print();
617
618 if (else_statement) {
619 printf("else ");
620 else_statement->print();
621 }
622
623 }
624
625
626 ast_selection_statement::ast_selection_statement(ast_expression *condition,
627 ast_node *then_statement,
628 ast_node *else_statement)
629 {
630 this->condition = condition;
631 this->then_statement = then_statement;
632 this->else_statement = else_statement;
633 }
634
635
636 void
637 ast_iteration_statement::print(void) const
638 {
639 switch (mode) {
640 case ast_for:
641 printf("for( ");
642 if (init_statement)
643 init_statement->print();
644 printf("; ");
645
646 if (condition)
647 condition->print();
648 printf("; ");
649
650 if (rest_expression)
651 rest_expression->print();
652 printf(") ");
653
654 body->print();
655 break;
656
657 case ast_while:
658 printf("while ( ");
659 if (condition)
660 condition->print();
661 printf(") ");
662 body->print();
663 break;
664
665 case ast_do_while:
666 printf("do ");
667 body->print();
668 printf("while ( ");
669 if (condition)
670 condition->print();
671 printf("); ");
672 break;
673 }
674 }
675
676
677 ast_iteration_statement::ast_iteration_statement(int mode,
678 ast_node *init,
679 ast_node *condition,
680 ast_expression *rest_expression,
681 ast_node *body)
682 {
683 this->mode = ast_iteration_modes(mode);
684 this->init_statement = init;
685 this->condition = condition;
686 this->rest_expression = rest_expression;
687 this->body = body;
688 }
689
690
691 void
692 ast_struct_specifier::print(void) const
693 {
694 printf("struct %s { ", name);
695 foreach_list_const(n, &this->declarations) {
696 ast_node *ast = exec_node_data(ast_node, n, link);
697 ast->print();
698 }
699 printf("} ");
700 }
701
702
703 ast_struct_specifier::ast_struct_specifier(char *identifier,
704 ast_node *declarator_list)
705 {
706 name = identifier;
707 this->declarations.push_degenerate_list_at_head(&declarator_list->link);
708 }
709
710 bool
711 do_common_optimization(exec_list *ir, bool linked)
712 {
713 GLboolean progress = GL_FALSE;
714
715 progress = do_sub_to_add_neg(ir) || progress;
716
717 if (linked) {
718 progress = do_function_inlining(ir) || progress;
719 progress = do_dead_functions(ir) || progress;
720 }
721 progress = do_structure_splitting(ir) || progress;
722 progress = do_if_simplification(ir) || progress;
723 progress = do_copy_propagation(ir) || progress;
724 if (linked)
725 progress = do_dead_code(ir) || progress;
726 else
727 progress = do_dead_code_unlinked(ir) || progress;
728 progress = do_dead_code_local(ir) || progress;
729 progress = do_tree_grafting(ir) || progress;
730 progress = do_constant_propagation(ir) || progress;
731 if (linked)
732 progress = do_constant_variable(ir) || progress;
733 else
734 progress = do_constant_variable_unlinked(ir) || progress;
735 progress = do_constant_folding(ir) || progress;
736 progress = do_algebraic(ir) || progress;
737 progress = do_if_return(ir) || progress;
738 progress = do_vec_index_to_swizzle(ir) || progress;
739 progress = do_swizzle_swizzle(ir) || progress;
740 progress = do_noop_swizzle(ir) || progress;
741
742 return progress;
743 }
744
745 extern "C" {
746
747 /**
748 * To be called at GL teardown time, this frees compiler datastructures.
749 *
750 * After calling this, any previously compiled shaders and shader
751 * programs would be invalid. So this should happen at approximately
752 * program exit.
753 */
754 void
755 _mesa_destroy_shader_compiler(void)
756 {
757 _mesa_destroy_shader_compiler_caches();
758
759 _mesa_glsl_release_types();
760 }
761
762 /**
763 * Releases compiler caches to trade off performance for memory.
764 *
765 * Intended to be used with glReleaseShaderCompiler().
766 */
767 void
768 _mesa_destroy_shader_compiler_caches(void)
769 {
770 _mesa_glsl_release_functions();
771 }
772
773 }