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