blob: cb7b6d36a2d883be5d7deb5524ad80b1ab3e004a [file] [log] [blame]
Ian Romanicka87ac252010-02-22 13:19:34 -08001/*
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>
Ian Romanicka87ac252010-02-22 13:19:34 -080025#include <string.h>
26#include <assert.h>
Ian Romanicka87ac252010-02-22 13:19:34 -080027
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070028extern "C" {
29#include <talloc.h>
Ian Romanick667f4e12010-06-30 16:42:07 -070030#include "main/mtypes.h"
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070031}
32
Ian Romanicka87ac252010-02-22 13:19:34 -080033#include "ast.h"
34#include "glsl_parser_extras.h"
Ian Romanickd59673c2010-02-25 17:17:23 -080035#include "glsl_parser.h"
Ian Romanicka87ac252010-02-22 13:19:34 -080036
Ian Romanick5bfe30a2010-04-07 16:44:30 -070037const char *
38_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
39{
40 switch (target) {
41 case vertex_shader: return "vertex";
42 case fragment_shader: return "fragment";
43 case geometry_shader: return "geometry";
Eric Anholt81f49a72010-04-29 17:57:28 -070044 case ir_shader: break;
Ian Romanick5bfe30a2010-04-07 16:44:30 -070045 }
46
47 assert(!"Should not get here.");
Eric Anholt87a2ee82010-07-18 17:47:15 -070048 return "unknown";
Ian Romanick5bfe30a2010-04-07 16:44:30 -070049}
50
51
Ian Romanicka87ac252010-02-22 13:19:34 -080052void
Ian Romanick1f585182010-03-11 14:08:33 -080053_mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
54 const char *fmt, ...)
Ian Romanicka87ac252010-02-22 13:19:34 -080055{
Ian Romanicka87ac252010-02-22 13:19:34 -080056 va_list ap;
57
Ian Romanick71d0bbf2010-03-23 13:21:19 -070058 state->error = true;
Ian Romanick1f585182010-03-11 14:08:33 -080059
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070060 assert(state->info_log != NULL);
61 state->info_log = talloc_asprintf_append(state->info_log,
62 "%u:%u(%u): error: ",
63 locp->source,
64 locp->first_line,
65 locp->first_column);
Ian Romanicka87ac252010-02-22 13:19:34 -080066 va_start(ap, fmt);
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070067 state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
Ian Romanicka87ac252010-02-22 13:19:34 -080068 va_end(ap);
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070069 state->info_log = talloc_strdup_append(state->info_log, "\n");
Ian Romanicka87ac252010-02-22 13:19:34 -080070}
71
72
Ian Romanick56b8b212010-04-07 14:47:46 -070073void
Eric Anholt3623df62010-04-29 18:00:33 -070074_mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
Ian Romanick56b8b212010-04-07 14:47:46 -070075 const char *fmt, ...)
76{
Ian Romanick56b8b212010-04-07 14:47:46 -070077 va_list ap;
78
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070079 assert(state->info_log != NULL);
80 state->info_log = talloc_asprintf_append(state->info_log,
81 "%u:%u(%u): warning: ",
82 locp->source,
83 locp->first_line,
84 locp->first_column);
Ian Romanick56b8b212010-04-07 14:47:46 -070085 va_start(ap, fmt);
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070086 state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
Ian Romanick56b8b212010-04-07 14:47:46 -070087 va_end(ap);
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070088 state->info_log = talloc_strdup_append(state->info_log, "\n");
Ian Romanick56b8b212010-04-07 14:47:46 -070089}
90
91
Ian Romanicke7017612010-04-07 16:46:25 -070092bool
93_mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
94 const char *behavior, YYLTYPE *behavior_locp,
95 _mesa_glsl_parse_state *state)
96{
97 enum {
98 extension_disable,
99 extension_enable,
100 extension_require,
101 extension_warn
102 } ext_mode;
Ian Romanicke7017612010-04-07 16:46:25 -0700103
104 if (strcmp(behavior, "warn") == 0) {
105 ext_mode = extension_warn;
106 } else if (strcmp(behavior, "require") == 0) {
107 ext_mode = extension_require;
108 } else if (strcmp(behavior, "enable") == 0) {
109 ext_mode = extension_enable;
110 } else if (strcmp(behavior, "disable") == 0) {
111 ext_mode = extension_disable;
112 } else {
113 _mesa_glsl_error(behavior_locp, state,
114 "Unknown extension behavior `%s'",
115 behavior);
116 return false;
117 }
118
Ian Romanick887a8b02010-04-07 16:57:56 -0700119 bool unsupported = false;
120
Ian Romanicke7017612010-04-07 16:46:25 -0700121 if (strcmp(name, "all") == 0) {
122 if ((ext_mode == extension_enable) || (ext_mode == extension_require)) {
123 _mesa_glsl_error(name_locp, state, "Cannot %s all extensions",
124 (ext_mode == extension_enable)
125 ? "enable" : "require");
126 return false;
127 }
Ian Romanickeb56cea2010-04-23 13:32:23 -0700128 } else if (strcmp(name, "GL_ARB_draw_buffers") == 0) {
Ian Romanickc77b2572010-04-07 16:59:46 -0700129 /* This extension is only supported in fragment shaders.
130 */
131 if (state->target != fragment_shader) {
132 unsupported = true;
133 } else {
134 state->ARB_draw_buffers_enable = (ext_mode != extension_disable);
135 state->ARB_draw_buffers_warn = (ext_mode == extension_warn);
136 }
Ian Romanickeb56cea2010-04-23 13:32:23 -0700137 } else if (strcmp(name, "GL_ARB_texture_rectangle") == 0) {
Ian Romanick0c824652010-04-07 17:13:44 -0700138 state->ARB_texture_rectangle_enable = (ext_mode != extension_disable);
139 state->ARB_texture_rectangle_warn = (ext_mode == extension_warn);
Ian Romanick667f4e12010-06-30 16:42:07 -0700140 } else if (strcmp(name, "GL_EXT_texture_array") == 0) {
141 state->EXT_texture_array_enable = (ext_mode != extension_disable);
142 state->EXT_texture_array_warn = (ext_mode == extension_warn);
143
144 unsupported = !state->extensions->EXT_texture_array;
Ian Romanicke7017612010-04-07 16:46:25 -0700145 } else {
Ian Romanick887a8b02010-04-07 16:57:56 -0700146 unsupported = true;
147 }
148
149 if (unsupported) {
150 static const char *const fmt = "extension `%s' unsupported in %s shader";
151
Ian Romanicke7017612010-04-07 16:46:25 -0700152 if (ext_mode == extension_require) {
Ian Romanick887a8b02010-04-07 16:57:56 -0700153 _mesa_glsl_error(name_locp, state, fmt,
154 name, _mesa_glsl_shader_target_name(state->target));
Ian Romanicke7017612010-04-07 16:46:25 -0700155 return false;
Ian Romanick1799a0c2010-04-07 14:50:36 -0700156 } else {
Ian Romanick887a8b02010-04-07 16:57:56 -0700157 _mesa_glsl_warning(name_locp, state, fmt,
158 name, _mesa_glsl_shader_target_name(state->target));
Ian Romanicke7017612010-04-07 16:46:25 -0700159 }
160 }
161
162 return true;
163}
164
Ian Romanicka87ac252010-02-22 13:19:34 -0800165void
166_mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
167{
168 if (q->constant)
169 printf("const ");
170
171 if (q->invariant)
172 printf("invariant ");
173
174 if (q->attribute)
175 printf("attribute ");
176
177 if (q->varying)
178 printf("varying ");
179
180 if (q->in && q->out)
181 printf("inout ");
182 else {
183 if (q->in)
184 printf("in ");
185
186 if (q->out)
187 printf("out ");
188 }
189
190 if (q->centroid)
191 printf("centroid ");
192 if (q->uniform)
193 printf("uniform ");
194 if (q->smooth)
195 printf("smooth ");
196 if (q->flat)
197 printf("flat ");
198 if (q->noperspective)
199 printf("noperspective ");
200}
201
202
203void
204ast_node::print(void) const
205{
Ian Romanick03d3f3a2010-04-02 11:03:47 -0700206 printf("unhandled node ");
Ian Romanicka87ac252010-02-22 13:19:34 -0800207}
208
209
210ast_node::ast_node(void)
211{
Ian Romanick304ea902010-05-10 11:17:53 -0700212 /* empty */
Ian Romanicka87ac252010-02-22 13:19:34 -0800213}
214
Ian Romanicka87ac252010-02-22 13:19:34 -0800215
216static void
217ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
218{
219 if (is_array) {
220 printf("[ ");
221
222 if (array_size)
223 array_size->print();
224
225 printf("] ");
226 }
227}
228
229
Ian Romanicka87ac252010-02-22 13:19:34 -0800230void
231ast_compound_statement::print(void) const
232{
Ian Romanicka87ac252010-02-22 13:19:34 -0800233 printf("{\n");
234
Ian Romanick304ea902010-05-10 11:17:53 -0700235 foreach_list_const(n, &this->statements) {
236 ast_node *ast = exec_node_data(ast_node, n, link);
237 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800238 }
239
240 printf("}\n");
241}
242
243
244ast_compound_statement::ast_compound_statement(int new_scope,
245 ast_node *statements)
246{
247 this->new_scope = new_scope;
Ian Romanicka87ac252010-02-22 13:19:34 -0800248
249 if (statements != NULL) {
Ian Romanick304ea902010-05-10 11:17:53 -0700250 this->statements.push_degenerate_list_at_head(&statements->link);
Ian Romanicka87ac252010-02-22 13:19:34 -0800251 }
252}
253
254
255void
256ast_expression::print(void) const
257{
Ian Romanicka87ac252010-02-22 13:19:34 -0800258 switch (oper) {
259 case ast_assign:
Ian Romanicka87ac252010-02-22 13:19:34 -0800260 case ast_mul_assign:
261 case ast_div_assign:
262 case ast_mod_assign:
263 case ast_add_assign:
264 case ast_sub_assign:
265 case ast_ls_assign:
266 case ast_rs_assign:
267 case ast_and_assign:
268 case ast_xor_assign:
269 case ast_or_assign:
270 subexpressions[0]->print();
Ian Romanick88349b22010-02-22 19:10:25 -0800271 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800272 subexpressions[1]->print();
273 break;
274
275 case ast_field_selection:
276 subexpressions[0]->print();
277 printf(". %s ", primary_expression.identifier);
278 break;
279
280 case ast_plus:
281 case ast_neg:
282 case ast_bit_not:
283 case ast_logic_not:
284 case ast_pre_inc:
285 case ast_pre_dec:
Ian Romanick88349b22010-02-22 19:10:25 -0800286 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800287 subexpressions[0]->print();
288 break;
289
290 case ast_post_inc:
291 case ast_post_dec:
292 subexpressions[0]->print();
Ian Romanick88349b22010-02-22 19:10:25 -0800293 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800294 break;
295
296 case ast_conditional:
297 subexpressions[0]->print();
298 printf("? ");
299 subexpressions[1]->print();
300 printf(": ");
301 subexpressions[1]->print();
302 break;
303
304 case ast_array_index:
305 subexpressions[0]->print();
306 printf("[ ");
307 subexpressions[1]->print();
308 printf("] ");
309 break;
310
311 case ast_function_call: {
Ian Romanicka87ac252010-02-22 13:19:34 -0800312 subexpressions[0]->print();
313 printf("( ");
314
Ian Romanick304ea902010-05-10 11:17:53 -0700315 foreach_list_const (n, &this->expressions) {
Ian Romanick23849372010-05-14 16:06:41 -0700316 if (n != this->expressions.get_head())
317 printf(", ");
Ian Romanick304ea902010-05-10 11:17:53 -0700318
319 ast_node *ast = exec_node_data(ast_node, n, link);
320 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800321 }
322
323 printf(") ");
324 break;
325 }
326
327 case ast_identifier:
328 printf("%s ", primary_expression.identifier);
329 break;
330
331 case ast_int_constant:
332 printf("%d ", primary_expression.int_constant);
333 break;
334
335 case ast_uint_constant:
336 printf("%u ", primary_expression.uint_constant);
337 break;
338
339 case ast_float_constant:
340 printf("%f ", primary_expression.float_constant);
341 break;
342
343 case ast_bool_constant:
344 printf("%s ",
345 primary_expression.bool_constant
346 ? "true" : "false");
347 break;
348
349 case ast_sequence: {
Ian Romanicka87ac252010-02-22 13:19:34 -0800350 printf("( ");
Ian Romanick304ea902010-05-10 11:17:53 -0700351 foreach_list_const(n, & this->expressions) {
352 if (n != this->expressions.get_head())
Ian Romanicka87ac252010-02-22 13:19:34 -0800353 printf(", ");
354
Ian Romanick304ea902010-05-10 11:17:53 -0700355 ast_node *ast = exec_node_data(ast_node, n, link);
356 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800357 }
358 printf(") ");
359 break;
360 }
Ian Romanick88349b22010-02-22 19:10:25 -0800361
362 default:
363 assert(0);
364 break;
Ian Romanicka87ac252010-02-22 13:19:34 -0800365 }
366}
367
368ast_expression::ast_expression(int oper,
369 ast_expression *ex0,
370 ast_expression *ex1,
371 ast_expression *ex2)
372{
373 this->oper = ast_operators(oper);
374 this->subexpressions[0] = ex0;
375 this->subexpressions[1] = ex1;
376 this->subexpressions[2] = ex2;
Ian Romanicka87ac252010-02-22 13:19:34 -0800377}
378
379
380void
381ast_expression_statement::print(void) const
382{
383 if (expression)
384 expression->print();
385
386 printf("; ");
387}
388
389
390ast_expression_statement::ast_expression_statement(ast_expression *ex) :
391 expression(ex)
392{
393 /* empty */
394}
395
396
397void
398ast_function::print(void) const
399{
Ian Romanicka87ac252010-02-22 13:19:34 -0800400 return_type->print();
401 printf(" %s (", identifier);
402
Ian Romanick304ea902010-05-10 11:17:53 -0700403 foreach_list_const(n, & this->parameters) {
404 ast_node *ast = exec_node_data(ast_node, n, link);
405 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800406 }
407
408 printf(")");
409}
410
411
412ast_function::ast_function(void)
Ian Romanick92318a92010-03-31 18:23:21 -0700413 : is_definition(false), signature(NULL)
Ian Romanicka87ac252010-02-22 13:19:34 -0800414{
Ian Romanick304ea902010-05-10 11:17:53 -0700415 /* empty */
Ian Romanicka87ac252010-02-22 13:19:34 -0800416}
417
418
419void
420ast_fully_specified_type::print(void) const
421{
422 _mesa_ast_type_qualifier_print(& qualifier);
423 specifier->print();
424}
425
426
427void
428ast_parameter_declarator::print(void) const
429{
430 type->print();
431 if (identifier)
432 printf("%s ", identifier);
433 ast_opt_array_size_print(is_array, array_size);
434}
435
436
437void
438ast_function_definition::print(void) const
439{
440 prototype->print();
441 body->print();
442}
443
444
445void
446ast_declaration::print(void) const
447{
448 printf("%s ", identifier);
449 ast_opt_array_size_print(is_array, array_size);
450
451 if (initializer) {
452 printf("= ");
453 initializer->print();
454 }
455}
456
457
458ast_declaration::ast_declaration(char *identifier, int is_array,
459 ast_expression *array_size,
460 ast_expression *initializer)
461{
462 this->identifier = identifier;
463 this->is_array = is_array;
464 this->array_size = array_size;
465 this->initializer = initializer;
466}
467
468
469void
470ast_declarator_list::print(void) const
471{
Ian Romanicka87ac252010-02-22 13:19:34 -0800472 assert(type || invariant);
473
474 if (type)
475 type->print();
476 else
477 printf("invariant ");
478
Ian Romanick304ea902010-05-10 11:17:53 -0700479 foreach_list_const (ptr, & this->declarations) {
480 if (ptr != this->declarations.get_head())
Ian Romanicka87ac252010-02-22 13:19:34 -0800481 printf(", ");
482
Ian Romanick304ea902010-05-10 11:17:53 -0700483 ast_node *ast = exec_node_data(ast_node, ptr, link);
484 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800485 }
486
487 printf("; ");
488}
489
490
491ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
492{
493 this->type = type;
Ian Romanick38327062010-07-01 17:10:11 -0700494 this->invariant = false;
Ian Romanicka87ac252010-02-22 13:19:34 -0800495}
496
497void
498ast_jump_statement::print(void) const
499{
500 switch (mode) {
501 case ast_continue:
502 printf("continue; ");
503 break;
504 case ast_break:
505 printf("break; ");
506 break;
507 case ast_return:
508 printf("return ");
509 if (opt_return_value)
510 opt_return_value->print();
511
512 printf("; ");
513 break;
514 case ast_discard:
515 printf("discard; ");
516 break;
517 }
518}
519
520
521ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
522{
523 this->mode = ast_jump_modes(mode);
524
525 if (mode == ast_return)
526 opt_return_value = return_value;
527}
528
529
530void
531ast_selection_statement::print(void) const
532{
533 printf("if ( ");
534 condition->print();
535 printf(") ");
536
537 then_statement->print();
538
539 if (else_statement) {
540 printf("else ");
541 else_statement->print();
542 }
543
544}
545
546
547ast_selection_statement::ast_selection_statement(ast_expression *condition,
548 ast_node *then_statement,
549 ast_node *else_statement)
550{
551 this->condition = condition;
552 this->then_statement = then_statement;
553 this->else_statement = else_statement;
554}
555
556
557void
558ast_iteration_statement::print(void) const
559{
560 switch (mode) {
561 case ast_for:
562 printf("for( ");
563 if (init_statement)
564 init_statement->print();
565 printf("; ");
566
567 if (condition)
568 condition->print();
569 printf("; ");
570
571 if (rest_expression)
572 rest_expression->print();
573 printf(") ");
574
575 body->print();
576 break;
577
578 case ast_while:
579 printf("while ( ");
580 if (condition)
581 condition->print();
582 printf(") ");
583 body->print();
584 break;
585
586 case ast_do_while:
587 printf("do ");
588 body->print();
589 printf("while ( ");
590 if (condition)
591 condition->print();
592 printf("); ");
593 break;
594 }
595}
596
597
598ast_iteration_statement::ast_iteration_statement(int mode,
599 ast_node *init,
600 ast_node *condition,
601 ast_expression *rest_expression,
602 ast_node *body)
603{
604 this->mode = ast_iteration_modes(mode);
605 this->init_statement = init;
606 this->condition = condition;
607 this->rest_expression = rest_expression;
608 this->body = body;
609}
610
611
612void
613ast_struct_specifier::print(void) const
614{
Ian Romanicka87ac252010-02-22 13:19:34 -0800615 printf("struct %s { ", name);
Ian Romanick304ea902010-05-10 11:17:53 -0700616 foreach_list_const(n, &this->declarations) {
617 ast_node *ast = exec_node_data(ast_node, n, link);
618 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800619 }
620 printf("} ");
621}
622
623
624ast_struct_specifier::ast_struct_specifier(char *identifier,
625 ast_node *declarator_list)
626{
627 name = identifier;
Ian Romanick304ea902010-05-10 11:17:53 -0700628 this->declarations.push_degenerate_list_at_head(&declarator_list->link);
Ian Romanicka87ac252010-02-22 13:19:34 -0800629}