glsl_parser_extras.cpp revision 3097715d41da4b725b7ce9f9d5bbc0f684cbf0a6
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
28extern "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
116const 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
130void
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
150void
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 */
172enum 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 */
182struct _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 */
253static 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 */
276bool _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 */
326void _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 */
341static 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
352bool
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
410void
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
448void
449ast_node::print(void) const
450{
451   printf("unhandled node ");
452}
453
454
455ast_node::ast_node(void)
456{
457   this->location.source = 0;
458   this->location.line = 0;
459   this->location.column = 0;
460}
461
462
463static void
464ast_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
477void
478ast_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
491ast_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
502void
503ast_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
615ast_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
627void
628ast_expression_statement::print(void) const
629{
630   if (expression)
631      expression->print();
632
633   printf("; ");
634}
635
636
637ast_expression_statement::ast_expression_statement(ast_expression *ex) :
638   expression(ex)
639{
640   /* empty */
641}
642
643
644void
645ast_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
659ast_function::ast_function(void)
660   : is_definition(false), signature(NULL)
661{
662   /* empty */
663}
664
665
666void
667ast_fully_specified_type::print(void) const
668{
669   _mesa_ast_type_qualifier_print(& qualifier);
670   specifier->print();
671}
672
673
674void
675ast_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
684void
685ast_function_definition::print(void) const
686{
687   prototype->print();
688   body->print();
689}
690
691
692void
693ast_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
705ast_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
716void
717ast_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
738ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
739{
740   this->type = type;
741   this->invariant = false;
742}
743
744void
745ast_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
768ast_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
777void
778ast_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
794ast_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
804void
805ast_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
845ast_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
859void
860ast_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
871ast_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
883bool
884do_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
929extern "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 */
938void
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 */
951void
952_mesa_destroy_shader_compiler_caches(void)
953{
954   _mesa_glsl_release_functions();
955}
956
957}
958