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