Coverage Report

Created: 2025-12-31 06:24

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