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