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