Coverage Report

Created: 2026-08-31 06:32

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