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