blob: 0e8614cf37f36f7c133a1ffa575e3ecb6ff3809a [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
John Kessenich927608b2017-01-06 12:34:14 -07002// Copyright (C) 2016 Google, Inc.
3// Copyright (C) 2016 LunarG, Inc.
John Kesseniche01a9bc2016-03-12 20:11:22 -07004//
John Kessenich927608b2017-01-06 12:34:14 -07005// All rights reserved.
John Kesseniche01a9bc2016-03-12 20:11:22 -07006//
John Kessenich927608b2017-01-06 12:34:14 -07007// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
John Kesseniche01a9bc2016-03-12 20:11:22 -070010//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
14// Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following
16// disclaimer in the documentation and/or other materials provided
17// with the distribution.
18//
19// Neither the name of Google, Inc., nor the names of its
20// contributors may be used to endorse or promote products derived
21// from this software without specific prior written permission.
22//
John Kessenich927608b2017-01-06 12:34:14 -070023// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34// POSSIBILITY OF SUCH DAMAGE.
John Kesseniche01a9bc2016-03-12 20:11:22 -070035//
36
John Kessenichd016be12016-03-13 11:24:20 -060037//
38// This is a set of mutually recursive methods implementing the HLSL grammar.
39// Generally, each returns
40// - through an argument: a type specifically appropriate to which rule it
41// recognized
42// - through the return value: true/false to indicate whether or not it
43// recognized its rule
44//
45// As much as possible, only grammar recognition should happen in this file,
John Kessenich078d7f22016-03-14 10:02:11 -060046// with all other work being farmed out to hlslParseHelper.cpp, which in turn
John Kessenichd016be12016-03-13 11:24:20 -060047// will build the AST.
48//
49// The next token, yet to be "accepted" is always sitting in 'token'.
50// When a method says it accepts a rule, that means all tokens involved
51// in the rule will have been consumed, and none left in 'token'.
52//
53
John Kesseniche01a9bc2016-03-12 20:11:22 -070054#include "hlslTokens.h"
55#include "hlslGrammar.h"
steve-lunarg1868b142016-10-20 13:07:10 -060056#include "hlslAttributes.h"
John Kesseniche01a9bc2016-03-12 20:11:22 -070057
58namespace glslang {
59
60// Root entry point to this recursive decent parser.
61// Return true if compilation unit was successfully accepted.
62bool HlslGrammar::parse()
63{
64 advanceToken();
65 return acceptCompilationUnit();
66}
67
68void HlslGrammar::expected(const char* syntax)
69{
70 parseContext.error(token.loc, "Expected", syntax, "");
71}
72
LoopDawg4886f692016-06-29 10:58:58 -060073void HlslGrammar::unimplemented(const char* error)
74{
75 parseContext.error(token.loc, "Unimplemented", error, "");
76}
77
John Kessenich7a41f962017-03-22 11:38:22 -060078// IDENTIFIER
79// THIS
80// type that can be used as IDENTIFIER
81//
John Kessenichaecd4972016-03-14 10:46:34 -060082// Only process the next token if it is an identifier.
83// Return true if it was an identifier.
84bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
85{
John Kessenich7a41f962017-03-22 11:38:22 -060086 // IDENTIFIER
John Kessenichaecd4972016-03-14 10:46:34 -060087 if (peekTokenClass(EHTokIdentifier)) {
88 idToken = token;
89 advanceToken();
90 return true;
91 }
92
John Kessenich7a41f962017-03-22 11:38:22 -060093 // THIS
94 // -> maps to the IDENTIFIER spelled with the internal special name for 'this'
95 if (peekTokenClass(EHTokThis)) {
96 idToken = token;
97 advanceToken();
98 idToken.tokenClass = EHTokIdentifier;
99 idToken.string = NewPoolTString(intermediate.implicitThisName);
100 return true;
101 }
102
103 // type that can be used as IDENTIFIER
104
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700105 // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers),
106 // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a
107 // valid identifier, nor is "linear". This code special cases the known instances of this, so
108 // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed.
John Kessenichecba76f2017-01-06 00:34:48 -0700109
John Kessenich0320d092017-06-13 22:22:52 -0600110 const char* idString = getTypeString(peek());
111 if (idString == nullptr)
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700112 return false;
steve-lunarg75fd2232016-11-16 13:22:11 -0700113
John Kessenich0320d092017-06-13 22:22:52 -0600114 token.string = NewPoolTString(idString);
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700115 token.tokenClass = EHTokIdentifier;
John Kessenich0320d092017-06-13 22:22:52 -0600116 idToken = token;
117 typeIdentifiers = true;
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700118
119 advanceToken();
120
121 return true;
John Kessenichaecd4972016-03-14 10:46:34 -0600122}
123
John Kesseniche01a9bc2016-03-12 20:11:22 -0700124// compilationUnit
John Kessenich8f9fdc92017-03-30 16:22:26 -0600125// : declaration_list EOF
John Kesseniche01a9bc2016-03-12 20:11:22 -0700126//
127bool HlslGrammar::acceptCompilationUnit()
128{
John Kessenichd016be12016-03-13 11:24:20 -0600129 TIntermNode* unitNode = nullptr;
130
John Kessenich8f9fdc92017-03-30 16:22:26 -0600131 if (! acceptDeclarationList(unitNode))
132 return false;
steve-lunargcb88de52016-08-03 07:04:18 -0600133
John Kessenich8f9fdc92017-03-30 16:22:26 -0600134 if (! peekTokenClass(EHTokNone))
135 return false;
John Kesseniche01a9bc2016-03-12 20:11:22 -0700136
John Kessenichd016be12016-03-13 11:24:20 -0600137 // set root of AST
John Kessenichca71d942017-03-07 20:44:09 -0700138 if (unitNode && !unitNode->getAsAggregate())
139 unitNode = intermediate.growAggregate(nullptr, unitNode);
John Kessenich078d7f22016-03-14 10:02:11 -0600140 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600141
John Kesseniche01a9bc2016-03-12 20:11:22 -0700142 return true;
143}
144
John Kessenich8f9fdc92017-03-30 16:22:26 -0600145// 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//
155bool HlslGrammar::acceptDeclarationList(TIntermNode*& nodeList)
156{
157 do {
158 // HLSL allows extra semicolons between global declarations
159 do { } while (acceptTokenClass(EHTokSemicolon));
160
161 // EOF or RIGHT_BRACE
162 if (peekTokenClass(EHTokNone) || peekTokenClass(EHTokRightBrace))
163 return true;
164
165 // declaration
166 if (! acceptDeclaration(nodeList))
167 return false;
168 } while (true);
169
170 return true;
171}
172
LoopDawg4886f692016-06-29 10:58:58 -0600173// sampler_state
John Kessenichecba76f2017-01-06 00:34:48 -0700174// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
LoopDawg4886f692016-06-29 10:58:58 -0600175//
176// sampler_state_assignment
177// : sampler_state_identifier EQUAL value SEMICOLON
178//
179// sampler_state_identifier
180// : ADDRESSU
181// | ADDRESSV
182// | ADDRESSW
183// | BORDERCOLOR
184// | FILTER
185// | MAXANISOTROPY
186// | MAXLOD
187// | MINLOD
188// | MIPLODBIAS
189//
190bool HlslGrammar::acceptSamplerState()
191{
192 // TODO: this should be genericized to accept a list of valid tokens and
193 // return token/value pairs. Presently it is specific to texture values.
194
195 if (! acceptTokenClass(EHTokLeftBrace))
196 return true;
197
198 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
John Kessenichecba76f2017-01-06 00:34:48 -0700199
LoopDawg4886f692016-06-29 10:58:58 -0600200 do {
201 // read state name
202 HlslToken state;
203 if (! acceptIdentifier(state))
204 break; // end of list
205
206 // FXC accepts any case
207 TString stateName = *state.string;
208 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
209
210 if (! acceptTokenClass(EHTokAssign)) {
211 expected("assign");
212 return false;
213 }
214
215 if (stateName == "minlod" || stateName == "maxlod") {
216 if (! peekTokenClass(EHTokIntConstant)) {
217 expected("integer");
218 return false;
219 }
220
221 TIntermTyped* lod = nullptr;
222 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
223 return false;
224 } else if (stateName == "maxanisotropy") {
225 if (! peekTokenClass(EHTokIntConstant)) {
226 expected("integer");
227 return false;
228 }
229
230 TIntermTyped* maxAnisotropy = nullptr;
231 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
232 return false;
233 } else if (stateName == "filter") {
234 HlslToken filterMode;
235 if (! acceptIdentifier(filterMode)) {
236 expected("filter mode");
237 return false;
238 }
239 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
240 HlslToken addrMode;
241 if (! acceptIdentifier(addrMode)) {
242 expected("texture address mode");
243 return false;
244 }
245 } else if (stateName == "miplodbias") {
246 TIntermTyped* lodBias = nullptr;
247 if (! acceptLiteral(lodBias)) {
248 expected("lod bias");
249 return false;
250 }
251 } else if (stateName == "bordercolor") {
252 return false;
253 } else {
254 expected("texture state");
255 return false;
256 }
257
258 // SEMICOLON
259 if (! acceptTokenClass(EHTokSemicolon)) {
260 expected("semicolon");
261 return false;
262 }
263 } while (true);
264
265 if (! acceptTokenClass(EHTokRightBrace))
266 return false;
267
268 return true;
269}
270
271// sampler_declaration_dx9
272// : SAMPLER identifier EQUAL sampler_type sampler_state
273//
John Kesseniche4821e42016-07-16 10:19:43 -0600274bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600275{
276 if (! acceptTokenClass(EHTokSampler))
277 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700278
LoopDawg4886f692016-06-29 10:58:58 -0600279 // TODO: remove this when DX9 style declarations are implemented.
280 unimplemented("Direct3D 9 sampler declaration");
281
282 // read sampler name
283 HlslToken name;
284 if (! acceptIdentifier(name)) {
285 expected("sampler name");
286 return false;
287 }
288
289 if (! acceptTokenClass(EHTokAssign)) {
290 expected("=");
291 return false;
292 }
293
294 return false;
295}
296
John Kesseniche01a9bc2016-03-12 20:11:22 -0700297// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600298// : sampler_declaration_dx9 post_decls SEMICOLON
John Kessenich054378d2017-06-19 15:13:26 -0600299// | fully_specified_type // for cbuffer/tbuffer
300// | fully_specified_type declarator_list SEMICOLON // for non cbuffer/tbuffer
John Kessenich630dd7d2016-06-12 23:52:12 -0600301// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600302// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600303// | typedef declaration
John Kessenich8f9fdc92017-03-30 16:22:26 -0600304// | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
John Kessenich87142c72016-03-12 20:24:24 -0700305//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600306// declarator_list
307// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600308//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600309// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600310// : identifier array_specifier post_decls
311// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600312// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600313//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600314// Parsing has to go pretty far in to know whether it's a variable, prototype, or
315// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600316// as above. (The 'identifier' in the first item in init_declarator list is the
317// same as 'identifier' for function declarations.)
318//
John Kessenichca71d942017-03-07 20:44:09 -0700319// This can generate more than one subtree, one per initializer or a function body.
320// All initializer subtrees are put in their own aggregate node, making one top-level
321// node for all the initializers. Each function created is a top-level node to grow
322// into the passed-in nodeList.
John Kessenichd016be12016-03-13 11:24:20 -0600323//
John Kessenichca71d942017-03-07 20:44:09 -0700324// If 'nodeList' is passed in as non-null, it must an aggregate to extend for
325// each top-level node the declaration creates. Otherwise, if only one top-level
326// node in generated here, that is want is returned in nodeList.
John Kessenich02467d82017-01-19 15:41:47 -0700327//
John Kessenichca71d942017-03-07 20:44:09 -0700328bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700329{
John Kessenich8f9fdc92017-03-30 16:22:26 -0600330 // NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
331 if (acceptTokenClass(EHTokNamespace)) {
332 HlslToken namespaceToken;
333 if (!acceptIdentifier(namespaceToken)) {
334 expected("namespace name");
335 return false;
336 }
337 parseContext.pushNamespace(*namespaceToken.string);
338 if (!acceptTokenClass(EHTokLeftBrace)) {
339 expected("{");
340 return false;
341 }
342 if (!acceptDeclarationList(nodeList)) {
343 expected("declaration list");
344 return false;
345 }
346 if (!acceptTokenClass(EHTokRightBrace)) {
347 expected("}");
348 return false;
349 }
350 parseContext.popNamespace();
351 return true;
352 }
353
John Kessenich54ee28f2017-03-11 14:13:00 -0700354 bool declarator_list = false; // true when processing comma separation
John Kessenichd016be12016-03-13 11:24:20 -0600355
steve-lunarg1868b142016-10-20 13:07:10 -0600356 // attributes
John Kessenich088d52b2017-03-11 17:55:28 -0700357 TFunctionDeclarator declarator;
358 acceptAttributes(declarator.attributes);
steve-lunarg1868b142016-10-20 13:07:10 -0600359
John Kessenich5e69ec62016-07-05 00:02:40 -0600360 // typedef
361 bool typedefDecl = acceptTokenClass(EHTokTypedef);
362
John Kesseniche82061d2016-09-27 14:38:57 -0600363 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600364
365 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600366 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
367 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
368 // HLSL shaders, this will have to be a master level switch
369 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
John Kessenichecba76f2017-01-06 00:34:48 -0700370 // For that reason, this line is commented out
John Kessenichca71d942017-03-07 20:44:09 -0700371 // if (acceptSamplerDeclarationDX9(declaredType))
372 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600373
John Kessenich2fcdd642017-06-19 15:41:11 -0600374 bool forbidDeclarators = (peekTokenClass(EHTokCBuffer) || peekTokenClass(EHTokTBuffer));
LoopDawg4886f692016-06-29 10:58:58 -0600375 // fully_specified_type
John Kessenich54ee28f2017-03-11 14:13:00 -0700376 if (! acceptFullySpecifiedType(declaredType, nodeList))
John Kessenich87142c72016-03-12 20:24:24 -0700377 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600378
John Kessenich2fcdd642017-06-19 15:41:11 -0600379 // cbuffer and tbuffer end with the closing '}'.
380 // No semicolon is included.
381 if (forbidDeclarators)
382 return true;
383
John Kessenich054378d2017-06-19 15:13:26 -0600384 // declarator_list
385 // : declarator
386 // : identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600387 HlslToken idToken;
John Kessenichca71d942017-03-07 20:44:09 -0700388 TIntermAggregate* initializers = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600389 while (acceptIdentifier(idToken)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -0600390 const TString *fullName = idToken.string;
391 if (parseContext.symbolTable.atGlobalLevel())
392 parseContext.getFullNamespaceName(fullName);
John Kessenich78388722017-03-08 18:53:51 -0700393 if (peekTokenClass(EHTokLeftParen)) {
394 // looks like function parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600395
John Kessenich78388722017-03-08 18:53:51 -0700396 // Potentially rename shader entry point function. No-op most of the time.
John Kessenich8f9fdc92017-03-30 16:22:26 -0600397 parseContext.renameShaderFunction(fullName);
steve-lunargf1e0c872016-10-31 15:13:43 -0600398
John Kessenich78388722017-03-08 18:53:51 -0700399 // function_parameters
John Kessenich8f9fdc92017-03-30 16:22:26 -0600400 declarator.function = new TFunction(fullName, declaredType);
John Kessenich088d52b2017-03-11 17:55:28 -0700401 if (!acceptFunctionParameters(*declarator.function)) {
John Kessenich78388722017-03-08 18:53:51 -0700402 expected("function parameter list");
403 return false;
404 }
405
John Kessenich630dd7d2016-06-12 23:52:12 -0600406 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -0700407 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600408
John Kessenichd5ed0b62016-07-04 17:32:45 -0600409 // compound_statement (function body definition) or just a prototype?
John Kessenich088d52b2017-03-11 17:55:28 -0700410 declarator.loc = token.loc;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600411 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich54ee28f2017-03-11 14:13:00 -0700412 if (declarator_list)
John Kessenichd5ed0b62016-07-04 17:32:45 -0600413 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600414 if (typedefDecl)
415 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenichb16f7e62017-03-11 19:32:47 -0700416 return acceptFunctionDefinition(declarator, nodeList, nullptr);
John Kessenich5e69ec62016-07-05 00:02:40 -0600417 } else {
418 if (typedefDecl)
419 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich088d52b2017-03-11 17:55:28 -0700420 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600421 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600422 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600423 // A variable declaration. Fix the storage qualifier if it's a global.
424 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
425 declaredType.getQualifier().storage = EvqUniform;
426
John Kessenichecba76f2017-01-06 00:34:48 -0700427 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600428 // the number of types can expand when arrayness is different.
429 TType variableType;
430 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600431
John Kesseniche82061d2016-09-27 14:38:57 -0600432 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600433 TArraySizes* arraySizes = nullptr;
434 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600435
John Kesseniche82061d2016-09-27 14:38:57 -0600436 // Fix arrayness in the variableType
437 if (declaredType.isImplicitlySizedArray()) {
438 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
439 // of different sizes, for this case sharing the shallow copy of arrayness
440 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
441 variableType.newArraySizes(declaredType.getArraySizes());
442 }
443 if (arraySizes || variableType.isArray()) {
444 // In the most general case, arrayness is potentially coming both from the
445 // declared type and from the variable: "int[] a[];" or just one or the other.
446 // Merge it all to the variableType, so all arrayness is part of the variableType.
447 parseContext.arrayDimMerge(variableType, arraySizes);
448 }
449
LoopDawg4886f692016-06-29 10:58:58 -0600450 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600451 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600452 if (! acceptSamplerState())
453 return false;
454 }
455
John Kessenichd5ed0b62016-07-04 17:32:45 -0600456 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600457 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600458
459 // EQUAL assignment_expression
460 TIntermTyped* expressionNode = nullptr;
461 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600462 if (typedefDecl)
463 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600464 if (! acceptAssignmentExpression(expressionNode)) {
465 expected("initializer");
466 return false;
467 }
468 }
469
John Kessenich6dbc0a72016-09-27 19:13:05 -0600470 // TODO: things scoped within an annotation need their own name space;
471 // TODO: strings are not yet handled.
472 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
473 if (typedefDecl)
John Kessenich8f9fdc92017-03-30 16:22:26 -0600474 parseContext.declareTypedef(idToken.loc, *fullName, variableType);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600475 else if (variableType.getBasicType() == EbtBlock) {
steve-lunarga766b832017-04-25 09:30:28 -0600476 parseContext.declareBlock(idToken.loc, variableType, fullName,
477 variableType.isArray() ? &variableType.getArraySizes() : nullptr);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600478 parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
479 } else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700480 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600481 // this isn't really an individual variable, but a member of the $Global buffer
John Kessenich8f9fdc92017-03-30 16:22:26 -0600482 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600483 } else {
484 // Declare the variable and add any initializer code to the AST.
485 // The top-level node is always made into an aggregate, as that's
486 // historically how the AST has been.
John Kessenichca71d942017-03-07 20:44:09 -0700487 initializers = intermediate.growAggregate(initializers,
John Kessenich8f9fdc92017-03-30 16:22:26 -0600488 parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode),
John Kessenichca71d942017-03-07 20:44:09 -0700489 idToken.loc);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600490 }
491 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600492 }
John Kessenich5f934b02016-03-13 17:58:25 -0600493 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600494
John Kessenich054378d2017-06-19 15:13:26 -0600495 // COMMA
496 if (acceptTokenClass(EHTokComma))
John Kessenich54ee28f2017-03-11 14:13:00 -0700497 declarator_list = true;
John Kessenich2fcdd642017-06-19 15:41:11 -0600498 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600499
John Kessenichca71d942017-03-07 20:44:09 -0700500 // The top-level initializer node is a sequence.
501 if (initializers != nullptr)
502 initializers->setOperator(EOpSequence);
503
504 // Add the initializers' aggregate to the nodeList we were handed.
505 if (nodeList)
506 nodeList = intermediate.growAggregate(nodeList, initializers);
507 else
508 nodeList = initializers;
John Kessenich87142c72016-03-12 20:24:24 -0700509
John Kessenich2fcdd642017-06-19 15:41:11 -0600510 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600511 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich2fcdd642017-06-19 15:41:11 -0600512 // This may have been a false detection of what appeared to be a declaration, but
513 // was actually an assignment such as "float = 4", where "float" is an identifier.
514 // We put the token back to let further parsing happen for cases where that may
515 // happen. This errors on the side of caution, and mostly triggers the error.
John Kessenich13075c62017-04-11 09:51:32 -0600516 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700517 recedeToken();
John Kessenich13075c62017-04-11 09:51:32 -0600518 return false;
John Kessenich13075c62017-04-11 09:51:32 -0600519 } else {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700520 expected(";");
John Kessenich13075c62017-04-11 09:51:32 -0600521 return false;
522 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600523 }
John Kessenichecba76f2017-01-06 00:34:48 -0700524
John Kesseniche01a9bc2016-03-12 20:11:22 -0700525 return true;
526}
527
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600528// control_declaration
529// : fully_specified_type identifier EQUAL expression
530//
531bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
532{
533 node = nullptr;
534
535 // fully_specified_type
536 TType type;
537 if (! acceptFullySpecifiedType(type))
538 return false;
539
John Kessenich057df292017-03-06 18:18:37 -0700540 // filter out type casts
541 if (peekTokenClass(EHTokLeftParen)) {
542 recedeToken();
543 return false;
544 }
545
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600546 // identifier
547 HlslToken idToken;
548 if (! acceptIdentifier(idToken)) {
549 expected("identifier");
550 return false;
551 }
552
553 // EQUAL
554 TIntermTyped* expressionNode = nullptr;
555 if (! acceptTokenClass(EHTokAssign)) {
556 expected("=");
557 return false;
558 }
559
560 // expression
561 if (! acceptExpression(expressionNode)) {
562 expected("initializer");
563 return false;
564 }
565
John Kesseniche82061d2016-09-27 14:38:57 -0600566 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600567
568 return true;
569}
570
John Kessenich87142c72016-03-12 20:24:24 -0700571// fully_specified_type
572// : type_specifier
573// | type_qualifier type_specifier
574//
575bool HlslGrammar::acceptFullySpecifiedType(TType& type)
576{
John Kessenich54ee28f2017-03-11 14:13:00 -0700577 TIntermNode* nodeList = nullptr;
578 return acceptFullySpecifiedType(type, nodeList);
579}
580bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
581{
John Kessenich87142c72016-03-12 20:24:24 -0700582 // type_qualifier
583 TQualifier qualifier;
584 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600585 if (! acceptQualifier(qualifier))
586 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600587 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700588
589 // type_specifier
John Kessenich54ee28f2017-03-11 14:13:00 -0700590 if (! acceptType(type, nodeList)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -0700591 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700592 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700593 // qualifier. Back it out, if we did.
594 if (qualifier.sample)
595 recedeToken();
596
John Kessenich87142c72016-03-12 20:24:24 -0700597 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700598 }
John Kessenich3d157c52016-07-25 16:05:33 -0600599 if (type.getBasicType() == EbtBlock) {
600 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600601 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600602 // further, it can create an anonymous instance of the block
John Kessenich13075c62017-04-11 09:51:32 -0600603 if (peek() != EHTokIdentifier)
John Kessenich3d157c52016-07-25 16:05:33 -0600604 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600605 } else {
606 // Some qualifiers are set when parsing the type. Merge those with
607 // whatever comes from acceptQualifier.
608 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700609
steve-lunargbb0183f2016-10-04 16:58:14 -0600610 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600611 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700612
steve-lunarg08e0c082017-03-29 20:01:13 -0600613 if (type.getQualifier().storage == EvqOut ||
steve-lunarg5da1f032017-02-12 17:50:28 -0700614 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700615 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700616 qualifier.readonly = type.getQualifier().readonly;
617 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700618
John Kessenichecd08bc2017-08-07 23:40:05 -0600619 if (type.isBuiltIn())
steve-lunarg08e0c082017-03-29 20:01:13 -0600620 qualifier.builtIn = type.getQualifier().builtIn;
621
steve-lunargf49cdf42016-11-17 15:04:20 -0700622 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600623 }
John Kessenich87142c72016-03-12 20:24:24 -0700624
625 return true;
626}
627
John Kessenich630dd7d2016-06-12 23:52:12 -0600628// type_qualifier
629// : qualifier qualifier ...
630//
631// Zero or more of these, so this can't return false.
632//
John Kessenichb9e39122016-08-17 10:22:08 -0600633bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700634{
John Kessenich630dd7d2016-06-12 23:52:12 -0600635 do {
636 switch (peek()) {
637 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600638 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600639 break;
640 case EHTokExtern:
641 // TODO: no meaning in glslang?
642 break;
643 case EHTokShared:
644 // TODO: hint
645 break;
646 case EHTokGroupShared:
647 qualifier.storage = EvqShared;
648 break;
649 case EHTokUniform:
650 qualifier.storage = EvqUniform;
651 break;
652 case EHTokConst:
653 qualifier.storage = EvqConst;
654 break;
655 case EHTokVolatile:
656 qualifier.volatil = true;
657 break;
658 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600659 qualifier.smooth = true;
660 break;
661 case EHTokCentroid:
662 qualifier.centroid = true;
663 break;
664 case EHTokNointerpolation:
665 qualifier.flat = true;
666 break;
667 case EHTokNoperspective:
668 qualifier.nopersp = true;
669 break;
670 case EHTokSample:
671 qualifier.sample = true;
672 break;
673 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600674 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600675 break;
676 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600677 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600678 break;
679 case EHTokPrecise:
680 qualifier.noContraction = true;
681 break;
LoopDawg9249c702016-07-12 20:44:32 -0600682 case EHTokIn:
xavierb1d97532017-06-20 07:49:22 +0200683 qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn;
LoopDawg9249c702016-07-12 20:44:32 -0600684 break;
685 case EHTokOut:
xavierb1d97532017-06-20 07:49:22 +0200686 qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut;
LoopDawg9249c702016-07-12 20:44:32 -0600687 break;
688 case EHTokInOut:
689 qualifier.storage = EvqInOut;
690 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600691 case EHTokLayout:
692 if (! acceptLayoutQualifierList(qualifier))
693 return false;
694 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700695 case EHTokGloballyCoherent:
696 qualifier.coherent = true;
697 break;
John Kessenich36b218d2017-03-15 09:05:14 -0600698 case EHTokInline:
699 // TODO: map this to SPIR-V function control
700 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700701
702 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
703 // for output variables.
704 case EHTokPoint:
705 qualifier.storage = EvqIn;
706 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
707 return false;
708 break;
709 case EHTokLine:
710 qualifier.storage = EvqIn;
711 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
712 return false;
713 break;
714 case EHTokTriangle:
715 qualifier.storage = EvqIn;
716 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
717 return false;
718 break;
719 case EHTokLineAdj:
720 qualifier.storage = EvqIn;
721 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
722 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700723 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700724 case EHTokTriangleAdj:
725 qualifier.storage = EvqIn;
726 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
727 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700728 break;
729
John Kessenich630dd7d2016-06-12 23:52:12 -0600730 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600731 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600732 }
733 advanceToken();
734 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700735}
736
John Kessenichb9e39122016-08-17 10:22:08 -0600737// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600738// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600739//
740// layout_qualifier
741// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600742// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600743//
744// Zero or more of these, so this can't return false.
745//
746bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
747{
748 if (! acceptTokenClass(EHTokLayout))
749 return false;
750
751 // LEFT_PAREN
752 if (! acceptTokenClass(EHTokLeftParen))
753 return false;
754
755 do {
756 // identifier
757 HlslToken idToken;
758 if (! acceptIdentifier(idToken))
759 break;
760
761 // EQUAL expression
762 if (acceptTokenClass(EHTokAssign)) {
763 TIntermTyped* expr;
764 if (! acceptConditionalExpression(expr)) {
765 expected("expression");
766 return false;
767 }
768 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
769 } else
770 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
771
772 // COMMA
773 if (! acceptTokenClass(EHTokComma))
774 break;
775 } while (true);
776
777 // RIGHT_PAREN
778 if (! acceptTokenClass(EHTokRightParen)) {
779 expected(")");
780 return false;
781 }
782
783 return true;
784}
785
LoopDawg6daaa4f2016-06-23 19:13:48 -0600786// template_type
787// : FLOAT
788// | DOUBLE
789// | INT
790// | DWORD
791// | UINT
792// | BOOL
793//
steve-lunargf49cdf42016-11-17 15:04:20 -0700794bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600795{
796 switch (peek()) {
797 case EHTokFloat:
798 basicType = EbtFloat;
799 break;
800 case EHTokDouble:
801 basicType = EbtDouble;
802 break;
803 case EHTokInt:
804 case EHTokDword:
805 basicType = EbtInt;
806 break;
807 case EHTokUint:
808 basicType = EbtUint;
809 break;
810 case EHTokBool:
811 basicType = EbtBool;
812 break;
813 default:
814 return false;
815 }
816
817 advanceToken();
818
819 return true;
820}
821
822// vector_template_type
823// : VECTOR
824// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
825//
826bool HlslGrammar::acceptVectorTemplateType(TType& type)
827{
828 if (! acceptTokenClass(EHTokVector))
829 return false;
830
831 if (! acceptTokenClass(EHTokLeftAngle)) {
832 // in HLSL, 'vector' alone means float4.
833 new(&type) TType(EbtFloat, EvqTemporary, 4);
834 return true;
835 }
836
837 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700838 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600839 expected("scalar type");
840 return false;
841 }
842
843 // COMMA
844 if (! acceptTokenClass(EHTokComma)) {
845 expected(",");
846 return false;
847 }
848
849 // integer
850 if (! peekTokenClass(EHTokIntConstant)) {
851 expected("literal integer");
852 return false;
853 }
854
855 TIntermTyped* vecSize;
856 if (! acceptLiteral(vecSize))
857 return false;
858
859 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
860
861 new(&type) TType(basicType, EvqTemporary, vecSizeI);
862
863 if (vecSizeI == 1)
864 type.makeVector();
865
866 if (!acceptTokenClass(EHTokRightAngle)) {
867 expected("right angle bracket");
868 return false;
869 }
870
871 return true;
872}
873
874// matrix_template_type
875// : MATRIX
876// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
877//
878bool HlslGrammar::acceptMatrixTemplateType(TType& type)
879{
880 if (! acceptTokenClass(EHTokMatrix))
881 return false;
882
883 if (! acceptTokenClass(EHTokLeftAngle)) {
884 // in HLSL, 'matrix' alone means float4x4.
885 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
886 return true;
887 }
888
889 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700890 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600891 expected("scalar type");
892 return false;
893 }
894
895 // COMMA
896 if (! acceptTokenClass(EHTokComma)) {
897 expected(",");
898 return false;
899 }
900
901 // integer rows
902 if (! peekTokenClass(EHTokIntConstant)) {
903 expected("literal integer");
904 return false;
905 }
906
907 TIntermTyped* rows;
908 if (! acceptLiteral(rows))
909 return false;
910
911 // COMMA
912 if (! acceptTokenClass(EHTokComma)) {
913 expected(",");
914 return false;
915 }
John Kessenichecba76f2017-01-06 00:34:48 -0700916
LoopDawg6daaa4f2016-06-23 19:13:48 -0600917 // integer cols
918 if (! peekTokenClass(EHTokIntConstant)) {
919 expected("literal integer");
920 return false;
921 }
922
923 TIntermTyped* cols;
924 if (! acceptLiteral(cols))
925 return false;
926
927 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600928 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
929 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600930
931 if (!acceptTokenClass(EHTokRightAngle)) {
932 expected("right angle bracket");
933 return false;
934 }
935
936 return true;
937}
938
steve-lunargf49cdf42016-11-17 15:04:20 -0700939// layout_geometry
940// : LINESTREAM
941// | POINTSTREAM
942// | TRIANGLESTREAM
943//
944bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
945{
946 // read geometry type
947 const EHlslTokenClass geometryType = peek();
948
949 switch (geometryType) {
950 case EHTokPointStream: geometry = ElgPoints; break;
951 case EHTokLineStream: geometry = ElgLineStrip; break;
952 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
953 default:
954 return false; // not a layout geometry
955 }
956
957 advanceToken(); // consume the layout keyword
958 return true;
959}
960
steve-lunarg858c9282017-01-07 08:54:10 -0700961// tessellation_decl_type
962// : INPUTPATCH
963// | OUTPUTPATCH
964//
steve-lunarg067eb9b2017-04-01 15:34:48 -0600965bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType)
steve-lunarg858c9282017-01-07 08:54:10 -0700966{
967 // read geometry type
968 const EHlslTokenClass tessType = peek();
969
970 switch (tessType) {
steve-lunarg067eb9b2017-04-01 15:34:48 -0600971 case EHTokInputPatch: patchType = EbvInputPatch; break;
972 case EHTokOutputPatch: patchType = EbvOutputPatch; break;
steve-lunarg858c9282017-01-07 08:54:10 -0700973 default:
974 return false; // not a tessellation decl
975 }
976
977 advanceToken(); // consume the keyword
978 return true;
979}
980
981// tessellation_patch_template_type
982// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
983//
984bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
985{
steve-lunarg067eb9b2017-04-01 15:34:48 -0600986 TBuiltInVariable patchType;
987
988 if (! acceptTessellationDeclType(patchType))
steve-lunarg858c9282017-01-07 08:54:10 -0700989 return false;
990
991 if (! acceptTokenClass(EHTokLeftAngle))
992 return false;
993
994 if (! acceptType(type)) {
995 expected("tessellation patch type");
996 return false;
997 }
998
999 if (! acceptTokenClass(EHTokComma))
1000 return false;
1001
1002 // integer size
1003 if (! peekTokenClass(EHTokIntConstant)) {
1004 expected("literal integer");
1005 return false;
1006 }
1007
1008 TIntermTyped* size;
1009 if (! acceptLiteral(size))
1010 return false;
1011
1012 TArraySizes* arraySizes = new TArraySizes;
1013 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
1014 type.newArraySizes(*arraySizes);
steve-lunarg067eb9b2017-04-01 15:34:48 -06001015 type.getQualifier().builtIn = patchType;
steve-lunarg858c9282017-01-07 08:54:10 -07001016
1017 if (! acceptTokenClass(EHTokRightAngle)) {
1018 expected("right angle bracket");
1019 return false;
1020 }
1021
1022 return true;
1023}
1024
steve-lunargf49cdf42016-11-17 15:04:20 -07001025// stream_out_template_type
1026// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
1027//
1028bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
1029{
1030 geometry = ElgNone;
1031
1032 if (! acceptOutputPrimitiveGeometry(geometry))
1033 return false;
1034
1035 if (! acceptTokenClass(EHTokLeftAngle))
1036 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001037
steve-lunargf49cdf42016-11-17 15:04:20 -07001038 if (! acceptType(type)) {
1039 expected("stream output type");
1040 return false;
1041 }
1042
steve-lunarg08e0c082017-03-29 20:01:13 -06001043 type.getQualifier().storage = EvqOut;
1044 type.getQualifier().builtIn = EbvGsOutputStream;
steve-lunargf49cdf42016-11-17 15:04:20 -07001045
1046 if (! acceptTokenClass(EHTokRightAngle)) {
1047 expected("right angle bracket");
1048 return false;
1049 }
1050
1051 return true;
1052}
John Kessenichecba76f2017-01-06 00:34:48 -07001053
John Kessenicha1e2d492016-09-20 13:22:58 -06001054// annotations
1055// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -06001056//
John Kessenicha1e2d492016-09-20 13:22:58 -06001057bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -06001058{
John Kessenicha1e2d492016-09-20 13:22:58 -06001059 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -06001060 return false;
1061
John Kessenicha1e2d492016-09-20 13:22:58 -06001062 // note that we are nesting a name space
1063 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -06001064
1065 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1066 do {
1067 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
1068 while (acceptTokenClass(EHTokSemicolon))
1069 ;
1070
1071 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -06001072 break;
John Kessenich86f71382016-09-19 20:23:18 -06001073
1074 // declaration
John Kessenichca71d942017-03-07 20:44:09 -07001075 TIntermNode* node = nullptr;
John Kessenich86f71382016-09-19 20:23:18 -06001076 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -06001077 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -06001078 return false;
1079 }
1080 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -06001081
1082 parseContext.unnestAnnotations();
1083 return true;
John Kessenich86f71382016-09-19 20:23:18 -06001084}
LoopDawg6daaa4f2016-06-23 19:13:48 -06001085
LoopDawg4886f692016-06-29 10:58:58 -06001086// sampler_type
1087// : SAMPLER
1088// | SAMPLER1D
1089// | SAMPLER2D
1090// | SAMPLER3D
1091// | SAMPLERCUBE
1092// | SAMPLERSTATE
1093// | SAMPLERCOMPARISONSTATE
1094bool HlslGrammar::acceptSamplerType(TType& type)
1095{
1096 // read sampler type
1097 const EHlslTokenClass samplerType = peek();
1098
LoopDawga78b0292016-07-19 14:28:05 -06001099 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001100 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001101
LoopDawga78b0292016-07-19 14:28:05 -06001102 bool isShadow = false;
1103
LoopDawg4886f692016-06-29 10:58:58 -06001104 switch (samplerType) {
1105 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001106 case EHTokSampler1d: /*dim = Esd1D*/; break;
1107 case EHTokSampler2d: /*dim = Esd2D*/; break;
1108 case EHTokSampler3d: /*dim = Esd3D*/; break;
1109 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001110 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001111 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001112 default:
1113 return false; // not a sampler declaration
1114 }
1115
1116 advanceToken(); // consume the sampler type keyword
1117
1118 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001119
1120 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001121 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001122
1123 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1124
1125 return true;
1126}
1127
1128// texture_type
1129// | BUFFER
1130// | TEXTURE1D
1131// | TEXTURE1DARRAY
1132// | TEXTURE2D
1133// | TEXTURE2DARRAY
1134// | TEXTURE3D
1135// | TEXTURECUBE
1136// | TEXTURECUBEARRAY
1137// | TEXTURE2DMS
1138// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001139// | RWBUFFER
1140// | RWTEXTURE1D
1141// | RWTEXTURE1DARRAY
1142// | RWTEXTURE2D
1143// | RWTEXTURE2DARRAY
1144// | RWTEXTURE3D
1145
LoopDawg4886f692016-06-29 10:58:58 -06001146bool HlslGrammar::acceptTextureType(TType& type)
1147{
1148 const EHlslTokenClass textureType = peek();
1149
1150 TSamplerDim dim = EsdNone;
1151 bool array = false;
1152 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001153 bool image = false;
steve-lunargbf1537f2017-03-31 17:40:09 -06001154 bool combined = true;
LoopDawg4886f692016-06-29 10:58:58 -06001155
1156 switch (textureType) {
steve-lunargbf1537f2017-03-31 17:40:09 -06001157 case EHTokBuffer: dim = EsdBuffer; combined = false; break;
John Kessenichf36542f2017-03-31 14:39:30 -06001158 case EHTokTexture1d: dim = Esd1D; break;
1159 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1160 case EHTokTexture2d: dim = Esd2D; break;
1161 case EHTokTexture2darray: dim = Esd2D; array = true; break;
1162 case EHTokTexture3d: dim = Esd3D; break;
1163 case EHTokTextureCube: dim = EsdCube; break;
1164 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1165 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1166 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
1167 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1168 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1169 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1170 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1171 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1172 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001173 default:
1174 return false; // not a texture declaration
1175 }
1176
1177 advanceToken(); // consume the texture object keyword
1178
1179 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001180
LoopDawg4886f692016-06-29 10:58:58 -06001181 TIntermTyped* msCount = nullptr;
1182
steve-lunargbb0183f2016-10-04 16:58:14 -06001183 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001184 if (acceptTokenClass(EHTokLeftAngle)) {
1185 if (! acceptType(txType)) {
1186 expected("scalar or vector type");
1187 return false;
1188 }
1189
1190 const TBasicType basicRetType = txType.getBasicType() ;
1191
1192 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
1193 unimplemented("basic type in texture");
1194 return false;
1195 }
1196
steve-lunargd53f7172016-07-27 15:46:48 -06001197 // Buffers can handle small mats if they fit in 4 components
1198 if (dim == EsdBuffer && txType.isMatrix()) {
1199 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1200 expected("components < 4 in matrix buffer type");
1201 return false;
1202 }
1203
1204 // TODO: except we don't handle it yet...
1205 unimplemented("matrix type in buffer");
1206 return false;
1207 }
1208
LoopDawg4886f692016-06-29 10:58:58 -06001209 if (!txType.isScalar() && !txType.isVector()) {
1210 expected("scalar or vector type");
1211 return false;
1212 }
1213
LoopDawg4886f692016-06-29 10:58:58 -06001214 if (ms && acceptTokenClass(EHTokComma)) {
1215 // read sample count for multisample types, if given
1216 if (! peekTokenClass(EHTokIntConstant)) {
1217 expected("multisample count");
1218 return false;
1219 }
1220
1221 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1222 return false;
1223 }
1224
1225 if (! acceptTokenClass(EHTokRightAngle)) {
1226 expected("right angle bracket");
1227 return false;
1228 }
1229 } else if (ms) {
1230 expected("texture type for multisample");
1231 return false;
John Kessenichf36542f2017-03-31 14:39:30 -06001232 } else if (image) {
steve-lunargbb0183f2016-10-04 16:58:14 -06001233 expected("type for RWTexture/RWBuffer");
1234 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001235 }
1236
1237 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001238 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001239
1240 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001241 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001242
steve-lunarg4f2da272016-10-10 15:24:57 -06001243 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1244 if (image || dim == EsdBuffer)
1245 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001246
1247 // Non-image Buffers are combined
1248 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001249 sampler.set(txType.getBasicType(), dim, array);
1250 } else {
1251 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001252 if (image) {
1253 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1254 } else {
1255 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1256 }
steve-lunargd53f7172016-07-27 15:46:48 -06001257 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001258
1259 // Remember the declared vector size.
1260 sampler.vectorSize = txType.getVectorSize();
John Kessenichecba76f2017-01-06 00:34:48 -07001261
steve-lunargbf1537f2017-03-31 17:40:09 -06001262 // Force uncombined, if necessary
1263 if (!combined)
1264 sampler.combined = false;
1265
LoopDawg4886f692016-06-29 10:58:58 -06001266 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001267 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001268
1269 return true;
1270}
1271
John Kessenich87142c72016-03-12 20:24:24 -07001272// If token is for a type, update 'type' with the type information,
1273// and return true and advance.
1274// Otherwise, return false, and don't advance
1275bool HlslGrammar::acceptType(TType& type)
1276{
John Kessenich54ee28f2017-03-11 14:13:00 -07001277 TIntermNode* nodeList = nullptr;
1278 return acceptType(type, nodeList);
1279}
1280bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
1281{
steve-lunarg3226b082016-10-26 19:18:55 -06001282 // Basic types for min* types, broken out here in case of future
1283 // changes, e.g, to use native halfs.
1284 static const TBasicType min16float_bt = EbtFloat;
1285 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001286 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001287 static const TBasicType min16int_bt = EbtInt;
1288 static const TBasicType min12int_bt = EbtInt;
1289 static const TBasicType min16uint_bt = EbtUint;
1290
John Kessenich0320d092017-06-13 22:22:52 -06001291 // Some types might have turned into identifiers. Take the hit for checking
1292 // when this has happened.
1293 if (typeIdentifiers) {
1294 const char* identifierString = getTypeString(peek());
1295 if (identifierString != nullptr) {
1296 TString name = identifierString;
1297 // if it's an identifier, it's not a type
1298 if (parseContext.symbolTable.find(name) != nullptr)
1299 return false;
1300 }
1301 }
1302
John Kessenich9c86c6a2016-05-03 22:49:24 -06001303 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001304 case EHTokVector:
1305 return acceptVectorTemplateType(type);
1306 break;
1307
1308 case EHTokMatrix:
1309 return acceptMatrixTemplateType(type);
1310 break;
1311
steve-lunargf49cdf42016-11-17 15:04:20 -07001312 case EHTokPointStream: // fall through
1313 case EHTokLineStream: // ...
1314 case EHTokTriangleStream: // ...
1315 {
1316 TLayoutGeometry geometry;
1317 if (! acceptStreamOutTemplateType(type, geometry))
1318 return false;
1319
1320 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1321 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001322
steve-lunargf49cdf42016-11-17 15:04:20 -07001323 return true;
1324 }
1325
steve-lunarg858c9282017-01-07 08:54:10 -07001326 case EHTokInputPatch: // fall through
1327 case EHTokOutputPatch: // ...
1328 {
1329 if (! acceptTessellationPatchTemplateType(type))
1330 return false;
1331
1332 return true;
1333 }
1334
LoopDawg4886f692016-06-29 10:58:58 -06001335 case EHTokSampler: // fall through
1336 case EHTokSampler1d: // ...
1337 case EHTokSampler2d: // ...
1338 case EHTokSampler3d: // ...
1339 case EHTokSamplerCube: // ...
1340 case EHTokSamplerState: // ...
1341 case EHTokSamplerComparisonState: // ...
1342 return acceptSamplerType(type);
1343 break;
1344
1345 case EHTokBuffer: // fall through
1346 case EHTokTexture1d: // ...
1347 case EHTokTexture1darray: // ...
1348 case EHTokTexture2d: // ...
1349 case EHTokTexture2darray: // ...
1350 case EHTokTexture3d: // ...
1351 case EHTokTextureCube: // ...
1352 case EHTokTextureCubearray: // ...
1353 case EHTokTexture2DMS: // ...
1354 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001355 case EHTokRWTexture1d: // ...
1356 case EHTokRWTexture1darray: // ...
1357 case EHTokRWTexture2d: // ...
1358 case EHTokRWTexture2darray: // ...
1359 case EHTokRWTexture3d: // ...
1360 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001361 return acceptTextureType(type);
1362 break;
1363
steve-lunarg5da1f032017-02-12 17:50:28 -07001364 case EHTokAppendStructuredBuffer:
1365 case EHTokByteAddressBuffer:
1366 case EHTokConsumeStructuredBuffer:
1367 case EHTokRWByteAddressBuffer:
1368 case EHTokRWStructuredBuffer:
1369 case EHTokStructuredBuffer:
1370 return acceptStructBufferType(type);
1371 break;
1372
steve-lunarga766b832017-04-25 09:30:28 -06001373 case EHTokConstantBuffer:
1374 return acceptConstantBufferType(type);
1375
John Kessenich27ffb292017-03-03 17:01:01 -07001376 case EHTokClass:
John Kesseniche6e74942016-06-11 16:43:14 -06001377 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001378 case EHTokCBuffer:
1379 case EHTokTBuffer:
John Kessenich54ee28f2017-03-11 14:13:00 -07001380 return acceptStruct(type, nodeList);
John Kesseniche6e74942016-06-11 16:43:14 -06001381
1382 case EHTokIdentifier:
1383 // An identifier could be for a user-defined type.
1384 // Note we cache the symbol table lookup, to save for a later rule
1385 // when this is not a type.
John Kessenichf4ba25e2017-03-21 18:35:04 -06001386 if (parseContext.lookupUserType(*token.string, type) != nullptr) {
John Kesseniche6e74942016-06-11 16:43:14 -06001387 advanceToken();
1388 return true;
1389 } else
1390 return false;
1391
John Kessenich71351de2016-06-08 12:50:56 -06001392 case EHTokVoid:
1393 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001394 break;
John Kessenich71351de2016-06-08 12:50:56 -06001395
John Kessenicha1e2d492016-09-20 13:22:58 -06001396 case EHTokString:
1397 new(&type) TType(EbtString);
1398 break;
1399
John Kessenich87142c72016-03-12 20:24:24 -07001400 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001401 new(&type) TType(EbtFloat);
1402 break;
John Kessenich87142c72016-03-12 20:24:24 -07001403 case EHTokFloat1:
1404 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001405 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001406 break;
John Kessenich87142c72016-03-12 20:24:24 -07001407 case EHTokFloat2:
1408 new(&type) TType(EbtFloat, EvqTemporary, 2);
1409 break;
1410 case EHTokFloat3:
1411 new(&type) TType(EbtFloat, EvqTemporary, 3);
1412 break;
1413 case EHTokFloat4:
1414 new(&type) TType(EbtFloat, EvqTemporary, 4);
1415 break;
1416
John Kessenich71351de2016-06-08 12:50:56 -06001417 case EHTokDouble:
1418 new(&type) TType(EbtDouble);
1419 break;
1420 case EHTokDouble1:
1421 new(&type) TType(EbtDouble);
1422 type.makeVector();
1423 break;
1424 case EHTokDouble2:
1425 new(&type) TType(EbtDouble, EvqTemporary, 2);
1426 break;
1427 case EHTokDouble3:
1428 new(&type) TType(EbtDouble, EvqTemporary, 3);
1429 break;
1430 case EHTokDouble4:
1431 new(&type) TType(EbtDouble, EvqTemporary, 4);
1432 break;
1433
1434 case EHTokInt:
1435 case EHTokDword:
1436 new(&type) TType(EbtInt);
1437 break;
1438 case EHTokInt1:
1439 new(&type) TType(EbtInt);
1440 type.makeVector();
1441 break;
John Kessenich87142c72016-03-12 20:24:24 -07001442 case EHTokInt2:
1443 new(&type) TType(EbtInt, EvqTemporary, 2);
1444 break;
1445 case EHTokInt3:
1446 new(&type) TType(EbtInt, EvqTemporary, 3);
1447 break;
1448 case EHTokInt4:
1449 new(&type) TType(EbtInt, EvqTemporary, 4);
1450 break;
1451
John Kessenich71351de2016-06-08 12:50:56 -06001452 case EHTokUint:
1453 new(&type) TType(EbtUint);
1454 break;
1455 case EHTokUint1:
1456 new(&type) TType(EbtUint);
1457 type.makeVector();
1458 break;
1459 case EHTokUint2:
1460 new(&type) TType(EbtUint, EvqTemporary, 2);
1461 break;
1462 case EHTokUint3:
1463 new(&type) TType(EbtUint, EvqTemporary, 3);
1464 break;
1465 case EHTokUint4:
1466 new(&type) TType(EbtUint, EvqTemporary, 4);
1467 break;
1468
1469 case EHTokBool:
1470 new(&type) TType(EbtBool);
1471 break;
1472 case EHTokBool1:
1473 new(&type) TType(EbtBool);
1474 type.makeVector();
1475 break;
John Kessenich87142c72016-03-12 20:24:24 -07001476 case EHTokBool2:
1477 new(&type) TType(EbtBool, EvqTemporary, 2);
1478 break;
1479 case EHTokBool3:
1480 new(&type) TType(EbtBool, EvqTemporary, 3);
1481 break;
1482 case EHTokBool4:
1483 new(&type) TType(EbtBool, EvqTemporary, 4);
1484 break;
1485
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001486 case EHTokHalf:
John Kessenich96f65522017-06-06 23:35:25 -06001487 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001488 break;
1489 case EHTokHalf1:
John Kessenich96f65522017-06-06 23:35:25 -06001490 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001491 type.makeVector();
1492 break;
1493 case EHTokHalf2:
John Kessenich96f65522017-06-06 23:35:25 -06001494 new(&type) TType(half_bt, EvqTemporary, 2);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001495 break;
1496 case EHTokHalf3:
John Kessenich96f65522017-06-06 23:35:25 -06001497 new(&type) TType(half_bt, EvqTemporary, 3);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001498 break;
1499 case EHTokHalf4:
John Kessenich96f65522017-06-06 23:35:25 -06001500 new(&type) TType(half_bt, EvqTemporary, 4);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001501 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001502
steve-lunarg3226b082016-10-26 19:18:55 -06001503 case EHTokMin16float:
1504 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1505 break;
1506 case EHTokMin16float1:
1507 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1508 type.makeVector();
1509 break;
1510 case EHTokMin16float2:
1511 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1512 break;
1513 case EHTokMin16float3:
1514 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1515 break;
1516 case EHTokMin16float4:
1517 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1518 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001519
steve-lunarg3226b082016-10-26 19:18:55 -06001520 case EHTokMin10float:
1521 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1522 break;
1523 case EHTokMin10float1:
1524 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1525 type.makeVector();
1526 break;
1527 case EHTokMin10float2:
1528 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1529 break;
1530 case EHTokMin10float3:
1531 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1532 break;
1533 case EHTokMin10float4:
1534 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1535 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001536
steve-lunarg3226b082016-10-26 19:18:55 -06001537 case EHTokMin16int:
1538 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1539 break;
1540 case EHTokMin16int1:
1541 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1542 type.makeVector();
1543 break;
1544 case EHTokMin16int2:
1545 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1546 break;
1547 case EHTokMin16int3:
1548 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1549 break;
1550 case EHTokMin16int4:
1551 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1552 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001553
steve-lunarg3226b082016-10-26 19:18:55 -06001554 case EHTokMin12int:
1555 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1556 break;
1557 case EHTokMin12int1:
1558 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1559 type.makeVector();
1560 break;
1561 case EHTokMin12int2:
1562 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1563 break;
1564 case EHTokMin12int3:
1565 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1566 break;
1567 case EHTokMin12int4:
1568 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1569 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001570
steve-lunarg3226b082016-10-26 19:18:55 -06001571 case EHTokMin16uint:
1572 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1573 break;
1574 case EHTokMin16uint1:
1575 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1576 type.makeVector();
1577 break;
1578 case EHTokMin16uint2:
1579 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1580 break;
1581 case EHTokMin16uint3:
1582 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1583 break;
1584 case EHTokMin16uint4:
1585 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1586 break;
1587
John Kessenich0133c122016-05-20 12:17:26 -06001588 case EHTokInt1x1:
1589 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1590 break;
1591 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001592 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001593 break;
1594 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001595 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001596 break;
1597 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001598 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001599 break;
1600 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001601 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001602 break;
1603 case EHTokInt2x2:
1604 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1605 break;
1606 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001607 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001608 break;
1609 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001610 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001611 break;
1612 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001613 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001614 break;
1615 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001616 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001617 break;
1618 case EHTokInt3x3:
1619 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1620 break;
1621 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001622 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001623 break;
1624 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001625 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001626 break;
1627 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001628 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001629 break;
1630 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001631 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001632 break;
1633 case EHTokInt4x4:
1634 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1635 break;
1636
John Kessenich71351de2016-06-08 12:50:56 -06001637 case EHTokUint1x1:
1638 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1639 break;
1640 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001641 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001642 break;
1643 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001644 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001645 break;
1646 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001647 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001648 break;
1649 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001650 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001651 break;
1652 case EHTokUint2x2:
1653 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1654 break;
1655 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001656 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001657 break;
1658 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001659 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001660 break;
1661 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001662 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001663 break;
1664 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001665 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001666 break;
1667 case EHTokUint3x3:
1668 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1669 break;
1670 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001671 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001672 break;
1673 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001674 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001675 break;
1676 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001677 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001678 break;
1679 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001680 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001681 break;
1682 case EHTokUint4x4:
1683 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1684 break;
1685
1686 case EHTokBool1x1:
1687 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1688 break;
1689 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001690 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001691 break;
1692 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001693 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001694 break;
1695 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001696 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001697 break;
1698 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001699 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001700 break;
1701 case EHTokBool2x2:
1702 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1703 break;
1704 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001705 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001706 break;
1707 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001708 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001709 break;
1710 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001711 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001712 break;
1713 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001714 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001715 break;
1716 case EHTokBool3x3:
1717 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1718 break;
1719 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001720 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001721 break;
1722 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001723 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001724 break;
1725 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001726 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001727 break;
1728 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001729 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001730 break;
1731 case EHTokBool4x4:
1732 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1733 break;
1734
John Kessenich0133c122016-05-20 12:17:26 -06001735 case EHTokFloat1x1:
1736 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1737 break;
1738 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001739 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001740 break;
1741 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001742 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001743 break;
1744 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001745 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001746 break;
1747 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001748 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001749 break;
John Kessenich87142c72016-03-12 20:24:24 -07001750 case EHTokFloat2x2:
1751 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1752 break;
1753 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001754 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001755 break;
1756 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001757 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001758 break;
John Kessenich0133c122016-05-20 12:17:26 -06001759 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001760 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001761 break;
John Kessenich87142c72016-03-12 20:24:24 -07001762 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001763 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001764 break;
1765 case EHTokFloat3x3:
1766 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1767 break;
1768 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001769 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001770 break;
John Kessenich0133c122016-05-20 12:17:26 -06001771 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001772 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001773 break;
John Kessenich87142c72016-03-12 20:24:24 -07001774 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001775 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001776 break;
1777 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001778 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001779 break;
1780 case EHTokFloat4x4:
1781 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1782 break;
1783
John Kessenich96f65522017-06-06 23:35:25 -06001784 case EHTokHalf1x1:
1785 new(&type) TType(half_bt, EvqTemporary, 0, 1, 1);
1786 break;
1787 case EHTokHalf1x2:
1788 new(&type) TType(half_bt, EvqTemporary, 0, 1, 2);
1789 break;
1790 case EHTokHalf1x3:
1791 new(&type) TType(half_bt, EvqTemporary, 0, 1, 3);
1792 break;
1793 case EHTokHalf1x4:
1794 new(&type) TType(half_bt, EvqTemporary, 0, 1, 4);
1795 break;
1796 case EHTokHalf2x1:
1797 new(&type) TType(half_bt, EvqTemporary, 0, 2, 1);
1798 break;
1799 case EHTokHalf2x2:
1800 new(&type) TType(half_bt, EvqTemporary, 0, 2, 2);
1801 break;
1802 case EHTokHalf2x3:
1803 new(&type) TType(half_bt, EvqTemporary, 0, 2, 3);
1804 break;
1805 case EHTokHalf2x4:
1806 new(&type) TType(half_bt, EvqTemporary, 0, 2, 4);
1807 break;
1808 case EHTokHalf3x1:
1809 new(&type) TType(half_bt, EvqTemporary, 0, 3, 1);
1810 break;
1811 case EHTokHalf3x2:
1812 new(&type) TType(half_bt, EvqTemporary, 0, 3, 2);
1813 break;
1814 case EHTokHalf3x3:
1815 new(&type) TType(half_bt, EvqTemporary, 0, 3, 3);
1816 break;
1817 case EHTokHalf3x4:
1818 new(&type) TType(half_bt, EvqTemporary, 0, 3, 4);
1819 break;
1820 case EHTokHalf4x1:
1821 new(&type) TType(half_bt, EvqTemporary, 0, 4, 1);
1822 break;
1823 case EHTokHalf4x2:
1824 new(&type) TType(half_bt, EvqTemporary, 0, 4, 2);
1825 break;
1826 case EHTokHalf4x3:
1827 new(&type) TType(half_bt, EvqTemporary, 0, 4, 3);
1828 break;
1829 case EHTokHalf4x4:
1830 new(&type) TType(half_bt, EvqTemporary, 0, 4, 4);
1831 break;
1832
John Kessenich0133c122016-05-20 12:17:26 -06001833 case EHTokDouble1x1:
1834 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1835 break;
1836 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001837 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001838 break;
1839 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001840 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001841 break;
1842 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001843 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001844 break;
1845 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001846 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001847 break;
1848 case EHTokDouble2x2:
1849 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1850 break;
1851 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001852 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001853 break;
1854 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001855 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001856 break;
1857 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001858 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001859 break;
1860 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001861 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001862 break;
1863 case EHTokDouble3x3:
1864 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1865 break;
1866 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001867 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001868 break;
1869 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001870 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001871 break;
1872 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001873 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001874 break;
1875 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001876 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001877 break;
1878 case EHTokDouble4x4:
1879 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1880 break;
1881
John Kessenich87142c72016-03-12 20:24:24 -07001882 default:
1883 return false;
1884 }
1885
1886 advanceToken();
1887
1888 return true;
1889}
1890
John Kesseniche6e74942016-06-11 16:43:14 -06001891// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001892// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1893// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07001894// | struct_type IDENTIFIER // use of previously declared struct type
John Kessenich3d157c52016-07-25 16:05:33 -06001895//
1896// struct_type
1897// : STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07001898// | CLASS
John Kessenich3d157c52016-07-25 16:05:33 -06001899// | CBUFFER
1900// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001901//
John Kessenich54ee28f2017-03-11 14:13:00 -07001902bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
John Kesseniche6e74942016-06-11 16:43:14 -06001903{
John Kessenichb804de62016-09-05 12:19:18 -06001904 // This storage qualifier will tell us whether it's an AST
1905 // block type or just a generic structure type.
1906 TStorageQualifier storageQualifier = EvqTemporary;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06001907 bool readonly = false;
John Kessenich3d157c52016-07-25 16:05:33 -06001908
steve-lunarg7b1dcd62017-04-20 13:16:23 -06001909 if (acceptTokenClass(EHTokCBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06001910 // CBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06001911 storageQualifier = EvqUniform;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06001912 } else if (acceptTokenClass(EHTokTBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06001913 // TBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06001914 storageQualifier = EvqBuffer;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06001915 readonly = true;
John Kessenich054378d2017-06-19 15:13:26 -06001916 } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) {
1917 // Neither CLASS nor STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06001918 return false;
John Kessenich054378d2017-06-19 15:13:26 -06001919 }
1920
1921 // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06001922
1923 // IDENTIFIER
1924 TString structName = "";
1925 if (peekTokenClass(EHTokIdentifier)) {
1926 structName = *token.string;
1927 advanceToken();
1928 }
1929
John Kessenich3d157c52016-07-25 16:05:33 -06001930 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001931 TQualifier postDeclQualifier;
1932 postDeclQualifier.clear();
John Kessenich854fe242017-03-02 14:30:59 -07001933 bool postDeclsFound = acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001934
John Kessenichf3d88bd2017-03-19 12:24:29 -06001935 // LEFT_BRACE, or
John Kessenich854fe242017-03-02 14:30:59 -07001936 // struct_type IDENTIFIER
John Kesseniche6e74942016-06-11 16:43:14 -06001937 if (! acceptTokenClass(EHTokLeftBrace)) {
John Kessenich854fe242017-03-02 14:30:59 -07001938 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
1939 // struct_type IDENTIFIER
1940 return true;
1941 } else {
1942 expected("{");
1943 return false;
1944 }
John Kesseniche6e74942016-06-11 16:43:14 -06001945 }
1946
John Kessenichf3d88bd2017-03-19 12:24:29 -06001947
John Kesseniche6e74942016-06-11 16:43:14 -06001948 // struct_declaration_list
1949 TTypeList* typeList;
John Kessenichf3d88bd2017-03-19 12:24:29 -06001950 // Save each member function so they can be processed after we have a fully formed 'this'.
1951 TVector<TFunctionDeclarator> functionDeclarators;
1952
1953 parseContext.pushNamespace(structName);
John Kessenichaa3c64c2017-03-28 09:52:38 -06001954 bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06001955 parseContext.popNamespace();
1956
1957 if (! acceptedList) {
John Kesseniche6e74942016-06-11 16:43:14 -06001958 expected("struct member declarations");
1959 return false;
1960 }
1961
1962 // RIGHT_BRACE
1963 if (! acceptTokenClass(EHTokRightBrace)) {
1964 expected("}");
1965 return false;
1966 }
1967
1968 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001969 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001970 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001971 else {
John Kessenich7735b942016-09-05 12:40:06 -06001972 postDeclQualifier.storage = storageQualifier;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06001973 postDeclQualifier.readonly = readonly;
John Kessenich7735b942016-09-05 12:40:06 -06001974 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001975 }
John Kesseniche6e74942016-06-11 16:43:14 -06001976
John Kessenich727b3742017-02-03 17:57:55 -07001977 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06001978
John Kessenich4960baa2017-03-19 18:09:59 -06001979 // For member functions: now that we know the type of 'this', go back and
1980 // - add their implicit argument with 'this' (not to the mangling, just the argument list)
1981 // - parse the functions, their tokens were saved for deferred parsing (now)
1982 for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
1983 // update signature
1984 if (functionDeclarators[b].function->hasImplicitThis())
John Kessenich37789792017-03-21 23:56:40 -06001985 functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName);
John Kessenich4960baa2017-03-19 18:09:59 -06001986 }
1987
John Kessenichf3d88bd2017-03-19 12:24:29 -06001988 // All member functions get parsed inside the class/struct namespace and with the
1989 // class/struct members in a symbol-table level.
1990 parseContext.pushNamespace(structName);
John Kessenich0a2a0cd2017-05-16 23:16:26 -06001991 parseContext.pushThisScope(type, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06001992 bool deferredSuccess = true;
1993 for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
1994 // parse body
1995 pushTokenStream(functionDeclarators[b].body);
1996 if (! acceptFunctionBody(functionDeclarators[b], nodeList))
1997 deferredSuccess = false;
1998 popTokenStream();
1999 }
John Kessenich37789792017-03-21 23:56:40 -06002000 parseContext.popThisScope();
John Kessenichf3d88bd2017-03-19 12:24:29 -06002001 parseContext.popNamespace();
2002
2003 return deferredSuccess;
John Kesseniche6e74942016-06-11 16:43:14 -06002004}
2005
steve-lunarga766b832017-04-25 09:30:28 -06002006// constantbuffer
2007// : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE
2008bool HlslGrammar::acceptConstantBufferType(TType& type)
2009{
2010 if (! acceptTokenClass(EHTokConstantBuffer))
2011 return false;
2012
2013 if (! acceptTokenClass(EHTokLeftAngle)) {
2014 expected("left angle bracket");
2015 return false;
2016 }
2017
2018 TType templateType;
2019 if (! acceptType(templateType)) {
2020 expected("type");
2021 return false;
2022 }
2023
2024 if (! acceptTokenClass(EHTokRightAngle)) {
2025 expected("right angle bracket");
2026 return false;
2027 }
2028
2029 TQualifier postDeclQualifier;
2030 postDeclQualifier.clear();
2031 postDeclQualifier.storage = EvqUniform;
2032
2033 if (templateType.isStruct()) {
2034 // Make a block from the type parsed as the template argument
2035 TTypeList* typeList = templateType.getWritableStruct();
2036 new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock
2037
2038 type.getQualifier().storage = EvqUniform;
2039
2040 return true;
2041 } else {
2042 parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", "");
2043 return false;
2044 }
2045}
2046
steve-lunarg5da1f032017-02-12 17:50:28 -07002047// struct_buffer
2048// : APPENDSTRUCTUREDBUFFER
2049// | BYTEADDRESSBUFFER
2050// | CONSUMESTRUCTUREDBUFFER
2051// | RWBYTEADDRESSBUFFER
2052// | RWSTRUCTUREDBUFFER
2053// | STRUCTUREDBUFFER
2054bool HlslGrammar::acceptStructBufferType(TType& type)
2055{
2056 const EHlslTokenClass structBuffType = peek();
2057
2058 // TODO: globallycoherent
2059 bool hasTemplateType = true;
2060 bool readonly = false;
2061
2062 TStorageQualifier storage = EvqBuffer;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002063 TBuiltInVariable builtinType = EbvNone;
steve-lunarg5da1f032017-02-12 17:50:28 -07002064
2065 switch (structBuffType) {
2066 case EHTokAppendStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002067 builtinType = EbvAppendConsume;
2068 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002069 case EHTokByteAddressBuffer:
2070 hasTemplateType = false;
2071 readonly = true;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002072 builtinType = EbvByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002073 break;
2074 case EHTokConsumeStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002075 builtinType = EbvAppendConsume;
2076 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002077 case EHTokRWByteAddressBuffer:
2078 hasTemplateType = false;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002079 builtinType = EbvRWByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002080 break;
2081 case EHTokRWStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002082 builtinType = EbvRWStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002083 break;
2084 case EHTokStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002085 builtinType = EbvStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002086 readonly = true;
2087 break;
2088 default:
2089 return false; // not a structure buffer type
2090 }
2091
2092 advanceToken(); // consume the structure keyword
2093
2094 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
2095 TType* templateType = new TType;
2096
2097 if (hasTemplateType) {
2098 if (! acceptTokenClass(EHTokLeftAngle)) {
2099 expected("left angle bracket");
2100 return false;
2101 }
2102
2103 if (! acceptType(*templateType)) {
2104 expected("type");
2105 return false;
2106 }
2107 if (! acceptTokenClass(EHTokRightAngle)) {
2108 expected("right angle bracket");
2109 return false;
2110 }
2111 } else {
2112 // byte address buffers have no explicit type.
2113 TType uintType(EbtUint, storage);
2114 templateType->shallowCopy(uintType);
2115 }
2116
2117 // Create an unsized array out of that type.
2118 // TODO: does this work if it's already an array type?
2119 TArraySizes unsizedArray;
2120 unsizedArray.addInnerSize(UnsizedArraySize);
2121 templateType->newArraySizes(unsizedArray);
steve-lunarg40efe5c2017-03-06 12:01:44 -07002122 templateType->getQualifier().storage = storage;
steve-lunargdd8287a2017-02-23 18:04:12 -07002123
2124 // field name is canonical for all structbuffers
2125 templateType->setFieldName("@data");
steve-lunarg5da1f032017-02-12 17:50:28 -07002126
steve-lunarg5da1f032017-02-12 17:50:28 -07002127 TTypeList* blockStruct = new TTypeList;
2128 TTypeLoc member = { templateType, token.loc };
2129 blockStruct->push_back(member);
2130
steve-lunargdd8287a2017-02-23 18:04:12 -07002131 // This is the type of the buffer block (SSBO)
steve-lunarg5da1f032017-02-12 17:50:28 -07002132 TType blockType(blockStruct, "", templateType->getQualifier());
2133
steve-lunargdd8287a2017-02-23 18:04:12 -07002134 blockType.getQualifier().storage = storage;
2135 blockType.getQualifier().readonly = readonly;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002136 blockType.getQualifier().builtIn = builtinType;
steve-lunargdd8287a2017-02-23 18:04:12 -07002137
2138 // We may have created an equivalent type before, in which case we should use its
2139 // deep structure.
2140 parseContext.shareStructBufferType(blockType);
2141
steve-lunarg5da1f032017-02-12 17:50:28 -07002142 type.shallowCopy(blockType);
2143
2144 return true;
2145}
2146
John Kesseniche6e74942016-06-11 16:43:14 -06002147// struct_declaration_list
2148// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
2149//
2150// struct_declaration
2151// : fully_specified_type struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07002152// | fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition
John Kesseniche6e74942016-06-11 16:43:14 -06002153//
2154// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06002155// : IDENTIFIER post_decls
2156// | IDENTIFIER array_specifier post_decls
John Kessenich54ee28f2017-03-11 14:13:00 -07002157// | IDENTIFIER function_parameters post_decls // member-function prototype
John Kesseniche6e74942016-06-11 16:43:14 -06002158//
John Kessenichaa3c64c2017-03-28 09:52:38 -06002159bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002160 TVector<TFunctionDeclarator>& declarators)
John Kesseniche6e74942016-06-11 16:43:14 -06002161{
2162 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002163 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06002164
2165 do {
2166 // success on seeing the RIGHT_BRACE coming up
2167 if (peekTokenClass(EHTokRightBrace))
John Kessenichb16f7e62017-03-11 19:32:47 -07002168 break;
John Kesseniche6e74942016-06-11 16:43:14 -06002169
2170 // struct_declaration
John Kessenich54ee28f2017-03-11 14:13:00 -07002171
2172 bool declarator_list = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002173
2174 // fully_specified_type
2175 TType memberType;
John Kessenich54ee28f2017-03-11 14:13:00 -07002176 if (! acceptFullySpecifiedType(memberType, nodeList)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002177 expected("member type");
2178 return false;
2179 }
2180
2181 // struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07002182 bool functionDefinitionAccepted = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002183 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002184 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002185 expected("member name");
2186 return false;
2187 }
2188
John Kessenich54ee28f2017-03-11 14:13:00 -07002189 if (peekTokenClass(EHTokLeftParen)) {
2190 // function_parameters
2191 if (!declarator_list) {
John Kessenichb16f7e62017-03-11 19:32:47 -07002192 declarators.resize(declarators.size() + 1);
2193 // request a token stream for deferred processing
John Kessenichf3d88bd2017-03-19 12:24:29 -06002194 functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
2195 declarators.back());
John Kessenich54ee28f2017-03-11 14:13:00 -07002196 if (functionDefinitionAccepted)
2197 break;
2198 }
2199 expected("member-function definition");
2200 return false;
2201 } else {
2202 // add it to the list of members
2203 TTypeLoc member = { new TType(EbtVoid), token.loc };
2204 member.type->shallowCopy(memberType);
2205 member.type->setFieldName(*idToken.string);
2206 typeList->push_back(member);
John Kesseniche6e74942016-06-11 16:43:14 -06002207
John Kessenich54ee28f2017-03-11 14:13:00 -07002208 // array_specifier
2209 TArraySizes* arraySizes = nullptr;
2210 acceptArraySpecifier(arraySizes);
2211 if (arraySizes)
2212 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06002213
John Kessenich54ee28f2017-03-11 14:13:00 -07002214 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06002215
John Kessenich54ee28f2017-03-11 14:13:00 -07002216 // EQUAL assignment_expression
2217 if (acceptTokenClass(EHTokAssign)) {
2218 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
2219 TIntermTyped* expressionNode = nullptr;
2220 if (! acceptAssignmentExpression(expressionNode)) {
2221 expected("initializer");
2222 return false;
2223 }
John Kessenich18adbdb2017-02-02 15:16:20 -07002224 }
2225 }
John Kesseniche6e74942016-06-11 16:43:14 -06002226 // success on seeing the SEMICOLON coming up
2227 if (peekTokenClass(EHTokSemicolon))
2228 break;
2229
2230 // COMMA
John Kessenich54ee28f2017-03-11 14:13:00 -07002231 if (acceptTokenClass(EHTokComma))
2232 declarator_list = true;
2233 else {
John Kesseniche6e74942016-06-11 16:43:14 -06002234 expected(",");
2235 return false;
2236 }
2237
2238 } while (true);
2239
2240 // SEMI_COLON
John Kessenich54ee28f2017-03-11 14:13:00 -07002241 if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002242 expected(";");
2243 return false;
2244 }
2245
2246 } while (true);
John Kessenichb16f7e62017-03-11 19:32:47 -07002247
John Kessenichb16f7e62017-03-11 19:32:47 -07002248 return true;
John Kesseniche6e74942016-06-11 16:43:14 -06002249}
2250
John Kessenich54ee28f2017-03-11 14:13:00 -07002251// member_function_definition
2252// | function_parameters post_decls compound_statement
2253//
2254// Expects type to have EvqGlobal for a static member and
2255// EvqTemporary for non-static member.
John Kessenichf3d88bd2017-03-19 12:24:29 -06002256bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, const TString& memberName,
2257 TFunctionDeclarator& declarator)
John Kessenich54ee28f2017-03-11 14:13:00 -07002258{
John Kessenich54ee28f2017-03-11 14:13:00 -07002259 bool accepted = false;
2260
John Kessenich4dc835c2017-03-28 23:43:10 -06002261 const TString* functionName = &memberName;
2262 parseContext.getFullNamespaceName(functionName);
John Kessenich088d52b2017-03-11 17:55:28 -07002263 declarator.function = new TFunction(functionName, type);
John Kessenich4960baa2017-03-19 18:09:59 -06002264 if (type.getQualifier().storage == EvqTemporary)
2265 declarator.function->setImplicitThis();
John Kessenich37789792017-03-21 23:56:40 -06002266 else
2267 declarator.function->setIllegalImplicitThis();
John Kessenich54ee28f2017-03-11 14:13:00 -07002268
2269 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -07002270 if (acceptFunctionParameters(*declarator.function)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002271 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -07002272 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich54ee28f2017-03-11 14:13:00 -07002273
2274 // compound_statement (function body definition)
2275 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich088d52b2017-03-11 17:55:28 -07002276 declarator.loc = token.loc;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002277 declarator.body = new TVector<HlslToken>;
2278 accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
John Kessenich54ee28f2017-03-11 14:13:00 -07002279 }
2280 } else
2281 expected("function parameter list");
2282
John Kessenich54ee28f2017-03-11 14:13:00 -07002283 return accepted;
2284}
2285
John Kessenich5f934b02016-03-13 17:58:25 -06002286// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06002287// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06002288// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002289//
2290bool HlslGrammar::acceptFunctionParameters(TFunction& function)
2291{
John Kessenich078d7f22016-03-14 10:02:11 -06002292 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002293 if (! acceptTokenClass(EHTokLeftParen))
2294 return false;
2295
John Kessenich71351de2016-06-08 12:50:56 -06002296 // VOID RIGHT_PAREN
2297 if (! acceptTokenClass(EHTokVoid)) {
2298 do {
2299 // parameter_declaration
2300 if (! acceptParameterDeclaration(function))
2301 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002302
John Kessenich71351de2016-06-08 12:50:56 -06002303 // COMMA
2304 if (! acceptTokenClass(EHTokComma))
2305 break;
2306 } while (true);
2307 }
John Kessenich5f934b02016-03-13 17:58:25 -06002308
John Kessenich078d7f22016-03-14 10:02:11 -06002309 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002310 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002311 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002312 return false;
2313 }
2314
2315 return true;
2316}
2317
steve-lunarg26d31452016-12-23 18:56:57 -07002318// default_parameter_declaration
2319// : EQUAL conditional_expression
2320// : EQUAL initializer
2321bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2322{
2323 node = nullptr;
2324
2325 // Valid not to have a default_parameter_declaration
2326 if (!acceptTokenClass(EHTokAssign))
2327 return true;
2328
2329 if (!acceptConditionalExpression(node)) {
2330 if (!acceptInitializer(node))
2331 return false;
2332
2333 // For initializer lists, we have to const-fold into a constructor for the type, so build
2334 // that.
John Kessenichc633f642017-04-03 21:48:37 -06002335 TFunction* constructor = parseContext.makeConstructorCall(token.loc, type);
steve-lunarg26d31452016-12-23 18:56:57 -07002336 if (constructor == nullptr) // cannot construct
2337 return false;
2338
2339 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002340 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002341 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002342
steve-lunarg26d31452016-12-23 18:56:57 -07002343 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2344 }
2345
2346 // If this is simply a constant, we can use it directly.
2347 if (node->getAsConstantUnion())
2348 return true;
2349
2350 // Otherwise, it has to be const-foldable.
2351 TIntermTyped* origNode = node;
2352
2353 node = intermediate.fold(node->getAsAggregate());
2354
2355 if (node != nullptr && origNode != node)
2356 return true;
2357
2358 parseContext.error(token.loc, "invalid default parameter value", "", "");
2359
2360 return false;
2361}
2362
John Kessenich5f934b02016-03-13 17:58:25 -06002363// parameter_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002364// : fully_specified_type post_decls [ = default_parameter_declaration ]
2365// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002366//
2367bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2368{
2369 // fully_specified_type
2370 TType* type = new TType;
2371 if (! acceptFullySpecifiedType(*type))
2372 return false;
2373
2374 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002375 HlslToken idToken;
2376 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002377
John Kessenich19b92ff2016-06-19 11:50:34 -06002378 // array_specifier
2379 TArraySizes* arraySizes = nullptr;
2380 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002381 if (arraySizes) {
2382 if (arraySizes->isImplicit()) {
2383 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2384 return false;
2385 }
2386
John Kessenich19b92ff2016-06-19 11:50:34 -06002387 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002388 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002389
2390 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002391 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002392
steve-lunarg26d31452016-12-23 18:56:57 -07002393 TIntermTyped* defaultValue;
2394 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2395 return false;
2396
John Kessenich5aa59e22016-06-17 15:50:47 -06002397 parseContext.paramFix(*type);
2398
steve-lunarg26d31452016-12-23 18:56:57 -07002399 // If any prior parameters have default values, all the parameters after that must as well.
2400 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2401 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2402 return false;
2403 }
2404
2405 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002406 function.addParameter(param);
2407
2408 return true;
2409}
2410
2411// Do the work to create the function definition in addition to
2412// parsing the body (compound_statement).
John Kessenichb16f7e62017-03-11 19:32:47 -07002413//
2414// If 'deferredTokens' are passed in, just get the token stream,
2415// don't process.
2416//
2417bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
2418 TVector<HlslToken>* deferredTokens)
John Kessenich5f934b02016-03-13 17:58:25 -06002419{
John Kessenich088d52b2017-03-11 17:55:28 -07002420 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
John Kessenich5f934b02016-03-13 17:58:25 -06002421
John Kessenichb16f7e62017-03-11 19:32:47 -07002422 if (deferredTokens)
2423 return captureBlockTokens(*deferredTokens);
2424 else
John Kessenich4960baa2017-03-19 18:09:59 -06002425 return acceptFunctionBody(declarator, nodeList);
John Kessenich088d52b2017-03-11 17:55:28 -07002426}
2427
2428bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
2429{
2430 // we might get back an entry-point
John Kessenichca71d942017-03-07 20:44:09 -07002431 TIntermNode* entryPointNode = nullptr;
2432
John Kessenich077e0522016-06-09 02:02:17 -06002433 // This does a pushScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002434 TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function,
2435 declarator.attributes, entryPointNode);
John Kessenich5f934b02016-03-13 17:58:25 -06002436
2437 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002438 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002439 if (! acceptCompoundStatement(functionBody))
2440 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002441
John Kessenich54ee28f2017-03-11 14:13:00 -07002442 // this does a popScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002443 parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode);
John Kessenichca71d942017-03-07 20:44:09 -07002444
2445 // Hook up the 1 or 2 function definitions.
2446 nodeList = intermediate.growAggregate(nodeList, functionNode);
2447 nodeList = intermediate.growAggregate(nodeList, entryPointNode);
John Kessenich02467d82017-01-19 15:41:47 -07002448
2449 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002450}
2451
John Kessenich0d2b6de2016-06-05 11:23:11 -06002452// Accept an expression with parenthesis around it, where
2453// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002454// syntactically required ones like in "if ( expression )".
2455//
2456// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002457//
2458// Note this one is not set up to be speculative; as it gives
2459// errors if not found.
2460//
2461bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2462{
2463 // LEFT_PAREN
2464 if (! acceptTokenClass(EHTokLeftParen))
2465 expected("(");
2466
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002467 bool decl = false;
2468 TIntermNode* declNode = nullptr;
2469 decl = acceptControlDeclaration(declNode);
2470 if (decl) {
2471 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2472 expected("initialized declaration");
2473 return false;
2474 } else
2475 expression = declNode->getAsTyped();
2476 } else {
2477 // no declaration
2478 if (! acceptExpression(expression)) {
2479 expected("expression");
2480 return false;
2481 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002482 }
2483
2484 // RIGHT_PAREN
2485 if (! acceptTokenClass(EHTokRightParen))
2486 expected(")");
2487
2488 return true;
2489}
2490
John Kessenich34fb0362016-05-03 23:17:20 -06002491// The top-level full expression recognizer.
2492//
John Kessenich87142c72016-03-12 20:24:24 -07002493// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002494// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002495//
2496bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2497{
LoopDawgef764a22016-06-03 09:17:51 -06002498 node = nullptr;
2499
John Kessenich34fb0362016-05-03 23:17:20 -06002500 // assignment_expression
2501 if (! acceptAssignmentExpression(node))
2502 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002503
John Kessenich34fb0362016-05-03 23:17:20 -06002504 if (! peekTokenClass(EHTokComma))
2505 return true;
2506
2507 do {
2508 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002509 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002510 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002511
John Kessenich34fb0362016-05-03 23:17:20 -06002512 // ... assignment_expression
2513 TIntermTyped* rightNode = nullptr;
2514 if (! acceptAssignmentExpression(rightNode)) {
2515 expected("assignment expression");
2516 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002517 }
2518
John Kessenich34fb0362016-05-03 23:17:20 -06002519 node = intermediate.addComma(node, rightNode, loc);
2520
2521 if (! peekTokenClass(EHTokComma))
2522 return true;
2523 } while (true);
2524}
2525
John Kessenich07354242016-07-01 19:58:06 -06002526// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002527// : LEFT_BRACE RIGHT_BRACE
2528// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002529//
2530// initializer_list
2531// : assignment_expression COMMA assignment_expression COMMA ...
2532//
2533bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2534{
2535 // LEFT_BRACE
2536 if (! acceptTokenClass(EHTokLeftBrace))
2537 return false;
2538
John Kessenich98ad4852016-11-27 17:39:07 -07002539 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002540 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002541 if (acceptTokenClass(EHTokRightBrace)) {
2542 // a zero-length initializer list
2543 node = intermediate.makeAggregate(loc);
2544 return true;
2545 }
2546
2547 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002548 node = nullptr;
2549 do {
2550 // assignment_expression
2551 TIntermTyped* expr;
2552 if (! acceptAssignmentExpression(expr)) {
2553 expected("assignment expression in initializer list");
2554 return false;
2555 }
LoopDawg0fca0ba2017-07-10 15:43:40 -06002556
2557 const bool firstNode = (node == nullptr);
2558
John Kessenich07354242016-07-01 19:58:06 -06002559 node = intermediate.growAggregate(node, expr, loc);
2560
LoopDawg0fca0ba2017-07-10 15:43:40 -06002561 // If every sub-node in the list has qualifier EvqConst, the returned node becomes
2562 // EvqConst. Otherwise, it becomes EvqTemporary. That doesn't happen with e.g.
2563 // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are.
2564 if (firstNode && expr->getQualifier().storage == EvqConst)
2565 node->getQualifier().storage = EvqConst;
2566 else if (expr->getQualifier().storage != EvqConst)
2567 node->getQualifier().storage = EvqTemporary;
2568
John Kessenich07354242016-07-01 19:58:06 -06002569 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002570 if (acceptTokenClass(EHTokComma)) {
2571 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2572 return true;
John Kessenich07354242016-07-01 19:58:06 -06002573 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002574 }
John Kessenich07354242016-07-01 19:58:06 -06002575
2576 // RIGHT_BRACE
2577 if (acceptTokenClass(EHTokRightBrace))
2578 return true;
2579
2580 expected(", or }");
2581 return false;
2582 } while (true);
2583}
2584
John Kessenich34fb0362016-05-03 23:17:20 -06002585// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002586// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002587//
2588// a op (b op (c op d))
2589//
2590// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002591// : initializer
2592// | conditional_expression
2593// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002594//
2595bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2596{
John Kessenich07354242016-07-01 19:58:06 -06002597 // initializer
2598 if (peekTokenClass(EHTokLeftBrace)) {
2599 if (acceptInitializer(node))
2600 return true;
2601
2602 expected("initializer");
2603 return false;
2604 }
2605
John Kessenich00957f82016-07-27 10:39:57 -06002606 // conditional_expression
2607 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002608 return false;
2609
John Kessenich07354242016-07-01 19:58:06 -06002610 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002611 TOperator assignOp = HlslOpMap::assignment(peek());
2612 if (assignOp == EOpNull)
2613 return true;
2614
John Kessenich00957f82016-07-27 10:39:57 -06002615 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002616 TSourceLoc loc = token.loc;
2617 advanceToken();
2618
John Kessenich00957f82016-07-27 10:39:57 -06002619 // conditional_expression assign_op conditional_expression ...
2620 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002621 // gets the right-to-left associativity.
2622 TIntermTyped* rightNode = nullptr;
2623 if (! acceptAssignmentExpression(rightNode)) {
2624 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002625 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002626 }
2627
John Kessenichd21baed2016-09-16 03:05:12 -06002628 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002629 node = parseContext.handleLvalue(loc, "assign", node);
2630
John Kessenichfea226b2016-07-28 17:53:56 -06002631 if (node == nullptr) {
2632 parseContext.error(loc, "could not create assignment", "", "");
2633 return false;
2634 }
John Kessenich34fb0362016-05-03 23:17:20 -06002635
2636 if (! peekTokenClass(EHTokComma))
2637 return true;
2638
2639 return true;
2640}
2641
John Kessenich00957f82016-07-27 10:39:57 -06002642// Accept a conditional expression, which associates right-to-left,
2643// accomplished by the "true" expression calling down to lower
2644// precedence levels than this level.
2645//
2646// conditional_expression
2647// : binary_expression
2648// | binary_expression QUESTION expression COLON assignment_expression
2649//
2650bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2651{
2652 // binary_expression
2653 if (! acceptBinaryExpression(node, PlLogicalOr))
2654 return false;
2655
2656 if (! acceptTokenClass(EHTokQuestion))
2657 return true;
2658
John Kessenich636b62d2017-04-11 19:45:00 -06002659 node = parseContext.convertConditionalExpression(token.loc, node, false);
John Kessenich7e997e22017-03-30 22:09:30 -06002660 if (node == nullptr)
2661 return false;
2662
John Kessenichf6deacd2017-06-06 19:52:55 -06002663 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
2664
John Kessenich00957f82016-07-27 10:39:57 -06002665 TIntermTyped* trueNode = nullptr;
2666 if (! acceptExpression(trueNode)) {
2667 expected("expression after ?");
2668 return false;
2669 }
2670 TSourceLoc loc = token.loc;
2671
2672 if (! acceptTokenClass(EHTokColon)) {
2673 expected(":");
2674 return false;
2675 }
2676
2677 TIntermTyped* falseNode = nullptr;
2678 if (! acceptAssignmentExpression(falseNode)) {
2679 expected("expression after :");
2680 return false;
2681 }
2682
John Kessenichf6deacd2017-06-06 19:52:55 -06002683 --parseContext.controlFlowNestingLevel;
2684
John Kessenich00957f82016-07-27 10:39:57 -06002685 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2686
2687 return true;
2688}
2689
John Kessenich34fb0362016-05-03 23:17:20 -06002690// Accept a binary expression, for binary operations that
2691// associate left-to-right. This is, it is implicit, for example
2692//
2693// ((a op b) op c) op d
2694//
2695// binary_expression
2696// : expression op expression op expression ...
2697//
2698// where 'expression' is the next higher level in precedence.
2699//
2700bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2701{
2702 if (precedenceLevel > PlMul)
2703 return acceptUnaryExpression(node);
2704
2705 // assignment_expression
2706 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2707 return false;
2708
John Kessenich34fb0362016-05-03 23:17:20 -06002709 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002710 TOperator op = HlslOpMap::binary(peek());
2711 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2712 if (tokenLevel < precedenceLevel)
2713 return true;
2714
John Kessenich34fb0362016-05-03 23:17:20 -06002715 // ... op
2716 TSourceLoc loc = token.loc;
2717 advanceToken();
2718
2719 // ... expression
2720 TIntermTyped* rightNode = nullptr;
2721 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2722 expected("expression");
2723 return false;
2724 }
2725
2726 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002727 if (node == nullptr) {
2728 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2729 return false;
2730 }
John Kessenich34fb0362016-05-03 23:17:20 -06002731 } while (true);
2732}
2733
2734// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002735// : (type) unary_expression
2736// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002737// | - unary_expression
2738// | ! unary_expression
2739// | ~ unary_expression
2740// | ++ unary_expression
2741// | -- unary_expression
2742// | postfix_expression
2743//
2744bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2745{
John Kessenich1cc1a282016-06-03 16:55:49 -06002746 // (type) unary_expression
2747 // Have to look two steps ahead, because this could be, e.g., a
2748 // postfix_expression instead, since that also starts with at "(".
2749 if (acceptTokenClass(EHTokLeftParen)) {
2750 TType castType;
2751 if (acceptType(castType)) {
John Kessenich82ae8c32017-06-13 23:13:10 -06002752 // recognize any array_specifier as part of the type
2753 TArraySizes* arraySizes = nullptr;
2754 acceptArraySpecifier(arraySizes);
2755 if (arraySizes != nullptr)
2756 castType.newArraySizes(*arraySizes);
2757 TSourceLoc loc = token.loc;
steve-lunarg5964c642016-07-30 07:38:55 -06002758 if (acceptTokenClass(EHTokRightParen)) {
2759 // We've matched "(type)" now, get the expression to cast
steve-lunarg5964c642016-07-30 07:38:55 -06002760 if (! acceptUnaryExpression(node))
2761 return false;
2762
2763 // Hook it up like a constructor
John Kessenichc633f642017-04-03 21:48:37 -06002764 TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType);
steve-lunarg5964c642016-07-30 07:38:55 -06002765 if (constructorFunction == nullptr) {
2766 expected("type that can be constructed");
2767 return false;
2768 }
2769 TIntermTyped* arguments = nullptr;
2770 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2771 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2772
2773 return true;
2774 } else {
2775 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2776 // the '(int' part. We must back up twice.
2777 recedeToken();
2778 recedeToken();
John Kessenich82ae8c32017-06-13 23:13:10 -06002779
2780 // Note, there are no array constructors like
2781 // (float[2](...))
2782 if (arraySizes != nullptr)
2783 parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", "");
John Kessenich1cc1a282016-06-03 16:55:49 -06002784 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002785 } else {
2786 // This isn't a type cast, but it still started "(", so if it is a
2787 // unary expression, it can only be a postfix_expression, so try that.
2788 // Back it up first.
2789 recedeToken();
2790 return acceptPostfixExpression(node);
2791 }
2792 }
2793
2794 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002795 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002796
John Kessenich1cc1a282016-06-03 16:55:49 -06002797 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002798 if (unaryOp == EOpNull)
2799 return acceptPostfixExpression(node);
2800
2801 // op unary_expression
2802 TSourceLoc loc = token.loc;
2803 advanceToken();
2804 if (! acceptUnaryExpression(node))
2805 return false;
2806
2807 // + is a no-op
2808 if (unaryOp == EOpAdd)
2809 return true;
2810
2811 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002812
2813 // These unary ops require lvalues
2814 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2815 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002816
2817 return node != nullptr;
2818}
2819
2820// postfix_expression
2821// : LEFT_PAREN expression RIGHT_PAREN
2822// | literal
2823// | constructor
John Kessenich8f9fdc92017-03-30 16:22:26 -06002824// | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ]
John Kessenich34fb0362016-05-03 23:17:20 -06002825// | function_call
2826// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2827// | postfix_expression DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07002828// | postfix_expression DOT IDENTIFIER arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06002829// | postfix_expression arguments
John Kessenich34fb0362016-05-03 23:17:20 -06002830// | postfix_expression INC_OP
2831// | postfix_expression DEC_OP
2832//
2833bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2834{
2835 // Not implemented as self-recursive:
John Kessenich54ee28f2017-03-11 14:13:00 -07002836 // The logical "right recursion" is done with a loop at the end
John Kessenich34fb0362016-05-03 23:17:20 -06002837
2838 // idToken will pick up either a variable or a function name in a function call
2839 HlslToken idToken;
2840
John Kessenich21472ae2016-06-04 11:46:33 -06002841 // Find something before the postfix operations, as they can't operate
2842 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002843 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002844 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002845 if (! acceptExpression(node)) {
2846 expected("expression");
2847 return false;
2848 }
2849 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002850 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002851 return false;
2852 }
John Kessenich34fb0362016-05-03 23:17:20 -06002853 } else if (acceptLiteral(node)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06002854 // literal (nothing else to do yet)
John Kessenich34fb0362016-05-03 23:17:20 -06002855 } else if (acceptConstructor(node)) {
2856 // constructor (nothing else to do yet)
2857 } else if (acceptIdentifier(idToken)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06002858 // user-type, namespace name, variable, or function name
2859 TString* fullName = idToken.string;
2860 while (acceptTokenClass(EHTokColonColon)) {
2861 // user-type or namespace name
2862 fullName = NewPoolTString(fullName->c_str());
2863 fullName->append(parseContext.scopeMangler);
2864 if (acceptIdentifier(idToken))
2865 fullName->append(*idToken.string);
2866 else {
2867 expected("identifier after ::");
John Kessenich54ee28f2017-03-11 14:13:00 -07002868 return false;
2869 }
John Kessenich8f9fdc92017-03-30 16:22:26 -06002870 }
2871 if (! peekTokenClass(EHTokLeftParen)) {
2872 node = parseContext.handleVariable(idToken.loc, fullName);
2873 } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) {
John Kessenich34fb0362016-05-03 23:17:20 -06002874 // function_call (nothing else to do yet)
2875 } else {
2876 expected("function call arguments");
2877 return false;
2878 }
John Kessenich21472ae2016-06-04 11:46:33 -06002879 } else {
2880 // nothing found, can't post operate
2881 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002882 }
2883
John Kessenich21472ae2016-06-04 11:46:33 -06002884 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002885 do {
2886 TSourceLoc loc = token.loc;
2887 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002888
John Kessenich34fb0362016-05-03 23:17:20 -06002889 // Consume only a valid post-unary operator, otherwise we are done.
2890 switch (postOp) {
2891 case EOpIndexDirectStruct:
2892 case EOpIndexIndirect:
2893 case EOpPostIncrement:
2894 case EOpPostDecrement:
John Kessenich54ee28f2017-03-11 14:13:00 -07002895 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06002896 advanceToken();
2897 break;
2898 default:
2899 return true;
2900 }
John Kessenich87142c72016-03-12 20:24:24 -07002901
John Kessenich34fb0362016-05-03 23:17:20 -06002902 // We have a valid post-unary operator, process it.
2903 switch (postOp) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002904 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06002905 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002906 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002907 // DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07002908 // includes swizzles, member variables, and member functions
John Kessenich93a162a2016-06-17 17:16:27 -06002909 HlslToken field;
2910 if (! acceptIdentifier(field)) {
2911 expected("swizzle or member");
2912 return false;
2913 }
LoopDawg4886f692016-06-29 10:58:58 -06002914
John Kessenich516d92d2017-03-08 20:09:03 -07002915 if (peekTokenClass(EHTokLeftParen)) {
2916 // member function
2917 TIntermTyped* thisNode = node;
LoopDawg4886f692016-06-29 10:58:58 -06002918
John Kessenich516d92d2017-03-08 20:09:03 -07002919 // arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06002920 if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) {
LoopDawg4886f692016-06-29 10:58:58 -06002921 expected("function parameters");
2922 return false;
2923 }
John Kessenich516d92d2017-03-08 20:09:03 -07002924 } else
2925 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002926
John Kessenich34fb0362016-05-03 23:17:20 -06002927 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002928 }
John Kessenich34fb0362016-05-03 23:17:20 -06002929 case EOpIndexIndirect:
2930 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002931 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002932 TIntermTyped* indexNode = nullptr;
2933 if (! acceptExpression(indexNode) ||
2934 ! peekTokenClass(EHTokRightBracket)) {
2935 expected("expression followed by ']'");
2936 return false;
2937 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002938 advanceToken();
2939 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
steve-lunarg2efd6c62017-04-06 20:22:20 -06002940 if (node == nullptr)
2941 return false;
John Kessenich19b92ff2016-06-19 11:50:34 -06002942 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002943 }
2944 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002945 // INC_OP
2946 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002947 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002948 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002949 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002950 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002951 break;
2952 default:
2953 assert(0);
2954 break;
2955 }
2956 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002957}
2958
John Kessenichd016be12016-03-13 11:24:20 -06002959// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002960// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002961//
2962bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2963{
2964 // type
2965 TType type;
2966 if (acceptType(type)) {
John Kessenichc633f642017-04-03 21:48:37 -06002967 TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type);
John Kessenichd016be12016-03-13 11:24:20 -06002968 if (constructorFunction == nullptr)
2969 return false;
2970
2971 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002972 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002973 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002974 // It's possible this is a type keyword used as an identifier. Put the token back
2975 // for later use.
2976 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06002977 return false;
2978 }
2979
2980 // hook it up
2981 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2982
2983 return true;
2984 }
2985
2986 return false;
2987}
2988
John Kessenich34fb0362016-05-03 23:17:20 -06002989// The function_call identifier was already recognized, and passed in as idToken.
2990//
2991// function_call
2992// : [idToken] arguments
2993//
John Kessenich8f9fdc92017-03-30 16:22:26 -06002994bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject)
John Kessenich34fb0362016-05-03 23:17:20 -06002995{
John Kessenich54ee28f2017-03-11 14:13:00 -07002996 // name
2997 TString* functionName = nullptr;
John Kessenich8f9fdc92017-03-30 16:22:26 -06002998 if (baseObject == nullptr) {
2999 functionName = &name;
3000 } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) {
John Kessenich4960baa2017-03-19 18:09:59 -06003001 // Built-in methods are not in the symbol table as methods, but as global functions
3002 // taking an explicit 'this' as the first argument.
steve-lunarge7d07522017-03-19 18:12:37 -06003003 functionName = NewPoolTString(BUILTIN_PREFIX);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003004 functionName->append(name);
John Kessenich4960baa2017-03-19 18:09:59 -06003005 } else {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003006 if (! baseObject->getType().isStruct()) {
3007 expected("structure");
3008 return false;
3009 }
John Kessenich54ee28f2017-03-11 14:13:00 -07003010 functionName = NewPoolTString("");
John Kessenich8f9fdc92017-03-30 16:22:26 -06003011 functionName->append(baseObject->getType().getTypeName());
John Kessenichf3d88bd2017-03-19 12:24:29 -06003012 parseContext.addScopeMangler(*functionName);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003013 functionName->append(name);
John Kessenich5f12d2f2017-03-11 09:39:55 -07003014 }
LoopDawg4886f692016-06-29 10:58:58 -06003015
John Kessenich54ee28f2017-03-11 14:13:00 -07003016 // function
3017 TFunction* function = new TFunction(functionName, TType(EbtVoid));
3018
3019 // arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07003020 TIntermTyped* arguments = nullptr;
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003021 if (baseObject != nullptr) {
3022 // Non-static member functions have an implicit first argument of the base object.
John Kessenich54ee28f2017-03-11 14:13:00 -07003023 parseContext.handleFunctionArgument(function, arguments, baseObject);
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003024 }
John Kessenich4678ca92016-05-13 09:33:42 -06003025 if (! acceptArguments(function, arguments))
3026 return false;
3027
John Kessenich54ee28f2017-03-11 14:13:00 -07003028 // call
John Kessenich8f9fdc92017-03-30 16:22:26 -06003029 node = parseContext.handleFunctionCall(loc, function, arguments);
John Kessenich4678ca92016-05-13 09:33:42 -06003030
3031 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06003032}
3033
John Kessenich87142c72016-03-12 20:24:24 -07003034// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06003035// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003036//
John Kessenichd016be12016-03-13 11:24:20 -06003037// The arguments are pushed onto the 'function' argument list and
3038// onto the 'arguments' aggregate.
3039//
John Kessenich4678ca92016-05-13 09:33:42 -06003040bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07003041{
John Kessenich078d7f22016-03-14 10:02:11 -06003042 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003043 if (! acceptTokenClass(EHTokLeftParen))
3044 return false;
3045
John Kessenich2aa12b12017-04-18 14:47:33 -06003046 // RIGHT_PAREN
3047 if (acceptTokenClass(EHTokRightParen))
3048 return true;
3049
3050 // must now be at least one expression...
John Kessenich87142c72016-03-12 20:24:24 -07003051 do {
John Kessenichd016be12016-03-13 11:24:20 -06003052 // expression
John Kessenich87142c72016-03-12 20:24:24 -07003053 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06003054 if (! acceptAssignmentExpression(arg))
John Kessenich2aa12b12017-04-18 14:47:33 -06003055 return false;
John Kessenichd016be12016-03-13 11:24:20 -06003056
3057 // hook it up
3058 parseContext.handleFunctionArgument(function, arguments, arg);
3059
John Kessenich078d7f22016-03-14 10:02:11 -06003060 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07003061 if (! acceptTokenClass(EHTokComma))
3062 break;
3063 } while (true);
3064
John Kessenich078d7f22016-03-14 10:02:11 -06003065 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003066 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003067 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003068 return false;
3069 }
3070
3071 return true;
3072}
3073
3074bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
3075{
3076 switch (token.tokenClass) {
3077 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003078 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003079 break;
steve-lunarg2de32912016-07-28 14:49:48 -06003080 case EHTokUintConstant:
3081 node = intermediate.addConstantUnion(token.u, token.loc, true);
3082 break;
John Kessenich87142c72016-03-12 20:24:24 -07003083 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003084 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003085 break;
3086 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003087 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003088 break;
3089 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003090 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003091 break;
John Kessenich86f71382016-09-19 20:23:18 -06003092 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07003093 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06003094 break;
John Kessenich87142c72016-03-12 20:24:24 -07003095
3096 default:
3097 return false;
3098 }
3099
3100 advanceToken();
3101
3102 return true;
3103}
3104
John Kessenich0e071192017-06-06 11:37:33 -06003105// simple_statement
3106// : SEMICOLON
3107// | declaration_statement
3108// | expression SEMICOLON
3109//
3110bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement)
3111{
3112 // SEMICOLON
3113 if (acceptTokenClass(EHTokSemicolon))
3114 return true;
3115
3116 // declaration
3117 if (acceptDeclaration(statement))
3118 return true;
3119
3120 // expression
3121 TIntermTyped* node;
3122 if (acceptExpression(node))
3123 statement = node;
3124 else
3125 return false;
3126
3127 // SEMICOLON (following an expression)
3128 if (acceptTokenClass(EHTokSemicolon))
3129 return true;
3130 else {
3131 expected(";");
3132 return false;
3133 }
3134}
3135
John Kessenich5f934b02016-03-13 17:58:25 -06003136// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06003137// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003138//
John Kessenich21472ae2016-06-04 11:46:33 -06003139bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07003140{
John Kessenich21472ae2016-06-04 11:46:33 -06003141 TIntermAggregate* compoundStatement = nullptr;
3142
John Kessenich34fb0362016-05-03 23:17:20 -06003143 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003144 if (! acceptTokenClass(EHTokLeftBrace))
3145 return false;
3146
3147 // statement statement ...
3148 TIntermNode* statement = nullptr;
3149 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06003150 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
3151 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
3152 branch->getFlowOp() == EOpDefault)) {
3153 // hook up individual subsequences within a switch statement
3154 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
3155 compoundStatement = nullptr;
3156 } else {
3157 // hook it up to the growing compound statement
3158 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
3159 }
John Kessenich5f934b02016-03-13 17:58:25 -06003160 }
John Kessenich34fb0362016-05-03 23:17:20 -06003161 if (compoundStatement)
3162 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06003163
John Kessenich21472ae2016-06-04 11:46:33 -06003164 retStatement = compoundStatement;
3165
John Kessenich34fb0362016-05-03 23:17:20 -06003166 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003167 return acceptTokenClass(EHTokRightBrace);
3168}
3169
John Kessenich0d2b6de2016-06-05 11:23:11 -06003170bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
3171{
3172 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06003173 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003174 parseContext.popScope();
3175
3176 return result;
3177}
3178
John Kessenich077e0522016-06-09 02:02:17 -06003179bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003180{
John Kessenich077e0522016-06-09 02:02:17 -06003181 parseContext.pushScope();
3182 bool result = acceptCompoundStatement(statement);
3183 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06003184
3185 return result;
3186}
3187
John Kessenich5f934b02016-03-13 17:58:25 -06003188// statement
John Kessenich21472ae2016-06-04 11:46:33 -06003189// : attributes attributed_statement
3190//
3191// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003192// : compound_statement
John Kessenich0e071192017-06-06 11:37:33 -06003193// | simple_statement
John Kessenich21472ae2016-06-04 11:46:33 -06003194// | selection_statement
3195// | switch_statement
3196// | case_label
John Kessenich0e071192017-06-06 11:37:33 -06003197// | default_label
John Kessenich21472ae2016-06-04 11:46:33 -06003198// | iteration_statement
3199// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003200//
3201bool HlslGrammar::acceptStatement(TIntermNode*& statement)
3202{
John Kessenich21472ae2016-06-04 11:46:33 -06003203 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06003204
John Kessenich21472ae2016-06-04 11:46:33 -06003205 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06003206 TAttributeMap attributes;
3207 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003208
John Kessenich21472ae2016-06-04 11:46:33 -06003209 // attributed_statement
3210 switch (peek()) {
3211 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06003212 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06003213
John Kessenich21472ae2016-06-04 11:46:33 -06003214 case EHTokIf:
Rex Xu57e65922017-07-04 23:23:40 +08003215 return acceptSelectionStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003216
John Kessenich21472ae2016-06-04 11:46:33 -06003217 case EHTokSwitch:
Rex Xu57e65922017-07-04 23:23:40 +08003218 return acceptSwitchStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003219
John Kessenich21472ae2016-06-04 11:46:33 -06003220 case EHTokFor:
3221 case EHTokDo:
3222 case EHTokWhile:
steve-lunargf1709e72017-05-02 20:14:50 -06003223 return acceptIterationStatement(statement, attributes);
John Kessenich21472ae2016-06-04 11:46:33 -06003224
3225 case EHTokContinue:
3226 case EHTokBreak:
3227 case EHTokDiscard:
3228 case EHTokReturn:
3229 return acceptJumpStatement(statement);
3230
3231 case EHTokCase:
3232 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003233 case EHTokDefault:
3234 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003235
John Kessenich21472ae2016-06-04 11:46:33 -06003236 case EHTokRightBrace:
3237 // Performance: not strictly necessary, but stops a bunch of hunting early,
3238 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06003239 return false;
3240
John Kessenich21472ae2016-06-04 11:46:33 -06003241 default:
John Kessenich0e071192017-06-06 11:37:33 -06003242 return acceptSimpleStatement(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003243 }
3244
John Kessenich5f934b02016-03-13 17:58:25 -06003245 return true;
John Kessenich87142c72016-03-12 20:24:24 -07003246}
3247
John Kessenich21472ae2016-06-04 11:46:33 -06003248// attributes
3249// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
3250//
3251// attribute:
3252// : UNROLL
3253// | UNROLL LEFT_PAREN literal RIGHT_PAREN
3254// | FASTOPT
3255// | ALLOW_UAV_CONDITION
3256// | BRANCH
3257// | FLATTEN
3258// | FORCECASE
3259// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06003260// | DOMAIN
3261// | EARLYDEPTHSTENCIL
3262// | INSTANCE
3263// | MAXTESSFACTOR
3264// | OUTPUTCONTROLPOINTS
3265// | OUTPUTTOPOLOGY
3266// | PARTITIONING
3267// | PATCHCONSTANTFUNC
3268// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06003269//
steve-lunarg1868b142016-10-20 13:07:10 -06003270void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003271{
steve-lunarg1868b142016-10-20 13:07:10 -06003272 // For now, accept the [ XXX(X) ] syntax, but drop all but
3273 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06003274 // TODO: subset to correct set? Pass on?
3275 do {
steve-lunarg1868b142016-10-20 13:07:10 -06003276 HlslToken idToken;
3277
John Kessenich0d2b6de2016-06-05 11:23:11 -06003278 // LEFT_BRACKET?
3279 if (! acceptTokenClass(EHTokLeftBracket))
3280 return;
3281
3282 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06003283 if (acceptIdentifier(idToken)) {
3284 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06003285 } else if (! peekTokenClass(EHTokRightBracket)) {
3286 expected("identifier");
3287 advanceToken();
3288 }
3289
steve-lunarga22f7db2016-11-11 08:17:44 -07003290 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06003291
3292 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003293 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07003294 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06003295
John Kessenich0d2b6de2016-06-05 11:23:11 -06003296 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07003297 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07003298
steve-lunarga22f7db2016-11-11 08:17:44 -07003299 while (acceptAssignmentExpression(node)) {
3300 expectingExpression = false;
3301 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06003302 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07003303 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06003304 }
3305
steve-lunarga22f7db2016-11-11 08:17:44 -07003306 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06003307 if (! acceptTokenClass(EHTokRightParen))
3308 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07003309
3310 // Error for partial or missing expression
3311 if (expectingExpression || expressions->getSequence().empty())
3312 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06003313 }
3314
3315 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06003316 if (!acceptTokenClass(EHTokRightBracket)) {
3317 expected("]");
3318 return;
3319 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003320
steve-lunarg1868b142016-10-20 13:07:10 -06003321 // Add any values we found into the attribute map. This accepts
3322 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07003323 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003324 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06003325}
3326
John Kessenich0d2b6de2016-06-05 11:23:11 -06003327// selection_statement
3328// : IF LEFT_PAREN expression RIGHT_PAREN statement
3329// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
3330//
Rex Xu57e65922017-07-04 23:23:40 +08003331bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003332{
John Kessenich0d2b6de2016-06-05 11:23:11 -06003333 TSourceLoc loc = token.loc;
3334
Rex Xu57e65922017-07-04 23:23:40 +08003335 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3336
John Kessenich0d2b6de2016-06-05 11:23:11 -06003337 // IF
3338 if (! acceptTokenClass(EHTokIf))
3339 return false;
3340
3341 // so that something declared in the condition is scoped to the lifetimes
3342 // of the then-else statements
3343 parseContext.pushScope();
3344
3345 // LEFT_PAREN expression RIGHT_PAREN
3346 TIntermTyped* condition;
3347 if (! acceptParenExpression(condition))
3348 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003349 condition = parseContext.convertConditionalExpression(loc, condition);
3350 if (condition == nullptr)
3351 return false;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003352
3353 // create the child statements
3354 TIntermNodePair thenElse = { nullptr, nullptr };
3355
John Kessenichf6deacd2017-06-06 19:52:55 -06003356 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
3357
John Kessenich0d2b6de2016-06-05 11:23:11 -06003358 // then statement
3359 if (! acceptScopedStatement(thenElse.node1)) {
3360 expected("then statement");
3361 return false;
3362 }
3363
3364 // ELSE
3365 if (acceptTokenClass(EHTokElse)) {
3366 // else statement
3367 if (! acceptScopedStatement(thenElse.node2)) {
3368 expected("else statement");
3369 return false;
3370 }
3371 }
3372
3373 // Put the pieces together
Rex Xu57e65922017-07-04 23:23:40 +08003374 statement = intermediate.addSelection(condition, thenElse, loc, control);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003375 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003376 --parseContext.controlFlowNestingLevel;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003377
3378 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003379}
3380
John Kessenichd02dc5d2016-07-01 00:04:11 -06003381// switch_statement
3382// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
3383//
Rex Xu57e65922017-07-04 23:23:40 +08003384bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003385{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003386 // SWITCH
3387 TSourceLoc loc = token.loc;
Rex Xu57e65922017-07-04 23:23:40 +08003388
3389 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3390
John Kessenichd02dc5d2016-07-01 00:04:11 -06003391 if (! acceptTokenClass(EHTokSwitch))
3392 return false;
3393
3394 // LEFT_PAREN expression RIGHT_PAREN
3395 parseContext.pushScope();
3396 TIntermTyped* switchExpression;
3397 if (! acceptParenExpression(switchExpression)) {
3398 parseContext.popScope();
3399 return false;
3400 }
3401
3402 // compound_statement
3403 parseContext.pushSwitchSequence(new TIntermSequence);
John Kessenichf6deacd2017-06-06 19:52:55 -06003404
3405 ++parseContext.controlFlowNestingLevel;
John Kessenichd02dc5d2016-07-01 00:04:11 -06003406 bool statementOkay = acceptCompoundStatement(statement);
John Kessenichf6deacd2017-06-06 19:52:55 -06003407 --parseContext.controlFlowNestingLevel;
3408
John Kessenichd02dc5d2016-07-01 00:04:11 -06003409 if (statementOkay)
Rex Xu57e65922017-07-04 23:23:40 +08003410 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, control);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003411
3412 parseContext.popSwitchSequence();
3413 parseContext.popScope();
3414
3415 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003416}
3417
John Kessenich119f8f62016-06-05 15:44:07 -06003418// iteration_statement
3419// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3420// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3421// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3422//
3423// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
steve-lunargf1709e72017-05-02 20:14:50 -06003424bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003425{
John Kessenich119f8f62016-06-05 15:44:07 -06003426 TSourceLoc loc = token.loc;
3427 TIntermTyped* condition = nullptr;
3428
3429 EHlslTokenClass loop = peek();
3430 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3431
3432 // WHILE or DO or FOR
3433 advanceToken();
steve-lunargf1709e72017-05-02 20:14:50 -06003434
3435 const TLoopControl control = parseContext.handleLoopControl(attributes);
John Kessenich119f8f62016-06-05 15:44:07 -06003436
3437 switch (loop) {
3438 case EHTokWhile:
3439 // so that something declared in the condition is scoped to the lifetime
3440 // of the while sub-statement
John Kessenichf6deacd2017-06-06 19:52:55 -06003441 parseContext.pushScope(); // this only needs to work right if no errors
John Kessenich119f8f62016-06-05 15:44:07 -06003442 parseContext.nestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003443 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003444
3445 // LEFT_PAREN condition RIGHT_PAREN
3446 if (! acceptParenExpression(condition))
3447 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003448 condition = parseContext.convertConditionalExpression(loc, condition);
3449 if (condition == nullptr)
3450 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003451
3452 // statement
3453 if (! acceptScopedStatement(statement)) {
3454 expected("while sub-statement");
3455 return false;
3456 }
3457
3458 parseContext.unnestLooping();
3459 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003460 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003461
steve-lunargf1709e72017-05-02 20:14:50 -06003462 statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003463
3464 return true;
3465
3466 case EHTokDo:
John Kessenichf6deacd2017-06-06 19:52:55 -06003467 parseContext.nestLooping(); // this only needs to work right if no errors
3468 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003469
John Kessenich119f8f62016-06-05 15:44:07 -06003470 // statement
John Kessenich0c6f9362017-04-20 11:08:24 -06003471 if (! acceptScopedStatement(statement)) {
John Kessenich119f8f62016-06-05 15:44:07 -06003472 expected("do sub-statement");
3473 return false;
3474 }
3475
John Kessenich119f8f62016-06-05 15:44:07 -06003476 // WHILE
3477 if (! acceptTokenClass(EHTokWhile)) {
3478 expected("while");
3479 return false;
3480 }
3481
3482 // LEFT_PAREN condition RIGHT_PAREN
3483 TIntermTyped* condition;
3484 if (! acceptParenExpression(condition))
3485 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003486 condition = parseContext.convertConditionalExpression(loc, condition);
3487 if (condition == nullptr)
3488 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003489
3490 if (! acceptTokenClass(EHTokSemicolon))
3491 expected(";");
3492
3493 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003494 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003495
steve-lunargf1709e72017-05-02 20:14:50 -06003496 statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003497
3498 return true;
3499
3500 case EHTokFor:
3501 {
3502 // LEFT_PAREN
3503 if (! acceptTokenClass(EHTokLeftParen))
3504 expected("(");
3505
3506 // so that something declared in the condition is scoped to the lifetime
3507 // of the for sub-statement
3508 parseContext.pushScope();
3509
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003510 // initializer
3511 TIntermNode* initNode = nullptr;
John Kessenich0e071192017-06-06 11:37:33 -06003512 if (! acceptSimpleStatement(initNode))
3513 expected("for-loop initializer statement");
John Kessenich119f8f62016-06-05 15:44:07 -06003514
John Kessenichf6deacd2017-06-06 19:52:55 -06003515 parseContext.nestLooping(); // this only needs to work right if no errors
3516 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003517
3518 // condition SEMI_COLON
3519 acceptExpression(condition);
3520 if (! acceptTokenClass(EHTokSemicolon))
3521 expected(";");
John Kessenich7e997e22017-03-30 22:09:30 -06003522 if (condition != nullptr) {
3523 condition = parseContext.convertConditionalExpression(loc, condition);
3524 if (condition == nullptr)
3525 return false;
3526 }
John Kessenich119f8f62016-06-05 15:44:07 -06003527
3528 // iterator SEMI_COLON
3529 TIntermTyped* iterator = nullptr;
3530 acceptExpression(iterator);
3531 if (! acceptTokenClass(EHTokRightParen))
3532 expected(")");
3533
3534 // statement
3535 if (! acceptScopedStatement(statement)) {
3536 expected("for sub-statement");
3537 return false;
3538 }
3539
steve-lunargf1709e72017-05-02 20:14:50 -06003540 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003541
3542 parseContext.popScope();
3543 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003544 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003545
3546 return true;
3547 }
3548
3549 default:
3550 return false;
3551 }
John Kessenich21472ae2016-06-04 11:46:33 -06003552}
3553
3554// jump_statement
3555// : CONTINUE SEMICOLON
3556// | BREAK SEMICOLON
3557// | DISCARD SEMICOLON
3558// | RETURN SEMICOLON
3559// | RETURN expression SEMICOLON
3560//
3561bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3562{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003563 EHlslTokenClass jump = peek();
3564 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003565 case EHTokContinue:
3566 case EHTokBreak:
3567 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003568 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003569 advanceToken();
3570 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003571 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003572 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003573 return false;
3574 }
John Kessenich21472ae2016-06-04 11:46:33 -06003575
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003576 switch (jump) {
3577 case EHTokContinue:
3578 statement = intermediate.addBranch(EOpContinue, token.loc);
3579 break;
3580 case EHTokBreak:
3581 statement = intermediate.addBranch(EOpBreak, token.loc);
3582 break;
3583 case EHTokDiscard:
3584 statement = intermediate.addBranch(EOpKill, token.loc);
3585 break;
3586
3587 case EHTokReturn:
3588 {
3589 // expression
3590 TIntermTyped* node;
3591 if (acceptExpression(node)) {
3592 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003593 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003594 } else
3595 statement = intermediate.addBranch(EOpReturn, token.loc);
3596 break;
3597 }
3598
3599 default:
3600 assert(0);
3601 return false;
3602 }
3603
3604 // SEMICOLON
3605 if (! acceptTokenClass(EHTokSemicolon))
3606 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003607
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003608 return true;
3609}
John Kessenich21472ae2016-06-04 11:46:33 -06003610
John Kessenichd02dc5d2016-07-01 00:04:11 -06003611// case_label
3612// : CASE expression COLON
3613//
John Kessenich21472ae2016-06-04 11:46:33 -06003614bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3615{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003616 TSourceLoc loc = token.loc;
3617 if (! acceptTokenClass(EHTokCase))
3618 return false;
3619
3620 TIntermTyped* expression;
3621 if (! acceptExpression(expression)) {
3622 expected("case expression");
3623 return false;
3624 }
3625
3626 if (! acceptTokenClass(EHTokColon)) {
3627 expected(":");
3628 return false;
3629 }
3630
3631 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3632
3633 return true;
3634}
3635
3636// default_label
3637// : DEFAULT COLON
3638//
3639bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3640{
3641 TSourceLoc loc = token.loc;
3642 if (! acceptTokenClass(EHTokDefault))
3643 return false;
3644
3645 if (! acceptTokenClass(EHTokColon)) {
3646 expected(":");
3647 return false;
3648 }
3649
3650 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3651
3652 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003653}
3654
John Kessenich19b92ff2016-06-19 11:50:34 -06003655// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003656// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3657// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003658//
3659void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3660{
3661 arraySizes = nullptr;
3662
steve-lunarg7b211a32016-10-13 12:26:18 -06003663 // Early-out if there aren't any array dimensions
3664 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003665 return;
3666
steve-lunarg7b211a32016-10-13 12:26:18 -06003667 // If we get here, we have at least one array dimension. This will track the sizes we find.
John Kessenich19b92ff2016-06-19 11:50:34 -06003668 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003669
3670 // Collect each array dimension.
3671 while (acceptTokenClass(EHTokLeftBracket)) {
3672 TSourceLoc loc = token.loc;
3673 TIntermTyped* sizeExpr = nullptr;
3674
John Kessenich057df292017-03-06 18:18:37 -07003675 // Array sizing expression is optional. If omitted, array will be later sized by initializer list.
steve-lunarg7b211a32016-10-13 12:26:18 -06003676 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3677
3678 if (! acceptTokenClass(EHTokRightBracket)) {
3679 expected("]");
3680 return;
3681 }
3682
3683 if (hasArraySize) {
3684 TArraySize arraySize;
3685 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3686 arraySizes->addInnerSize(arraySize);
3687 } else {
3688 arraySizes->addInnerSize(0); // sized by initializers.
3689 }
steve-lunarg265c0612016-09-27 10:57:35 -06003690 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003691}
3692
John Kessenich630dd7d2016-06-12 23:52:12 -06003693// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003694// : COLON semantic // optional
3695// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3696// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003697// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003698// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003699//
John Kessenich854fe242017-03-02 14:30:59 -07003700// Return true if any tokens were accepted. That is,
3701// false can be returned on successfully recognizing nothing,
3702// not necessarily meaning bad syntax.
3703//
3704bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003705{
John Kessenich854fe242017-03-02 14:30:59 -07003706 bool found = false;
3707
John Kessenich630dd7d2016-06-12 23:52:12 -06003708 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003709 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003710 if (acceptTokenClass(EHTokColon)) {
John Kessenich854fe242017-03-02 14:30:59 -07003711 found = true;
John Kessenich630dd7d2016-06-12 23:52:12 -06003712 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003713 if (peekTokenClass(EHTokLayout))
3714 acceptLayoutQualifierList(qualifier);
3715 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003716 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003717 if (! acceptTokenClass(EHTokLeftParen)) {
3718 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003719 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003720 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003721 HlslToken locationToken;
3722 if (! acceptIdentifier(locationToken)) {
3723 expected("c[subcomponent][.component]");
John Kessenich854fe242017-03-02 14:30:59 -07003724 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003725 }
3726 HlslToken componentToken;
3727 if (acceptTokenClass(EHTokDot)) {
3728 if (! acceptIdentifier(componentToken)) {
3729 expected("component");
John Kessenich854fe242017-03-02 14:30:59 -07003730 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003731 }
3732 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003733 if (! acceptTokenClass(EHTokRightParen)) {
3734 expected(")");
3735 break;
3736 }
John Kessenich7735b942016-09-05 12:40:06 -06003737 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003738 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003739 expected("layout, semantic, packoffset, or register");
John Kessenich854fe242017-03-02 14:30:59 -07003740 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003741 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003742 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3743 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003744 if (! acceptTokenClass(EHTokLeftParen)) {
3745 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003746 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003747 }
John Kessenichb38f0712016-07-30 10:29:54 -06003748 HlslToken registerDesc; // for Type#
3749 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003750 if (! acceptIdentifier(registerDesc)) {
3751 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003752 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003753 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003754 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3755 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003756 // Then we didn't really see the registerDesc yet, it was
3757 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003758 profile = registerDesc;
3759 if (! acceptIdentifier(registerDesc)) {
3760 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003761 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003762 }
3763 }
John Kessenichb38f0712016-07-30 10:29:54 -06003764 int subComponent = 0;
3765 if (acceptTokenClass(EHTokLeftBracket)) {
3766 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3767 if (! peekTokenClass(EHTokIntConstant)) {
3768 expected("literal integer");
John Kessenich854fe242017-03-02 14:30:59 -07003769 return false;
John Kessenichb38f0712016-07-30 10:29:54 -06003770 }
3771 subComponent = token.i;
3772 advanceToken();
3773 if (! acceptTokenClass(EHTokRightBracket)) {
3774 expected("]");
3775 break;
3776 }
3777 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003778 // (COMMA SPACEN)opt
3779 HlslToken spaceDesc;
3780 if (acceptTokenClass(EHTokComma)) {
3781 if (! acceptIdentifier(spaceDesc)) {
3782 expected ("space identifier");
John Kessenich854fe242017-03-02 14:30:59 -07003783 return false;
John Kessenichcfd7ce82016-09-05 16:03:12 -06003784 }
3785 }
3786 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003787 if (! acceptTokenClass(EHTokRightParen)) {
3788 expected(")");
3789 break;
3790 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003791 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003792 } else {
3793 // semantic, in idToken.string
John Kessenich2dd643f2017-03-14 21:50:06 -06003794 TString semanticUpperCase = *idToken.string;
3795 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
3796 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
John Kessenich630dd7d2016-06-12 23:52:12 -06003797 }
John Kessenich854fe242017-03-02 14:30:59 -07003798 } else if (peekTokenClass(EHTokLeftAngle)) {
3799 found = true;
John Kessenicha1e2d492016-09-20 13:22:58 -06003800 acceptAnnotations(qualifier);
John Kessenich854fe242017-03-02 14:30:59 -07003801 } else
John Kessenich630dd7d2016-06-12 23:52:12 -06003802 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003803
John Kessenich630dd7d2016-06-12 23:52:12 -06003804 } while (true);
John Kessenich854fe242017-03-02 14:30:59 -07003805
3806 return found;
John Kessenich078d7f22016-03-14 10:02:11 -06003807}
3808
John Kessenichb16f7e62017-03-11 19:32:47 -07003809//
3810// Get the stream of tokens from the scanner, but skip all syntactic/semantic
3811// processing.
3812//
3813bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
3814{
3815 if (! peekTokenClass(EHTokLeftBrace))
3816 return false;
3817
3818 int braceCount = 0;
3819
3820 do {
3821 switch (peek()) {
3822 case EHTokLeftBrace:
3823 ++braceCount;
3824 break;
3825 case EHTokRightBrace:
3826 --braceCount;
3827 break;
3828 case EHTokNone:
3829 // End of input before balance { } is bad...
3830 return false;
3831 default:
3832 break;
3833 }
3834
3835 tokens.push_back(token);
3836 advanceToken();
3837 } while (braceCount > 0);
3838
3839 return true;
3840}
3841
John Kessenich0320d092017-06-13 22:22:52 -06003842// Return a string for just the types that can also be declared as an identifier.
3843const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const
3844{
3845 switch (tokenClass) {
3846 case EHTokSample: return "sample";
3847 case EHTokHalf: return "half";
3848 case EHTokHalf1x1: return "half1x1";
3849 case EHTokHalf1x2: return "half1x2";
3850 case EHTokHalf1x3: return "half1x3";
3851 case EHTokHalf1x4: return "half1x4";
3852 case EHTokHalf2x1: return "half2x1";
3853 case EHTokHalf2x2: return "half2x2";
3854 case EHTokHalf2x3: return "half2x3";
3855 case EHTokHalf2x4: return "half2x4";
3856 case EHTokHalf3x1: return "half3x1";
3857 case EHTokHalf3x2: return "half3x2";
3858 case EHTokHalf3x3: return "half3x3";
3859 case EHTokHalf3x4: return "half3x4";
3860 case EHTokHalf4x1: return "half4x1";
3861 case EHTokHalf4x2: return "half4x2";
3862 case EHTokHalf4x3: return "half4x3";
3863 case EHTokHalf4x4: return "half4x4";
3864 case EHTokBool: return "bool";
3865 case EHTokFloat: return "float";
3866 case EHTokDouble: return "double";
3867 case EHTokInt: return "int";
3868 case EHTokUint: return "uint";
3869 case EHTokMin16float: return "min16float";
3870 case EHTokMin10float: return "min10float";
3871 case EHTokMin16int: return "min16int";
3872 case EHTokMin12int: return "min12int";
3873 default:
3874 return nullptr;
3875 }
3876}
3877
John Kesseniche01a9bc2016-03-12 20:11:22 -07003878} // end namespace glslang