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