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