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