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