1 // 2 // Copyright (C) 2016-2018 Google, Inc. 3 // Copyright (C) 2016 LunarG, Inc. 4 // 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions 9 // are met: 10 // 11 // Redistributions of source code must retain the above copyright 12 // notice, this list of conditions and the following disclaimer. 13 // 14 // Redistributions in binary form must reproduce the above 15 // copyright notice, this list of conditions and the following 16 // disclaimer in the documentation and/or other materials provided 17 // with the distribution. 18 // 19 // Neither the name of Google, Inc., nor the names of its 20 // contributors may be used to endorse or promote products derived 21 // from this software without specific prior written permission. 22 // 23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 // POSSIBILITY OF SUCH DAMAGE. 35 // 36 37 // 38 // This is a set of mutually recursive methods implementing the HLSL grammar. 39 // Generally, each returns 40 // - through an argument: a type specifically appropriate to which rule it 41 // recognized 42 // - through the return value: true/false to indicate whether or not it 43 // recognized its rule 44 // 45 // As much as possible, only grammar recognition should happen in this file, 46 // with all other work being farmed out to hlslParseHelper.cpp, which in turn 47 // will build the AST. 48 // 49 // The next token, yet to be "accepted" is always sitting in 'token'. 50 // When a method says it accepts a rule, that means all tokens involved 51 // in the rule will have been consumed, and none left in 'token'. 52 // 53 54 #include "hlslTokens.h" 55 #include "hlslGrammar.h" 56 #include "hlslAttributes.h" 57 58 namespace glslang { 59 60 // Root entry point to this recursive decent parser. 61 // Return true if compilation unit was successfully accepted. 62 bool HlslGrammar::parse() 63 { 64 advanceToken(); 65 return acceptCompilationUnit(); 66 } 67 68 void HlslGrammar::expected(const char* syntax) 69 { 70 parseContext.error(token.loc, "Expected", syntax, ""); 71 } 72 73 void HlslGrammar::unimplemented(const char* error) 74 { 75 parseContext.error(token.loc, "Unimplemented", error, ""); 76 } 77 78 // IDENTIFIER 79 // THIS 80 // type that can be used as IDENTIFIER 81 // 82 // Only process the next token if it is an identifier. 83 // Return true if it was an identifier. 84 bool HlslGrammar::acceptIdentifier(HlslToken& idToken) 85 { 86 // IDENTIFIER 87 if (peekTokenClass(EHTokIdentifier)) { 88 idToken = token; 89 advanceToken(); 90 return true; 91 } 92 93 // THIS 94 // -> maps to the IDENTIFIER spelled with the internal special name for 'this' 95 if (peekTokenClass(EHTokThis)) { 96 idToken = token; 97 advanceToken(); 98 idToken.tokenClass = EHTokIdentifier; 99 idToken.string = NewPoolTString(intermediate.implicitThisName); 100 return true; 101 } 102 103 // type that can be used as IDENTIFIER 104 105 // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers), 106 // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a 107 // valid identifier, nor is "linear". This code special cases the known instances of this, so 108 // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed. 109 110 const char* idString = getTypeString(peek()); 111 if (idString == nullptr) 112 return false; 113 114 token.string = NewPoolTString(idString); 115 token.tokenClass = EHTokIdentifier; 116 idToken = token; 117 typeIdentifiers = true; 118 119 advanceToken(); 120 121 return true; 122 } 123 124 // compilationUnit 125 // : declaration_list EOF 126 // 127 bool HlslGrammar::acceptCompilationUnit() 128 { 129 if (! acceptDeclarationList(unitNode)) 130 return false; 131 132 if (! peekTokenClass(EHTokNone)) 133 return false; 134 135 // set root of AST 136 if (unitNode && !unitNode->getAsAggregate()) 137 unitNode = intermediate.growAggregate(nullptr, unitNode); 138 intermediate.setTreeRoot(unitNode); 139 140 return true; 141 } 142 143 // Recognize the following, but with the extra condition that it can be 144 // successfully terminated by EOF or '}'. 145 // 146 // declaration_list 147 // : list of declaration_or_semicolon followed by EOF or RIGHT_BRACE 148 // 149 // declaration_or_semicolon 150 // : declaration 151 // : SEMICOLON 152 // 153 bool HlslGrammar::acceptDeclarationList(TIntermNode*& nodeList) 154 { 155 do { 156 // HLSL allows extra semicolons between global declarations 157 do { } while (acceptTokenClass(EHTokSemicolon)); 158 159 // EOF or RIGHT_BRACE 160 if (peekTokenClass(EHTokNone) || peekTokenClass(EHTokRightBrace)) 161 return true; 162 163 // declaration 164 if (! acceptDeclaration(nodeList)) 165 return false; 166 } while (true); 167 168 return true; 169 } 170 171 // sampler_state 172 // : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE 173 // 174 // sampler_state_assignment 175 // : sampler_state_identifier EQUAL value SEMICOLON 176 // 177 // sampler_state_identifier 178 // : ADDRESSU 179 // | ADDRESSV 180 // | ADDRESSW 181 // | BORDERCOLOR 182 // | FILTER 183 // | MAXANISOTROPY 184 // | MAXLOD 185 // | MINLOD 186 // | MIPLODBIAS 187 // 188 bool HlslGrammar::acceptSamplerState() 189 { 190 // TODO: this should be genericized to accept a list of valid tokens and 191 // return token/value pairs. Presently it is specific to texture values. 192 193 if (! acceptTokenClass(EHTokLeftBrace)) 194 return true; 195 196 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", ""); 197 198 do { 199 // read state name 200 HlslToken state; 201 if (! acceptIdentifier(state)) 202 break; // end of list 203 204 // FXC accepts any case 205 TString stateName = *state.string; 206 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower); 207 208 if (! acceptTokenClass(EHTokAssign)) { 209 expected("assign"); 210 return false; 211 } 212 213 if (stateName == "minlod" || stateName == "maxlod") { 214 if (! peekTokenClass(EHTokIntConstant)) { 215 expected("integer"); 216 return false; 217 } 218 219 TIntermTyped* lod = nullptr; 220 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer 221 return false; 222 } else if (stateName == "maxanisotropy") { 223 if (! peekTokenClass(EHTokIntConstant)) { 224 expected("integer"); 225 return false; 226 } 227 228 TIntermTyped* maxAnisotropy = nullptr; 229 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer 230 return false; 231 } else if (stateName == "filter") { 232 HlslToken filterMode; 233 if (! acceptIdentifier(filterMode)) { 234 expected("filter mode"); 235 return false; 236 } 237 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") { 238 HlslToken addrMode; 239 if (! acceptIdentifier(addrMode)) { 240 expected("texture address mode"); 241 return false; 242 } 243 } else if (stateName == "miplodbias") { 244 TIntermTyped* lodBias = nullptr; 245 if (! acceptLiteral(lodBias)) { 246 expected("lod bias"); 247 return false; 248 } 249 } else if (stateName == "bordercolor") { 250 return false; 251 } else { 252 expected("texture state"); 253 return false; 254 } 255 256 // SEMICOLON 257 if (! acceptTokenClass(EHTokSemicolon)) { 258 expected("semicolon"); 259 return false; 260 } 261 } while (true); 262 263 if (! acceptTokenClass(EHTokRightBrace)) 264 return false; 265 266 return true; 267 } 268 269 // sampler_declaration_dx9 270 // : SAMPLER identifier EQUAL sampler_type sampler_state 271 // 272 bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/) 273 { 274 if (! acceptTokenClass(EHTokSampler)) 275 return false; 276 277 // TODO: remove this when DX9 style declarations are implemented. 278 unimplemented("Direct3D 9 sampler declaration"); 279 280 // read sampler name 281 HlslToken name; 282 if (! acceptIdentifier(name)) { 283 expected("sampler name"); 284 return false; 285 } 286 287 if (! acceptTokenClass(EHTokAssign)) { 288 expected("="); 289 return false; 290 } 291 292 return false; 293 } 294 295 // declaration 296 // : attributes attributed_declaration 297 // | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE 298 // 299 // attributed_declaration 300 // : sampler_declaration_dx9 post_decls SEMICOLON 301 // | fully_specified_type // for cbuffer/tbuffer 302 // | fully_specified_type declarator_list SEMICOLON // for non cbuffer/tbuffer 303 // | fully_specified_type identifier function_parameters post_decls compound_statement // function definition 304 // | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition 305 // | typedef declaration 306 // 307 // declarator_list 308 // : declarator COMMA declarator COMMA declarator... // zero or more declarators 309 // 310 // declarator 311 // : identifier array_specifier post_decls 312 // | identifier array_specifier post_decls EQUAL assignment_expression 313 // | identifier function_parameters post_decls // function prototype 314 // 315 // Parsing has to go pretty far in to know whether it's a variable, prototype, or 316 // function definition, so the implementation below doesn't perfectly divide up the grammar 317 // as above. (The 'identifier' in the first item in init_declarator list is the 318 // same as 'identifier' for function declarations.) 319 // 320 // This can generate more than one subtree, one per initializer or a function body. 321 // All initializer subtrees are put in their own aggregate node, making one top-level 322 // node for all the initializers. Each function created is a top-level node to grow 323 // into the passed-in nodeList. 324 // 325 // If 'nodeList' is passed in as non-null, it must be an aggregate to extend for 326 // each top-level node the declaration creates. Otherwise, if only one top-level 327 // node in generated here, that is want is returned in nodeList. 328 // 329 bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList) 330 { 331 // NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE 332 if (acceptTokenClass(EHTokNamespace)) { 333 HlslToken namespaceToken; 334 if (!acceptIdentifier(namespaceToken)) { 335 expected("namespace name"); 336 return false; 337 } 338 parseContext.pushNamespace(*namespaceToken.string); 339 if (!acceptTokenClass(EHTokLeftBrace)) { 340 expected("{"); 341 return false; 342 } 343 if (!acceptDeclarationList(nodeList)) { 344 expected("declaration list"); 345 return false; 346 } 347 if (!acceptTokenClass(EHTokRightBrace)) { 348 expected("}"); 349 return false; 350 } 351 parseContext.popNamespace(); 352 return true; 353 } 354 355 bool declarator_list = false; // true when processing comma separation 356 357 // attributes 358 TFunctionDeclarator declarator; 359 acceptAttributes(declarator.attributes); 360 361 // typedef 362 bool typedefDecl = acceptTokenClass(EHTokTypedef); 363 364 TType declaredType; 365 366 // DX9 sampler declaration use a different syntax 367 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to 368 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9 369 // HLSL shaders, this will have to be a master level switch 370 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used 371 // For that reason, this line is commented out 372 // if (acceptSamplerDeclarationDX9(declaredType)) 373 // return true; 374 375 bool forbidDeclarators = (peekTokenClass(EHTokCBuffer) || peekTokenClass(EHTokTBuffer)); 376 // fully_specified_type 377 if (! acceptFullySpecifiedType(declaredType, nodeList, declarator.attributes, forbidDeclarators)) 378 return false; 379 380 // cbuffer and tbuffer end with the closing '}'. 381 // No semicolon is included. 382 if (forbidDeclarators) 383 return true; 384 385 // declarator_list 386 // : declarator 387 // : identifier 388 HlslToken idToken; 389 TIntermAggregate* initializers = nullptr; 390 while (acceptIdentifier(idToken)) { 391 TString *fullName = idToken.string; 392 if (parseContext.symbolTable.atGlobalLevel()) 393 parseContext.getFullNamespaceName(fullName); 394 if (peekTokenClass(EHTokLeftParen)) { 395 // looks like function parameters 396 397 // merge in the attributes into the return type 398 parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType, true); 399 400 // Potentially rename shader entry point function. No-op most of the time. 401 parseContext.renameShaderFunction(fullName); 402 403 // function_parameters 404 declarator.function = new TFunction(fullName, declaredType); 405 if (!acceptFunctionParameters(*declarator.function)) { 406 expected("function parameter list"); 407 return false; 408 } 409 410 // post_decls 411 acceptPostDecls(declarator.function->getWritableType().getQualifier()); 412 413 // compound_statement (function body definition) or just a prototype? 414 declarator.loc = token.loc; 415 if (peekTokenClass(EHTokLeftBrace)) { 416 if (declarator_list) 417 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", ""); 418 if (typedefDecl) 419 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", ""); 420 return acceptFunctionDefinition(declarator, nodeList, nullptr); 421 } else { 422 if (typedefDecl) 423 parseContext.error(idToken.loc, "function typedefs not implemented", "{", ""); 424 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true); 425 } 426 } else { 427 // A variable declaration. 428 429 // merge in the attributes, the first time around, into the shared type 430 if (! declarator_list) 431 parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType); 432 433 // Fix the storage qualifier if it's a global. 434 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) 435 declaredType.getQualifier().storage = EvqUniform; 436 437 // recognize array_specifier 438 TArraySizes* arraySizes = nullptr; 439 acceptArraySpecifier(arraySizes); 440 441 // We can handle multiple variables per type declaration, so 442 // the number of types can expand when arrayness is different. 443 TType variableType; 444 variableType.shallowCopy(declaredType); 445 446 // In the most general case, arrayness is potentially coming both from the 447 // declared type and from the variable: "int[] a[];" or just one or the other. 448 // Merge it all to the variableType, so all arrayness is part of the variableType. 449 variableType.transferArraySizes(arraySizes); 450 variableType.copyArrayInnerSizes(declaredType.getArraySizes()); 451 452 // samplers accept immediate sampler state 453 if (variableType.getBasicType() == EbtSampler) { 454 if (! acceptSamplerState()) 455 return false; 456 } 457 458 // post_decls 459 acceptPostDecls(variableType.getQualifier()); 460 461 // EQUAL assignment_expression 462 TIntermTyped* expressionNode = nullptr; 463 if (acceptTokenClass(EHTokAssign)) { 464 if (typedefDecl) 465 parseContext.error(idToken.loc, "can't have an initializer", "typedef", ""); 466 if (! acceptAssignmentExpression(expressionNode)) { 467 expected("initializer"); 468 return false; 469 } 470 } 471 472 // TODO: things scoped within an annotation need their own name space; 473 // TODO: strings are not yet handled. 474 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) { 475 if (typedefDecl) 476 parseContext.declareTypedef(idToken.loc, *fullName, variableType); 477 else if (variableType.getBasicType() == EbtBlock) { 478 if (expressionNode) 479 parseContext.error(idToken.loc, "buffer aliasing not yet supported", "block initializer", ""); 480 parseContext.declareBlock(idToken.loc, variableType, fullName); 481 parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName); 482 } else { 483 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) { 484 // this isn't really an individual variable, but a member of the $Global buffer 485 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName); 486 } else { 487 // Declare the variable and add any initializer code to the AST. 488 // The top-level node is always made into an aggregate, as that's 489 // historically how the AST has been. 490 initializers = intermediate.growAggregate(initializers, 491 parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode), 492 idToken.loc); 493 } 494 } 495 } 496 } 497 498 // COMMA 499 if (acceptTokenClass(EHTokComma)) 500 declarator_list = true; 501 } 502 503 // The top-level initializer node is a sequence. 504 if (initializers != nullptr) 505 initializers->setOperator(EOpSequence); 506 507 // if we have a locally scoped static, it needs a globally scoped initializer 508 if (declaredType.getQualifier().storage == EvqGlobal && !parseContext.symbolTable.atGlobalLevel()) { 509 unitNode = intermediate.growAggregate(unitNode, initializers, idToken.loc); 510 } else { 511 // Add the initializers' aggregate to the nodeList we were handed. 512 if (nodeList) 513 nodeList = intermediate.growAggregate(nodeList, initializers); 514 else 515 nodeList = initializers; 516 } 517 518 // SEMICOLON 519 if (! acceptTokenClass(EHTokSemicolon)) { 520 // This may have been a false detection of what appeared to be a declaration, but 521 // was actually an assignment such as "float = 4", where "float" is an identifier. 522 // We put the token back to let further parsing happen for cases where that may 523 // happen. This errors on the side of caution, and mostly triggers the error. 524 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma) 525 recedeToken(); 526 else 527 expected(";"); 528 return false; 529 } 530 531 return true; 532 } 533 534 // control_declaration 535 // : fully_specified_type identifier EQUAL expression 536 // 537 bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node) 538 { 539 node = nullptr; 540 TAttributes attributes; 541 542 // fully_specified_type 543 TType type; 544 if (! acceptFullySpecifiedType(type, attributes)) 545 return false; 546 547 if (attributes.size() > 0) 548 parseContext.warn(token.loc, "attributes don't apply to control declaration", "", ""); 549 550 // filter out type casts 551 if (peekTokenClass(EHTokLeftParen)) { 552 recedeToken(); 553 return false; 554 } 555 556 // identifier 557 HlslToken idToken; 558 if (! acceptIdentifier(idToken)) { 559 expected("identifier"); 560 return false; 561 } 562 563 // EQUAL 564 TIntermTyped* expressionNode = nullptr; 565 if (! acceptTokenClass(EHTokAssign)) { 566 expected("="); 567 return false; 568 } 569 570 // expression 571 if (! acceptExpression(expressionNode)) { 572 expected("initializer"); 573 return false; 574 } 575 576 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode); 577 578 return true; 579 } 580 581 // fully_specified_type 582 // : type_specifier 583 // | type_qualifier type_specifier 584 // 585 bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributes& attributes) 586 { 587 TIntermNode* nodeList = nullptr; 588 return acceptFullySpecifiedType(type, nodeList, attributes); 589 } 590 bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributes& attributes, bool forbidDeclarators) 591 { 592 // type_qualifier 593 TQualifier qualifier; 594 qualifier.clear(); 595 if (! acceptQualifier(qualifier)) 596 return false; 597 TSourceLoc loc = token.loc; 598 599 // type_specifier 600 if (! acceptType(type, nodeList)) { 601 // If this is not a type, we may have inadvertently gone down a wrong path 602 // by parsing "sample", which can be treated like either an identifier or a 603 // qualifier. Back it out, if we did. 604 if (qualifier.sample) 605 recedeToken(); 606 607 return false; 608 } 609 610 if (type.getBasicType() == EbtBlock) { 611 // the type was a block, which set some parts of the qualifier 612 parseContext.mergeQualifiers(type.getQualifier(), qualifier); 613 614 // merge in the attributes 615 parseContext.transferTypeAttributes(token.loc, attributes, type); 616 617 // further, it can create an anonymous instance of the block 618 // (cbuffer and tbuffer don't consume the next identifier, and 619 // should set forbidDeclarators) 620 if (forbidDeclarators || peek() != EHTokIdentifier) 621 parseContext.declareBlock(loc, type); 622 } else { 623 // Some qualifiers are set when parsing the type. Merge those with 624 // whatever comes from acceptQualifier. 625 assert(qualifier.layoutFormat == ElfNone); 626 627 qualifier.layoutFormat = type.getQualifier().layoutFormat; 628 qualifier.precision = type.getQualifier().precision; 629 630 if (type.getQualifier().storage == EvqOut || 631 type.getQualifier().storage == EvqBuffer) { 632 qualifier.storage = type.getQualifier().storage; 633 qualifier.readonly = type.getQualifier().readonly; 634 } 635 636 if (type.isBuiltIn()) 637 qualifier.builtIn = type.getQualifier().builtIn; 638 639 type.getQualifier() = qualifier; 640 } 641 642 return true; 643 } 644 645 // type_qualifier 646 // : qualifier qualifier ... 647 // 648 // Zero or more of these, so this can't return false. 649 // 650 bool HlslGrammar::acceptQualifier(TQualifier& qualifier) 651 { 652 do { 653 switch (peek()) { 654 case EHTokStatic: 655 qualifier.storage = EvqGlobal; 656 break; 657 case EHTokExtern: 658 // TODO: no meaning in glslang? 659 break; 660 case EHTokShared: 661 // TODO: hint 662 break; 663 case EHTokGroupShared: 664 qualifier.storage = EvqShared; 665 break; 666 case EHTokUniform: 667 qualifier.storage = EvqUniform; 668 break; 669 case EHTokConst: 670 qualifier.storage = EvqConst; 671 break; 672 case EHTokVolatile: 673 qualifier.volatil = true; 674 break; 675 case EHTokLinear: 676 qualifier.smooth = true; 677 break; 678 case EHTokCentroid: 679 qualifier.centroid = true; 680 break; 681 case EHTokNointerpolation: 682 qualifier.flat = true; 683 break; 684 case EHTokNoperspective: 685 qualifier.nopersp = true; 686 break; 687 case EHTokSample: 688 qualifier.sample = true; 689 break; 690 case EHTokRowMajor: 691 qualifier.layoutMatrix = ElmColumnMajor; 692 break; 693 case EHTokColumnMajor: 694 qualifier.layoutMatrix = ElmRowMajor; 695 break; 696 case EHTokPrecise: 697 qualifier.noContraction = true; 698 break; 699 case EHTokIn: 700 qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn; 701 break; 702 case EHTokOut: 703 qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut; 704 break; 705 case EHTokInOut: 706 qualifier.storage = EvqInOut; 707 break; 708 case EHTokLayout: 709 if (! acceptLayoutQualifierList(qualifier)) 710 return false; 711 continue; 712 case EHTokGloballyCoherent: 713 qualifier.coherent = true; 714 break; 715 case EHTokInline: 716 // TODO: map this to SPIR-V function control 717 break; 718 719 // GS geometries: these are specified on stage input variables, and are an error (not verified here) 720 // for output variables. 721 case EHTokPoint: 722 qualifier.storage = EvqIn; 723 if (!parseContext.handleInputGeometry(token.loc, ElgPoints)) 724 return false; 725 break; 726 case EHTokLine: 727 qualifier.storage = EvqIn; 728 if (!parseContext.handleInputGeometry(token.loc, ElgLines)) 729 return false; 730 break; 731 case EHTokTriangle: 732 qualifier.storage = EvqIn; 733 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles)) 734 return false; 735 break; 736 case EHTokLineAdj: 737 qualifier.storage = EvqIn; 738 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency)) 739 return false; 740 break; 741 case EHTokTriangleAdj: 742 qualifier.storage = EvqIn; 743 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency)) 744 return false; 745 break; 746 747 default: 748 return true; 749 } 750 advanceToken(); 751 } while (true); 752 } 753 754 // layout_qualifier_list 755 // : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN 756 // 757 // layout_qualifier 758 // : identifier 759 // | identifier EQUAL expression 760 // 761 // Zero or more of these, so this can't return false. 762 // 763 bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier) 764 { 765 if (! acceptTokenClass(EHTokLayout)) 766 return false; 767 768 // LEFT_PAREN 769 if (! acceptTokenClass(EHTokLeftParen)) 770 return false; 771 772 do { 773 // identifier 774 HlslToken idToken; 775 if (! acceptIdentifier(idToken)) 776 break; 777 778 // EQUAL expression 779 if (acceptTokenClass(EHTokAssign)) { 780 TIntermTyped* expr; 781 if (! acceptConditionalExpression(expr)) { 782 expected("expression"); 783 return false; 784 } 785 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr); 786 } else 787 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string); 788 789 // COMMA 790 if (! acceptTokenClass(EHTokComma)) 791 break; 792 } while (true); 793 794 // RIGHT_PAREN 795 if (! acceptTokenClass(EHTokRightParen)) { 796 expected(")"); 797 return false; 798 } 799 800 return true; 801 } 802 803 // template_type 804 // : FLOAT 805 // | DOUBLE 806 // | INT 807 // | DWORD 808 // | UINT 809 // | BOOL 810 // 811 bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType) 812 { 813 switch (peek()) { 814 case EHTokFloat: 815 basicType = EbtFloat; 816 break; 817 case EHTokDouble: 818 basicType = EbtDouble; 819 break; 820 case EHTokInt: 821 case EHTokDword: 822 basicType = EbtInt; 823 break; 824 case EHTokUint: 825 basicType = EbtUint; 826 break; 827 case EHTokBool: 828 basicType = EbtBool; 829 break; 830 default: 831 return false; 832 } 833 834 advanceToken(); 835 836 return true; 837 } 838 839 // vector_template_type 840 // : VECTOR 841 // | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE 842 // 843 bool HlslGrammar::acceptVectorTemplateType(TType& type) 844 { 845 if (! acceptTokenClass(EHTokVector)) 846 return false; 847 848 if (! acceptTokenClass(EHTokLeftAngle)) { 849 // in HLSL, 'vector' alone means float4. 850 new(&type) TType(EbtFloat, EvqTemporary, 4); 851 return true; 852 } 853 854 TBasicType basicType; 855 if (! acceptTemplateVecMatBasicType(basicType)) { 856 expected("scalar type"); 857 return false; 858 } 859 860 // COMMA 861 if (! acceptTokenClass(EHTokComma)) { 862 expected(","); 863 return false; 864 } 865 866 // integer 867 if (! peekTokenClass(EHTokIntConstant)) { 868 expected("literal integer"); 869 return false; 870 } 871 872 TIntermTyped* vecSize; 873 if (! acceptLiteral(vecSize)) 874 return false; 875 876 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst(); 877 878 new(&type) TType(basicType, EvqTemporary, vecSizeI); 879 880 if (vecSizeI == 1) 881 type.makeVector(); 882 883 if (!acceptTokenClass(EHTokRightAngle)) { 884 expected("right angle bracket"); 885 return false; 886 } 887 888 return true; 889 } 890 891 // matrix_template_type 892 // : MATRIX 893 // | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE 894 // 895 bool HlslGrammar::acceptMatrixTemplateType(TType& type) 896 { 897 if (! acceptTokenClass(EHTokMatrix)) 898 return false; 899 900 if (! acceptTokenClass(EHTokLeftAngle)) { 901 // in HLSL, 'matrix' alone means float4x4. 902 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4); 903 return true; 904 } 905 906 TBasicType basicType; 907 if (! acceptTemplateVecMatBasicType(basicType)) { 908 expected("scalar type"); 909 return false; 910 } 911 912 // COMMA 913 if (! acceptTokenClass(EHTokComma)) { 914 expected(","); 915 return false; 916 } 917 918 // integer rows 919 if (! peekTokenClass(EHTokIntConstant)) { 920 expected("literal integer"); 921 return false; 922 } 923 924 TIntermTyped* rows; 925 if (! acceptLiteral(rows)) 926 return false; 927 928 // COMMA 929 if (! acceptTokenClass(EHTokComma)) { 930 expected(","); 931 return false; 932 } 933 934 // integer cols 935 if (! peekTokenClass(EHTokIntConstant)) { 936 expected("literal integer"); 937 return false; 938 } 939 940 TIntermTyped* cols; 941 if (! acceptLiteral(cols)) 942 return false; 943 944 new(&type) TType(basicType, EvqTemporary, 0, 945 rows->getAsConstantUnion()->getConstArray()[0].getIConst(), 946 cols->getAsConstantUnion()->getConstArray()[0].getIConst()); 947 948 if (!acceptTokenClass(EHTokRightAngle)) { 949 expected("right angle bracket"); 950 return false; 951 } 952 953 return true; 954 } 955 956 // layout_geometry 957 // : LINESTREAM 958 // | POINTSTREAM 959 // | TRIANGLESTREAM 960 // 961 bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry) 962 { 963 // read geometry type 964 const EHlslTokenClass geometryType = peek(); 965 966 switch (geometryType) { 967 case EHTokPointStream: geometry = ElgPoints; break; 968 case EHTokLineStream: geometry = ElgLineStrip; break; 969 case EHTokTriangleStream: geometry = ElgTriangleStrip; break; 970 default: 971 return false; // not a layout geometry 972 } 973 974 advanceToken(); // consume the layout keyword 975 return true; 976 } 977 978 // tessellation_decl_type 979 // : INPUTPATCH 980 // | OUTPUTPATCH 981 // 982 bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType) 983 { 984 // read geometry type 985 const EHlslTokenClass tessType = peek(); 986 987 switch (tessType) { 988 case EHTokInputPatch: patchType = EbvInputPatch; break; 989 case EHTokOutputPatch: patchType = EbvOutputPatch; break; 990 default: 991 return false; // not a tessellation decl 992 } 993 994 advanceToken(); // consume the keyword 995 return true; 996 } 997 998 // tessellation_patch_template_type 999 // : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE 1000 // 1001 bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type) 1002 { 1003 TBuiltInVariable patchType; 1004 1005 if (! acceptTessellationDeclType(patchType)) 1006 return false; 1007 1008 if (! acceptTokenClass(EHTokLeftAngle)) 1009 return false; 1010 1011 if (! acceptType(type)) { 1012 expected("tessellation patch type"); 1013 return false; 1014 } 1015 1016 if (! acceptTokenClass(EHTokComma)) 1017 return false; 1018 1019 // integer size 1020 if (! peekTokenClass(EHTokIntConstant)) { 1021 expected("literal integer"); 1022 return false; 1023 } 1024 1025 TIntermTyped* size; 1026 if (! acceptLiteral(size)) 1027 return false; 1028 1029 TArraySizes* arraySizes = new TArraySizes; 1030 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst()); 1031 type.transferArraySizes(arraySizes); 1032 type.getQualifier().builtIn = patchType; 1033 1034 if (! acceptTokenClass(EHTokRightAngle)) { 1035 expected("right angle bracket"); 1036 return false; 1037 } 1038 1039 return true; 1040 } 1041 1042 // stream_out_template_type 1043 // : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE 1044 // 1045 bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry) 1046 { 1047 geometry = ElgNone; 1048 1049 if (! acceptOutputPrimitiveGeometry(geometry)) 1050 return false; 1051 1052 if (! acceptTokenClass(EHTokLeftAngle)) 1053 return false; 1054 1055 if (! acceptType(type)) { 1056 expected("stream output type"); 1057 return false; 1058 } 1059 1060 type.getQualifier().storage = EvqOut; 1061 type.getQualifier().builtIn = EbvGsOutputStream; 1062 1063 if (! acceptTokenClass(EHTokRightAngle)) { 1064 expected("right angle bracket"); 1065 return false; 1066 } 1067 1068 return true; 1069 } 1070 1071 // annotations 1072 // : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE 1073 // 1074 bool HlslGrammar::acceptAnnotations(TQualifier&) 1075 { 1076 if (! acceptTokenClass(EHTokLeftAngle)) 1077 return false; 1078 1079 // note that we are nesting a name space 1080 parseContext.nestAnnotations(); 1081 1082 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE 1083 do { 1084 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not 1085 while (acceptTokenClass(EHTokSemicolon)) 1086 ; 1087 1088 if (acceptTokenClass(EHTokRightAngle)) 1089 break; 1090 1091 // declaration 1092 TIntermNode* node = nullptr; 1093 if (! acceptDeclaration(node)) { 1094 expected("declaration in annotation"); 1095 return false; 1096 } 1097 } while (true); 1098 1099 parseContext.unnestAnnotations(); 1100 return true; 1101 } 1102 1103 // subpass input type 1104 // : SUBPASSINPUT 1105 // | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE 1106 // | SUBPASSINPUTMS 1107 // | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE 1108 bool HlslGrammar::acceptSubpassInputType(TType& type) 1109 { 1110 // read subpass type 1111 const EHlslTokenClass subpassInputType = peek(); 1112 1113 bool multisample; 1114 1115 switch (subpassInputType) { 1116 case EHTokSubpassInput: multisample = false; break; 1117 case EHTokSubpassInputMS: multisample = true; break; 1118 default: 1119 return false; // not a subpass input declaration 1120 } 1121 1122 advanceToken(); // consume the sampler type keyword 1123 1124 TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4 1125 1126 if (acceptTokenClass(EHTokLeftAngle)) { 1127 if (! acceptType(subpassType)) { 1128 expected("scalar or vector type"); 1129 return false; 1130 } 1131 1132 const TBasicType basicRetType = subpassType.getBasicType() ; 1133 1134 switch (basicRetType) { 1135 case EbtFloat: 1136 case EbtUint: 1137 case EbtInt: 1138 case EbtStruct: 1139 break; 1140 default: 1141 unimplemented("basic type in subpass input"); 1142 return false; 1143 } 1144 1145 if (! acceptTokenClass(EHTokRightAngle)) { 1146 expected("right angle bracket"); 1147 return false; 1148 } 1149 } 1150 1151 const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType() 1152 : subpassType.getBasicType(); 1153 1154 TSampler sampler; 1155 sampler.setSubpass(subpassBasicType, multisample); 1156 1157 // Remember the declared return type. Function returns false on error. 1158 if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc)) 1159 return false; 1160 1161 type.shallowCopy(TType(sampler, EvqUniform)); 1162 1163 return true; 1164 } 1165 1166 // sampler_type for DX9 compatibility 1167 // : SAMPLER 1168 // | SAMPLER1D 1169 // | SAMPLER2D 1170 // | SAMPLER3D 1171 // | SAMPLERCUBE 1172 bool HlslGrammar::acceptSamplerTypeDX9(TType &type) 1173 { 1174 // read sampler type 1175 const EHlslTokenClass samplerType = peek(); 1176 1177 TSamplerDim dim = EsdNone; 1178 TType txType(EbtFloat, EvqUniform, 4); // default type is float4 1179 1180 bool isShadow = false; 1181 1182 switch (samplerType) 1183 { 1184 case EHTokSampler: dim = Esd2D; break; 1185 case EHTokSampler1d: dim = Esd1D; break; 1186 case EHTokSampler2d: dim = Esd2D; break; 1187 case EHTokSampler3d: dim = Esd3D; break; 1188 case EHTokSamplerCube: dim = EsdCube; break; 1189 default: 1190 return false; // not a dx9 sampler declaration 1191 } 1192 1193 advanceToken(); // consume the sampler type keyword 1194 1195 TArraySizes *arraySizes = nullptr; // TODO: array 1196 1197 TSampler sampler; 1198 sampler.set(txType.getBasicType(), dim, false, isShadow, false); 1199 1200 if (!parseContext.setTextureReturnType(sampler, txType, token.loc)) 1201 return false; 1202 1203 type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); 1204 type.getQualifier().layoutFormat = ElfNone; 1205 1206 return true; 1207 } 1208 1209 // sampler_type 1210 // : SAMPLER 1211 // | SAMPLER1D 1212 // | SAMPLER2D 1213 // | SAMPLER3D 1214 // | SAMPLERCUBE 1215 // | SAMPLERSTATE 1216 // | SAMPLERCOMPARISONSTATE 1217 bool HlslGrammar::acceptSamplerType(TType& type) 1218 { 1219 // read sampler type 1220 const EHlslTokenClass samplerType = peek(); 1221 1222 // TODO: for DX9 1223 // TSamplerDim dim = EsdNone; 1224 1225 bool isShadow = false; 1226 1227 switch (samplerType) { 1228 case EHTokSampler: break; 1229 case EHTokSampler1d: /*dim = Esd1D*/; break; 1230 case EHTokSampler2d: /*dim = Esd2D*/; break; 1231 case EHTokSampler3d: /*dim = Esd3D*/; break; 1232 case EHTokSamplerCube: /*dim = EsdCube*/; break; 1233 case EHTokSamplerState: break; 1234 case EHTokSamplerComparisonState: isShadow = true; break; 1235 default: 1236 return false; // not a sampler declaration 1237 } 1238 1239 advanceToken(); // consume the sampler type keyword 1240 1241 TArraySizes* arraySizes = nullptr; // TODO: array 1242 1243 TSampler sampler; 1244 sampler.setPureSampler(isShadow); 1245 1246 type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); 1247 1248 return true; 1249 } 1250 1251 // texture_type 1252 // | BUFFER 1253 // | TEXTURE1D 1254 // | TEXTURE1DARRAY 1255 // | TEXTURE2D 1256 // | TEXTURE2DARRAY 1257 // | TEXTURE3D 1258 // | TEXTURECUBE 1259 // | TEXTURECUBEARRAY 1260 // | TEXTURE2DMS 1261 // | TEXTURE2DMSARRAY 1262 // | RWBUFFER 1263 // | RWTEXTURE1D 1264 // | RWTEXTURE1DARRAY 1265 // | RWTEXTURE2D 1266 // | RWTEXTURE2DARRAY 1267 // | RWTEXTURE3D 1268 1269 bool HlslGrammar::acceptTextureType(TType& type) 1270 { 1271 const EHlslTokenClass textureType = peek(); 1272 1273 TSamplerDim dim = EsdNone; 1274 bool array = false; 1275 bool ms = false; 1276 bool image = false; 1277 bool combined = true; 1278 1279 switch (textureType) { 1280 case EHTokBuffer: dim = EsdBuffer; combined = false; break; 1281 case EHTokTexture1d: dim = Esd1D; break; 1282 case EHTokTexture1darray: dim = Esd1D; array = true; break; 1283 case EHTokTexture2d: dim = Esd2D; break; 1284 case EHTokTexture2darray: dim = Esd2D; array = true; break; 1285 case EHTokTexture3d: dim = Esd3D; break; 1286 case EHTokTextureCube: dim = EsdCube; break; 1287 case EHTokTextureCubearray: dim = EsdCube; array = true; break; 1288 case EHTokTexture2DMS: dim = Esd2D; ms = true; break; 1289 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break; 1290 case EHTokRWBuffer: dim = EsdBuffer; image=true; break; 1291 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break; 1292 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break; 1293 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break; 1294 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break; 1295 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break; 1296 default: 1297 return false; // not a texture declaration 1298 } 1299 1300 advanceToken(); // consume the texture object keyword 1301 1302 TType txType(EbtFloat, EvqUniform, 4); // default type is float4 1303 1304 TIntermTyped* msCount = nullptr; 1305 1306 // texture type: required for multisample types and RWBuffer/RWTextures! 1307 if (acceptTokenClass(EHTokLeftAngle)) { 1308 if (! acceptType(txType)) { 1309 expected("scalar or vector type"); 1310 return false; 1311 } 1312 1313 const TBasicType basicRetType = txType.getBasicType() ; 1314 1315 switch (basicRetType) { 1316 case EbtFloat: 1317 case EbtUint: 1318 case EbtInt: 1319 case EbtStruct: 1320 break; 1321 default: 1322 unimplemented("basic type in texture"); 1323 return false; 1324 } 1325 1326 // Buffers can handle small mats if they fit in 4 components 1327 if (dim == EsdBuffer && txType.isMatrix()) { 1328 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) { 1329 expected("components < 4 in matrix buffer type"); 1330 return false; 1331 } 1332 1333 // TODO: except we don't handle it yet... 1334 unimplemented("matrix type in buffer"); 1335 return false; 1336 } 1337 1338 if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) { 1339 expected("scalar, vector, or struct type"); 1340 return false; 1341 } 1342 1343 if (ms && acceptTokenClass(EHTokComma)) { 1344 // read sample count for multisample types, if given 1345 if (! peekTokenClass(EHTokIntConstant)) { 1346 expected("multisample count"); 1347 return false; 1348 } 1349 1350 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer 1351 return false; 1352 } 1353 1354 if (! acceptTokenClass(EHTokRightAngle)) { 1355 expected("right angle bracket"); 1356 return false; 1357 } 1358 } else if (ms) { 1359 expected("texture type for multisample"); 1360 return false; 1361 } else if (image) { 1362 expected("type for RWTexture/RWBuffer"); 1363 return false; 1364 } 1365 1366 TArraySizes* arraySizes = nullptr; 1367 const bool shadow = false; // declared on the sampler 1368 1369 TSampler sampler; 1370 TLayoutFormat format = ElfNone; 1371 1372 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set. 1373 if (image || dim == EsdBuffer) 1374 format = parseContext.getLayoutFromTxType(token.loc, txType); 1375 1376 const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType() 1377 : txType.getBasicType(); 1378 1379 // Non-image Buffers are combined 1380 if (dim == EsdBuffer && !image) { 1381 sampler.set(txType.getBasicType(), dim, array); 1382 } else { 1383 // DX10 textures are separated. TODO: DX9. 1384 if (image) { 1385 sampler.setImage(txBasicType, dim, array, shadow, ms); 1386 } else { 1387 sampler.setTexture(txBasicType, dim, array, shadow, ms); 1388 } 1389 } 1390 1391 // Remember the declared return type. Function returns false on error. 1392 if (!parseContext.setTextureReturnType(sampler, txType, token.loc)) 1393 return false; 1394 1395 // Force uncombined, if necessary 1396 if (!combined) 1397 sampler.combined = false; 1398 1399 type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); 1400 type.getQualifier().layoutFormat = format; 1401 1402 return true; 1403 } 1404 1405 // If token is for a type, update 'type' with the type information, 1406 // and return true and advance. 1407 // Otherwise, return false, and don't advance 1408 bool HlslGrammar::acceptType(TType& type) 1409 { 1410 TIntermNode* nodeList = nullptr; 1411 return acceptType(type, nodeList); 1412 } 1413 bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList) 1414 { 1415 // Basic types for min* types, use native halfs if the option allows them. 1416 bool enable16BitTypes = parseContext.hlslEnable16BitTypes(); 1417 1418 const TBasicType min16float_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; 1419 const TBasicType min10float_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; 1420 const TBasicType half_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; 1421 const TBasicType min16int_bt = enable16BitTypes ? EbtInt16 : EbtInt; 1422 const TBasicType min12int_bt = enable16BitTypes ? EbtInt16 : EbtInt; 1423 const TBasicType min16uint_bt = enable16BitTypes ? EbtUint16 : EbtUint; 1424 1425 // Some types might have turned into identifiers. Take the hit for checking 1426 // when this has happened. 1427 if (typeIdentifiers) { 1428 const char* identifierString = getTypeString(peek()); 1429 if (identifierString != nullptr) { 1430 TString name = identifierString; 1431 // if it's an identifier, it's not a type 1432 if (parseContext.symbolTable.find(name) != nullptr) 1433 return false; 1434 } 1435 } 1436 1437 bool isUnorm = false; 1438 bool isSnorm = false; 1439 1440 // Accept snorm and unorm. Presently, this is ignored, save for an error check below. 1441 switch (peek()) { 1442 case EHTokUnorm: 1443 isUnorm = true; 1444 advanceToken(); // eat the token 1445 break; 1446 case EHTokSNorm: 1447 isSnorm = true; 1448 advanceToken(); // eat the token 1449 break; 1450 default: 1451 break; 1452 } 1453 1454 switch (peek()) { 1455 case EHTokVector: 1456 return acceptVectorTemplateType(type); 1457 break; 1458 1459 case EHTokMatrix: 1460 return acceptMatrixTemplateType(type); 1461 break; 1462 1463 case EHTokPointStream: // fall through 1464 case EHTokLineStream: // ... 1465 case EHTokTriangleStream: // ... 1466 { 1467 TLayoutGeometry geometry; 1468 if (! acceptStreamOutTemplateType(type, geometry)) 1469 return false; 1470 1471 if (! parseContext.handleOutputGeometry(token.loc, geometry)) 1472 return false; 1473 1474 return true; 1475 } 1476 1477 case EHTokInputPatch: // fall through 1478 case EHTokOutputPatch: // ... 1479 { 1480 if (! acceptTessellationPatchTemplateType(type)) 1481 return false; 1482 1483 return true; 1484 } 1485 1486 case EHTokSampler: // fall through 1487 case EHTokSampler1d: // ... 1488 case EHTokSampler2d: // ... 1489 case EHTokSampler3d: // ... 1490 case EHTokSamplerCube: // ... 1491 if (parseContext.hlslDX9Compatible()) 1492 return acceptSamplerTypeDX9(type); 1493 else 1494 return acceptSamplerType(type); 1495 break; 1496 1497 case EHTokSamplerState: // fall through 1498 case EHTokSamplerComparisonState: // ... 1499 return acceptSamplerType(type); 1500 break; 1501 1502 case EHTokSubpassInput: // fall through 1503 case EHTokSubpassInputMS: // ... 1504 return acceptSubpassInputType(type); 1505 break; 1506 1507 case EHTokBuffer: // fall through 1508 case EHTokTexture1d: // ... 1509 case EHTokTexture1darray: // ... 1510 case EHTokTexture2d: // ... 1511 case EHTokTexture2darray: // ... 1512 case EHTokTexture3d: // ... 1513 case EHTokTextureCube: // ... 1514 case EHTokTextureCubearray: // ... 1515 case EHTokTexture2DMS: // ... 1516 case EHTokTexture2DMSarray: // ... 1517 case EHTokRWTexture1d: // ... 1518 case EHTokRWTexture1darray: // ... 1519 case EHTokRWTexture2d: // ... 1520 case EHTokRWTexture2darray: // ... 1521 case EHTokRWTexture3d: // ... 1522 case EHTokRWBuffer: // ... 1523 return acceptTextureType(type); 1524 break; 1525 1526 case EHTokAppendStructuredBuffer: 1527 case EHTokByteAddressBuffer: 1528 case EHTokConsumeStructuredBuffer: 1529 case EHTokRWByteAddressBuffer: 1530 case EHTokRWStructuredBuffer: 1531 case EHTokStructuredBuffer: 1532 return acceptStructBufferType(type); 1533 break; 1534 1535 case EHTokTextureBuffer: 1536 return acceptTextureBufferType(type); 1537 break; 1538 1539 case EHTokConstantBuffer: 1540 return acceptConstantBufferType(type); 1541 1542 case EHTokClass: 1543 case EHTokStruct: 1544 case EHTokCBuffer: 1545 case EHTokTBuffer: 1546 return acceptStruct(type, nodeList); 1547 1548 case EHTokIdentifier: 1549 // An identifier could be for a user-defined type. 1550 // Note we cache the symbol table lookup, to save for a later rule 1551 // when this is not a type. 1552 if (parseContext.lookupUserType(*token.string, type) != nullptr) { 1553 advanceToken(); 1554 return true; 1555 } else 1556 return false; 1557 1558 case EHTokVoid: 1559 new(&type) TType(EbtVoid); 1560 break; 1561 1562 case EHTokString: 1563 new(&type) TType(EbtString); 1564 break; 1565 1566 case EHTokFloat: 1567 new(&type) TType(EbtFloat); 1568 break; 1569 case EHTokFloat1: 1570 new(&type) TType(EbtFloat); 1571 type.makeVector(); 1572 break; 1573 case EHTokFloat2: 1574 new(&type) TType(EbtFloat, EvqTemporary, 2); 1575 break; 1576 case EHTokFloat3: 1577 new(&type) TType(EbtFloat, EvqTemporary, 3); 1578 break; 1579 case EHTokFloat4: 1580 new(&type) TType(EbtFloat, EvqTemporary, 4); 1581 break; 1582 1583 case EHTokDouble: 1584 new(&type) TType(EbtDouble); 1585 break; 1586 case EHTokDouble1: 1587 new(&type) TType(EbtDouble); 1588 type.makeVector(); 1589 break; 1590 case EHTokDouble2: 1591 new(&type) TType(EbtDouble, EvqTemporary, 2); 1592 break; 1593 case EHTokDouble3: 1594 new(&type) TType(EbtDouble, EvqTemporary, 3); 1595 break; 1596 case EHTokDouble4: 1597 new(&type) TType(EbtDouble, EvqTemporary, 4); 1598 break; 1599 1600 case EHTokInt: 1601 case EHTokDword: 1602 new(&type) TType(EbtInt); 1603 break; 1604 case EHTokInt1: 1605 new(&type) TType(EbtInt); 1606 type.makeVector(); 1607 break; 1608 case EHTokInt2: 1609 new(&type) TType(EbtInt, EvqTemporary, 2); 1610 break; 1611 case EHTokInt3: 1612 new(&type) TType(EbtInt, EvqTemporary, 3); 1613 break; 1614 case EHTokInt4: 1615 new(&type) TType(EbtInt, EvqTemporary, 4); 1616 break; 1617 1618 case EHTokUint: 1619 new(&type) TType(EbtUint); 1620 break; 1621 case EHTokUint1: 1622 new(&type) TType(EbtUint); 1623 type.makeVector(); 1624 break; 1625 case EHTokUint2: 1626 new(&type) TType(EbtUint, EvqTemporary, 2); 1627 break; 1628 case EHTokUint3: 1629 new(&type) TType(EbtUint, EvqTemporary, 3); 1630 break; 1631 case EHTokUint4: 1632 new(&type) TType(EbtUint, EvqTemporary, 4); 1633 break; 1634 1635 case EHTokUint64: 1636 new(&type) TType(EbtUint64); 1637 break; 1638 1639 case EHTokBool: 1640 new(&type) TType(EbtBool); 1641 break; 1642 case EHTokBool1: 1643 new(&type) TType(EbtBool); 1644 type.makeVector(); 1645 break; 1646 case EHTokBool2: 1647 new(&type) TType(EbtBool, EvqTemporary, 2); 1648 break; 1649 case EHTokBool3: 1650 new(&type) TType(EbtBool, EvqTemporary, 3); 1651 break; 1652 case EHTokBool4: 1653 new(&type) TType(EbtBool, EvqTemporary, 4); 1654 break; 1655 1656 case EHTokHalf: 1657 new(&type) TType(half_bt, EvqTemporary); 1658 break; 1659 case EHTokHalf1: 1660 new(&type) TType(half_bt, EvqTemporary); 1661 type.makeVector(); 1662 break; 1663 case EHTokHalf2: 1664 new(&type) TType(half_bt, EvqTemporary, 2); 1665 break; 1666 case EHTokHalf3: 1667 new(&type) TType(half_bt, EvqTemporary, 3); 1668 break; 1669 case EHTokHalf4: 1670 new(&type) TType(half_bt, EvqTemporary, 4); 1671 break; 1672 1673 case EHTokMin16float: 1674 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium); 1675 break; 1676 case EHTokMin16float1: 1677 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium); 1678 type.makeVector(); 1679 break; 1680 case EHTokMin16float2: 1681 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2); 1682 break; 1683 case EHTokMin16float3: 1684 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3); 1685 break; 1686 case EHTokMin16float4: 1687 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4); 1688 break; 1689 1690 case EHTokMin10float: 1691 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium); 1692 break; 1693 case EHTokMin10float1: 1694 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium); 1695 type.makeVector(); 1696 break; 1697 case EHTokMin10float2: 1698 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2); 1699 break; 1700 case EHTokMin10float3: 1701 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3); 1702 break; 1703 case EHTokMin10float4: 1704 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4); 1705 break; 1706 1707 case EHTokMin16int: 1708 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium); 1709 break; 1710 case EHTokMin16int1: 1711 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium); 1712 type.makeVector(); 1713 break; 1714 case EHTokMin16int2: 1715 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2); 1716 break; 1717 case EHTokMin16int3: 1718 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3); 1719 break; 1720 case EHTokMin16int4: 1721 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4); 1722 break; 1723 1724 case EHTokMin12int: 1725 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium); 1726 break; 1727 case EHTokMin12int1: 1728 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium); 1729 type.makeVector(); 1730 break; 1731 case EHTokMin12int2: 1732 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2); 1733 break; 1734 case EHTokMin12int3: 1735 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3); 1736 break; 1737 case EHTokMin12int4: 1738 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4); 1739 break; 1740 1741 case EHTokMin16uint: 1742 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium); 1743 break; 1744 case EHTokMin16uint1: 1745 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium); 1746 type.makeVector(); 1747 break; 1748 case EHTokMin16uint2: 1749 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2); 1750 break; 1751 case EHTokMin16uint3: 1752 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3); 1753 break; 1754 case EHTokMin16uint4: 1755 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4); 1756 break; 1757 1758 case EHTokInt1x1: 1759 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1); 1760 break; 1761 case EHTokInt1x2: 1762 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2); 1763 break; 1764 case EHTokInt1x3: 1765 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3); 1766 break; 1767 case EHTokInt1x4: 1768 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4); 1769 break; 1770 case EHTokInt2x1: 1771 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1); 1772 break; 1773 case EHTokInt2x2: 1774 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2); 1775 break; 1776 case EHTokInt2x3: 1777 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3); 1778 break; 1779 case EHTokInt2x4: 1780 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4); 1781 break; 1782 case EHTokInt3x1: 1783 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1); 1784 break; 1785 case EHTokInt3x2: 1786 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2); 1787 break; 1788 case EHTokInt3x3: 1789 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3); 1790 break; 1791 case EHTokInt3x4: 1792 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4); 1793 break; 1794 case EHTokInt4x1: 1795 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1); 1796 break; 1797 case EHTokInt4x2: 1798 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2); 1799 break; 1800 case EHTokInt4x3: 1801 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3); 1802 break; 1803 case EHTokInt4x4: 1804 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4); 1805 break; 1806 1807 case EHTokUint1x1: 1808 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1); 1809 break; 1810 case EHTokUint1x2: 1811 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2); 1812 break; 1813 case EHTokUint1x3: 1814 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3); 1815 break; 1816 case EHTokUint1x4: 1817 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4); 1818 break; 1819 case EHTokUint2x1: 1820 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1); 1821 break; 1822 case EHTokUint2x2: 1823 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2); 1824 break; 1825 case EHTokUint2x3: 1826 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3); 1827 break; 1828 case EHTokUint2x4: 1829 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4); 1830 break; 1831 case EHTokUint3x1: 1832 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1); 1833 break; 1834 case EHTokUint3x2: 1835 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2); 1836 break; 1837 case EHTokUint3x3: 1838 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3); 1839 break; 1840 case EHTokUint3x4: 1841 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4); 1842 break; 1843 case EHTokUint4x1: 1844 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1); 1845 break; 1846 case EHTokUint4x2: 1847 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2); 1848 break; 1849 case EHTokUint4x3: 1850 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3); 1851 break; 1852 case EHTokUint4x4: 1853 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4); 1854 break; 1855 1856 case EHTokBool1x1: 1857 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1); 1858 break; 1859 case EHTokBool1x2: 1860 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2); 1861 break; 1862 case EHTokBool1x3: 1863 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3); 1864 break; 1865 case EHTokBool1x4: 1866 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4); 1867 break; 1868 case EHTokBool2x1: 1869 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1); 1870 break; 1871 case EHTokBool2x2: 1872 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2); 1873 break; 1874 case EHTokBool2x3: 1875 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3); 1876 break; 1877 case EHTokBool2x4: 1878 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4); 1879 break; 1880 case EHTokBool3x1: 1881 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1); 1882 break; 1883 case EHTokBool3x2: 1884 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2); 1885 break; 1886 case EHTokBool3x3: 1887 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3); 1888 break; 1889 case EHTokBool3x4: 1890 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4); 1891 break; 1892 case EHTokBool4x1: 1893 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1); 1894 break; 1895 case EHTokBool4x2: 1896 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2); 1897 break; 1898 case EHTokBool4x3: 1899 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3); 1900 break; 1901 case EHTokBool4x4: 1902 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4); 1903 break; 1904 1905 case EHTokFloat1x1: 1906 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1); 1907 break; 1908 case EHTokFloat1x2: 1909 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2); 1910 break; 1911 case EHTokFloat1x3: 1912 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3); 1913 break; 1914 case EHTokFloat1x4: 1915 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4); 1916 break; 1917 case EHTokFloat2x1: 1918 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1); 1919 break; 1920 case EHTokFloat2x2: 1921 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2); 1922 break; 1923 case EHTokFloat2x3: 1924 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3); 1925 break; 1926 case EHTokFloat2x4: 1927 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4); 1928 break; 1929 case EHTokFloat3x1: 1930 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1); 1931 break; 1932 case EHTokFloat3x2: 1933 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2); 1934 break; 1935 case EHTokFloat3x3: 1936 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3); 1937 break; 1938 case EHTokFloat3x4: 1939 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4); 1940 break; 1941 case EHTokFloat4x1: 1942 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1); 1943 break; 1944 case EHTokFloat4x2: 1945 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2); 1946 break; 1947 case EHTokFloat4x3: 1948 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3); 1949 break; 1950 case EHTokFloat4x4: 1951 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4); 1952 break; 1953 1954 case EHTokHalf1x1: 1955 new(&type) TType(half_bt, EvqTemporary, 0, 1, 1); 1956 break; 1957 case EHTokHalf1x2: 1958 new(&type) TType(half_bt, EvqTemporary, 0, 1, 2); 1959 break; 1960 case EHTokHalf1x3: 1961 new(&type) TType(half_bt, EvqTemporary, 0, 1, 3); 1962 break; 1963 case EHTokHalf1x4: 1964 new(&type) TType(half_bt, EvqTemporary, 0, 1, 4); 1965 break; 1966 case EHTokHalf2x1: 1967 new(&type) TType(half_bt, EvqTemporary, 0, 2, 1); 1968 break; 1969 case EHTokHalf2x2: 1970 new(&type) TType(half_bt, EvqTemporary, 0, 2, 2); 1971 break; 1972 case EHTokHalf2x3: 1973 new(&type) TType(half_bt, EvqTemporary, 0, 2, 3); 1974 break; 1975 case EHTokHalf2x4: 1976 new(&type) TType(half_bt, EvqTemporary, 0, 2, 4); 1977 break; 1978 case EHTokHalf3x1: 1979 new(&type) TType(half_bt, EvqTemporary, 0, 3, 1); 1980 break; 1981 case EHTokHalf3x2: 1982 new(&type) TType(half_bt, EvqTemporary, 0, 3, 2); 1983 break; 1984 case EHTokHalf3x3: 1985 new(&type) TType(half_bt, EvqTemporary, 0, 3, 3); 1986 break; 1987 case EHTokHalf3x4: 1988 new(&type) TType(half_bt, EvqTemporary, 0, 3, 4); 1989 break; 1990 case EHTokHalf4x1: 1991 new(&type) TType(half_bt, EvqTemporary, 0, 4, 1); 1992 break; 1993 case EHTokHalf4x2: 1994 new(&type) TType(half_bt, EvqTemporary, 0, 4, 2); 1995 break; 1996 case EHTokHalf4x3: 1997 new(&type) TType(half_bt, EvqTemporary, 0, 4, 3); 1998 break; 1999 case EHTokHalf4x4: 2000 new(&type) TType(half_bt, EvqTemporary, 0, 4, 4); 2001 break; 2002 2003 case EHTokDouble1x1: 2004 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1); 2005 break; 2006 case EHTokDouble1x2: 2007 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2); 2008 break; 2009 case EHTokDouble1x3: 2010 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3); 2011 break; 2012 case EHTokDouble1x4: 2013 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4); 2014 break; 2015 case EHTokDouble2x1: 2016 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1); 2017 break; 2018 case EHTokDouble2x2: 2019 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2); 2020 break; 2021 case EHTokDouble2x3: 2022 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3); 2023 break; 2024 case EHTokDouble2x4: 2025 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4); 2026 break; 2027 case EHTokDouble3x1: 2028 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1); 2029 break; 2030 case EHTokDouble3x2: 2031 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2); 2032 break; 2033 case EHTokDouble3x3: 2034 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3); 2035 break; 2036 case EHTokDouble3x4: 2037 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4); 2038 break; 2039 case EHTokDouble4x1: 2040 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1); 2041 break; 2042 case EHTokDouble4x2: 2043 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2); 2044 break; 2045 case EHTokDouble4x3: 2046 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3); 2047 break; 2048 case EHTokDouble4x4: 2049 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4); 2050 break; 2051 2052 default: 2053 return false; 2054 } 2055 2056 advanceToken(); 2057 2058 if ((isUnorm || isSnorm) && !type.isFloatingDomain()) { 2059 parseContext.error(token.loc, "unorm and snorm only valid in floating point domain", "", ""); 2060 return false; 2061 } 2062 2063 return true; 2064 } 2065 2066 // struct 2067 // : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE 2068 // | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE 2069 // | struct_type IDENTIFIER // use of previously declared struct type 2070 // 2071 // struct_type 2072 // : STRUCT 2073 // | CLASS 2074 // | CBUFFER 2075 // | TBUFFER 2076 // 2077 bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) 2078 { 2079 // This storage qualifier will tell us whether it's an AST 2080 // block type or just a generic structure type. 2081 TStorageQualifier storageQualifier = EvqTemporary; 2082 bool readonly = false; 2083 2084 if (acceptTokenClass(EHTokCBuffer)) { 2085 // CBUFFER 2086 storageQualifier = EvqUniform; 2087 } else if (acceptTokenClass(EHTokTBuffer)) { 2088 // TBUFFER 2089 storageQualifier = EvqBuffer; 2090 readonly = true; 2091 } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) { 2092 // Neither CLASS nor STRUCT 2093 return false; 2094 } 2095 2096 // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT 2097 2098 2099 // IDENTIFIER. It might also be a keyword which can double as an identifier. 2100 // For example: 'cbuffer ConstantBuffer' or 'struct ConstantBuffer' is legal. 2101 // 'cbuffer int' is also legal, and 'struct int' appears rejected only because 2102 // it attempts to redefine the 'int' type. 2103 const char* idString = getTypeString(peek()); 2104 TString structName = ""; 2105 if (peekTokenClass(EHTokIdentifier) || idString != nullptr) { 2106 if (idString != nullptr) 2107 structName = *idString; 2108 else 2109 structName = *token.string; 2110 advanceToken(); 2111 } 2112 2113 // post_decls 2114 TQualifier postDeclQualifier; 2115 postDeclQualifier.clear(); 2116 bool postDeclsFound = acceptPostDecls(postDeclQualifier); 2117 2118 // LEFT_BRACE, or 2119 // struct_type IDENTIFIER 2120 if (! acceptTokenClass(EHTokLeftBrace)) { 2121 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) { 2122 // struct_type IDENTIFIER 2123 return true; 2124 } else { 2125 expected("{"); 2126 return false; 2127 } 2128 } 2129 2130 2131 // struct_declaration_list 2132 TTypeList* typeList; 2133 // Save each member function so they can be processed after we have a fully formed 'this'. 2134 TVector<TFunctionDeclarator> functionDeclarators; 2135 2136 parseContext.pushNamespace(structName); 2137 bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators); 2138 parseContext.popNamespace(); 2139 2140 if (! acceptedList) { 2141 expected("struct member declarations"); 2142 return false; 2143 } 2144 2145 // RIGHT_BRACE 2146 if (! acceptTokenClass(EHTokRightBrace)) { 2147 expected("}"); 2148 return false; 2149 } 2150 2151 // create the user-defined type 2152 if (storageQualifier == EvqTemporary) 2153 new(&type) TType(typeList, structName); 2154 else { 2155 postDeclQualifier.storage = storageQualifier; 2156 postDeclQualifier.readonly = readonly; 2157 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock 2158 } 2159 2160 parseContext.declareStruct(token.loc, structName, type); 2161 2162 // For member functions: now that we know the type of 'this', go back and 2163 // - add their implicit argument with 'this' (not to the mangling, just the argument list) 2164 // - parse the functions, their tokens were saved for deferred parsing (now) 2165 for (int b = 0; b < (int)functionDeclarators.size(); ++b) { 2166 // update signature 2167 if (functionDeclarators[b].function->hasImplicitThis()) 2168 functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName); 2169 } 2170 2171 // All member functions get parsed inside the class/struct namespace and with the 2172 // class/struct members in a symbol-table level. 2173 parseContext.pushNamespace(structName); 2174 parseContext.pushThisScope(type, functionDeclarators); 2175 bool deferredSuccess = true; 2176 for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) { 2177 // parse body 2178 pushTokenStream(functionDeclarators[b].body); 2179 if (! acceptFunctionBody(functionDeclarators[b], nodeList)) 2180 deferredSuccess = false; 2181 popTokenStream(); 2182 } 2183 parseContext.popThisScope(); 2184 parseContext.popNamespace(); 2185 2186 return deferredSuccess; 2187 } 2188 2189 // constantbuffer 2190 // : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE 2191 bool HlslGrammar::acceptConstantBufferType(TType& type) 2192 { 2193 if (! acceptTokenClass(EHTokConstantBuffer)) 2194 return false; 2195 2196 if (! acceptTokenClass(EHTokLeftAngle)) { 2197 expected("left angle bracket"); 2198 return false; 2199 } 2200 2201 TType templateType; 2202 if (! acceptType(templateType)) { 2203 expected("type"); 2204 return false; 2205 } 2206 2207 if (! acceptTokenClass(EHTokRightAngle)) { 2208 expected("right angle bracket"); 2209 return false; 2210 } 2211 2212 TQualifier postDeclQualifier; 2213 postDeclQualifier.clear(); 2214 postDeclQualifier.storage = EvqUniform; 2215 2216 if (templateType.isStruct()) { 2217 // Make a block from the type parsed as the template argument 2218 TTypeList* typeList = templateType.getWritableStruct(); 2219 new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock 2220 2221 type.getQualifier().storage = EvqUniform; 2222 2223 return true; 2224 } else { 2225 parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", ""); 2226 return false; 2227 } 2228 } 2229 2230 // texture_buffer 2231 // : TEXTUREBUFFER LEFT_ANGLE type RIGHT_ANGLE 2232 bool HlslGrammar::acceptTextureBufferType(TType& type) 2233 { 2234 if (! acceptTokenClass(EHTokTextureBuffer)) 2235 return false; 2236 2237 if (! acceptTokenClass(EHTokLeftAngle)) { 2238 expected("left angle bracket"); 2239 return false; 2240 } 2241 2242 TType templateType; 2243 if (! acceptType(templateType)) { 2244 expected("type"); 2245 return false; 2246 } 2247 2248 if (! acceptTokenClass(EHTokRightAngle)) { 2249 expected("right angle bracket"); 2250 return false; 2251 } 2252 2253 templateType.getQualifier().storage = EvqBuffer; 2254 templateType.getQualifier().readonly = true; 2255 2256 TType blockType(templateType.getWritableStruct(), "", templateType.getQualifier()); 2257 2258 blockType.getQualifier().storage = EvqBuffer; 2259 blockType.getQualifier().readonly = true; 2260 2261 type.shallowCopy(blockType); 2262 2263 return true; 2264 } 2265 2266 2267 // struct_buffer 2268 // : APPENDSTRUCTUREDBUFFER 2269 // | BYTEADDRESSBUFFER 2270 // | CONSUMESTRUCTUREDBUFFER 2271 // | RWBYTEADDRESSBUFFER 2272 // | RWSTRUCTUREDBUFFER 2273 // | STRUCTUREDBUFFER 2274 bool HlslGrammar::acceptStructBufferType(TType& type) 2275 { 2276 const EHlslTokenClass structBuffType = peek(); 2277 2278 // TODO: globallycoherent 2279 bool hasTemplateType = true; 2280 bool readonly = false; 2281 2282 TStorageQualifier storage = EvqBuffer; 2283 TBuiltInVariable builtinType = EbvNone; 2284 2285 switch (structBuffType) { 2286 case EHTokAppendStructuredBuffer: 2287 builtinType = EbvAppendConsume; 2288 break; 2289 case EHTokByteAddressBuffer: 2290 hasTemplateType = false; 2291 readonly = true; 2292 builtinType = EbvByteAddressBuffer; 2293 break; 2294 case EHTokConsumeStructuredBuffer: 2295 builtinType = EbvAppendConsume; 2296 break; 2297 case EHTokRWByteAddressBuffer: 2298 hasTemplateType = false; 2299 builtinType = EbvRWByteAddressBuffer; 2300 break; 2301 case EHTokRWStructuredBuffer: 2302 builtinType = EbvRWStructuredBuffer; 2303 break; 2304 case EHTokStructuredBuffer: 2305 builtinType = EbvStructuredBuffer; 2306 readonly = true; 2307 break; 2308 default: 2309 return false; // not a structure buffer type 2310 } 2311 2312 advanceToken(); // consume the structure keyword 2313 2314 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct 2315 TType* templateType = new TType; 2316 2317 if (hasTemplateType) { 2318 if (! acceptTokenClass(EHTokLeftAngle)) { 2319 expected("left angle bracket"); 2320 return false; 2321 } 2322 2323 if (! acceptType(*templateType)) { 2324 expected("type"); 2325 return false; 2326 } 2327 if (! acceptTokenClass(EHTokRightAngle)) { 2328 expected("right angle bracket"); 2329 return false; 2330 } 2331 } else { 2332 // byte address buffers have no explicit type. 2333 TType uintType(EbtUint, storage); 2334 templateType->shallowCopy(uintType); 2335 } 2336 2337 // Create an unsized array out of that type. 2338 // TODO: does this work if it's already an array type? 2339 TArraySizes* unsizedArray = new TArraySizes; 2340 unsizedArray->addInnerSize(UnsizedArraySize); 2341 templateType->transferArraySizes(unsizedArray); 2342 templateType->getQualifier().storage = storage; 2343 2344 // field name is canonical for all structbuffers 2345 templateType->setFieldName("@data"); 2346 2347 TTypeList* blockStruct = new TTypeList; 2348 TTypeLoc member = { templateType, token.loc }; 2349 blockStruct->push_back(member); 2350 2351 // This is the type of the buffer block (SSBO) 2352 TType blockType(blockStruct, "", templateType->getQualifier()); 2353 2354 blockType.getQualifier().storage = storage; 2355 blockType.getQualifier().readonly = readonly; 2356 blockType.getQualifier().builtIn = builtinType; 2357 2358 // We may have created an equivalent type before, in which case we should use its 2359 // deep structure. 2360 parseContext.shareStructBufferType(blockType); 2361 2362 type.shallowCopy(blockType); 2363 2364 return true; 2365 } 2366 2367 // struct_declaration_list 2368 // : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ... 2369 // 2370 // struct_declaration 2371 // : attributes fully_specified_type struct_declarator COMMA struct_declarator ... 2372 // | attributes fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition 2373 // 2374 // struct_declarator 2375 // : IDENTIFIER post_decls 2376 // | IDENTIFIER array_specifier post_decls 2377 // | IDENTIFIER function_parameters post_decls // member-function prototype 2378 // 2379 bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList, 2380 TVector<TFunctionDeclarator>& declarators) 2381 { 2382 typeList = new TTypeList(); 2383 HlslToken idToken; 2384 2385 do { 2386 // success on seeing the RIGHT_BRACE coming up 2387 if (peekTokenClass(EHTokRightBrace)) 2388 break; 2389 2390 // struct_declaration 2391 2392 // attributes 2393 TAttributes attributes; 2394 acceptAttributes(attributes); 2395 2396 bool declarator_list = false; 2397 2398 // fully_specified_type 2399 TType memberType; 2400 if (! acceptFullySpecifiedType(memberType, nodeList, attributes)) { 2401 expected("member type"); 2402 return false; 2403 } 2404 2405 // merge in the attributes 2406 parseContext.transferTypeAttributes(token.loc, attributes, memberType); 2407 2408 // struct_declarator COMMA struct_declarator ... 2409 bool functionDefinitionAccepted = false; 2410 do { 2411 if (! acceptIdentifier(idToken)) { 2412 expected("member name"); 2413 return false; 2414 } 2415 2416 if (peekTokenClass(EHTokLeftParen)) { 2417 // function_parameters 2418 if (!declarator_list) { 2419 declarators.resize(declarators.size() + 1); 2420 // request a token stream for deferred processing 2421 functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string, 2422 declarators.back()); 2423 if (functionDefinitionAccepted) 2424 break; 2425 } 2426 expected("member-function definition"); 2427 return false; 2428 } else { 2429 // add it to the list of members 2430 TTypeLoc member = { new TType(EbtVoid), token.loc }; 2431 member.type->shallowCopy(memberType); 2432 member.type->setFieldName(*idToken.string); 2433 typeList->push_back(member); 2434 2435 // array_specifier 2436 TArraySizes* arraySizes = nullptr; 2437 acceptArraySpecifier(arraySizes); 2438 if (arraySizes) 2439 typeList->back().type->transferArraySizes(arraySizes); 2440 2441 acceptPostDecls(member.type->getQualifier()); 2442 2443 // EQUAL assignment_expression 2444 if (acceptTokenClass(EHTokAssign)) { 2445 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", ""); 2446 TIntermTyped* expressionNode = nullptr; 2447 if (! acceptAssignmentExpression(expressionNode)) { 2448 expected("initializer"); 2449 return false; 2450 } 2451 } 2452 } 2453 // success on seeing the SEMICOLON coming up 2454 if (peekTokenClass(EHTokSemicolon)) 2455 break; 2456 2457 // COMMA 2458 if (acceptTokenClass(EHTokComma)) 2459 declarator_list = true; 2460 else { 2461 expected(","); 2462 return false; 2463 } 2464 2465 } while (true); 2466 2467 // SEMI_COLON 2468 if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) { 2469 expected(";"); 2470 return false; 2471 } 2472 2473 } while (true); 2474 2475 return true; 2476 } 2477 2478 // member_function_definition 2479 // | function_parameters post_decls compound_statement 2480 // 2481 // Expects type to have EvqGlobal for a static member and 2482 // EvqTemporary for non-static member. 2483 bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, TString& memberName, 2484 TFunctionDeclarator& declarator) 2485 { 2486 bool accepted = false; 2487 2488 TString* functionName = &memberName; 2489 parseContext.getFullNamespaceName(functionName); 2490 declarator.function = new TFunction(functionName, type); 2491 if (type.getQualifier().storage == EvqTemporary) 2492 declarator.function->setImplicitThis(); 2493 else 2494 declarator.function->setIllegalImplicitThis(); 2495 2496 // function_parameters 2497 if (acceptFunctionParameters(*declarator.function)) { 2498 // post_decls 2499 acceptPostDecls(declarator.function->getWritableType().getQualifier()); 2500 2501 // compound_statement (function body definition) 2502 if (peekTokenClass(EHTokLeftBrace)) { 2503 declarator.loc = token.loc; 2504 declarator.body = new TVector<HlslToken>; 2505 accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body); 2506 } 2507 } else 2508 expected("function parameter list"); 2509 2510 return accepted; 2511 } 2512 2513 // function_parameters 2514 // : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN 2515 // | LEFT_PAREN VOID RIGHT_PAREN 2516 // 2517 bool HlslGrammar::acceptFunctionParameters(TFunction& function) 2518 { 2519 // LEFT_PAREN 2520 if (! acceptTokenClass(EHTokLeftParen)) 2521 return false; 2522 2523 // VOID RIGHT_PAREN 2524 if (! acceptTokenClass(EHTokVoid)) { 2525 do { 2526 // parameter_declaration 2527 if (! acceptParameterDeclaration(function)) 2528 break; 2529 2530 // COMMA 2531 if (! acceptTokenClass(EHTokComma)) 2532 break; 2533 } while (true); 2534 } 2535 2536 // RIGHT_PAREN 2537 if (! acceptTokenClass(EHTokRightParen)) { 2538 expected(")"); 2539 return false; 2540 } 2541 2542 return true; 2543 } 2544 2545 // default_parameter_declaration 2546 // : EQUAL conditional_expression 2547 // : EQUAL initializer 2548 bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node) 2549 { 2550 node = nullptr; 2551 2552 // Valid not to have a default_parameter_declaration 2553 if (!acceptTokenClass(EHTokAssign)) 2554 return true; 2555 2556 if (!acceptConditionalExpression(node)) { 2557 if (!acceptInitializer(node)) 2558 return false; 2559 2560 // For initializer lists, we have to const-fold into a constructor for the type, so build 2561 // that. 2562 TFunction* constructor = parseContext.makeConstructorCall(token.loc, type); 2563 if (constructor == nullptr) // cannot construct 2564 return false; 2565 2566 TIntermTyped* arguments = nullptr; 2567 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++) 2568 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped()); 2569 2570 node = parseContext.handleFunctionCall(token.loc, constructor, node); 2571 } 2572 2573 if (node == nullptr) 2574 return false; 2575 2576 // If this is simply a constant, we can use it directly. 2577 if (node->getAsConstantUnion()) 2578 return true; 2579 2580 // Otherwise, it has to be const-foldable. 2581 TIntermTyped* origNode = node; 2582 2583 node = intermediate.fold(node->getAsAggregate()); 2584 2585 if (node != nullptr && origNode != node) 2586 return true; 2587 2588 parseContext.error(token.loc, "invalid default parameter value", "", ""); 2589 2590 return false; 2591 } 2592 2593 // parameter_declaration 2594 // : attributes attributed_declaration 2595 // 2596 // attributed_declaration 2597 // : fully_specified_type post_decls [ = default_parameter_declaration ] 2598 // | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ] 2599 // 2600 bool HlslGrammar::acceptParameterDeclaration(TFunction& function) 2601 { 2602 // attributes 2603 TAttributes attributes; 2604 acceptAttributes(attributes); 2605 2606 // fully_specified_type 2607 TType* type = new TType; 2608 if (! acceptFullySpecifiedType(*type, attributes)) 2609 return false; 2610 2611 // merge in the attributes 2612 parseContext.transferTypeAttributes(token.loc, attributes, *type); 2613 2614 // identifier 2615 HlslToken idToken; 2616 acceptIdentifier(idToken); 2617 2618 // array_specifier 2619 TArraySizes* arraySizes = nullptr; 2620 acceptArraySpecifier(arraySizes); 2621 if (arraySizes) { 2622 if (arraySizes->hasUnsized()) { 2623 parseContext.error(token.loc, "function parameter requires array size", "[]", ""); 2624 return false; 2625 } 2626 2627 type->transferArraySizes(arraySizes); 2628 } 2629 2630 // post_decls 2631 acceptPostDecls(type->getQualifier()); 2632 2633 TIntermTyped* defaultValue; 2634 if (!acceptDefaultParameterDeclaration(*type, defaultValue)) 2635 return false; 2636 2637 parseContext.paramFix(*type); 2638 2639 // If any prior parameters have default values, all the parameters after that must as well. 2640 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) { 2641 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), ""); 2642 return false; 2643 } 2644 2645 TParameter param = { idToken.string, type, defaultValue }; 2646 function.addParameter(param); 2647 2648 return true; 2649 } 2650 2651 // Do the work to create the function definition in addition to 2652 // parsing the body (compound_statement). 2653 // 2654 // If 'deferredTokens' are passed in, just get the token stream, 2655 // don't process. 2656 // 2657 bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList, 2658 TVector<HlslToken>* deferredTokens) 2659 { 2660 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */); 2661 2662 if (deferredTokens) 2663 return captureBlockTokens(*deferredTokens); 2664 else 2665 return acceptFunctionBody(declarator, nodeList); 2666 } 2667 2668 bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList) 2669 { 2670 // we might get back an entry-point 2671 TIntermNode* entryPointNode = nullptr; 2672 2673 // This does a pushScope() 2674 TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function, 2675 declarator.attributes, entryPointNode); 2676 2677 // compound_statement 2678 TIntermNode* functionBody = nullptr; 2679 if (! acceptCompoundStatement(functionBody)) 2680 return false; 2681 2682 // this does a popScope() 2683 parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode); 2684 2685 // Hook up the 1 or 2 function definitions. 2686 nodeList = intermediate.growAggregate(nodeList, functionNode); 2687 nodeList = intermediate.growAggregate(nodeList, entryPointNode); 2688 2689 return true; 2690 } 2691 2692 // Accept an expression with parenthesis around it, where 2693 // the parenthesis ARE NOT expression parenthesis, but the 2694 // syntactically required ones like in "if ( expression )". 2695 // 2696 // Also accepts a declaration expression; "if (int a = expression)". 2697 // 2698 // Note this one is not set up to be speculative; as it gives 2699 // errors if not found. 2700 // 2701 bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression) 2702 { 2703 expression = nullptr; 2704 2705 // LEFT_PAREN 2706 if (! acceptTokenClass(EHTokLeftParen)) 2707 expected("("); 2708 2709 bool decl = false; 2710 TIntermNode* declNode = nullptr; 2711 decl = acceptControlDeclaration(declNode); 2712 if (decl) { 2713 if (declNode == nullptr || declNode->getAsTyped() == nullptr) { 2714 expected("initialized declaration"); 2715 return false; 2716 } else 2717 expression = declNode->getAsTyped(); 2718 } else { 2719 // no declaration 2720 if (! acceptExpression(expression)) { 2721 expected("expression"); 2722 return false; 2723 } 2724 } 2725 2726 // RIGHT_PAREN 2727 if (! acceptTokenClass(EHTokRightParen)) 2728 expected(")"); 2729 2730 return true; 2731 } 2732 2733 // The top-level full expression recognizer. 2734 // 2735 // expression 2736 // : assignment_expression COMMA assignment_expression COMMA assignment_expression ... 2737 // 2738 bool HlslGrammar::acceptExpression(TIntermTyped*& node) 2739 { 2740 node = nullptr; 2741 2742 // assignment_expression 2743 if (! acceptAssignmentExpression(node)) 2744 return false; 2745 2746 if (! peekTokenClass(EHTokComma)) 2747 return true; 2748 2749 do { 2750 // ... COMMA 2751 TSourceLoc loc = token.loc; 2752 advanceToken(); 2753 2754 // ... assignment_expression 2755 TIntermTyped* rightNode = nullptr; 2756 if (! acceptAssignmentExpression(rightNode)) { 2757 expected("assignment expression"); 2758 return false; 2759 } 2760 2761 node = intermediate.addComma(node, rightNode, loc); 2762 2763 if (! peekTokenClass(EHTokComma)) 2764 return true; 2765 } while (true); 2766 } 2767 2768 // initializer 2769 // : LEFT_BRACE RIGHT_BRACE 2770 // | LEFT_BRACE initializer_list RIGHT_BRACE 2771 // 2772 // initializer_list 2773 // : assignment_expression COMMA assignment_expression COMMA ... 2774 // 2775 bool HlslGrammar::acceptInitializer(TIntermTyped*& node) 2776 { 2777 // LEFT_BRACE 2778 if (! acceptTokenClass(EHTokLeftBrace)) 2779 return false; 2780 2781 // RIGHT_BRACE 2782 TSourceLoc loc = token.loc; 2783 if (acceptTokenClass(EHTokRightBrace)) { 2784 // a zero-length initializer list 2785 node = intermediate.makeAggregate(loc); 2786 return true; 2787 } 2788 2789 // initializer_list 2790 node = nullptr; 2791 do { 2792 // assignment_expression 2793 TIntermTyped* expr; 2794 if (! acceptAssignmentExpression(expr)) { 2795 expected("assignment expression in initializer list"); 2796 return false; 2797 } 2798 2799 const bool firstNode = (node == nullptr); 2800 2801 node = intermediate.growAggregate(node, expr, loc); 2802 2803 // If every sub-node in the list has qualifier EvqConst, the returned node becomes 2804 // EvqConst. Otherwise, it becomes EvqTemporary. That doesn't happen with e.g. 2805 // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are. 2806 if (firstNode && expr->getQualifier().storage == EvqConst) 2807 node->getQualifier().storage = EvqConst; 2808 else if (expr->getQualifier().storage != EvqConst) 2809 node->getQualifier().storage = EvqTemporary; 2810 2811 // COMMA 2812 if (acceptTokenClass(EHTokComma)) { 2813 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma 2814 return true; 2815 continue; 2816 } 2817 2818 // RIGHT_BRACE 2819 if (acceptTokenClass(EHTokRightBrace)) 2820 return true; 2821 2822 expected(", or }"); 2823 return false; 2824 } while (true); 2825 } 2826 2827 // Accept an assignment expression, where assignment operations 2828 // associate right-to-left. That is, it is implicit, for example 2829 // 2830 // a op (b op (c op d)) 2831 // 2832 // assigment_expression 2833 // : initializer 2834 // | conditional_expression 2835 // | conditional_expression assign_op conditional_expression assign_op conditional_expression ... 2836 // 2837 bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) 2838 { 2839 // initializer 2840 if (peekTokenClass(EHTokLeftBrace)) { 2841 if (acceptInitializer(node)) 2842 return true; 2843 2844 expected("initializer"); 2845 return false; 2846 } 2847 2848 // conditional_expression 2849 if (! acceptConditionalExpression(node)) 2850 return false; 2851 2852 // assignment operation? 2853 TOperator assignOp = HlslOpMap::assignment(peek()); 2854 if (assignOp == EOpNull) 2855 return true; 2856 2857 // assign_op 2858 TSourceLoc loc = token.loc; 2859 advanceToken(); 2860 2861 // conditional_expression assign_op conditional_expression ... 2862 // Done by recursing this function, which automatically 2863 // gets the right-to-left associativity. 2864 TIntermTyped* rightNode = nullptr; 2865 if (! acceptAssignmentExpression(rightNode)) { 2866 expected("assignment expression"); 2867 return false; 2868 } 2869 2870 node = parseContext.handleAssign(loc, assignOp, node, rightNode); 2871 node = parseContext.handleLvalue(loc, "assign", node); 2872 2873 if (node == nullptr) { 2874 parseContext.error(loc, "could not create assignment", "", ""); 2875 return false; 2876 } 2877 2878 if (! peekTokenClass(EHTokComma)) 2879 return true; 2880 2881 return true; 2882 } 2883 2884 // Accept a conditional expression, which associates right-to-left, 2885 // accomplished by the "true" expression calling down to lower 2886 // precedence levels than this level. 2887 // 2888 // conditional_expression 2889 // : binary_expression 2890 // | binary_expression QUESTION expression COLON assignment_expression 2891 // 2892 bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node) 2893 { 2894 // binary_expression 2895 if (! acceptBinaryExpression(node, PlLogicalOr)) 2896 return false; 2897 2898 if (! acceptTokenClass(EHTokQuestion)) 2899 return true; 2900 2901 node = parseContext.convertConditionalExpression(token.loc, node, false); 2902 if (node == nullptr) 2903 return false; 2904 2905 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors 2906 2907 TIntermTyped* trueNode = nullptr; 2908 if (! acceptExpression(trueNode)) { 2909 expected("expression after ?"); 2910 return false; 2911 } 2912 TSourceLoc loc = token.loc; 2913 2914 if (! acceptTokenClass(EHTokColon)) { 2915 expected(":"); 2916 return false; 2917 } 2918 2919 TIntermTyped* falseNode = nullptr; 2920 if (! acceptAssignmentExpression(falseNode)) { 2921 expected("expression after :"); 2922 return false; 2923 } 2924 2925 --parseContext.controlFlowNestingLevel; 2926 2927 node = intermediate.addSelection(node, trueNode, falseNode, loc); 2928 2929 return true; 2930 } 2931 2932 // Accept a binary expression, for binary operations that 2933 // associate left-to-right. This is, it is implicit, for example 2934 // 2935 // ((a op b) op c) op d 2936 // 2937 // binary_expression 2938 // : expression op expression op expression ... 2939 // 2940 // where 'expression' is the next higher level in precedence. 2941 // 2942 bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel) 2943 { 2944 if (precedenceLevel > PlMul) 2945 return acceptUnaryExpression(node); 2946 2947 // assignment_expression 2948 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1))) 2949 return false; 2950 2951 do { 2952 TOperator op = HlslOpMap::binary(peek()); 2953 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op); 2954 if (tokenLevel < precedenceLevel) 2955 return true; 2956 2957 // ... op 2958 TSourceLoc loc = token.loc; 2959 advanceToken(); 2960 2961 // ... expression 2962 TIntermTyped* rightNode = nullptr; 2963 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) { 2964 expected("expression"); 2965 return false; 2966 } 2967 2968 node = intermediate.addBinaryMath(op, node, rightNode, loc); 2969 if (node == nullptr) { 2970 parseContext.error(loc, "Could not perform requested binary operation", "", ""); 2971 return false; 2972 } 2973 } while (true); 2974 } 2975 2976 // unary_expression 2977 // : (type) unary_expression 2978 // | + unary_expression 2979 // | - unary_expression 2980 // | ! unary_expression 2981 // | ~ unary_expression 2982 // | ++ unary_expression 2983 // | -- unary_expression 2984 // | postfix_expression 2985 // 2986 bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) 2987 { 2988 // (type) unary_expression 2989 // Have to look two steps ahead, because this could be, e.g., a 2990 // postfix_expression instead, since that also starts with at "(". 2991 if (acceptTokenClass(EHTokLeftParen)) { 2992 TType castType; 2993 if (acceptType(castType)) { 2994 // recognize any array_specifier as part of the type 2995 TArraySizes* arraySizes = nullptr; 2996 acceptArraySpecifier(arraySizes); 2997 if (arraySizes != nullptr) 2998 castType.transferArraySizes(arraySizes); 2999 TSourceLoc loc = token.loc; 3000 if (acceptTokenClass(EHTokRightParen)) { 3001 // We've matched "(type)" now, get the expression to cast 3002 if (! acceptUnaryExpression(node)) 3003 return false; 3004 3005 // Hook it up like a constructor 3006 TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType); 3007 if (constructorFunction == nullptr) { 3008 expected("type that can be constructed"); 3009 return false; 3010 } 3011 TIntermTyped* arguments = nullptr; 3012 parseContext.handleFunctionArgument(constructorFunction, arguments, node); 3013 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments); 3014 3015 return node != nullptr; 3016 } else { 3017 // This could be a parenthesized constructor, ala (int(3)), and we just accepted 3018 // the '(int' part. We must back up twice. 3019 recedeToken(); 3020 recedeToken(); 3021 3022 // Note, there are no array constructors like 3023 // (float[2](...)) 3024 if (arraySizes != nullptr) 3025 parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", ""); 3026 } 3027 } else { 3028 // This isn't a type cast, but it still started "(", so if it is a 3029 // unary expression, it can only be a postfix_expression, so try that. 3030 // Back it up first. 3031 recedeToken(); 3032 return acceptPostfixExpression(node); 3033 } 3034 } 3035 3036 // peek for "op unary_expression" 3037 TOperator unaryOp = HlslOpMap::preUnary(peek()); 3038 3039 // postfix_expression (if no unary operator) 3040 if (unaryOp == EOpNull) 3041 return acceptPostfixExpression(node); 3042 3043 // op unary_expression 3044 TSourceLoc loc = token.loc; 3045 advanceToken(); 3046 if (! acceptUnaryExpression(node)) 3047 return false; 3048 3049 // + is a no-op 3050 if (unaryOp == EOpAdd) 3051 return true; 3052 3053 node = intermediate.addUnaryMath(unaryOp, node, loc); 3054 3055 // These unary ops require lvalues 3056 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement) 3057 node = parseContext.handleLvalue(loc, "unary operator", node); 3058 3059 return node != nullptr; 3060 } 3061 3062 // postfix_expression 3063 // : LEFT_PAREN expression RIGHT_PAREN 3064 // | literal 3065 // | constructor 3066 // | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ] 3067 // | function_call 3068 // | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET 3069 // | postfix_expression DOT IDENTIFIER 3070 // | postfix_expression DOT IDENTIFIER arguments 3071 // | postfix_expression arguments 3072 // | postfix_expression INC_OP 3073 // | postfix_expression DEC_OP 3074 // 3075 bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node) 3076 { 3077 // Not implemented as self-recursive: 3078 // The logical "right recursion" is done with a loop at the end 3079 3080 // idToken will pick up either a variable or a function name in a function call 3081 HlslToken idToken; 3082 3083 // Find something before the postfix operations, as they can't operate 3084 // on nothing. So, no "return true", they fall through, only "return false". 3085 if (acceptTokenClass(EHTokLeftParen)) { 3086 // LEFT_PAREN expression RIGHT_PAREN 3087 if (! acceptExpression(node)) { 3088 expected("expression"); 3089 return false; 3090 } 3091 if (! acceptTokenClass(EHTokRightParen)) { 3092 expected(")"); 3093 return false; 3094 } 3095 } else if (acceptLiteral(node)) { 3096 // literal (nothing else to do yet) 3097 } else if (acceptConstructor(node)) { 3098 // constructor (nothing else to do yet) 3099 } else if (acceptIdentifier(idToken)) { 3100 // user-type, namespace name, variable, or function name 3101 TString* fullName = idToken.string; 3102 while (acceptTokenClass(EHTokColonColon)) { 3103 // user-type or namespace name 3104 fullName = NewPoolTString(fullName->c_str()); 3105 fullName->append(parseContext.scopeMangler); 3106 if (acceptIdentifier(idToken)) 3107 fullName->append(*idToken.string); 3108 else { 3109 expected("identifier after ::"); 3110 return false; 3111 } 3112 } 3113 if (! peekTokenClass(EHTokLeftParen)) { 3114 node = parseContext.handleVariable(idToken.loc, fullName); 3115 if (node == nullptr) 3116 return false; 3117 } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) { 3118 // function_call (nothing else to do yet) 3119 } else { 3120 expected("function call arguments"); 3121 return false; 3122 } 3123 } else { 3124 // nothing found, can't post operate 3125 return false; 3126 } 3127 3128 // Something was found, chain as many postfix operations as exist. 3129 do { 3130 TSourceLoc loc = token.loc; 3131 TOperator postOp = HlslOpMap::postUnary(peek()); 3132 3133 // Consume only a valid post-unary operator, otherwise we are done. 3134 switch (postOp) { 3135 case EOpIndexDirectStruct: 3136 case EOpIndexIndirect: 3137 case EOpPostIncrement: 3138 case EOpPostDecrement: 3139 case EOpScoping: 3140 advanceToken(); 3141 break; 3142 default: 3143 return true; 3144 } 3145 3146 // We have a valid post-unary operator, process it. 3147 switch (postOp) { 3148 case EOpScoping: 3149 case EOpIndexDirectStruct: 3150 { 3151 // DOT IDENTIFIER 3152 // includes swizzles, member variables, and member functions 3153 HlslToken field; 3154 if (! acceptIdentifier(field)) { 3155 expected("swizzle or member"); 3156 return false; 3157 } 3158 3159 if (peekTokenClass(EHTokLeftParen)) { 3160 // member function 3161 TIntermTyped* thisNode = node; 3162 3163 // arguments 3164 if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) { 3165 expected("function parameters"); 3166 return false; 3167 } 3168 } else 3169 node = parseContext.handleDotDereference(field.loc, node, *field.string); 3170 3171 break; 3172 } 3173 case EOpIndexIndirect: 3174 { 3175 // LEFT_BRACKET integer_expression RIGHT_BRACKET 3176 TIntermTyped* indexNode = nullptr; 3177 if (! acceptExpression(indexNode) || 3178 ! peekTokenClass(EHTokRightBracket)) { 3179 expected("expression followed by ']'"); 3180 return false; 3181 } 3182 advanceToken(); 3183 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode); 3184 if (node == nullptr) 3185 return false; 3186 break; 3187 } 3188 case EOpPostIncrement: 3189 // INC_OP 3190 // fall through 3191 case EOpPostDecrement: 3192 // DEC_OP 3193 node = intermediate.addUnaryMath(postOp, node, loc); 3194 node = parseContext.handleLvalue(loc, "unary operator", node); 3195 break; 3196 default: 3197 assert(0); 3198 break; 3199 } 3200 } while (true); 3201 } 3202 3203 // constructor 3204 // : type argument_list 3205 // 3206 bool HlslGrammar::acceptConstructor(TIntermTyped*& node) 3207 { 3208 // type 3209 TType type; 3210 if (acceptType(type)) { 3211 TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type); 3212 if (constructorFunction == nullptr) 3213 return false; 3214 3215 // arguments 3216 TIntermTyped* arguments = nullptr; 3217 if (! acceptArguments(constructorFunction, arguments)) { 3218 // It's possible this is a type keyword used as an identifier. Put the token back 3219 // for later use. 3220 recedeToken(); 3221 return false; 3222 } 3223 3224 // hook it up 3225 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments); 3226 3227 return node != nullptr; 3228 } 3229 3230 return false; 3231 } 3232 3233 // The function_call identifier was already recognized, and passed in as idToken. 3234 // 3235 // function_call 3236 // : [idToken] arguments 3237 // 3238 bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject) 3239 { 3240 // name 3241 TString* functionName = nullptr; 3242 if (baseObject == nullptr) { 3243 functionName = &name; 3244 } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) { 3245 // Built-in methods are not in the symbol table as methods, but as global functions 3246 // taking an explicit 'this' as the first argument. 3247 functionName = NewPoolTString(BUILTIN_PREFIX); 3248 functionName->append(name); 3249 } else { 3250 if (! baseObject->getType().isStruct()) { 3251 expected("structure"); 3252 return false; 3253 } 3254 functionName = NewPoolTString(""); 3255 functionName->append(baseObject->getType().getTypeName()); 3256 parseContext.addScopeMangler(*functionName); 3257 functionName->append(name); 3258 } 3259 3260 // function 3261 TFunction* function = new TFunction(functionName, TType(EbtVoid)); 3262 3263 // arguments 3264 TIntermTyped* arguments = nullptr; 3265 if (baseObject != nullptr) { 3266 // Non-static member functions have an implicit first argument of the base object. 3267 parseContext.handleFunctionArgument(function, arguments, baseObject); 3268 } 3269 if (! acceptArguments(function, arguments)) 3270 return false; 3271 3272 // call 3273 node = parseContext.handleFunctionCall(loc, function, arguments); 3274 3275 return node != nullptr; 3276 } 3277 3278 // arguments 3279 // : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN 3280 // 3281 // The arguments are pushed onto the 'function' argument list and 3282 // onto the 'arguments' aggregate. 3283 // 3284 bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments) 3285 { 3286 // LEFT_PAREN 3287 if (! acceptTokenClass(EHTokLeftParen)) 3288 return false; 3289 3290 // RIGHT_PAREN 3291 if (acceptTokenClass(EHTokRightParen)) 3292 return true; 3293 3294 // must now be at least one expression... 3295 do { 3296 // expression 3297 TIntermTyped* arg; 3298 if (! acceptAssignmentExpression(arg)) 3299 return false; 3300 3301 // hook it up 3302 parseContext.handleFunctionArgument(function, arguments, arg); 3303 3304 // COMMA 3305 if (! acceptTokenClass(EHTokComma)) 3306 break; 3307 } while (true); 3308 3309 // RIGHT_PAREN 3310 if (! acceptTokenClass(EHTokRightParen)) { 3311 expected(")"); 3312 return false; 3313 } 3314 3315 return true; 3316 } 3317 3318 bool HlslGrammar::acceptLiteral(TIntermTyped*& node) 3319 { 3320 switch (token.tokenClass) { 3321 case EHTokIntConstant: 3322 node = intermediate.addConstantUnion(token.i, token.loc, true); 3323 break; 3324 case EHTokUintConstant: 3325 node = intermediate.addConstantUnion(token.u, token.loc, true); 3326 break; 3327 case EHTokFloat16Constant: 3328 node = intermediate.addConstantUnion(token.d, EbtFloat16, token.loc, true); 3329 break; 3330 case EHTokFloatConstant: 3331 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true); 3332 break; 3333 case EHTokDoubleConstant: 3334 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true); 3335 break; 3336 case EHTokBoolConstant: 3337 node = intermediate.addConstantUnion(token.b, token.loc, true); 3338 break; 3339 case EHTokStringConstant: 3340 node = intermediate.addConstantUnion(token.string, token.loc, true); 3341 break; 3342 3343 default: 3344 return false; 3345 } 3346 3347 advanceToken(); 3348 3349 return true; 3350 } 3351 3352 // simple_statement 3353 // : SEMICOLON 3354 // | declaration_statement 3355 // | expression SEMICOLON 3356 // 3357 bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement) 3358 { 3359 // SEMICOLON 3360 if (acceptTokenClass(EHTokSemicolon)) 3361 return true; 3362 3363 // declaration 3364 if (acceptDeclaration(statement)) 3365 return true; 3366 3367 // expression 3368 TIntermTyped* node; 3369 if (acceptExpression(node)) 3370 statement = node; 3371 else 3372 return false; 3373 3374 // SEMICOLON (following an expression) 3375 if (acceptTokenClass(EHTokSemicolon)) 3376 return true; 3377 else { 3378 expected(";"); 3379 return false; 3380 } 3381 } 3382 3383 // compound_statement 3384 // : LEFT_CURLY statement statement ... RIGHT_CURLY 3385 // 3386 bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement) 3387 { 3388 TIntermAggregate* compoundStatement = nullptr; 3389 3390 // LEFT_CURLY 3391 if (! acceptTokenClass(EHTokLeftBrace)) 3392 return false; 3393 3394 // statement statement ... 3395 TIntermNode* statement = nullptr; 3396 while (acceptStatement(statement)) { 3397 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr; 3398 if (branch != nullptr && (branch->getFlowOp() == EOpCase || 3399 branch->getFlowOp() == EOpDefault)) { 3400 // hook up individual subsequences within a switch statement 3401 parseContext.wrapupSwitchSubsequence(compoundStatement, statement); 3402 compoundStatement = nullptr; 3403 } else { 3404 // hook it up to the growing compound statement 3405 compoundStatement = intermediate.growAggregate(compoundStatement, statement); 3406 } 3407 } 3408 if (compoundStatement) 3409 compoundStatement->setOperator(EOpSequence); 3410 3411 retStatement = compoundStatement; 3412 3413 // RIGHT_CURLY 3414 return acceptTokenClass(EHTokRightBrace); 3415 } 3416 3417 bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement) 3418 { 3419 parseContext.pushScope(); 3420 bool result = acceptStatement(statement); 3421 parseContext.popScope(); 3422 3423 return result; 3424 } 3425 3426 bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement) 3427 { 3428 parseContext.pushScope(); 3429 bool result = acceptCompoundStatement(statement); 3430 parseContext.popScope(); 3431 3432 return result; 3433 } 3434 3435 // statement 3436 // : attributes attributed_statement 3437 // 3438 // attributed_statement 3439 // : compound_statement 3440 // | simple_statement 3441 // | selection_statement 3442 // | switch_statement 3443 // | case_label 3444 // | default_label 3445 // | iteration_statement 3446 // | jump_statement 3447 // 3448 bool HlslGrammar::acceptStatement(TIntermNode*& statement) 3449 { 3450 statement = nullptr; 3451 3452 // attributes 3453 TAttributes attributes; 3454 acceptAttributes(attributes); 3455 3456 // attributed_statement 3457 switch (peek()) { 3458 case EHTokLeftBrace: 3459 return acceptScopedCompoundStatement(statement); 3460 3461 case EHTokIf: 3462 return acceptSelectionStatement(statement, attributes); 3463 3464 case EHTokSwitch: 3465 return acceptSwitchStatement(statement, attributes); 3466 3467 case EHTokFor: 3468 case EHTokDo: 3469 case EHTokWhile: 3470 return acceptIterationStatement(statement, attributes); 3471 3472 case EHTokContinue: 3473 case EHTokBreak: 3474 case EHTokDiscard: 3475 case EHTokReturn: 3476 return acceptJumpStatement(statement); 3477 3478 case EHTokCase: 3479 return acceptCaseLabel(statement); 3480 case EHTokDefault: 3481 return acceptDefaultLabel(statement); 3482 3483 case EHTokRightBrace: 3484 // Performance: not strictly necessary, but stops a bunch of hunting early, 3485 // and is how sequences of statements end. 3486 return false; 3487 3488 default: 3489 return acceptSimpleStatement(statement); 3490 } 3491 3492 return true; 3493 } 3494 3495 // attributes 3496 // : [zero or more:] bracketed-attribute 3497 // 3498 // bracketed-attribute: 3499 // : LEFT_BRACKET scoped-attribute RIGHT_BRACKET 3500 // : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET 3501 // 3502 // scoped-attribute: 3503 // : attribute 3504 // | namespace COLON COLON attribute 3505 // 3506 // attribute: 3507 // : UNROLL 3508 // | UNROLL LEFT_PAREN literal RIGHT_PAREN 3509 // | FASTOPT 3510 // | ALLOW_UAV_CONDITION 3511 // | BRANCH 3512 // | FLATTEN 3513 // | FORCECASE 3514 // | CALL 3515 // | DOMAIN 3516 // | EARLYDEPTHSTENCIL 3517 // | INSTANCE 3518 // | MAXTESSFACTOR 3519 // | OUTPUTCONTROLPOINTS 3520 // | OUTPUTTOPOLOGY 3521 // | PARTITIONING 3522 // | PATCHCONSTANTFUNC 3523 // | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN 3524 // 3525 void HlslGrammar::acceptAttributes(TAttributes& attributes) 3526 { 3527 // For now, accept the [ XXX(X) ] syntax, but drop all but 3528 // numthreads, which is used to set the CS local size. 3529 // TODO: subset to correct set? Pass on? 3530 do { 3531 HlslToken attributeToken; 3532 3533 // LEFT_BRACKET? 3534 if (! acceptTokenClass(EHTokLeftBracket)) 3535 return; 3536 // another LEFT_BRACKET? 3537 bool doubleBrackets = false; 3538 if (acceptTokenClass(EHTokLeftBracket)) 3539 doubleBrackets = true; 3540 3541 // attribute? (could be namespace; will adjust later) 3542 if (!acceptIdentifier(attributeToken)) { 3543 if (!peekTokenClass(EHTokRightBracket)) { 3544 expected("namespace or attribute identifier"); 3545 advanceToken(); 3546 } 3547 } 3548 3549 TString nameSpace; 3550 if (acceptTokenClass(EHTokColonColon)) { 3551 // namespace COLON COLON 3552 nameSpace = *attributeToken.string; 3553 // attribute 3554 if (!acceptIdentifier(attributeToken)) { 3555 expected("attribute identifier"); 3556 return; 3557 } 3558 } 3559 3560 TIntermAggregate* expressions = nullptr; 3561 3562 // (x, ...) 3563 if (acceptTokenClass(EHTokLeftParen)) { 3564 expressions = new TIntermAggregate; 3565 3566 TIntermTyped* node; 3567 bool expectingExpression = false; 3568 3569 while (acceptAssignmentExpression(node)) { 3570 expectingExpression = false; 3571 expressions->getSequence().push_back(node); 3572 if (acceptTokenClass(EHTokComma)) 3573 expectingExpression = true; 3574 } 3575 3576 // 'expressions' is an aggregate with the expressions in it 3577 if (! acceptTokenClass(EHTokRightParen)) 3578 expected(")"); 3579 3580 // Error for partial or missing expression 3581 if (expectingExpression || expressions->getSequence().empty()) 3582 expected("expression"); 3583 } 3584 3585 // RIGHT_BRACKET 3586 if (!acceptTokenClass(EHTokRightBracket)) { 3587 expected("]"); 3588 return; 3589 } 3590 // another RIGHT_BRACKET? 3591 if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) { 3592 expected("]]"); 3593 return; 3594 } 3595 3596 // Add any values we found into the attribute map. 3597 if (attributeToken.string != nullptr) { 3598 TAttributeType attributeType = parseContext.attributeFromName(nameSpace, *attributeToken.string); 3599 if (attributeType == EatNone) 3600 parseContext.warn(attributeToken.loc, "unrecognized attribute", attributeToken.string->c_str(), ""); 3601 else { 3602 TAttributeArgs attributeArgs = { attributeType, expressions }; 3603 attributes.push_back(attributeArgs); 3604 } 3605 } 3606 } while (true); 3607 } 3608 3609 // selection_statement 3610 // : IF LEFT_PAREN expression RIGHT_PAREN statement 3611 // : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement 3612 // 3613 bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributes& attributes) 3614 { 3615 TSourceLoc loc = token.loc; 3616 3617 // IF 3618 if (! acceptTokenClass(EHTokIf)) 3619 return false; 3620 3621 // so that something declared in the condition is scoped to the lifetimes 3622 // of the then-else statements 3623 parseContext.pushScope(); 3624 3625 // LEFT_PAREN expression RIGHT_PAREN 3626 TIntermTyped* condition; 3627 if (! acceptParenExpression(condition)) 3628 return false; 3629 condition = parseContext.convertConditionalExpression(loc, condition); 3630 if (condition == nullptr) 3631 return false; 3632 3633 // create the child statements 3634 TIntermNodePair thenElse = { nullptr, nullptr }; 3635 3636 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors 3637 3638 // then statement 3639 if (! acceptScopedStatement(thenElse.node1)) { 3640 expected("then statement"); 3641 return false; 3642 } 3643 3644 // ELSE 3645 if (acceptTokenClass(EHTokElse)) { 3646 // else statement 3647 if (! acceptScopedStatement(thenElse.node2)) { 3648 expected("else statement"); 3649 return false; 3650 } 3651 } 3652 3653 // Put the pieces together 3654 statement = intermediate.addSelection(condition, thenElse, loc); 3655 parseContext.handleSelectionAttributes(loc, statement->getAsSelectionNode(), attributes); 3656 3657 parseContext.popScope(); 3658 --parseContext.controlFlowNestingLevel; 3659 3660 return true; 3661 } 3662 3663 // switch_statement 3664 // : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement 3665 // 3666 bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributes& attributes) 3667 { 3668 // SWITCH 3669 TSourceLoc loc = token.loc; 3670 3671 if (! acceptTokenClass(EHTokSwitch)) 3672 return false; 3673 3674 // LEFT_PAREN expression RIGHT_PAREN 3675 parseContext.pushScope(); 3676 TIntermTyped* switchExpression; 3677 if (! acceptParenExpression(switchExpression)) { 3678 parseContext.popScope(); 3679 return false; 3680 } 3681 3682 // compound_statement 3683 parseContext.pushSwitchSequence(new TIntermSequence); 3684 3685 ++parseContext.controlFlowNestingLevel; 3686 bool statementOkay = acceptCompoundStatement(statement); 3687 --parseContext.controlFlowNestingLevel; 3688 3689 if (statementOkay) 3690 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, 3691 attributes); 3692 3693 parseContext.popSwitchSequence(); 3694 parseContext.popScope(); 3695 3696 return statementOkay; 3697 } 3698 3699 // iteration_statement 3700 // : WHILE LEFT_PAREN condition RIGHT_PAREN statement 3701 // | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON 3702 // | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement 3703 // 3704 // Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen. 3705 bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributes& attributes) 3706 { 3707 TSourceLoc loc = token.loc; 3708 TIntermTyped* condition = nullptr; 3709 3710 EHlslTokenClass loop = peek(); 3711 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile); 3712 3713 // WHILE or DO or FOR 3714 advanceToken(); 3715 3716 TIntermLoop* loopNode = nullptr; 3717 switch (loop) { 3718 case EHTokWhile: 3719 // so that something declared in the condition is scoped to the lifetime 3720 // of the while sub-statement 3721 parseContext.pushScope(); // this only needs to work right if no errors 3722 parseContext.nestLooping(); 3723 ++parseContext.controlFlowNestingLevel; 3724 3725 // LEFT_PAREN condition RIGHT_PAREN 3726 if (! acceptParenExpression(condition)) 3727 return false; 3728 condition = parseContext.convertConditionalExpression(loc, condition); 3729 if (condition == nullptr) 3730 return false; 3731 3732 // statement 3733 if (! acceptScopedStatement(statement)) { 3734 expected("while sub-statement"); 3735 return false; 3736 } 3737 3738 parseContext.unnestLooping(); 3739 parseContext.popScope(); 3740 --parseContext.controlFlowNestingLevel; 3741 3742 loopNode = intermediate.addLoop(statement, condition, nullptr, true, loc); 3743 statement = loopNode; 3744 break; 3745 3746 case EHTokDo: 3747 parseContext.nestLooping(); // this only needs to work right if no errors 3748 ++parseContext.controlFlowNestingLevel; 3749 3750 // statement 3751 if (! acceptScopedStatement(statement)) { 3752 expected("do sub-statement"); 3753 return false; 3754 } 3755 3756 // WHILE 3757 if (! acceptTokenClass(EHTokWhile)) { 3758 expected("while"); 3759 return false; 3760 } 3761 3762 // LEFT_PAREN condition RIGHT_PAREN 3763 if (! acceptParenExpression(condition)) 3764 return false; 3765 condition = parseContext.convertConditionalExpression(loc, condition); 3766 if (condition == nullptr) 3767 return false; 3768 3769 if (! acceptTokenClass(EHTokSemicolon)) 3770 expected(";"); 3771 3772 parseContext.unnestLooping(); 3773 --parseContext.controlFlowNestingLevel; 3774 3775 loopNode = intermediate.addLoop(statement, condition, 0, false, loc); 3776 statement = loopNode; 3777 break; 3778 3779 case EHTokFor: 3780 { 3781 // LEFT_PAREN 3782 if (! acceptTokenClass(EHTokLeftParen)) 3783 expected("("); 3784 3785 // so that something declared in the condition is scoped to the lifetime 3786 // of the for sub-statement 3787 parseContext.pushScope(); 3788 3789 // initializer 3790 TIntermNode* initNode = nullptr; 3791 if (! acceptSimpleStatement(initNode)) 3792 expected("for-loop initializer statement"); 3793 3794 parseContext.nestLooping(); // this only needs to work right if no errors 3795 ++parseContext.controlFlowNestingLevel; 3796 3797 // condition SEMI_COLON 3798 acceptExpression(condition); 3799 if (! acceptTokenClass(EHTokSemicolon)) 3800 expected(";"); 3801 if (condition != nullptr) { 3802 condition = parseContext.convertConditionalExpression(loc, condition); 3803 if (condition == nullptr) 3804 return false; 3805 } 3806 3807 // iterator SEMI_COLON 3808 TIntermTyped* iterator = nullptr; 3809 acceptExpression(iterator); 3810 if (! acceptTokenClass(EHTokRightParen)) 3811 expected(")"); 3812 3813 // statement 3814 if (! acceptScopedStatement(statement)) { 3815 expected("for sub-statement"); 3816 return false; 3817 } 3818 3819 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, loopNode); 3820 3821 parseContext.popScope(); 3822 parseContext.unnestLooping(); 3823 --parseContext.controlFlowNestingLevel; 3824 3825 break; 3826 } 3827 3828 default: 3829 return false; 3830 } 3831 3832 parseContext.handleLoopAttributes(loc, loopNode, attributes); 3833 return true; 3834 } 3835 3836 // jump_statement 3837 // : CONTINUE SEMICOLON 3838 // | BREAK SEMICOLON 3839 // | DISCARD SEMICOLON 3840 // | RETURN SEMICOLON 3841 // | RETURN expression SEMICOLON 3842 // 3843 bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement) 3844 { 3845 EHlslTokenClass jump = peek(); 3846 switch (jump) { 3847 case EHTokContinue: 3848 case EHTokBreak: 3849 case EHTokDiscard: 3850 case EHTokReturn: 3851 advanceToken(); 3852 break; 3853 default: 3854 // not something we handle in this function 3855 return false; 3856 } 3857 3858 switch (jump) { 3859 case EHTokContinue: 3860 statement = intermediate.addBranch(EOpContinue, token.loc); 3861 if (parseContext.loopNestingLevel == 0) { 3862 expected("loop"); 3863 return false; 3864 } 3865 break; 3866 case EHTokBreak: 3867 statement = intermediate.addBranch(EOpBreak, token.loc); 3868 if (parseContext.loopNestingLevel == 0 && parseContext.switchSequenceStack.size() == 0) { 3869 expected("loop or switch"); 3870 return false; 3871 } 3872 break; 3873 case EHTokDiscard: 3874 statement = intermediate.addBranch(EOpKill, token.loc); 3875 break; 3876 3877 case EHTokReturn: 3878 { 3879 // expression 3880 TIntermTyped* node; 3881 if (acceptExpression(node)) { 3882 // hook it up 3883 statement = parseContext.handleReturnValue(token.loc, node); 3884 } else 3885 statement = intermediate.addBranch(EOpReturn, token.loc); 3886 break; 3887 } 3888 3889 default: 3890 assert(0); 3891 return false; 3892 } 3893 3894 // SEMICOLON 3895 if (! acceptTokenClass(EHTokSemicolon)) 3896 expected(";"); 3897 3898 return true; 3899 } 3900 3901 // case_label 3902 // : CASE expression COLON 3903 // 3904 bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement) 3905 { 3906 TSourceLoc loc = token.loc; 3907 if (! acceptTokenClass(EHTokCase)) 3908 return false; 3909 3910 TIntermTyped* expression; 3911 if (! acceptExpression(expression)) { 3912 expected("case expression"); 3913 return false; 3914 } 3915 3916 if (! acceptTokenClass(EHTokColon)) { 3917 expected(":"); 3918 return false; 3919 } 3920 3921 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc); 3922 3923 return true; 3924 } 3925 3926 // default_label 3927 // : DEFAULT COLON 3928 // 3929 bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement) 3930 { 3931 TSourceLoc loc = token.loc; 3932 if (! acceptTokenClass(EHTokDefault)) 3933 return false; 3934 3935 if (! acceptTokenClass(EHTokColon)) { 3936 expected(":"); 3937 return false; 3938 } 3939 3940 statement = parseContext.intermediate.addBranch(EOpDefault, loc); 3941 3942 return true; 3943 } 3944 3945 // array_specifier 3946 // : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional 3947 // : LEFT_BRACKET RGHT_BRACKET // optional 3948 // 3949 void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes) 3950 { 3951 arraySizes = nullptr; 3952 3953 // Early-out if there aren't any array dimensions 3954 if (!peekTokenClass(EHTokLeftBracket)) 3955 return; 3956 3957 // If we get here, we have at least one array dimension. This will track the sizes we find. 3958 arraySizes = new TArraySizes; 3959 3960 // Collect each array dimension. 3961 while (acceptTokenClass(EHTokLeftBracket)) { 3962 TSourceLoc loc = token.loc; 3963 TIntermTyped* sizeExpr = nullptr; 3964 3965 // Array sizing expression is optional. If omitted, array will be later sized by initializer list. 3966 const bool hasArraySize = acceptAssignmentExpression(sizeExpr); 3967 3968 if (! acceptTokenClass(EHTokRightBracket)) { 3969 expected("]"); 3970 return; 3971 } 3972 3973 if (hasArraySize) { 3974 TArraySize arraySize; 3975 parseContext.arraySizeCheck(loc, sizeExpr, arraySize); 3976 arraySizes->addInnerSize(arraySize); 3977 } else { 3978 arraySizes->addInnerSize(0); // sized by initializers. 3979 } 3980 } 3981 } 3982 3983 // post_decls 3984 // : COLON semantic // optional 3985 // COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional 3986 // COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional 3987 // COLON LAYOUT layout_qualifier_list 3988 // annotations // optional 3989 // 3990 // Return true if any tokens were accepted. That is, 3991 // false can be returned on successfully recognizing nothing, 3992 // not necessarily meaning bad syntax. 3993 // 3994 bool HlslGrammar::acceptPostDecls(TQualifier& qualifier) 3995 { 3996 bool found = false; 3997 3998 do { 3999 // COLON 4000 if (acceptTokenClass(EHTokColon)) { 4001 found = true; 4002 HlslToken idToken; 4003 if (peekTokenClass(EHTokLayout)) 4004 acceptLayoutQualifierList(qualifier); 4005 else if (acceptTokenClass(EHTokPackOffset)) { 4006 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN 4007 if (! acceptTokenClass(EHTokLeftParen)) { 4008 expected("("); 4009 return false; 4010 } 4011 HlslToken locationToken; 4012 if (! acceptIdentifier(locationToken)) { 4013 expected("c[subcomponent][.component]"); 4014 return false; 4015 } 4016 HlslToken componentToken; 4017 if (acceptTokenClass(EHTokDot)) { 4018 if (! acceptIdentifier(componentToken)) { 4019 expected("component"); 4020 return false; 4021 } 4022 } 4023 if (! acceptTokenClass(EHTokRightParen)) { 4024 expected(")"); 4025 break; 4026 } 4027 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string); 4028 } else if (! acceptIdentifier(idToken)) { 4029 expected("layout, semantic, packoffset, or register"); 4030 return false; 4031 } else if (*idToken.string == "register") { 4032 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN 4033 // LEFT_PAREN 4034 if (! acceptTokenClass(EHTokLeftParen)) { 4035 expected("("); 4036 return false; 4037 } 4038 HlslToken registerDesc; // for Type# 4039 HlslToken profile; 4040 if (! acceptIdentifier(registerDesc)) { 4041 expected("register number description"); 4042 return false; 4043 } 4044 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) && 4045 acceptTokenClass(EHTokComma)) { 4046 // Then we didn't really see the registerDesc yet, it was 4047 // actually the profile. Adjust... 4048 profile = registerDesc; 4049 if (! acceptIdentifier(registerDesc)) { 4050 expected("register number description"); 4051 return false; 4052 } 4053 } 4054 int subComponent = 0; 4055 if (acceptTokenClass(EHTokLeftBracket)) { 4056 // LEFT_BRACKET subcomponent RIGHT_BRACKET 4057 if (! peekTokenClass(EHTokIntConstant)) { 4058 expected("literal integer"); 4059 return false; 4060 } 4061 subComponent = token.i; 4062 advanceToken(); 4063 if (! acceptTokenClass(EHTokRightBracket)) { 4064 expected("]"); 4065 break; 4066 } 4067 } 4068 // (COMMA SPACEN)opt 4069 HlslToken spaceDesc; 4070 if (acceptTokenClass(EHTokComma)) { 4071 if (! acceptIdentifier(spaceDesc)) { 4072 expected ("space identifier"); 4073 return false; 4074 } 4075 } 4076 // RIGHT_PAREN 4077 if (! acceptTokenClass(EHTokRightParen)) { 4078 expected(")"); 4079 break; 4080 } 4081 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string); 4082 } else { 4083 // semantic, in idToken.string 4084 TString semanticUpperCase = *idToken.string; 4085 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper); 4086 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase); 4087 } 4088 } else if (peekTokenClass(EHTokLeftAngle)) { 4089 found = true; 4090 acceptAnnotations(qualifier); 4091 } else 4092 break; 4093 4094 } while (true); 4095 4096 return found; 4097 } 4098 4099 // 4100 // Get the stream of tokens from the scanner, but skip all syntactic/semantic 4101 // processing. 4102 // 4103 bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens) 4104 { 4105 if (! peekTokenClass(EHTokLeftBrace)) 4106 return false; 4107 4108 int braceCount = 0; 4109 4110 do { 4111 switch (peek()) { 4112 case EHTokLeftBrace: 4113 ++braceCount; 4114 break; 4115 case EHTokRightBrace: 4116 --braceCount; 4117 break; 4118 case EHTokNone: 4119 // End of input before balance { } is bad... 4120 return false; 4121 default: 4122 break; 4123 } 4124 4125 tokens.push_back(token); 4126 advanceToken(); 4127 } while (braceCount > 0); 4128 4129 return true; 4130 } 4131 4132 // Return a string for just the types that can also be declared as an identifier. 4133 const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const 4134 { 4135 switch (tokenClass) { 4136 case EHTokSample: return "sample"; 4137 case EHTokHalf: return "half"; 4138 case EHTokHalf1x1: return "half1x1"; 4139 case EHTokHalf1x2: return "half1x2"; 4140 case EHTokHalf1x3: return "half1x3"; 4141 case EHTokHalf1x4: return "half1x4"; 4142 case EHTokHalf2x1: return "half2x1"; 4143 case EHTokHalf2x2: return "half2x2"; 4144 case EHTokHalf2x3: return "half2x3"; 4145 case EHTokHalf2x4: return "half2x4"; 4146 case EHTokHalf3x1: return "half3x1"; 4147 case EHTokHalf3x2: return "half3x2"; 4148 case EHTokHalf3x3: return "half3x3"; 4149 case EHTokHalf3x4: return "half3x4"; 4150 case EHTokHalf4x1: return "half4x1"; 4151 case EHTokHalf4x2: return "half4x2"; 4152 case EHTokHalf4x3: return "half4x3"; 4153 case EHTokHalf4x4: return "half4x4"; 4154 case EHTokBool: return "bool"; 4155 case EHTokFloat: return "float"; 4156 case EHTokDouble: return "double"; 4157 case EHTokInt: return "int"; 4158 case EHTokUint: return "uint"; 4159 case EHTokMin16float: return "min16float"; 4160 case EHTokMin10float: return "min10float"; 4161 case EHTokMin16int: return "min16int"; 4162 case EHTokMin12int: return "min12int"; 4163 case EHTokConstantBuffer: return "ConstantBuffer"; 4164 case EHTokLayout: return "layout"; 4165 default: 4166 return nullptr; 4167 } 4168 } 4169 4170 } // end namespace glslang 4171