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