[MESA]
[reactos.git] / reactos / dll / opengl / mesa / 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 "main/core.h" /* for struct gl_context */
30 }
31
32 #include "ralloc.h"
33 #include "ast.h"
34 #include "glsl_parser_extras.h"
35 #include "glsl_parser.h"
36 #include "ir_optimization.h"
37 #include "loop_analysis.h"
38
39 _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx,
40 GLenum target, void *mem_ctx)
41 {
42 switch (target) {
43 case GL_VERTEX_SHADER: this->target = vertex_shader; break;
44 case GL_FRAGMENT_SHADER: this->target = fragment_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 = ralloc_strdup(mem_ctx, "");
51 this->error = false;
52 this->loop_nesting_ast = NULL;
53 this->switch_state.switch_nesting_ast = NULL;
54
55 this->num_builtins_to_link = 0;
56
57 /* Set default language version and extensions */
58 this->language_version = 110;
59 this->es_shader = false;
60 this->ARB_texture_rectangle_enable = true;
61
62 this->extensions = &ctx->Extensions;
63
64 this->Const.MaxLights = ctx->Const.MaxLights;
65 this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes;
66 this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits;
67 this->Const.MaxTextureCoords = ctx->Const.MaxTextureCoordUnits;
68 this->Const.MaxVertexAttribs = ctx->Const.VertexProgram.MaxAttribs;
69 this->Const.MaxVertexUniformComponents = ctx->Const.VertexProgram.MaxUniformComponents;
70 this->Const.MaxVaryingFloats = ctx->Const.MaxVarying * 4;
71 this->Const.MaxVertexTextureImageUnits = ctx->Const.MaxVertexTextureImageUnits;
72 this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits;
73 this->Const.MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
74 this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
75
76 this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
77
78 /* Note: Once the OpenGL 3.0 'forward compatible' context or the OpenGL 3.2
79 * Core context is supported, this logic will need change. Older versions of
80 * GLSL are no longer supported outside the compatibility contexts of 3.x.
81 */
82 this->Const.GLSL_100ES = ctx->Extensions.ARB_ES2_compatibility;
83 this->Const.GLSL_110 = true;
84 this->Const.GLSL_120 = (ctx->Const.GLSLVersion >= 120);
85 this->Const.GLSL_130 = (ctx->Const.GLSLVersion >= 130);
86
87 const unsigned lowest_version = ctx->Extensions.ARB_ES2_compatibility ? 100 : 110;
88 const unsigned highest_version = ctx->Const.GLSLVersion;
89 char *supported = ralloc_strdup(this, "");
90
91 for (unsigned ver = lowest_version; ver <= highest_version; ver += 10) {
92 const char *const prefix = (ver == lowest_version)
93 ? ""
94 : ((ver == highest_version) ? ", and " : ", ");
95
96 ralloc_asprintf_append(& supported, "%s%d.%02d%s",
97 prefix,
98 ver / 100, ver % 100,
99 (ver == 100) ? " ES" : "");
100 }
101
102 this->supported_version_string = supported;
103
104 if (ctx->Const.ForceGLSLExtensionsWarn)
105 _mesa_glsl_process_extension("all", NULL, "warn", NULL, this);
106 }
107
108 const char *
109 _mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
110 {
111 switch (target) {
112 case vertex_shader: return "vertex";
113 case fragment_shader: return "fragment";
114 }
115
116 assert(!"Should not get here.");
117 return "unknown";
118 }
119
120
121 void
122 _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
123 const char *fmt, ...)
124 {
125 va_list ap;
126
127 state->error = true;
128
129 assert(state->info_log != NULL);
130 ralloc_asprintf_append(&state->info_log, "%u:%u(%u): error: ",
131 locp->source,
132 locp->first_line,
133 locp->first_column);
134 va_start(ap, fmt);
135 ralloc_vasprintf_append(&state->info_log, fmt, ap);
136 va_end(ap);
137 ralloc_strcat(&state->info_log, "\n");
138 }
139
140
141 void
142 _mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
143 const char *fmt, ...)
144 {
145 va_list ap;
146
147 assert(state->info_log != NULL);
148 ralloc_asprintf_append(&state->info_log, "%u:%u(%u): warning: ",
149 locp->source,
150 locp->first_line,
151 locp->first_column);
152 va_start(ap, fmt);
153 ralloc_vasprintf_append(&state->info_log, fmt, ap);
154 va_end(ap);
155 ralloc_strcat(&state->info_log, "\n");
156 }
157
158
159 /**
160 * Enum representing the possible behaviors that can be specified in
161 * an #extension directive.
162 */
163 enum ext_behavior {
164 extension_disable,
165 extension_enable,
166 extension_require,
167 extension_warn
168 };
169
170 /**
171 * Element type for _mesa_glsl_supported_extensions
172 */
173 struct _mesa_glsl_extension {
174 /**
175 * Name of the extension when referred to in a GLSL extension
176 * statement
177 */
178 const char *name;
179
180 /** True if this extension is available to vertex shaders */
181 bool avail_in_VS;
182
183 /** True if this extension is available to geometry shaders */
184 bool avail_in_GS;
185
186 /** True if this extension is available to fragment shaders */
187 bool avail_in_FS;
188
189 /** True if this extension is available to desktop GL shaders */
190 bool avail_in_GL;
191
192 /** True if this extension is available to GLES shaders */
193 bool avail_in_ES;
194
195 /**
196 * Flag in the gl_extensions struct indicating whether this
197 * extension is supported by the driver, or
198 * &gl_extensions::dummy_true if supported by all drivers.
199 *
200 * Note: the type (GLboolean gl_extensions::*) is a "pointer to
201 * member" type, the type-safe alternative to the "offsetof" macro.
202 * In a nutshell:
203 *
204 * - foo bar::* p declares p to be an "offset" to a field of type
205 * foo that exists within struct bar
206 * - &bar::baz computes the "offset" of field baz within struct bar
207 * - x.*p accesses the field of x that exists at "offset" p
208 * - x->*p is equivalent to (*x).*p
209 */
210 const GLboolean gl_extensions::* supported_flag;
211
212 /**
213 * Flag in the _mesa_glsl_parse_state struct that should be set
214 * when this extension is enabled.
215 *
216 * See note in _mesa_glsl_extension::supported_flag about "pointer
217 * to member" types.
218 */
219 bool _mesa_glsl_parse_state::* enable_flag;
220
221 /**
222 * Flag in the _mesa_glsl_parse_state struct that should be set
223 * when the shader requests "warn" behavior for this extension.
224 *
225 * See note in _mesa_glsl_extension::supported_flag about "pointer
226 * to member" types.
227 */
228 bool _mesa_glsl_parse_state::* warn_flag;
229
230
231 bool compatible_with_state(const _mesa_glsl_parse_state *state) const;
232 void set_flags(_mesa_glsl_parse_state *state, ext_behavior behavior) const;
233 };
234
235 #define EXT(NAME, VS, GS, FS, GL, ES, SUPPORTED_FLAG) \
236 { "GL_" #NAME, VS, GS, FS, GL, ES, &gl_extensions::SUPPORTED_FLAG, \
237 &_mesa_glsl_parse_state::NAME##_enable, \
238 &_mesa_glsl_parse_state::NAME##_warn }
239
240 /**
241 * Table of extensions that can be enabled/disabled within a shader,
242 * and the conditions under which they are supported.
243 */
244 static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
245 /* target availability API availability */
246 /* name VS GS FS GL ES supported flag */
247 EXT(ARB_conservative_depth, false, false, true, true, false, ARB_conservative_depth),
248 EXT(ARB_draw_buffers, false, false, true, true, false, dummy_true),
249 EXT(ARB_draw_instanced, true, false, false, true, false, ARB_draw_instanced),
250 EXT(ARB_texture_rectangle, true, false, true, true, false, dummy_true),
251 EXT(EXT_texture_array, true, false, true, true, false, EXT_texture_array),
252 EXT(ARB_shader_texture_lod, true, false, true, true, false, ARB_shader_texture_lod),
253 EXT(ARB_shader_stencil_export, false, false, true, true, false, ARB_shader_stencil_export),
254 EXT(AMD_conservative_depth, false, false, true, true, false, ARB_conservative_depth),
255 EXT(AMD_shader_stencil_export, false, false, true, true, false, ARB_shader_stencil_export),
256 EXT(OES_texture_3D, true, false, true, false, true, EXT_texture3D),
257 };
258
259 #undef EXT
260
261
262 /**
263 * Determine whether a given extension is compatible with the target,
264 * API, and extension information in the current parser state.
265 */
266 bool _mesa_glsl_extension::compatible_with_state(const _mesa_glsl_parse_state *
267 state) const
268 {
269 /* Check that this extension matches the type of shader we are
270 * compiling to.
271 */
272 switch (state->target) {
273 case vertex_shader:
274 if (!this->avail_in_VS) {
275 return false;
276 }
277 break;
278 case fragment_shader:
279 if (!this->avail_in_FS) {
280 return false;
281 }
282 break;
283 default:
284 assert (!"Unrecognized shader target");
285 return false;
286 }
287
288 /* Check that this extension matches whether we are compiling
289 * for desktop GL or GLES.
290 */
291 if (state->es_shader) {
292 if (!this->avail_in_ES) return false;
293 } else {
294 if (!this->avail_in_GL) return false;
295 }
296
297 /* Check that this extension is supported by the OpenGL
298 * implementation.
299 *
300 * Note: the ->* operator indexes into state->extensions by the
301 * offset this->supported_flag. See
302 * _mesa_glsl_extension::supported_flag for more info.
303 */
304 return state->extensions->*(this->supported_flag);
305 }
306
307 /**
308 * Set the appropriate flags in the parser state to establish the
309 * given behavior for this extension.
310 */
311 void _mesa_glsl_extension::set_flags(_mesa_glsl_parse_state *state,
312 ext_behavior behavior) const
313 {
314 /* Note: the ->* operator indexes into state by the
315 * offsets this->enable_flag and this->warn_flag. See
316 * _mesa_glsl_extension::supported_flag for more info.
317 */
318 state->*(this->enable_flag) = (behavior != extension_disable);
319 state->*(this->warn_flag) = (behavior == extension_warn);
320 }
321
322 /**
323 * Find an extension by name in _mesa_glsl_supported_extensions. If
324 * the name is not found, return NULL.
325 */
326 static const _mesa_glsl_extension *find_extension(const char *name)
327 {
328 for (unsigned i = 0; i < Elements(_mesa_glsl_supported_extensions); ++i) {
329 if (strcmp(name, _mesa_glsl_supported_extensions[i].name) == 0) {
330 return &_mesa_glsl_supported_extensions[i];
331 }
332 }
333 return NULL;
334 }
335
336
337 bool
338 _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
339 const char *behavior_string, YYLTYPE *behavior_locp,
340 _mesa_glsl_parse_state *state)
341 {
342 ext_behavior behavior;
343 if (strcmp(behavior_string, "warn") == 0) {
344 behavior = extension_warn;
345 } else if (strcmp(behavior_string, "require") == 0) {
346 behavior = extension_require;
347 } else if (strcmp(behavior_string, "enable") == 0) {
348 behavior = extension_enable;
349 } else if (strcmp(behavior_string, "disable") == 0) {
350 behavior = extension_disable;
351 } else {
352 _mesa_glsl_error(behavior_locp, state,
353 "Unknown extension behavior `%s'",
354 behavior_string);
355 return false;
356 }
357
358 if (strcmp(name, "all") == 0) {
359 if ((behavior == extension_enable) || (behavior == extension_require)) {
360 _mesa_glsl_error(name_locp, state, "Cannot %s all extensions",
361 (behavior == extension_enable)
362 ? "enable" : "require");
363 return false;
364 } else {
365 for (unsigned i = 0;
366 i < Elements(_mesa_glsl_supported_extensions); ++i) {
367 const _mesa_glsl_extension *extension
368 = &_mesa_glsl_supported_extensions[i];
369 if (extension->compatible_with_state(state)) {
370 _mesa_glsl_supported_extensions[i].set_flags(state, behavior);
371 }
372 }
373 }
374 } else {
375 const _mesa_glsl_extension *extension = find_extension(name);
376 if (extension && extension->compatible_with_state(state)) {
377 extension->set_flags(state, behavior);
378 } else {
379 static const char *const fmt = "extension `%s' unsupported in %s shader";
380
381 if (behavior == extension_require) {
382 _mesa_glsl_error(name_locp, state, fmt,
383 name, _mesa_glsl_shader_target_name(state->target));
384 return false;
385 } else {
386 _mesa_glsl_warning(name_locp, state, fmt,
387 name, _mesa_glsl_shader_target_name(state->target));
388 }
389 }
390 }
391
392 return true;
393 }
394
395 void
396 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
397 {
398 if (q->flags.q.constant)
399 printf("const ");
400
401 if (q->flags.q.invariant)
402 printf("invariant ");
403
404 if (q->flags.q.attribute)
405 printf("attribute ");
406
407 if (q->flags.q.varying)
408 printf("varying ");
409
410 if (q->flags.q.in && q->flags.q.out)
411 printf("inout ");
412 else {
413 if (q->flags.q.in)
414 printf("in ");
415
416 if (q->flags.q.out)
417 printf("out ");
418 }
419
420 if (q->flags.q.centroid)
421 printf("centroid ");
422 if (q->flags.q.uniform)
423 printf("uniform ");
424 if (q->flags.q.smooth)
425 printf("smooth ");
426 if (q->flags.q.flat)
427 printf("flat ");
428 if (q->flags.q.noperspective)
429 printf("noperspective ");
430 }
431
432
433 void
434 ast_node::print(void) const
435 {
436 printf("unhandled node ");
437 }
438
439
440 ast_node::ast_node(void)
441 {
442 this->location.source = 0;
443 this->location.line = 0;
444 this->location.column = 0;
445 }
446
447
448 static void
449 ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
450 {
451 if (is_array) {
452 printf("[ ");
453
454 if (array_size)
455 array_size->print();
456
457 printf("] ");
458 }
459 }
460
461
462 void
463 ast_compound_statement::print(void) const
464 {
465 printf("{\n");
466
467 foreach_list_const(n, &this->statements) {
468 ast_node *ast = exec_node_data(ast_node, n, link);
469 ast->print();
470 }
471
472 printf("}\n");
473 }
474
475
476 ast_compound_statement::ast_compound_statement(int new_scope,
477 ast_node *statements)
478 {
479 this->new_scope = new_scope;
480
481 if (statements != NULL) {
482 this->statements.push_degenerate_list_at_head(&statements->link);
483 }
484 }
485
486
487 void
488 ast_expression::print(void) const
489 {
490 switch (oper) {
491 case ast_assign:
492 case ast_mul_assign:
493 case ast_div_assign:
494 case ast_mod_assign:
495 case ast_add_assign:
496 case ast_sub_assign:
497 case ast_ls_assign:
498 case ast_rs_assign:
499 case ast_and_assign:
500 case ast_xor_assign:
501 case ast_or_assign:
502 subexpressions[0]->print();
503 printf("%s ", operator_string(oper));
504 subexpressions[1]->print();
505 break;
506
507 case ast_field_selection:
508 subexpressions[0]->print();
509 printf(". %s ", primary_expression.identifier);
510 break;
511
512 case ast_plus:
513 case ast_neg:
514 case ast_bit_not:
515 case ast_logic_not:
516 case ast_pre_inc:
517 case ast_pre_dec:
518 printf("%s ", operator_string(oper));
519 subexpressions[0]->print();
520 break;
521
522 case ast_post_inc:
523 case ast_post_dec:
524 subexpressions[0]->print();
525 printf("%s ", operator_string(oper));
526 break;
527
528 case ast_conditional:
529 subexpressions[0]->print();
530 printf("? ");
531 subexpressions[1]->print();
532 printf(": ");
533 subexpressions[2]->print();
534 break;
535
536 case ast_array_index:
537 subexpressions[0]->print();
538 printf("[ ");
539 subexpressions[1]->print();
540 printf("] ");
541 break;
542
543 case ast_function_call: {
544 subexpressions[0]->print();
545 printf("( ");
546
547 foreach_list_const (n, &this->expressions) {
548 if (n != this->expressions.get_head())
549 printf(", ");
550
551 ast_node *ast = exec_node_data(ast_node, n, link);
552 ast->print();
553 }
554
555 printf(") ");
556 break;
557 }
558
559 case ast_identifier:
560 printf("%s ", primary_expression.identifier);
561 break;
562
563 case ast_int_constant:
564 printf("%d ", primary_expression.int_constant);
565 break;
566
567 case ast_uint_constant:
568 printf("%u ", primary_expression.uint_constant);
569 break;
570
571 case ast_float_constant:
572 printf("%f ", primary_expression.float_constant);
573 break;
574
575 case ast_bool_constant:
576 printf("%s ",
577 primary_expression.bool_constant
578 ? "true" : "false");
579 break;
580
581 case ast_sequence: {
582 printf("( ");
583 foreach_list_const(n, & this->expressions) {
584 if (n != this->expressions.get_head())
585 printf(", ");
586
587 ast_node *ast = exec_node_data(ast_node, n, link);
588 ast->print();
589 }
590 printf(") ");
591 break;
592 }
593
594 default:
595 assert(0);
596 break;
597 }
598 }
599
600 ast_expression::ast_expression(int oper,
601 ast_expression *ex0,
602 ast_expression *ex1,
603 ast_expression *ex2)
604 {
605 this->oper = ast_operators(oper);
606 this->subexpressions[0] = ex0;
607 this->subexpressions[1] = ex1;
608 this->subexpressions[2] = ex2;
609 this->non_lvalue_description = NULL;
610 }
611
612
613 void
614 ast_expression_statement::print(void) const
615 {
616 if (expression)
617 expression->print();
618
619 printf("; ");
620 }
621
622
623 ast_expression_statement::ast_expression_statement(ast_expression *ex) :
624 expression(ex)
625 {
626 /* empty */
627 }
628
629
630 void
631 ast_function::print(void) const
632 {
633 return_type->print();
634 printf(" %s (", identifier);
635
636 foreach_list_const(n, & this->parameters) {
637 ast_node *ast = exec_node_data(ast_node, n, link);
638 ast->print();
639 }
640
641 printf(")");
642 }
643
644
645 ast_function::ast_function(void)
646 : is_definition(false), signature(NULL)
647 {
648 /* empty */
649 }
650
651
652 void
653 ast_fully_specified_type::print(void) const
654 {
655 _mesa_ast_type_qualifier_print(& qualifier);
656 specifier->print();
657 }
658
659
660 void
661 ast_parameter_declarator::print(void) const
662 {
663 type->print();
664 if (identifier)
665 printf("%s ", identifier);
666 ast_opt_array_size_print(is_array, array_size);
667 }
668
669
670 void
671 ast_function_definition::print(void) const
672 {
673 prototype->print();
674 body->print();
675 }
676
677
678 void
679 ast_declaration::print(void) const
680 {
681 printf("%s ", identifier);
682 ast_opt_array_size_print(is_array, array_size);
683
684 if (initializer) {
685 printf("= ");
686 initializer->print();
687 }
688 }
689
690
691 ast_declaration::ast_declaration(char *identifier, int is_array,
692 ast_expression *array_size,
693 ast_expression *initializer)
694 {
695 this->identifier = identifier;
696 this->is_array = is_array;
697 this->array_size = array_size;
698 this->initializer = initializer;
699 }
700
701
702 void
703 ast_declarator_list::print(void) const
704 {
705 assert(type || invariant);
706
707 if (type)
708 type->print();
709 else
710 printf("invariant ");
711
712 foreach_list_const (ptr, & this->declarations) {
713 if (ptr != this->declarations.get_head())
714 printf(", ");
715
716 ast_node *ast = exec_node_data(ast_node, ptr, link);
717 ast->print();
718 }
719
720 printf("; ");
721 }
722
723
724 ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
725 {
726 this->type = type;
727 this->invariant = false;
728 }
729
730 void
731 ast_jump_statement::print(void) const
732 {
733 switch (mode) {
734 case ast_continue:
735 printf("continue; ");
736 break;
737 case ast_break:
738 printf("break; ");
739 break;
740 case ast_return:
741 printf("return ");
742 if (opt_return_value)
743 opt_return_value->print();
744
745 printf("; ");
746 break;
747 case ast_discard:
748 printf("discard; ");
749 break;
750 }
751 }
752
753
754 ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
755 {
756 this->mode = ast_jump_modes(mode);
757
758 if (mode == ast_return)
759 opt_return_value = return_value;
760 }
761
762
763 void
764 ast_selection_statement::print(void) const
765 {
766 printf("if ( ");
767 condition->print();
768 printf(") ");
769
770 then_statement->print();
771
772 if (else_statement) {
773 printf("else ");
774 else_statement->print();
775 }
776
777 }
778
779
780 ast_selection_statement::ast_selection_statement(ast_expression *condition,
781 ast_node *then_statement,
782 ast_node *else_statement)
783 {
784 this->condition = condition;
785 this->then_statement = then_statement;
786 this->else_statement = else_statement;
787 }
788
789
790 void
791 ast_switch_statement::print(void) const
792 {
793 printf("switch ( ");
794 test_expression->print();
795 printf(") ");
796
797 body->print();
798 }
799
800
801 ast_switch_statement::ast_switch_statement(ast_expression *test_expression,
802 ast_node *body)
803 {
804 this->test_expression = test_expression;
805 this->body = body;
806 }
807
808
809 void
810 ast_switch_body::print(void) const
811 {
812 printf("{\n");
813 if (stmts != NULL) {
814 stmts->print();
815 }
816 printf("}\n");
817 }
818
819
820 ast_switch_body::ast_switch_body(ast_case_statement_list *stmts)
821 {
822 this->stmts = stmts;
823 }
824
825
826 void ast_case_label::print(void) const
827 {
828 if (test_value != NULL) {
829 printf("case ");
830 test_value->print();
831 printf(": ");
832 } else {
833 printf("default: ");
834 }
835 }
836
837
838 ast_case_label::ast_case_label(ast_expression *test_value)
839 {
840 this->test_value = test_value;
841 }
842
843
844 void ast_case_label_list::print(void) const
845 {
846 foreach_list_const(n, & this->labels) {
847 ast_node *ast = exec_node_data(ast_node, n, link);
848 ast->print();
849 }
850 printf("\n");
851 }
852
853
854 ast_case_label_list::ast_case_label_list(void)
855 {
856 }
857
858
859 void ast_case_statement::print(void) const
860 {
861 labels->print();
862 foreach_list_const(n, & this->stmts) {
863 ast_node *ast = exec_node_data(ast_node, n, link);
864 ast->print();
865 printf("\n");
866 }
867 }
868
869
870 ast_case_statement::ast_case_statement(ast_case_label_list *labels)
871 {
872 this->labels = labels;
873 }
874
875
876 void ast_case_statement_list::print(void) const
877 {
878 foreach_list_const(n, & this->cases) {
879 ast_node *ast = exec_node_data(ast_node, n, link);
880 ast->print();
881 }
882 }
883
884
885 ast_case_statement_list::ast_case_statement_list(void)
886 {
887 }
888
889
890 void
891 ast_iteration_statement::print(void) const
892 {
893 switch (mode) {
894 case ast_for:
895 printf("for( ");
896 if (init_statement)
897 init_statement->print();
898 printf("; ");
899
900 if (condition)
901 condition->print();
902 printf("; ");
903
904 if (rest_expression)
905 rest_expression->print();
906 printf(") ");
907
908 body->print();
909 break;
910
911 case ast_while:
912 printf("while ( ");
913 if (condition)
914 condition->print();
915 printf(") ");
916 body->print();
917 break;
918
919 case ast_do_while:
920 printf("do ");
921 body->print();
922 printf("while ( ");
923 if (condition)
924 condition->print();
925 printf("); ");
926 break;
927 }
928 }
929
930
931 ast_iteration_statement::ast_iteration_statement(int mode,
932 ast_node *init,
933 ast_node *condition,
934 ast_expression *rest_expression,
935 ast_node *body)
936 {
937 this->mode = ast_iteration_modes(mode);
938 this->init_statement = init;
939 this->condition = condition;
940 this->rest_expression = rest_expression;
941 this->body = body;
942 }
943
944
945 void
946 ast_struct_specifier::print(void) const
947 {
948 printf("struct %s { ", name);
949 foreach_list_const(n, &this->declarations) {
950 ast_node *ast = exec_node_data(ast_node, n, link);
951 ast->print();
952 }
953 printf("} ");
954 }
955
956
957 ast_struct_specifier::ast_struct_specifier(char *identifier,
958 ast_node *declarator_list)
959 {
960 if (identifier == NULL) {
961 static unsigned anon_count = 1;
962 identifier = ralloc_asprintf(this, "#anon_struct_%04x", anon_count);
963 anon_count++;
964 }
965 name = identifier;
966 this->declarations.push_degenerate_list_at_head(&declarator_list->link);
967 }
968
969 /**
970 * Do the set of common optimizations passes
971 *
972 * \param ir List of instructions to be optimized
973 * \param linked Is the shader linked? This enables
974 * optimizations passes that remove code at
975 * global scope and could cause linking to
976 * fail.
977 * \param uniform_locations_assigned Have locations already been assigned for
978 * uniforms? This prevents the declarations
979 * of unused uniforms from being removed.
980 * The setting of this flag only matters if
981 * \c linked is \c true.
982 * \param max_unroll_iterations Maximum number of loop iterations to be
983 * unrolled. Setting to 0 forces all loops
984 * to be unrolled.
985 */
986 bool
987 do_common_optimization(exec_list *ir, bool linked,
988 bool uniform_locations_assigned,
989 unsigned max_unroll_iterations)
990 {
991 GLboolean progress = GL_FALSE;
992
993 progress = lower_instructions(ir, SUB_TO_ADD_NEG) || progress;
994
995 if (linked) {
996 progress = do_function_inlining(ir) || progress;
997 progress = do_dead_functions(ir) || progress;
998 progress = do_structure_splitting(ir) || progress;
999 }
1000 progress = do_if_simplification(ir) || progress;
1001 progress = do_discard_simplification(ir) || progress;
1002 progress = do_copy_propagation(ir) || progress;
1003 progress = do_copy_propagation_elements(ir) || progress;
1004 if (linked)
1005 progress = do_dead_code(ir, uniform_locations_assigned) || progress;
1006 else
1007 progress = do_dead_code_unlinked(ir) || progress;
1008 progress = do_dead_code_local(ir) || progress;
1009 progress = do_tree_grafting(ir) || progress;
1010 progress = do_constant_propagation(ir) || progress;
1011 if (linked)
1012 progress = do_constant_variable(ir) || progress;
1013 else
1014 progress = do_constant_variable_unlinked(ir) || progress;
1015 progress = do_constant_folding(ir) || progress;
1016 progress = do_algebraic(ir) || progress;
1017 progress = do_lower_jumps(ir) || progress;
1018 progress = do_vec_index_to_swizzle(ir) || progress;
1019 progress = do_swizzle_swizzle(ir) || progress;
1020 progress = do_noop_swizzle(ir) || progress;
1021
1022 progress = optimize_redundant_jumps(ir) || progress;
1023
1024 loop_state *ls = analyze_loop_variables(ir);
1025 if (ls->loop_found) {
1026 progress = set_loop_controls(ir, ls) || progress;
1027 progress = unroll_loops(ir, ls, max_unroll_iterations) || progress;
1028 }
1029 delete ls;
1030
1031 return progress;
1032 }
1033
1034 extern "C" {
1035
1036 /**
1037 * To be called at GL teardown time, this frees compiler datastructures.
1038 *
1039 * After calling this, any previously compiled shaders and shader
1040 * programs would be invalid. So this should happen at approximately
1041 * program exit.
1042 */
1043 void
1044 _mesa_destroy_shader_compiler(void)
1045 {
1046 _mesa_destroy_shader_compiler_caches();
1047
1048 _mesa_glsl_release_types();
1049 }
1050
1051 /**
1052 * Releases compiler caches to trade off performance for memory.
1053 *
1054 * Intended to be used with glReleaseShaderCompiler().
1055 */
1056 void
1057 _mesa_destroy_shader_compiler_caches(void)
1058 {
1059 _mesa_glsl_release_functions();
1060 }
1061
1062 }