blob: 2e17c4c33723b8cd6b020d58b8d4a2c2a61de36a [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>
30}
31
Ian Romanicka87ac252010-02-22 13:19:34 -080032#include "ast.h"
33#include "glsl_parser_extras.h"
Ian Romanickd59673c2010-02-25 17:17:23 -080034#include "glsl_parser.h"
Ian Romanicka87ac252010-02-22 13:19:34 -080035
Ian Romanick5bfe30a2010-04-07 16:44:30 -070036const 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";
Eric Anholt81f49a72010-04-29 17:57:28 -070043 case ir_shader: break;
Ian Romanick5bfe30a2010-04-07 16:44:30 -070044 }
45
46 assert(!"Should not get here.");
47}
48
49
Ian Romanicka87ac252010-02-22 13:19:34 -080050void
Ian Romanick1f585182010-03-11 14:08:33 -080051_mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
52 const char *fmt, ...)
Ian Romanicka87ac252010-02-22 13:19:34 -080053{
Ian Romanicka87ac252010-02-22 13:19:34 -080054 va_list ap;
55
Ian Romanick71d0bbf2010-03-23 13:21:19 -070056 state->error = true;
Ian Romanick1f585182010-03-11 14:08:33 -080057
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070058 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);
Ian Romanicka87ac252010-02-22 13:19:34 -080064 va_start(ap, fmt);
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070065 state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
Ian Romanicka87ac252010-02-22 13:19:34 -080066 va_end(ap);
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070067 state->info_log = talloc_strdup_append(state->info_log, "\n");
Ian Romanicka87ac252010-02-22 13:19:34 -080068}
69
70
Ian Romanick56b8b212010-04-07 14:47:46 -070071void
Eric Anholt3623df62010-04-29 18:00:33 -070072_mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
Ian Romanick56b8b212010-04-07 14:47:46 -070073 const char *fmt, ...)
74{
Ian Romanick56b8b212010-04-07 14:47:46 -070075 va_list ap;
76
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070077 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);
Ian Romanick56b8b212010-04-07 14:47:46 -070083 va_start(ap, fmt);
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070084 state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
Ian Romanick56b8b212010-04-07 14:47:46 -070085 va_end(ap);
Kenneth Graunkeb2ba6fa2010-06-17 15:15:35 -070086 state->info_log = talloc_strdup_append(state->info_log, "\n");
Ian Romanick56b8b212010-04-07 14:47:46 -070087}
88
89
Ian Romanicke7017612010-04-07 16:46:25 -070090bool
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;
Ian Romanicke7017612010-04-07 16:46:25 -0700101
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
Ian Romanick887a8b02010-04-07 16:57:56 -0700117 bool unsupported = false;
118
Ian Romanicke7017612010-04-07 16:46:25 -0700119 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 }
Ian Romanickeb56cea2010-04-23 13:32:23 -0700126 } else if (strcmp(name, "GL_ARB_draw_buffers") == 0) {
Ian Romanickc77b2572010-04-07 16:59:46 -0700127 /* 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 }
Ian Romanickeb56cea2010-04-23 13:32:23 -0700135 } else if (strcmp(name, "GL_ARB_texture_rectangle") == 0) {
Ian Romanick0c824652010-04-07 17:13:44 -0700136 state->ARB_texture_rectangle_enable = (ext_mode != extension_disable);
137 state->ARB_texture_rectangle_warn = (ext_mode == extension_warn);
Ian Romanicke7017612010-04-07 16:46:25 -0700138 } else {
Ian Romanick887a8b02010-04-07 16:57:56 -0700139 unsupported = true;
140 }
141
142 if (unsupported) {
143 static const char *const fmt = "extension `%s' unsupported in %s shader";
144
Ian Romanicke7017612010-04-07 16:46:25 -0700145 if (ext_mode == extension_require) {
Ian Romanick887a8b02010-04-07 16:57:56 -0700146 _mesa_glsl_error(name_locp, state, fmt,
147 name, _mesa_glsl_shader_target_name(state->target));
Ian Romanicke7017612010-04-07 16:46:25 -0700148 return false;
Ian Romanick1799a0c2010-04-07 14:50:36 -0700149 } else {
Ian Romanick887a8b02010-04-07 16:57:56 -0700150 _mesa_glsl_warning(name_locp, state, fmt,
151 name, _mesa_glsl_shader_target_name(state->target));
Ian Romanicke7017612010-04-07 16:46:25 -0700152 }
153 }
154
155 return true;
156}
157
Ian Romanicka87ac252010-02-22 13:19:34 -0800158void
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{
Ian Romanick03d3f3a2010-04-02 11:03:47 -0700199 printf("unhandled node ");
Ian Romanicka87ac252010-02-22 13:19:34 -0800200}
201
202
203ast_node::ast_node(void)
204{
Ian Romanick304ea902010-05-10 11:17:53 -0700205 /* empty */
Ian Romanicka87ac252010-02-22 13:19:34 -0800206}
207
Ian Romanicka87ac252010-02-22 13:19:34 -0800208
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
Ian Romanicka87ac252010-02-22 13:19:34 -0800223void
224ast_compound_statement::print(void) const
225{
Ian Romanicka87ac252010-02-22 13:19:34 -0800226 printf("{\n");
227
Ian Romanick304ea902010-05-10 11:17:53 -0700228 foreach_list_const(n, &this->statements) {
229 ast_node *ast = exec_node_data(ast_node, n, link);
230 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800231 }
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;
Ian Romanicka87ac252010-02-22 13:19:34 -0800241
242 if (statements != NULL) {
Ian Romanick304ea902010-05-10 11:17:53 -0700243 this->statements.push_degenerate_list_at_head(&statements->link);
Ian Romanicka87ac252010-02-22 13:19:34 -0800244 }
245}
246
247
248void
249ast_expression::print(void) const
250{
Ian Romanicka87ac252010-02-22 13:19:34 -0800251 switch (oper) {
252 case ast_assign:
Ian Romanicka87ac252010-02-22 13:19:34 -0800253 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();
Ian Romanick88349b22010-02-22 19:10:25 -0800264 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800265 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:
Ian Romanick88349b22010-02-22 19:10:25 -0800279 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800280 subexpressions[0]->print();
281 break;
282
283 case ast_post_inc:
284 case ast_post_dec:
285 subexpressions[0]->print();
Ian Romanick88349b22010-02-22 19:10:25 -0800286 printf("%s ", operator_string(oper));
Ian Romanicka87ac252010-02-22 13:19:34 -0800287 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: {
Ian Romanicka87ac252010-02-22 13:19:34 -0800305 subexpressions[0]->print();
306 printf("( ");
307
Ian Romanick304ea902010-05-10 11:17:53 -0700308 foreach_list_const (n, &this->expressions) {
Ian Romanick23849372010-05-14 16:06:41 -0700309 if (n != this->expressions.get_head())
310 printf(", ");
Ian Romanick304ea902010-05-10 11:17:53 -0700311
312 ast_node *ast = exec_node_data(ast_node, n, link);
313 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800314 }
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: {
Ian Romanicka87ac252010-02-22 13:19:34 -0800343 printf("( ");
Ian Romanick304ea902010-05-10 11:17:53 -0700344 foreach_list_const(n, & this->expressions) {
345 if (n != this->expressions.get_head())
Ian Romanicka87ac252010-02-22 13:19:34 -0800346 printf(", ");
347
Ian Romanick304ea902010-05-10 11:17:53 -0700348 ast_node *ast = exec_node_data(ast_node, n, link);
349 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800350 }
351 printf(") ");
352 break;
353 }
Ian Romanick88349b22010-02-22 19:10:25 -0800354
355 default:
356 assert(0);
357 break;
Ian Romanicka87ac252010-02-22 13:19:34 -0800358 }
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;
Ian Romanicka87ac252010-02-22 13:19:34 -0800370}
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{
Ian Romanicka87ac252010-02-22 13:19:34 -0800393 return_type->print();
394 printf(" %s (", identifier);
395
Ian Romanick304ea902010-05-10 11:17:53 -0700396 foreach_list_const(n, & this->parameters) {
397 ast_node *ast = exec_node_data(ast_node, n, link);
398 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800399 }
400
401 printf(")");
402}
403
404
405ast_function::ast_function(void)
Ian Romanick92318a92010-03-31 18:23:21 -0700406 : is_definition(false), signature(NULL)
Ian Romanicka87ac252010-02-22 13:19:34 -0800407{
Ian Romanick304ea902010-05-10 11:17:53 -0700408 /* empty */
Ian Romanicka87ac252010-02-22 13:19:34 -0800409}
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{
Ian Romanicka87ac252010-02-22 13:19:34 -0800465 assert(type || invariant);
466
467 if (type)
468 type->print();
469 else
470 printf("invariant ");
471
Ian Romanick304ea902010-05-10 11:17:53 -0700472 foreach_list_const (ptr, & this->declarations) {
473 if (ptr != this->declarations.get_head())
Ian Romanicka87ac252010-02-22 13:19:34 -0800474 printf(", ");
475
Ian Romanick304ea902010-05-10 11:17:53 -0700476 ast_node *ast = exec_node_data(ast_node, ptr, link);
477 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800478 }
479
480 printf("; ");
481}
482
483
484ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
485{
486 this->type = type;
Ian Romanick38327062010-07-01 17:10:11 -0700487 this->invariant = false;
Ian Romanicka87ac252010-02-22 13:19:34 -0800488}
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{
Ian Romanicka87ac252010-02-22 13:19:34 -0800608 printf("struct %s { ", name);
Ian Romanick304ea902010-05-10 11:17:53 -0700609 foreach_list_const(n, &this->declarations) {
610 ast_node *ast = exec_node_data(ast_node, n, link);
611 ast->print();
Ian Romanicka87ac252010-02-22 13:19:34 -0800612 }
613 printf("} ");
614}
615
616
617ast_struct_specifier::ast_struct_specifier(char *identifier,
618 ast_node *declarator_list)
619{
620 name = identifier;
Ian Romanick304ea902010-05-10 11:17:53 -0700621 this->declarations.push_degenerate_list_at_head(&declarator_list->link);
Ian Romanicka87ac252010-02-22 13:19:34 -0800622}