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