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