Coverage Report

Created: 2026-05-30 06:33

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