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