blob: c71ba165f02936f94e2b26a788f92a0bfe2ba52b [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
John Kessenich77ea30b2017-09-30 14:34:50 -0600298// : attributes attributed_declaration
299// | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
300//
301// attributed_declaration
LoopDawg4886f692016-06-29 10:58:58 -0600302// : sampler_declaration_dx9 post_decls SEMICOLON
John Kessenich054378d2017-06-19 15:13:26 -0600303// | fully_specified_type // for cbuffer/tbuffer
304// | fully_specified_type declarator_list SEMICOLON // for non cbuffer/tbuffer
John Kessenich630dd7d2016-06-12 23:52:12 -0600305// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600306// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600307// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700308//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600309// declarator_list
310// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600311//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600312// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600313// : identifier array_specifier post_decls
314// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600315// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600316//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600317// Parsing has to go pretty far in to know whether it's a variable, prototype, or
318// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600319// as above. (The 'identifier' in the first item in init_declarator list is the
320// same as 'identifier' for function declarations.)
321//
John Kessenichca71d942017-03-07 20:44:09 -0700322// This can generate more than one subtree, one per initializer or a function body.
323// All initializer subtrees are put in their own aggregate node, making one top-level
324// node for all the initializers. Each function created is a top-level node to grow
325// into the passed-in nodeList.
John Kessenichd016be12016-03-13 11:24:20 -0600326//
John Kessenichca71d942017-03-07 20:44:09 -0700327// If 'nodeList' is passed in as non-null, it must an aggregate to extend for
328// each top-level node the declaration creates. Otherwise, if only one top-level
329// node in generated here, that is want is returned in nodeList.
John Kessenich02467d82017-01-19 15:41:47 -0700330//
John Kessenichca71d942017-03-07 20:44:09 -0700331bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700332{
John Kessenich8f9fdc92017-03-30 16:22:26 -0600333 // NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
334 if (acceptTokenClass(EHTokNamespace)) {
335 HlslToken namespaceToken;
336 if (!acceptIdentifier(namespaceToken)) {
337 expected("namespace name");
338 return false;
339 }
340 parseContext.pushNamespace(*namespaceToken.string);
341 if (!acceptTokenClass(EHTokLeftBrace)) {
342 expected("{");
343 return false;
344 }
345 if (!acceptDeclarationList(nodeList)) {
346 expected("declaration list");
347 return false;
348 }
349 if (!acceptTokenClass(EHTokRightBrace)) {
350 expected("}");
351 return false;
352 }
353 parseContext.popNamespace();
354 return true;
355 }
356
John Kessenich54ee28f2017-03-11 14:13:00 -0700357 bool declarator_list = false; // true when processing comma separation
John Kessenichd016be12016-03-13 11:24:20 -0600358
steve-lunarg1868b142016-10-20 13:07:10 -0600359 // attributes
John Kessenich088d52b2017-03-11 17:55:28 -0700360 TFunctionDeclarator declarator;
361 acceptAttributes(declarator.attributes);
steve-lunarg1868b142016-10-20 13:07:10 -0600362
John Kessenich5e69ec62016-07-05 00:02:40 -0600363 // typedef
364 bool typedefDecl = acceptTokenClass(EHTokTypedef);
365
John Kesseniche82061d2016-09-27 14:38:57 -0600366 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600367
368 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600369 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
370 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
371 // HLSL shaders, this will have to be a master level switch
372 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
John Kessenichecba76f2017-01-06 00:34:48 -0700373 // For that reason, this line is commented out
John Kessenichca71d942017-03-07 20:44:09 -0700374 // if (acceptSamplerDeclarationDX9(declaredType))
375 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600376
John Kessenich2fcdd642017-06-19 15:41:11 -0600377 bool forbidDeclarators = (peekTokenClass(EHTokCBuffer) || peekTokenClass(EHTokTBuffer));
LoopDawg4886f692016-06-29 10:58:58 -0600378 // fully_specified_type
John Kessenich046bae02017-12-23 17:29:45 -0700379 if (! acceptFullySpecifiedType(declaredType, nodeList, declarator.attributes))
John Kessenich87142c72016-03-12 20:24:24 -0700380 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600381
John Kessenich2fcdd642017-06-19 15:41:11 -0600382 // cbuffer and tbuffer end with the closing '}'.
383 // No semicolon is included.
384 if (forbidDeclarators)
385 return true;
386
John Kessenich054378d2017-06-19 15:13:26 -0600387 // declarator_list
388 // : declarator
389 // : identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600390 HlslToken idToken;
John Kessenichca71d942017-03-07 20:44:09 -0700391 TIntermAggregate* initializers = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600392 while (acceptIdentifier(idToken)) {
John Kessenich9855bda2017-09-11 21:48:19 -0600393 TString *fullName = idToken.string;
John Kessenich8f9fdc92017-03-30 16:22:26 -0600394 if (parseContext.symbolTable.atGlobalLevel())
395 parseContext.getFullNamespaceName(fullName);
John Kessenich78388722017-03-08 18:53:51 -0700396 if (peekTokenClass(EHTokLeftParen)) {
397 // looks like function parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600398
John Kessenich78388722017-03-08 18:53:51 -0700399 // Potentially rename shader entry point function. No-op most of the time.
John Kessenich8f9fdc92017-03-30 16:22:26 -0600400 parseContext.renameShaderFunction(fullName);
steve-lunargf1e0c872016-10-31 15:13:43 -0600401
John Kessenich78388722017-03-08 18:53:51 -0700402 // function_parameters
John Kessenich8f9fdc92017-03-30 16:22:26 -0600403 declarator.function = new TFunction(fullName, declaredType);
John Kessenich088d52b2017-03-11 17:55:28 -0700404 if (!acceptFunctionParameters(*declarator.function)) {
John Kessenich78388722017-03-08 18:53:51 -0700405 expected("function parameter list");
406 return false;
407 }
408
John Kessenich630dd7d2016-06-12 23:52:12 -0600409 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -0700410 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600411
John Kessenichd5ed0b62016-07-04 17:32:45 -0600412 // compound_statement (function body definition) or just a prototype?
John Kessenich088d52b2017-03-11 17:55:28 -0700413 declarator.loc = token.loc;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600414 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich54ee28f2017-03-11 14:13:00 -0700415 if (declarator_list)
John Kessenichd5ed0b62016-07-04 17:32:45 -0600416 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600417 if (typedefDecl)
418 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenichb16f7e62017-03-11 19:32:47 -0700419 return acceptFunctionDefinition(declarator, nodeList, nullptr);
John Kessenich5e69ec62016-07-05 00:02:40 -0600420 } else {
421 if (typedefDecl)
422 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich088d52b2017-03-11 17:55:28 -0700423 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600424 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600425 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600426 // A variable declaration. Fix the storage qualifier if it's a global.
427 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
428 declaredType.getQualifier().storage = EvqUniform;
429
John Kessenichecba76f2017-01-06 00:34:48 -0700430 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600431 // the number of types can expand when arrayness is different.
432 TType variableType;
433 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600434
John Kesseniche82061d2016-09-27 14:38:57 -0600435 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600436 TArraySizes* arraySizes = nullptr;
437 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600438
John Kesseniche82061d2016-09-27 14:38:57 -0600439 // Fix arrayness in the variableType
440 if (declaredType.isImplicitlySizedArray()) {
441 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
442 // of different sizes, for this case sharing the shallow copy of arrayness
443 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
444 variableType.newArraySizes(declaredType.getArraySizes());
445 }
446 if (arraySizes || variableType.isArray()) {
447 // In the most general case, arrayness is potentially coming both from the
448 // declared type and from the variable: "int[] a[];" or just one or the other.
449 // Merge it all to the variableType, so all arrayness is part of the variableType.
450 parseContext.arrayDimMerge(variableType, arraySizes);
451 }
452
LoopDawg4886f692016-06-29 10:58:58 -0600453 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600454 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600455 if (! acceptSamplerState())
456 return false;
457 }
458
John Kessenichd5ed0b62016-07-04 17:32:45 -0600459 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600460 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600461
462 // EQUAL assignment_expression
463 TIntermTyped* expressionNode = nullptr;
464 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600465 if (typedefDecl)
466 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600467 if (! acceptAssignmentExpression(expressionNode)) {
468 expected("initializer");
469 return false;
470 }
471 }
472
John Kessenich6dbc0a72016-09-27 19:13:05 -0600473 // TODO: things scoped within an annotation need their own name space;
474 // TODO: strings are not yet handled.
475 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
476 if (typedefDecl)
John Kessenich8f9fdc92017-03-30 16:22:26 -0600477 parseContext.declareTypedef(idToken.loc, *fullName, variableType);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600478 else if (variableType.getBasicType() == EbtBlock) {
John Kessenich8116cfc2017-12-09 04:42:42 -0700479 if (expressionNode)
480 parseContext.error(idToken.loc, "buffer aliasing not yet supported", "block initializer", "");
steve-lunarga766b832017-04-25 09:30:28 -0600481 parseContext.declareBlock(idToken.loc, variableType, fullName,
482 variableType.isArray() ? &variableType.getArraySizes() : nullptr);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600483 parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
484 } else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700485 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600486 // this isn't really an individual variable, but a member of the $Global buffer
John Kessenich8f9fdc92017-03-30 16:22:26 -0600487 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600488 } else {
489 // Declare the variable and add any initializer code to the AST.
490 // The top-level node is always made into an aggregate, as that's
491 // historically how the AST has been.
John Kessenichca71d942017-03-07 20:44:09 -0700492 initializers = intermediate.growAggregate(initializers,
John Kessenich8f9fdc92017-03-30 16:22:26 -0600493 parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode),
John Kessenichca71d942017-03-07 20:44:09 -0700494 idToken.loc);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600495 }
496 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600497 }
John Kessenich5f934b02016-03-13 17:58:25 -0600498 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600499
John Kessenich054378d2017-06-19 15:13:26 -0600500 // COMMA
501 if (acceptTokenClass(EHTokComma))
John Kessenich54ee28f2017-03-11 14:13:00 -0700502 declarator_list = true;
John Kessenich2fcdd642017-06-19 15:41:11 -0600503 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600504
John Kessenichca71d942017-03-07 20:44:09 -0700505 // The top-level initializer node is a sequence.
506 if (initializers != nullptr)
507 initializers->setOperator(EOpSequence);
508
509 // Add the initializers' aggregate to the nodeList we were handed.
510 if (nodeList)
511 nodeList = intermediate.growAggregate(nodeList, initializers);
512 else
513 nodeList = initializers;
John Kessenich87142c72016-03-12 20:24:24 -0700514
John Kessenich2fcdd642017-06-19 15:41:11 -0600515 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600516 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich2fcdd642017-06-19 15:41:11 -0600517 // This may have been a false detection of what appeared to be a declaration, but
518 // was actually an assignment such as "float = 4", where "float" is an identifier.
519 // We put the token back to let further parsing happen for cases where that may
520 // happen. This errors on the side of caution, and mostly triggers the error.
John Kessenich13075c62017-04-11 09:51:32 -0600521 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700522 recedeToken();
John Kessenich13075c62017-04-11 09:51:32 -0600523 return false;
John Kessenich13075c62017-04-11 09:51:32 -0600524 } else {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700525 expected(";");
John Kessenich13075c62017-04-11 09:51:32 -0600526 return false;
527 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600528 }
John Kessenichecba76f2017-01-06 00:34:48 -0700529
John Kesseniche01a9bc2016-03-12 20:11:22 -0700530 return true;
531}
532
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600533// control_declaration
534// : fully_specified_type identifier EQUAL expression
535//
536bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
537{
538 node = nullptr;
John Kessenich046bae02017-12-23 17:29:45 -0700539 TAttributeMap attributes;
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600540
541 // fully_specified_type
542 TType type;
John Kessenich046bae02017-12-23 17:29:45 -0700543 if (! acceptFullySpecifiedType(type, attributes))
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600544 return false;
545
John Kessenich057df292017-03-06 18:18:37 -0700546 // filter out type casts
547 if (peekTokenClass(EHTokLeftParen)) {
548 recedeToken();
549 return false;
550 }
551
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600552 // identifier
553 HlslToken idToken;
554 if (! acceptIdentifier(idToken)) {
555 expected("identifier");
556 return false;
557 }
558
559 // EQUAL
560 TIntermTyped* expressionNode = nullptr;
561 if (! acceptTokenClass(EHTokAssign)) {
562 expected("=");
563 return false;
564 }
565
566 // expression
567 if (! acceptExpression(expressionNode)) {
568 expected("initializer");
569 return false;
570 }
571
John Kesseniche82061d2016-09-27 14:38:57 -0600572 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600573
574 return true;
575}
576
John Kessenich87142c72016-03-12 20:24:24 -0700577// fully_specified_type
578// : type_specifier
579// | type_qualifier type_specifier
580//
John Kessenich046bae02017-12-23 17:29:45 -0700581bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributeMap& attributes)
John Kessenich87142c72016-03-12 20:24:24 -0700582{
John Kessenich54ee28f2017-03-11 14:13:00 -0700583 TIntermNode* nodeList = nullptr;
John Kessenich046bae02017-12-23 17:29:45 -0700584 return acceptFullySpecifiedType(type, nodeList, attributes);
John Kessenich54ee28f2017-03-11 14:13:00 -0700585}
John Kessenich046bae02017-12-23 17:29:45 -0700586bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributeMap& attributes)
John Kessenich54ee28f2017-03-11 14:13:00 -0700587{
John Kessenich87142c72016-03-12 20:24:24 -0700588 // type_qualifier
589 TQualifier qualifier;
590 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600591 if (! acceptQualifier(qualifier))
592 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600593 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700594
595 // type_specifier
John Kessenich54ee28f2017-03-11 14:13:00 -0700596 if (! acceptType(type, nodeList)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -0700597 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700598 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700599 // qualifier. Back it out, if we did.
600 if (qualifier.sample)
601 recedeToken();
602
John Kessenich87142c72016-03-12 20:24:24 -0700603 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700604 }
John Kessenich046bae02017-12-23 17:29:45 -0700605
John Kessenich3d157c52016-07-25 16:05:33 -0600606 if (type.getBasicType() == EbtBlock) {
607 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600608 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich046bae02017-12-23 17:29:45 -0700609
610 // merge in the attributes
611 parseContext.transferTypeAttributes(attributes, type);
612
John Kessenich3d157c52016-07-25 16:05:33 -0600613 // further, it can create an anonymous instance of the block
John Kessenich13075c62017-04-11 09:51:32 -0600614 if (peek() != EHTokIdentifier)
John Kessenich3d157c52016-07-25 16:05:33 -0600615 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600616 } else {
617 // Some qualifiers are set when parsing the type. Merge those with
618 // whatever comes from acceptQualifier.
619 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700620
steve-lunargbb0183f2016-10-04 16:58:14 -0600621 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600622 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700623
steve-lunarg08e0c082017-03-29 20:01:13 -0600624 if (type.getQualifier().storage == EvqOut ||
steve-lunarg5da1f032017-02-12 17:50:28 -0700625 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700626 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700627 qualifier.readonly = type.getQualifier().readonly;
628 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700629
John Kessenichecd08bc2017-08-07 23:40:05 -0600630 if (type.isBuiltIn())
steve-lunarg08e0c082017-03-29 20:01:13 -0600631 qualifier.builtIn = type.getQualifier().builtIn;
632
John Kessenich046bae02017-12-23 17:29:45 -0700633 type.getQualifier() = qualifier;
634
635 // merge in the attributes
636 parseContext.transferTypeAttributes(attributes, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600637 }
John Kessenich87142c72016-03-12 20:24:24 -0700638
639 return true;
640}
641
John Kessenich630dd7d2016-06-12 23:52:12 -0600642// type_qualifier
643// : qualifier qualifier ...
644//
645// Zero or more of these, so this can't return false.
646//
John Kessenichb9e39122016-08-17 10:22:08 -0600647bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700648{
John Kessenich630dd7d2016-06-12 23:52:12 -0600649 do {
650 switch (peek()) {
651 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600652 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600653 break;
654 case EHTokExtern:
655 // TODO: no meaning in glslang?
656 break;
657 case EHTokShared:
658 // TODO: hint
659 break;
660 case EHTokGroupShared:
661 qualifier.storage = EvqShared;
662 break;
663 case EHTokUniform:
664 qualifier.storage = EvqUniform;
665 break;
666 case EHTokConst:
667 qualifier.storage = EvqConst;
668 break;
669 case EHTokVolatile:
670 qualifier.volatil = true;
671 break;
672 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600673 qualifier.smooth = true;
674 break;
675 case EHTokCentroid:
676 qualifier.centroid = true;
677 break;
678 case EHTokNointerpolation:
679 qualifier.flat = true;
680 break;
681 case EHTokNoperspective:
682 qualifier.nopersp = true;
683 break;
684 case EHTokSample:
685 qualifier.sample = true;
686 break;
687 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600688 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600689 break;
690 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600691 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600692 break;
693 case EHTokPrecise:
694 qualifier.noContraction = true;
695 break;
LoopDawg9249c702016-07-12 20:44:32 -0600696 case EHTokIn:
xavierb1d97532017-06-20 07:49:22 +0200697 qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn;
LoopDawg9249c702016-07-12 20:44:32 -0600698 break;
699 case EHTokOut:
xavierb1d97532017-06-20 07:49:22 +0200700 qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut;
LoopDawg9249c702016-07-12 20:44:32 -0600701 break;
702 case EHTokInOut:
703 qualifier.storage = EvqInOut;
704 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600705 case EHTokLayout:
706 if (! acceptLayoutQualifierList(qualifier))
707 return false;
708 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700709 case EHTokGloballyCoherent:
710 qualifier.coherent = true;
711 break;
John Kessenich36b218d2017-03-15 09:05:14 -0600712 case EHTokInline:
713 // TODO: map this to SPIR-V function control
714 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700715
716 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
717 // for output variables.
718 case EHTokPoint:
719 qualifier.storage = EvqIn;
720 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
721 return false;
722 break;
723 case EHTokLine:
724 qualifier.storage = EvqIn;
725 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
726 return false;
727 break;
728 case EHTokTriangle:
729 qualifier.storage = EvqIn;
730 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
731 return false;
732 break;
733 case EHTokLineAdj:
734 qualifier.storage = EvqIn;
735 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
736 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700737 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700738 case EHTokTriangleAdj:
739 qualifier.storage = EvqIn;
740 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
741 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700742 break;
743
John Kessenich630dd7d2016-06-12 23:52:12 -0600744 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600745 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600746 }
747 advanceToken();
748 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700749}
750
John Kessenichb9e39122016-08-17 10:22:08 -0600751// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600752// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600753//
754// layout_qualifier
755// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600756// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600757//
758// Zero or more of these, so this can't return false.
759//
760bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
761{
762 if (! acceptTokenClass(EHTokLayout))
763 return false;
764
765 // LEFT_PAREN
766 if (! acceptTokenClass(EHTokLeftParen))
767 return false;
768
769 do {
770 // identifier
771 HlslToken idToken;
772 if (! acceptIdentifier(idToken))
773 break;
774
775 // EQUAL expression
776 if (acceptTokenClass(EHTokAssign)) {
777 TIntermTyped* expr;
778 if (! acceptConditionalExpression(expr)) {
779 expected("expression");
780 return false;
781 }
782 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
783 } else
784 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
785
786 // COMMA
787 if (! acceptTokenClass(EHTokComma))
788 break;
789 } while (true);
790
791 // RIGHT_PAREN
792 if (! acceptTokenClass(EHTokRightParen)) {
793 expected(")");
794 return false;
795 }
796
797 return true;
798}
799
LoopDawg6daaa4f2016-06-23 19:13:48 -0600800// template_type
801// : FLOAT
802// | DOUBLE
803// | INT
804// | DWORD
805// | UINT
806// | BOOL
807//
steve-lunargf49cdf42016-11-17 15:04:20 -0700808bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600809{
810 switch (peek()) {
811 case EHTokFloat:
812 basicType = EbtFloat;
813 break;
814 case EHTokDouble:
815 basicType = EbtDouble;
816 break;
817 case EHTokInt:
818 case EHTokDword:
819 basicType = EbtInt;
820 break;
821 case EHTokUint:
822 basicType = EbtUint;
823 break;
824 case EHTokBool:
825 basicType = EbtBool;
826 break;
827 default:
828 return false;
829 }
830
831 advanceToken();
832
833 return true;
834}
835
836// vector_template_type
837// : VECTOR
838// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
839//
840bool HlslGrammar::acceptVectorTemplateType(TType& type)
841{
842 if (! acceptTokenClass(EHTokVector))
843 return false;
844
845 if (! acceptTokenClass(EHTokLeftAngle)) {
846 // in HLSL, 'vector' alone means float4.
847 new(&type) TType(EbtFloat, EvqTemporary, 4);
848 return true;
849 }
850
851 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700852 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600853 expected("scalar type");
854 return false;
855 }
856
857 // COMMA
858 if (! acceptTokenClass(EHTokComma)) {
859 expected(",");
860 return false;
861 }
862
863 // integer
864 if (! peekTokenClass(EHTokIntConstant)) {
865 expected("literal integer");
866 return false;
867 }
868
869 TIntermTyped* vecSize;
870 if (! acceptLiteral(vecSize))
871 return false;
872
873 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
874
875 new(&type) TType(basicType, EvqTemporary, vecSizeI);
876
877 if (vecSizeI == 1)
878 type.makeVector();
879
880 if (!acceptTokenClass(EHTokRightAngle)) {
881 expected("right angle bracket");
882 return false;
883 }
884
885 return true;
886}
887
888// matrix_template_type
889// : MATRIX
890// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
891//
892bool HlslGrammar::acceptMatrixTemplateType(TType& type)
893{
894 if (! acceptTokenClass(EHTokMatrix))
895 return false;
896
897 if (! acceptTokenClass(EHTokLeftAngle)) {
898 // in HLSL, 'matrix' alone means float4x4.
899 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
900 return true;
901 }
902
903 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700904 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600905 expected("scalar type");
906 return false;
907 }
908
909 // COMMA
910 if (! acceptTokenClass(EHTokComma)) {
911 expected(",");
912 return false;
913 }
914
915 // integer rows
916 if (! peekTokenClass(EHTokIntConstant)) {
917 expected("literal integer");
918 return false;
919 }
920
921 TIntermTyped* rows;
922 if (! acceptLiteral(rows))
923 return false;
924
925 // COMMA
926 if (! acceptTokenClass(EHTokComma)) {
927 expected(",");
928 return false;
929 }
John Kessenichecba76f2017-01-06 00:34:48 -0700930
LoopDawg6daaa4f2016-06-23 19:13:48 -0600931 // integer cols
932 if (! peekTokenClass(EHTokIntConstant)) {
933 expected("literal integer");
934 return false;
935 }
936
937 TIntermTyped* cols;
938 if (! acceptLiteral(cols))
939 return false;
940
941 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600942 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
943 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600944
945 if (!acceptTokenClass(EHTokRightAngle)) {
946 expected("right angle bracket");
947 return false;
948 }
949
950 return true;
951}
952
steve-lunargf49cdf42016-11-17 15:04:20 -0700953// layout_geometry
954// : LINESTREAM
955// | POINTSTREAM
956// | TRIANGLESTREAM
957//
958bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
959{
960 // read geometry type
961 const EHlslTokenClass geometryType = peek();
962
963 switch (geometryType) {
964 case EHTokPointStream: geometry = ElgPoints; break;
965 case EHTokLineStream: geometry = ElgLineStrip; break;
966 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
967 default:
968 return false; // not a layout geometry
969 }
970
971 advanceToken(); // consume the layout keyword
972 return true;
973}
974
steve-lunarg858c9282017-01-07 08:54:10 -0700975// tessellation_decl_type
976// : INPUTPATCH
977// | OUTPUTPATCH
978//
steve-lunarg067eb9b2017-04-01 15:34:48 -0600979bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType)
steve-lunarg858c9282017-01-07 08:54:10 -0700980{
981 // read geometry type
982 const EHlslTokenClass tessType = peek();
983
984 switch (tessType) {
steve-lunarg067eb9b2017-04-01 15:34:48 -0600985 case EHTokInputPatch: patchType = EbvInputPatch; break;
986 case EHTokOutputPatch: patchType = EbvOutputPatch; break;
steve-lunarg858c9282017-01-07 08:54:10 -0700987 default:
988 return false; // not a tessellation decl
989 }
990
991 advanceToken(); // consume the keyword
992 return true;
993}
994
995// tessellation_patch_template_type
996// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
997//
998bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
999{
steve-lunarg067eb9b2017-04-01 15:34:48 -06001000 TBuiltInVariable patchType;
1001
1002 if (! acceptTessellationDeclType(patchType))
steve-lunarg858c9282017-01-07 08:54:10 -07001003 return false;
1004
1005 if (! acceptTokenClass(EHTokLeftAngle))
1006 return false;
1007
1008 if (! acceptType(type)) {
1009 expected("tessellation patch type");
1010 return false;
1011 }
1012
1013 if (! acceptTokenClass(EHTokComma))
1014 return false;
1015
1016 // integer size
1017 if (! peekTokenClass(EHTokIntConstant)) {
1018 expected("literal integer");
1019 return false;
1020 }
1021
1022 TIntermTyped* size;
1023 if (! acceptLiteral(size))
1024 return false;
1025
1026 TArraySizes* arraySizes = new TArraySizes;
1027 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
1028 type.newArraySizes(*arraySizes);
steve-lunarg067eb9b2017-04-01 15:34:48 -06001029 type.getQualifier().builtIn = patchType;
steve-lunarg858c9282017-01-07 08:54:10 -07001030
1031 if (! acceptTokenClass(EHTokRightAngle)) {
1032 expected("right angle bracket");
1033 return false;
1034 }
1035
1036 return true;
1037}
1038
steve-lunargf49cdf42016-11-17 15:04:20 -07001039// stream_out_template_type
1040// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
1041//
1042bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
1043{
1044 geometry = ElgNone;
1045
1046 if (! acceptOutputPrimitiveGeometry(geometry))
1047 return false;
1048
1049 if (! acceptTokenClass(EHTokLeftAngle))
1050 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001051
steve-lunargf49cdf42016-11-17 15:04:20 -07001052 if (! acceptType(type)) {
1053 expected("stream output type");
1054 return false;
1055 }
1056
steve-lunarg08e0c082017-03-29 20:01:13 -06001057 type.getQualifier().storage = EvqOut;
1058 type.getQualifier().builtIn = EbvGsOutputStream;
steve-lunargf49cdf42016-11-17 15:04:20 -07001059
1060 if (! acceptTokenClass(EHTokRightAngle)) {
1061 expected("right angle bracket");
1062 return false;
1063 }
1064
1065 return true;
1066}
John Kessenichecba76f2017-01-06 00:34:48 -07001067
John Kessenicha1e2d492016-09-20 13:22:58 -06001068// annotations
1069// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -06001070//
John Kessenicha1e2d492016-09-20 13:22:58 -06001071bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -06001072{
John Kessenicha1e2d492016-09-20 13:22:58 -06001073 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -06001074 return false;
1075
John Kessenicha1e2d492016-09-20 13:22:58 -06001076 // note that we are nesting a name space
1077 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -06001078
1079 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1080 do {
1081 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
1082 while (acceptTokenClass(EHTokSemicolon))
1083 ;
1084
1085 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -06001086 break;
John Kessenich86f71382016-09-19 20:23:18 -06001087
1088 // declaration
John Kessenichca71d942017-03-07 20:44:09 -07001089 TIntermNode* node = nullptr;
John Kessenich86f71382016-09-19 20:23:18 -06001090 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -06001091 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -06001092 return false;
1093 }
1094 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -06001095
1096 parseContext.unnestAnnotations();
1097 return true;
John Kessenich86f71382016-09-19 20:23:18 -06001098}
LoopDawg6daaa4f2016-06-23 19:13:48 -06001099
LoopDawg7f93d562017-09-27 09:04:43 -06001100// subpass input type
1101// : SUBPASSINPUT
1102// | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1103// | SUBPASSINPUTMS
1104// | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1105bool HlslGrammar::acceptSubpassInputType(TType& type)
1106{
1107 // read subpass type
1108 const EHlslTokenClass subpassInputType = peek();
1109
1110 bool multisample;
1111
1112 switch (subpassInputType) {
1113 case EHTokSubpassInput: multisample = false; break;
1114 case EHTokSubpassInputMS: multisample = true; break;
1115 default:
1116 return false; // not a subpass input declaration
1117 }
1118
1119 advanceToken(); // consume the sampler type keyword
1120
1121 TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4
1122
1123 if (acceptTokenClass(EHTokLeftAngle)) {
1124 if (! acceptType(subpassType)) {
1125 expected("scalar or vector type");
1126 return false;
1127 }
1128
1129 const TBasicType basicRetType = subpassType.getBasicType() ;
1130
1131 switch (basicRetType) {
1132 case EbtFloat:
1133 case EbtUint:
1134 case EbtInt:
1135 case EbtStruct:
1136 break;
1137 default:
1138 unimplemented("basic type in subpass input");
1139 return false;
1140 }
1141
1142 if (! acceptTokenClass(EHTokRightAngle)) {
1143 expected("right angle bracket");
1144 return false;
1145 }
1146 }
1147
1148 const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType()
1149 : subpassType.getBasicType();
1150
1151 TSampler sampler;
1152 sampler.setSubpass(subpassBasicType, multisample);
1153
1154 // Remember the declared return type. Function returns false on error.
1155 if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc))
1156 return false;
1157
1158 type.shallowCopy(TType(sampler, EvqUniform));
1159
1160 return true;
1161}
1162
LoopDawg4886f692016-06-29 10:58:58 -06001163// sampler_type
1164// : SAMPLER
1165// | SAMPLER1D
1166// | SAMPLER2D
1167// | SAMPLER3D
1168// | SAMPLERCUBE
1169// | SAMPLERSTATE
1170// | SAMPLERCOMPARISONSTATE
1171bool HlslGrammar::acceptSamplerType(TType& type)
1172{
1173 // read sampler type
1174 const EHlslTokenClass samplerType = peek();
1175
LoopDawga78b0292016-07-19 14:28:05 -06001176 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001177 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001178
LoopDawga78b0292016-07-19 14:28:05 -06001179 bool isShadow = false;
1180
LoopDawg4886f692016-06-29 10:58:58 -06001181 switch (samplerType) {
1182 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001183 case EHTokSampler1d: /*dim = Esd1D*/; break;
1184 case EHTokSampler2d: /*dim = Esd2D*/; break;
1185 case EHTokSampler3d: /*dim = Esd3D*/; break;
1186 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001187 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001188 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001189 default:
1190 return false; // not a sampler declaration
1191 }
1192
1193 advanceToken(); // consume the sampler type keyword
1194
1195 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001196
1197 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001198 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001199
1200 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1201
1202 return true;
1203}
1204
1205// texture_type
1206// | BUFFER
1207// | TEXTURE1D
1208// | TEXTURE1DARRAY
1209// | TEXTURE2D
1210// | TEXTURE2DARRAY
1211// | TEXTURE3D
1212// | TEXTURECUBE
1213// | TEXTURECUBEARRAY
1214// | TEXTURE2DMS
1215// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001216// | RWBUFFER
1217// | RWTEXTURE1D
1218// | RWTEXTURE1DARRAY
1219// | RWTEXTURE2D
1220// | RWTEXTURE2DARRAY
1221// | RWTEXTURE3D
1222
LoopDawg4886f692016-06-29 10:58:58 -06001223bool HlslGrammar::acceptTextureType(TType& type)
1224{
1225 const EHlslTokenClass textureType = peek();
1226
1227 TSamplerDim dim = EsdNone;
1228 bool array = false;
1229 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001230 bool image = false;
steve-lunargbf1537f2017-03-31 17:40:09 -06001231 bool combined = true;
LoopDawg4886f692016-06-29 10:58:58 -06001232
1233 switch (textureType) {
steve-lunargbf1537f2017-03-31 17:40:09 -06001234 case EHTokBuffer: dim = EsdBuffer; combined = false; break;
John Kessenichf36542f2017-03-31 14:39:30 -06001235 case EHTokTexture1d: dim = Esd1D; break;
1236 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1237 case EHTokTexture2d: dim = Esd2D; break;
1238 case EHTokTexture2darray: dim = Esd2D; array = true; break;
1239 case EHTokTexture3d: dim = Esd3D; break;
1240 case EHTokTextureCube: dim = EsdCube; break;
1241 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1242 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1243 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
1244 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1245 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1246 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1247 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1248 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1249 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001250 default:
1251 return false; // not a texture declaration
1252 }
1253
1254 advanceToken(); // consume the texture object keyword
1255
1256 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001257
LoopDawg4886f692016-06-29 10:58:58 -06001258 TIntermTyped* msCount = nullptr;
1259
steve-lunargbb0183f2016-10-04 16:58:14 -06001260 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001261 if (acceptTokenClass(EHTokLeftAngle)) {
1262 if (! acceptType(txType)) {
1263 expected("scalar or vector type");
1264 return false;
1265 }
1266
1267 const TBasicType basicRetType = txType.getBasicType() ;
1268
LoopDawg5ee05892017-07-31 13:41:42 -06001269 switch (basicRetType) {
1270 case EbtFloat:
1271 case EbtUint:
1272 case EbtInt:
1273 case EbtStruct:
1274 break;
1275 default:
LoopDawg4886f692016-06-29 10:58:58 -06001276 unimplemented("basic type in texture");
1277 return false;
1278 }
1279
steve-lunargd53f7172016-07-27 15:46:48 -06001280 // Buffers can handle small mats if they fit in 4 components
1281 if (dim == EsdBuffer && txType.isMatrix()) {
1282 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1283 expected("components < 4 in matrix buffer type");
1284 return false;
1285 }
1286
1287 // TODO: except we don't handle it yet...
1288 unimplemented("matrix type in buffer");
1289 return false;
1290 }
1291
LoopDawg5ee05892017-07-31 13:41:42 -06001292 if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) {
1293 expected("scalar, vector, or struct type");
LoopDawg4886f692016-06-29 10:58:58 -06001294 return false;
1295 }
1296
LoopDawg4886f692016-06-29 10:58:58 -06001297 if (ms && acceptTokenClass(EHTokComma)) {
1298 // read sample count for multisample types, if given
1299 if (! peekTokenClass(EHTokIntConstant)) {
1300 expected("multisample count");
1301 return false;
1302 }
1303
1304 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1305 return false;
1306 }
1307
1308 if (! acceptTokenClass(EHTokRightAngle)) {
1309 expected("right angle bracket");
1310 return false;
1311 }
1312 } else if (ms) {
1313 expected("texture type for multisample");
1314 return false;
John Kessenichf36542f2017-03-31 14:39:30 -06001315 } else if (image) {
steve-lunargbb0183f2016-10-04 16:58:14 -06001316 expected("type for RWTexture/RWBuffer");
1317 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001318 }
1319
1320 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001321 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001322
1323 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001324 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001325
steve-lunarg4f2da272016-10-10 15:24:57 -06001326 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1327 if (image || dim == EsdBuffer)
1328 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001329
LoopDawg5ee05892017-07-31 13:41:42 -06001330 const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType()
1331 : txType.getBasicType();
1332
steve-lunargbb0183f2016-10-04 16:58:14 -06001333 // Non-image Buffers are combined
1334 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001335 sampler.set(txType.getBasicType(), dim, array);
1336 } else {
1337 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001338 if (image) {
LoopDawg5ee05892017-07-31 13:41:42 -06001339 sampler.setImage(txBasicType, dim, array, shadow, ms);
steve-lunargbb0183f2016-10-04 16:58:14 -06001340 } else {
LoopDawg5ee05892017-07-31 13:41:42 -06001341 sampler.setTexture(txBasicType, dim, array, shadow, ms);
steve-lunargbb0183f2016-10-04 16:58:14 -06001342 }
steve-lunargd53f7172016-07-27 15:46:48 -06001343 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001344
LoopDawg5ee05892017-07-31 13:41:42 -06001345 // Remember the declared return type. Function returns false on error.
1346 if (!parseContext.setTextureReturnType(sampler, txType, token.loc))
1347 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001348
steve-lunargbf1537f2017-03-31 17:40:09 -06001349 // Force uncombined, if necessary
1350 if (!combined)
1351 sampler.combined = false;
1352
LoopDawg4886f692016-06-29 10:58:58 -06001353 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001354 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001355
1356 return true;
1357}
1358
John Kessenich87142c72016-03-12 20:24:24 -07001359// If token is for a type, update 'type' with the type information,
1360// and return true and advance.
1361// Otherwise, return false, and don't advance
1362bool HlslGrammar::acceptType(TType& type)
1363{
John Kessenich54ee28f2017-03-11 14:13:00 -07001364 TIntermNode* nodeList = nullptr;
1365 return acceptType(type, nodeList);
1366}
1367bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
1368{
steve-lunarg3226b082016-10-26 19:18:55 -06001369 // Basic types for min* types, broken out here in case of future
1370 // changes, e.g, to use native halfs.
1371 static const TBasicType min16float_bt = EbtFloat;
1372 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001373 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001374 static const TBasicType min16int_bt = EbtInt;
1375 static const TBasicType min12int_bt = EbtInt;
1376 static const TBasicType min16uint_bt = EbtUint;
1377
John Kessenich0320d092017-06-13 22:22:52 -06001378 // Some types might have turned into identifiers. Take the hit for checking
1379 // when this has happened.
1380 if (typeIdentifiers) {
1381 const char* identifierString = getTypeString(peek());
1382 if (identifierString != nullptr) {
1383 TString name = identifierString;
1384 // if it's an identifier, it's not a type
1385 if (parseContext.symbolTable.find(name) != nullptr)
1386 return false;
1387 }
1388 }
1389
LoopDawgfa39cff2017-11-14 14:55:40 -07001390 bool isUnorm = false;
1391 bool isSnorm = false;
1392
1393 // Accept snorm and unorm. Presently, this is ignored, save for an error check below.
1394 switch (peek()) {
1395 case EHTokUnorm:
1396 isUnorm = true;
1397 advanceToken(); // eat the token
1398 break;
1399 case EHTokSNorm:
1400 isSnorm = true;
1401 advanceToken(); // eat the token
1402 break;
1403 default:
1404 break;
1405 }
1406
John Kessenich9c86c6a2016-05-03 22:49:24 -06001407 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001408 case EHTokVector:
1409 return acceptVectorTemplateType(type);
1410 break;
1411
1412 case EHTokMatrix:
1413 return acceptMatrixTemplateType(type);
1414 break;
1415
steve-lunargf49cdf42016-11-17 15:04:20 -07001416 case EHTokPointStream: // fall through
1417 case EHTokLineStream: // ...
1418 case EHTokTriangleStream: // ...
1419 {
1420 TLayoutGeometry geometry;
1421 if (! acceptStreamOutTemplateType(type, geometry))
1422 return false;
1423
1424 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1425 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001426
steve-lunargf49cdf42016-11-17 15:04:20 -07001427 return true;
1428 }
1429
steve-lunarg858c9282017-01-07 08:54:10 -07001430 case EHTokInputPatch: // fall through
1431 case EHTokOutputPatch: // ...
1432 {
1433 if (! acceptTessellationPatchTemplateType(type))
1434 return false;
1435
1436 return true;
1437 }
1438
LoopDawg4886f692016-06-29 10:58:58 -06001439 case EHTokSampler: // fall through
1440 case EHTokSampler1d: // ...
1441 case EHTokSampler2d: // ...
1442 case EHTokSampler3d: // ...
1443 case EHTokSamplerCube: // ...
1444 case EHTokSamplerState: // ...
1445 case EHTokSamplerComparisonState: // ...
1446 return acceptSamplerType(type);
1447 break;
1448
LoopDawg7f93d562017-09-27 09:04:43 -06001449 case EHTokSubpassInput: // fall through
1450 case EHTokSubpassInputMS: // ...
1451 return acceptSubpassInputType(type);
1452 break;
1453
LoopDawg4886f692016-06-29 10:58:58 -06001454 case EHTokBuffer: // fall through
1455 case EHTokTexture1d: // ...
1456 case EHTokTexture1darray: // ...
1457 case EHTokTexture2d: // ...
1458 case EHTokTexture2darray: // ...
1459 case EHTokTexture3d: // ...
1460 case EHTokTextureCube: // ...
1461 case EHTokTextureCubearray: // ...
1462 case EHTokTexture2DMS: // ...
1463 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001464 case EHTokRWTexture1d: // ...
1465 case EHTokRWTexture1darray: // ...
1466 case EHTokRWTexture2d: // ...
1467 case EHTokRWTexture2darray: // ...
1468 case EHTokRWTexture3d: // ...
1469 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001470 return acceptTextureType(type);
1471 break;
1472
steve-lunarg5da1f032017-02-12 17:50:28 -07001473 case EHTokAppendStructuredBuffer:
1474 case EHTokByteAddressBuffer:
1475 case EHTokConsumeStructuredBuffer:
1476 case EHTokRWByteAddressBuffer:
1477 case EHTokRWStructuredBuffer:
1478 case EHTokStructuredBuffer:
1479 return acceptStructBufferType(type);
1480 break;
1481
LoopDawge5530b92017-11-08 19:48:11 -07001482 case EHTokTextureBuffer:
1483 return acceptTextureBufferType(type);
1484 break;
1485
steve-lunarga766b832017-04-25 09:30:28 -06001486 case EHTokConstantBuffer:
1487 return acceptConstantBufferType(type);
1488
John Kessenich27ffb292017-03-03 17:01:01 -07001489 case EHTokClass:
John Kesseniche6e74942016-06-11 16:43:14 -06001490 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001491 case EHTokCBuffer:
1492 case EHTokTBuffer:
John Kessenich54ee28f2017-03-11 14:13:00 -07001493 return acceptStruct(type, nodeList);
John Kesseniche6e74942016-06-11 16:43:14 -06001494
1495 case EHTokIdentifier:
1496 // An identifier could be for a user-defined type.
1497 // Note we cache the symbol table lookup, to save for a later rule
1498 // when this is not a type.
John Kessenichf4ba25e2017-03-21 18:35:04 -06001499 if (parseContext.lookupUserType(*token.string, type) != nullptr) {
John Kesseniche6e74942016-06-11 16:43:14 -06001500 advanceToken();
1501 return true;
1502 } else
1503 return false;
1504
John Kessenich71351de2016-06-08 12:50:56 -06001505 case EHTokVoid:
1506 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001507 break;
John Kessenich71351de2016-06-08 12:50:56 -06001508
John Kessenicha1e2d492016-09-20 13:22:58 -06001509 case EHTokString:
1510 new(&type) TType(EbtString);
1511 break;
1512
John Kessenich87142c72016-03-12 20:24:24 -07001513 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001514 new(&type) TType(EbtFloat);
1515 break;
John Kessenich87142c72016-03-12 20:24:24 -07001516 case EHTokFloat1:
1517 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001518 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001519 break;
John Kessenich87142c72016-03-12 20:24:24 -07001520 case EHTokFloat2:
1521 new(&type) TType(EbtFloat, EvqTemporary, 2);
1522 break;
1523 case EHTokFloat3:
1524 new(&type) TType(EbtFloat, EvqTemporary, 3);
1525 break;
1526 case EHTokFloat4:
1527 new(&type) TType(EbtFloat, EvqTemporary, 4);
1528 break;
1529
John Kessenich71351de2016-06-08 12:50:56 -06001530 case EHTokDouble:
1531 new(&type) TType(EbtDouble);
1532 break;
1533 case EHTokDouble1:
1534 new(&type) TType(EbtDouble);
1535 type.makeVector();
1536 break;
1537 case EHTokDouble2:
1538 new(&type) TType(EbtDouble, EvqTemporary, 2);
1539 break;
1540 case EHTokDouble3:
1541 new(&type) TType(EbtDouble, EvqTemporary, 3);
1542 break;
1543 case EHTokDouble4:
1544 new(&type) TType(EbtDouble, EvqTemporary, 4);
1545 break;
1546
1547 case EHTokInt:
1548 case EHTokDword:
1549 new(&type) TType(EbtInt);
1550 break;
1551 case EHTokInt1:
1552 new(&type) TType(EbtInt);
1553 type.makeVector();
1554 break;
John Kessenich87142c72016-03-12 20:24:24 -07001555 case EHTokInt2:
1556 new(&type) TType(EbtInt, EvqTemporary, 2);
1557 break;
1558 case EHTokInt3:
1559 new(&type) TType(EbtInt, EvqTemporary, 3);
1560 break;
1561 case EHTokInt4:
1562 new(&type) TType(EbtInt, EvqTemporary, 4);
1563 break;
1564
John Kessenich71351de2016-06-08 12:50:56 -06001565 case EHTokUint:
1566 new(&type) TType(EbtUint);
1567 break;
1568 case EHTokUint1:
1569 new(&type) TType(EbtUint);
1570 type.makeVector();
1571 break;
1572 case EHTokUint2:
1573 new(&type) TType(EbtUint, EvqTemporary, 2);
1574 break;
1575 case EHTokUint3:
1576 new(&type) TType(EbtUint, EvqTemporary, 3);
1577 break;
1578 case EHTokUint4:
1579 new(&type) TType(EbtUint, EvqTemporary, 4);
1580 break;
1581
1582 case EHTokBool:
1583 new(&type) TType(EbtBool);
1584 break;
1585 case EHTokBool1:
1586 new(&type) TType(EbtBool);
1587 type.makeVector();
1588 break;
John Kessenich87142c72016-03-12 20:24:24 -07001589 case EHTokBool2:
1590 new(&type) TType(EbtBool, EvqTemporary, 2);
1591 break;
1592 case EHTokBool3:
1593 new(&type) TType(EbtBool, EvqTemporary, 3);
1594 break;
1595 case EHTokBool4:
1596 new(&type) TType(EbtBool, EvqTemporary, 4);
1597 break;
1598
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001599 case EHTokHalf:
John Kessenich96f65522017-06-06 23:35:25 -06001600 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001601 break;
1602 case EHTokHalf1:
John Kessenich96f65522017-06-06 23:35:25 -06001603 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001604 type.makeVector();
1605 break;
1606 case EHTokHalf2:
John Kessenich96f65522017-06-06 23:35:25 -06001607 new(&type) TType(half_bt, EvqTemporary, 2);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001608 break;
1609 case EHTokHalf3:
John Kessenich96f65522017-06-06 23:35:25 -06001610 new(&type) TType(half_bt, EvqTemporary, 3);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001611 break;
1612 case EHTokHalf4:
John Kessenich96f65522017-06-06 23:35:25 -06001613 new(&type) TType(half_bt, EvqTemporary, 4);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001614 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001615
steve-lunarg3226b082016-10-26 19:18:55 -06001616 case EHTokMin16float:
1617 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1618 break;
1619 case EHTokMin16float1:
1620 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1621 type.makeVector();
1622 break;
1623 case EHTokMin16float2:
1624 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1625 break;
1626 case EHTokMin16float3:
1627 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1628 break;
1629 case EHTokMin16float4:
1630 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1631 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001632
steve-lunarg3226b082016-10-26 19:18:55 -06001633 case EHTokMin10float:
1634 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1635 break;
1636 case EHTokMin10float1:
1637 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1638 type.makeVector();
1639 break;
1640 case EHTokMin10float2:
1641 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1642 break;
1643 case EHTokMin10float3:
1644 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1645 break;
1646 case EHTokMin10float4:
1647 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1648 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001649
steve-lunarg3226b082016-10-26 19:18:55 -06001650 case EHTokMin16int:
1651 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1652 break;
1653 case EHTokMin16int1:
1654 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1655 type.makeVector();
1656 break;
1657 case EHTokMin16int2:
1658 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1659 break;
1660 case EHTokMin16int3:
1661 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1662 break;
1663 case EHTokMin16int4:
1664 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1665 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001666
steve-lunarg3226b082016-10-26 19:18:55 -06001667 case EHTokMin12int:
1668 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1669 break;
1670 case EHTokMin12int1:
1671 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1672 type.makeVector();
1673 break;
1674 case EHTokMin12int2:
1675 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1676 break;
1677 case EHTokMin12int3:
1678 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1679 break;
1680 case EHTokMin12int4:
1681 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1682 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001683
steve-lunarg3226b082016-10-26 19:18:55 -06001684 case EHTokMin16uint:
1685 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1686 break;
1687 case EHTokMin16uint1:
1688 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1689 type.makeVector();
1690 break;
1691 case EHTokMin16uint2:
1692 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1693 break;
1694 case EHTokMin16uint3:
1695 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1696 break;
1697 case EHTokMin16uint4:
1698 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1699 break;
1700
John Kessenich0133c122016-05-20 12:17:26 -06001701 case EHTokInt1x1:
1702 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1703 break;
1704 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001705 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001706 break;
1707 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001708 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001709 break;
1710 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001711 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001712 break;
1713 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001714 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001715 break;
1716 case EHTokInt2x2:
1717 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1718 break;
1719 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001720 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001721 break;
1722 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001723 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001724 break;
1725 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001726 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001727 break;
1728 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001729 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001730 break;
1731 case EHTokInt3x3:
1732 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1733 break;
1734 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001735 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001736 break;
1737 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001738 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001739 break;
1740 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001741 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001742 break;
1743 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001744 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001745 break;
1746 case EHTokInt4x4:
1747 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1748 break;
1749
John Kessenich71351de2016-06-08 12:50:56 -06001750 case EHTokUint1x1:
1751 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1752 break;
1753 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001754 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001755 break;
1756 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001757 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001758 break;
1759 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001760 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001761 break;
1762 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001763 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001764 break;
1765 case EHTokUint2x2:
1766 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1767 break;
1768 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001769 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001770 break;
1771 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001772 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001773 break;
1774 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001775 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001776 break;
1777 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001778 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001779 break;
1780 case EHTokUint3x3:
1781 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1782 break;
1783 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001784 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001785 break;
1786 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001787 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001788 break;
1789 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001790 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001791 break;
1792 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001793 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001794 break;
1795 case EHTokUint4x4:
1796 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1797 break;
1798
1799 case EHTokBool1x1:
1800 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1801 break;
1802 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001803 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001804 break;
1805 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001806 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001807 break;
1808 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001809 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001810 break;
1811 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001812 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001813 break;
1814 case EHTokBool2x2:
1815 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1816 break;
1817 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001818 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001819 break;
1820 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001821 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001822 break;
1823 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001824 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001825 break;
1826 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001827 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001828 break;
1829 case EHTokBool3x3:
1830 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1831 break;
1832 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001833 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001834 break;
1835 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001836 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001837 break;
1838 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001839 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001840 break;
1841 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001842 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001843 break;
1844 case EHTokBool4x4:
1845 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1846 break;
1847
John Kessenich0133c122016-05-20 12:17:26 -06001848 case EHTokFloat1x1:
1849 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1850 break;
1851 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001852 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001853 break;
1854 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001855 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001856 break;
1857 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001858 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001859 break;
1860 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001861 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001862 break;
John Kessenich87142c72016-03-12 20:24:24 -07001863 case EHTokFloat2x2:
1864 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1865 break;
1866 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001867 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001868 break;
1869 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001870 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001871 break;
John Kessenich0133c122016-05-20 12:17:26 -06001872 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001873 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001874 break;
John Kessenich87142c72016-03-12 20:24:24 -07001875 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001876 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001877 break;
1878 case EHTokFloat3x3:
1879 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1880 break;
1881 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001882 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001883 break;
John Kessenich0133c122016-05-20 12:17:26 -06001884 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001885 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001886 break;
John Kessenich87142c72016-03-12 20:24:24 -07001887 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001888 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001889 break;
1890 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001891 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001892 break;
1893 case EHTokFloat4x4:
1894 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1895 break;
1896
John Kessenich96f65522017-06-06 23:35:25 -06001897 case EHTokHalf1x1:
1898 new(&type) TType(half_bt, EvqTemporary, 0, 1, 1);
1899 break;
1900 case EHTokHalf1x2:
1901 new(&type) TType(half_bt, EvqTemporary, 0, 1, 2);
1902 break;
1903 case EHTokHalf1x3:
1904 new(&type) TType(half_bt, EvqTemporary, 0, 1, 3);
1905 break;
1906 case EHTokHalf1x4:
1907 new(&type) TType(half_bt, EvqTemporary, 0, 1, 4);
1908 break;
1909 case EHTokHalf2x1:
1910 new(&type) TType(half_bt, EvqTemporary, 0, 2, 1);
1911 break;
1912 case EHTokHalf2x2:
1913 new(&type) TType(half_bt, EvqTemporary, 0, 2, 2);
1914 break;
1915 case EHTokHalf2x3:
1916 new(&type) TType(half_bt, EvqTemporary, 0, 2, 3);
1917 break;
1918 case EHTokHalf2x4:
1919 new(&type) TType(half_bt, EvqTemporary, 0, 2, 4);
1920 break;
1921 case EHTokHalf3x1:
1922 new(&type) TType(half_bt, EvqTemporary, 0, 3, 1);
1923 break;
1924 case EHTokHalf3x2:
1925 new(&type) TType(half_bt, EvqTemporary, 0, 3, 2);
1926 break;
1927 case EHTokHalf3x3:
1928 new(&type) TType(half_bt, EvqTemporary, 0, 3, 3);
1929 break;
1930 case EHTokHalf3x4:
1931 new(&type) TType(half_bt, EvqTemporary, 0, 3, 4);
1932 break;
1933 case EHTokHalf4x1:
1934 new(&type) TType(half_bt, EvqTemporary, 0, 4, 1);
1935 break;
1936 case EHTokHalf4x2:
1937 new(&type) TType(half_bt, EvqTemporary, 0, 4, 2);
1938 break;
1939 case EHTokHalf4x3:
1940 new(&type) TType(half_bt, EvqTemporary, 0, 4, 3);
1941 break;
1942 case EHTokHalf4x4:
1943 new(&type) TType(half_bt, EvqTemporary, 0, 4, 4);
1944 break;
1945
John Kessenich0133c122016-05-20 12:17:26 -06001946 case EHTokDouble1x1:
1947 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1948 break;
1949 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001950 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001951 break;
1952 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001953 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001954 break;
1955 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001956 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001957 break;
1958 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001959 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001960 break;
1961 case EHTokDouble2x2:
1962 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1963 break;
1964 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001965 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001966 break;
1967 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001968 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001969 break;
1970 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001971 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001972 break;
1973 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001974 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001975 break;
1976 case EHTokDouble3x3:
1977 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1978 break;
1979 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001980 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001981 break;
1982 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001983 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001984 break;
1985 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001986 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001987 break;
1988 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001989 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001990 break;
1991 case EHTokDouble4x4:
1992 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1993 break;
1994
John Kessenich87142c72016-03-12 20:24:24 -07001995 default:
1996 return false;
1997 }
1998
1999 advanceToken();
2000
LoopDawgfa39cff2017-11-14 14:55:40 -07002001 if ((isUnorm || isSnorm) && !type.isFloatingDomain()) {
2002 parseContext.error(token.loc, "unorm and snorm only valid in floating point domain", "", "");
2003 return false;
2004 }
2005
John Kessenich87142c72016-03-12 20:24:24 -07002006 return true;
2007}
2008
John Kesseniche6e74942016-06-11 16:43:14 -06002009// struct
John Kessenich3d157c52016-07-25 16:05:33 -06002010// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
2011// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07002012// | struct_type IDENTIFIER // use of previously declared struct type
John Kessenich3d157c52016-07-25 16:05:33 -06002013//
2014// struct_type
2015// : STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07002016// | CLASS
John Kessenich3d157c52016-07-25 16:05:33 -06002017// | CBUFFER
2018// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06002019//
John Kessenich54ee28f2017-03-11 14:13:00 -07002020bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
John Kesseniche6e74942016-06-11 16:43:14 -06002021{
John Kessenichb804de62016-09-05 12:19:18 -06002022 // This storage qualifier will tell us whether it's an AST
2023 // block type or just a generic structure type.
2024 TStorageQualifier storageQualifier = EvqTemporary;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002025 bool readonly = false;
John Kessenich3d157c52016-07-25 16:05:33 -06002026
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002027 if (acceptTokenClass(EHTokCBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06002028 // CBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06002029 storageQualifier = EvqUniform;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002030 } else if (acceptTokenClass(EHTokTBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06002031 // TBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06002032 storageQualifier = EvqBuffer;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002033 readonly = true;
John Kessenich054378d2017-06-19 15:13:26 -06002034 } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) {
2035 // Neither CLASS nor STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06002036 return false;
John Kessenich054378d2017-06-19 15:13:26 -06002037 }
2038
2039 // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06002040
LoopDawg7ee29ba2017-11-27 14:45:36 -07002041
2042 // IDENTIFIER. It might also be a keyword which can double as an identifier.
2043 // For example: 'cbuffer ConstantBuffer' or 'struct ConstantBuffer' is legal.
2044 // 'cbuffer int' is also legal, and 'struct int' appears rejected only because
2045 // it attempts to redefine the 'int' type.
2046 const char* idString = getTypeString(peek());
John Kesseniche6e74942016-06-11 16:43:14 -06002047 TString structName = "";
LoopDawg7ee29ba2017-11-27 14:45:36 -07002048 if (peekTokenClass(EHTokIdentifier) || idString != nullptr) {
2049 if (idString != nullptr)
2050 structName = *idString;
2051 else
2052 structName = *token.string;
John Kesseniche6e74942016-06-11 16:43:14 -06002053 advanceToken();
2054 }
2055
John Kessenich3d157c52016-07-25 16:05:33 -06002056 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002057 TQualifier postDeclQualifier;
2058 postDeclQualifier.clear();
John Kessenich854fe242017-03-02 14:30:59 -07002059 bool postDeclsFound = acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06002060
John Kessenichf3d88bd2017-03-19 12:24:29 -06002061 // LEFT_BRACE, or
John Kessenich854fe242017-03-02 14:30:59 -07002062 // struct_type IDENTIFIER
John Kesseniche6e74942016-06-11 16:43:14 -06002063 if (! acceptTokenClass(EHTokLeftBrace)) {
John Kessenich854fe242017-03-02 14:30:59 -07002064 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
2065 // struct_type IDENTIFIER
2066 return true;
2067 } else {
2068 expected("{");
2069 return false;
2070 }
John Kesseniche6e74942016-06-11 16:43:14 -06002071 }
2072
John Kessenichf3d88bd2017-03-19 12:24:29 -06002073
John Kesseniche6e74942016-06-11 16:43:14 -06002074 // struct_declaration_list
2075 TTypeList* typeList;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002076 // Save each member function so they can be processed after we have a fully formed 'this'.
2077 TVector<TFunctionDeclarator> functionDeclarators;
2078
2079 parseContext.pushNamespace(structName);
John Kessenichaa3c64c2017-03-28 09:52:38 -06002080 bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06002081 parseContext.popNamespace();
2082
2083 if (! acceptedList) {
John Kesseniche6e74942016-06-11 16:43:14 -06002084 expected("struct member declarations");
2085 return false;
2086 }
2087
2088 // RIGHT_BRACE
2089 if (! acceptTokenClass(EHTokRightBrace)) {
2090 expected("}");
2091 return false;
2092 }
2093
2094 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06002095 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06002096 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06002097 else {
John Kessenich7735b942016-09-05 12:40:06 -06002098 postDeclQualifier.storage = storageQualifier;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002099 postDeclQualifier.readonly = readonly;
John Kessenich7735b942016-09-05 12:40:06 -06002100 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06002101 }
John Kesseniche6e74942016-06-11 16:43:14 -06002102
John Kessenich727b3742017-02-03 17:57:55 -07002103 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06002104
John Kessenich4960baa2017-03-19 18:09:59 -06002105 // For member functions: now that we know the type of 'this', go back and
2106 // - add their implicit argument with 'this' (not to the mangling, just the argument list)
2107 // - parse the functions, their tokens were saved for deferred parsing (now)
2108 for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
2109 // update signature
2110 if (functionDeclarators[b].function->hasImplicitThis())
John Kessenich37789792017-03-21 23:56:40 -06002111 functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName);
John Kessenich4960baa2017-03-19 18:09:59 -06002112 }
2113
John Kessenichf3d88bd2017-03-19 12:24:29 -06002114 // All member functions get parsed inside the class/struct namespace and with the
2115 // class/struct members in a symbol-table level.
2116 parseContext.pushNamespace(structName);
John Kessenich0a2a0cd2017-05-16 23:16:26 -06002117 parseContext.pushThisScope(type, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06002118 bool deferredSuccess = true;
2119 for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
2120 // parse body
2121 pushTokenStream(functionDeclarators[b].body);
2122 if (! acceptFunctionBody(functionDeclarators[b], nodeList))
2123 deferredSuccess = false;
2124 popTokenStream();
2125 }
John Kessenich37789792017-03-21 23:56:40 -06002126 parseContext.popThisScope();
John Kessenichf3d88bd2017-03-19 12:24:29 -06002127 parseContext.popNamespace();
2128
2129 return deferredSuccess;
John Kesseniche6e74942016-06-11 16:43:14 -06002130}
2131
steve-lunarga766b832017-04-25 09:30:28 -06002132// constantbuffer
2133// : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE
2134bool HlslGrammar::acceptConstantBufferType(TType& type)
2135{
2136 if (! acceptTokenClass(EHTokConstantBuffer))
2137 return false;
2138
2139 if (! acceptTokenClass(EHTokLeftAngle)) {
2140 expected("left angle bracket");
2141 return false;
2142 }
2143
2144 TType templateType;
2145 if (! acceptType(templateType)) {
2146 expected("type");
2147 return false;
2148 }
2149
2150 if (! acceptTokenClass(EHTokRightAngle)) {
2151 expected("right angle bracket");
2152 return false;
2153 }
2154
2155 TQualifier postDeclQualifier;
2156 postDeclQualifier.clear();
2157 postDeclQualifier.storage = EvqUniform;
2158
2159 if (templateType.isStruct()) {
2160 // Make a block from the type parsed as the template argument
2161 TTypeList* typeList = templateType.getWritableStruct();
2162 new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock
2163
2164 type.getQualifier().storage = EvqUniform;
2165
2166 return true;
2167 } else {
2168 parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", "");
2169 return false;
2170 }
2171}
2172
LoopDawge5530b92017-11-08 19:48:11 -07002173// texture_buffer
2174// : TEXTUREBUFFER LEFT_ANGLE type RIGHT_ANGLE
2175bool HlslGrammar::acceptTextureBufferType(TType& type)
2176{
2177 if (! acceptTokenClass(EHTokTextureBuffer))
2178 return false;
2179
2180 if (! acceptTokenClass(EHTokLeftAngle)) {
2181 expected("left angle bracket");
2182 return false;
2183 }
2184
2185 TType templateType;
2186 if (! acceptType(templateType)) {
2187 expected("type");
2188 return false;
2189 }
2190
2191 if (! acceptTokenClass(EHTokRightAngle)) {
2192 expected("right angle bracket");
2193 return false;
2194 }
2195
2196 templateType.getQualifier().storage = EvqBuffer;
2197 templateType.getQualifier().readonly = true;
2198
2199 TType blockType(templateType.getWritableStruct(), "", templateType.getQualifier());
2200
2201 blockType.getQualifier().storage = EvqBuffer;
2202 blockType.getQualifier().readonly = true;
2203
2204 type.shallowCopy(blockType);
2205
2206 return true;
2207}
2208
2209
steve-lunarg5da1f032017-02-12 17:50:28 -07002210// struct_buffer
2211// : APPENDSTRUCTUREDBUFFER
2212// | BYTEADDRESSBUFFER
2213// | CONSUMESTRUCTUREDBUFFER
2214// | RWBYTEADDRESSBUFFER
2215// | RWSTRUCTUREDBUFFER
2216// | STRUCTUREDBUFFER
2217bool HlslGrammar::acceptStructBufferType(TType& type)
2218{
2219 const EHlslTokenClass structBuffType = peek();
2220
2221 // TODO: globallycoherent
2222 bool hasTemplateType = true;
2223 bool readonly = false;
2224
2225 TStorageQualifier storage = EvqBuffer;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002226 TBuiltInVariable builtinType = EbvNone;
steve-lunarg5da1f032017-02-12 17:50:28 -07002227
2228 switch (structBuffType) {
2229 case EHTokAppendStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002230 builtinType = EbvAppendConsume;
2231 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002232 case EHTokByteAddressBuffer:
2233 hasTemplateType = false;
2234 readonly = true;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002235 builtinType = EbvByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002236 break;
2237 case EHTokConsumeStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002238 builtinType = EbvAppendConsume;
2239 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002240 case EHTokRWByteAddressBuffer:
2241 hasTemplateType = false;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002242 builtinType = EbvRWByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002243 break;
2244 case EHTokRWStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002245 builtinType = EbvRWStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002246 break;
2247 case EHTokStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002248 builtinType = EbvStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002249 readonly = true;
2250 break;
2251 default:
2252 return false; // not a structure buffer type
2253 }
2254
2255 advanceToken(); // consume the structure keyword
2256
2257 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
2258 TType* templateType = new TType;
2259
2260 if (hasTemplateType) {
2261 if (! acceptTokenClass(EHTokLeftAngle)) {
2262 expected("left angle bracket");
2263 return false;
2264 }
2265
2266 if (! acceptType(*templateType)) {
2267 expected("type");
2268 return false;
2269 }
2270 if (! acceptTokenClass(EHTokRightAngle)) {
2271 expected("right angle bracket");
2272 return false;
2273 }
2274 } else {
2275 // byte address buffers have no explicit type.
2276 TType uintType(EbtUint, storage);
2277 templateType->shallowCopy(uintType);
2278 }
2279
2280 // Create an unsized array out of that type.
2281 // TODO: does this work if it's already an array type?
2282 TArraySizes unsizedArray;
2283 unsizedArray.addInnerSize(UnsizedArraySize);
2284 templateType->newArraySizes(unsizedArray);
steve-lunarg40efe5c2017-03-06 12:01:44 -07002285 templateType->getQualifier().storage = storage;
steve-lunargdd8287a2017-02-23 18:04:12 -07002286
2287 // field name is canonical for all structbuffers
2288 templateType->setFieldName("@data");
steve-lunarg5da1f032017-02-12 17:50:28 -07002289
steve-lunarg5da1f032017-02-12 17:50:28 -07002290 TTypeList* blockStruct = new TTypeList;
2291 TTypeLoc member = { templateType, token.loc };
2292 blockStruct->push_back(member);
2293
steve-lunargdd8287a2017-02-23 18:04:12 -07002294 // This is the type of the buffer block (SSBO)
steve-lunarg5da1f032017-02-12 17:50:28 -07002295 TType blockType(blockStruct, "", templateType->getQualifier());
2296
steve-lunargdd8287a2017-02-23 18:04:12 -07002297 blockType.getQualifier().storage = storage;
2298 blockType.getQualifier().readonly = readonly;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002299 blockType.getQualifier().builtIn = builtinType;
steve-lunargdd8287a2017-02-23 18:04:12 -07002300
2301 // We may have created an equivalent type before, in which case we should use its
2302 // deep structure.
2303 parseContext.shareStructBufferType(blockType);
2304
steve-lunarg5da1f032017-02-12 17:50:28 -07002305 type.shallowCopy(blockType);
2306
2307 return true;
2308}
2309
John Kesseniche6e74942016-06-11 16:43:14 -06002310// struct_declaration_list
2311// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
2312//
2313// struct_declaration
John Kessenichcc951f82017-12-06 07:33:36 -07002314// : attributes fully_specified_type struct_declarator COMMA struct_declarator ...
2315// | attributes fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition
John Kesseniche6e74942016-06-11 16:43:14 -06002316//
2317// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06002318// : IDENTIFIER post_decls
2319// | IDENTIFIER array_specifier post_decls
John Kessenich54ee28f2017-03-11 14:13:00 -07002320// | IDENTIFIER function_parameters post_decls // member-function prototype
John Kesseniche6e74942016-06-11 16:43:14 -06002321//
John Kessenichaa3c64c2017-03-28 09:52:38 -06002322bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002323 TVector<TFunctionDeclarator>& declarators)
John Kesseniche6e74942016-06-11 16:43:14 -06002324{
2325 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002326 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06002327
2328 do {
2329 // success on seeing the RIGHT_BRACE coming up
2330 if (peekTokenClass(EHTokRightBrace))
John Kessenichb16f7e62017-03-11 19:32:47 -07002331 break;
John Kesseniche6e74942016-06-11 16:43:14 -06002332
2333 // struct_declaration
John Kessenichcc951f82017-12-06 07:33:36 -07002334
2335 // attributes
2336 TAttributeMap attributes;
2337 acceptAttributes(attributes);
2338
John Kessenich54ee28f2017-03-11 14:13:00 -07002339 bool declarator_list = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002340
2341 // fully_specified_type
2342 TType memberType;
John Kessenich046bae02017-12-23 17:29:45 -07002343 if (! acceptFullySpecifiedType(memberType, nodeList, attributes)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002344 expected("member type");
2345 return false;
2346 }
2347
2348 // struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07002349 bool functionDefinitionAccepted = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002350 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002351 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002352 expected("member name");
2353 return false;
2354 }
2355
John Kessenich54ee28f2017-03-11 14:13:00 -07002356 if (peekTokenClass(EHTokLeftParen)) {
2357 // function_parameters
2358 if (!declarator_list) {
John Kessenichb16f7e62017-03-11 19:32:47 -07002359 declarators.resize(declarators.size() + 1);
2360 // request a token stream for deferred processing
John Kessenichf3d88bd2017-03-19 12:24:29 -06002361 functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
2362 declarators.back());
John Kessenich54ee28f2017-03-11 14:13:00 -07002363 if (functionDefinitionAccepted)
2364 break;
2365 }
2366 expected("member-function definition");
2367 return false;
2368 } else {
2369 // add it to the list of members
2370 TTypeLoc member = { new TType(EbtVoid), token.loc };
2371 member.type->shallowCopy(memberType);
2372 member.type->setFieldName(*idToken.string);
2373 typeList->push_back(member);
John Kesseniche6e74942016-06-11 16:43:14 -06002374
John Kessenich54ee28f2017-03-11 14:13:00 -07002375 // array_specifier
2376 TArraySizes* arraySizes = nullptr;
2377 acceptArraySpecifier(arraySizes);
2378 if (arraySizes)
2379 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06002380
John Kessenich54ee28f2017-03-11 14:13:00 -07002381 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06002382
John Kessenich54ee28f2017-03-11 14:13:00 -07002383 // EQUAL assignment_expression
2384 if (acceptTokenClass(EHTokAssign)) {
2385 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
2386 TIntermTyped* expressionNode = nullptr;
2387 if (! acceptAssignmentExpression(expressionNode)) {
2388 expected("initializer");
2389 return false;
2390 }
John Kessenich18adbdb2017-02-02 15:16:20 -07002391 }
2392 }
John Kesseniche6e74942016-06-11 16:43:14 -06002393 // success on seeing the SEMICOLON coming up
2394 if (peekTokenClass(EHTokSemicolon))
2395 break;
2396
2397 // COMMA
John Kessenich54ee28f2017-03-11 14:13:00 -07002398 if (acceptTokenClass(EHTokComma))
2399 declarator_list = true;
2400 else {
John Kesseniche6e74942016-06-11 16:43:14 -06002401 expected(",");
2402 return false;
2403 }
2404
2405 } while (true);
2406
2407 // SEMI_COLON
John Kessenich54ee28f2017-03-11 14:13:00 -07002408 if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002409 expected(";");
2410 return false;
2411 }
2412
2413 } while (true);
John Kessenichb16f7e62017-03-11 19:32:47 -07002414
John Kessenichb16f7e62017-03-11 19:32:47 -07002415 return true;
John Kesseniche6e74942016-06-11 16:43:14 -06002416}
2417
John Kessenich54ee28f2017-03-11 14:13:00 -07002418// member_function_definition
2419// | function_parameters post_decls compound_statement
2420//
2421// Expects type to have EvqGlobal for a static member and
2422// EvqTemporary for non-static member.
John Kessenich9855bda2017-09-11 21:48:19 -06002423bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, TString& memberName,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002424 TFunctionDeclarator& declarator)
John Kessenich54ee28f2017-03-11 14:13:00 -07002425{
John Kessenich54ee28f2017-03-11 14:13:00 -07002426 bool accepted = false;
2427
John Kessenich9855bda2017-09-11 21:48:19 -06002428 TString* functionName = &memberName;
John Kessenich4dc835c2017-03-28 23:43:10 -06002429 parseContext.getFullNamespaceName(functionName);
John Kessenich088d52b2017-03-11 17:55:28 -07002430 declarator.function = new TFunction(functionName, type);
John Kessenich4960baa2017-03-19 18:09:59 -06002431 if (type.getQualifier().storage == EvqTemporary)
2432 declarator.function->setImplicitThis();
John Kessenich37789792017-03-21 23:56:40 -06002433 else
2434 declarator.function->setIllegalImplicitThis();
John Kessenich54ee28f2017-03-11 14:13:00 -07002435
2436 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -07002437 if (acceptFunctionParameters(*declarator.function)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002438 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -07002439 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich54ee28f2017-03-11 14:13:00 -07002440
2441 // compound_statement (function body definition)
2442 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich088d52b2017-03-11 17:55:28 -07002443 declarator.loc = token.loc;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002444 declarator.body = new TVector<HlslToken>;
2445 accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
John Kessenich54ee28f2017-03-11 14:13:00 -07002446 }
2447 } else
2448 expected("function parameter list");
2449
John Kessenich54ee28f2017-03-11 14:13:00 -07002450 return accepted;
2451}
2452
John Kessenich5f934b02016-03-13 17:58:25 -06002453// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06002454// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06002455// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002456//
2457bool HlslGrammar::acceptFunctionParameters(TFunction& function)
2458{
John Kessenich078d7f22016-03-14 10:02:11 -06002459 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002460 if (! acceptTokenClass(EHTokLeftParen))
2461 return false;
2462
John Kessenich71351de2016-06-08 12:50:56 -06002463 // VOID RIGHT_PAREN
2464 if (! acceptTokenClass(EHTokVoid)) {
2465 do {
2466 // parameter_declaration
2467 if (! acceptParameterDeclaration(function))
2468 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002469
John Kessenich71351de2016-06-08 12:50:56 -06002470 // COMMA
2471 if (! acceptTokenClass(EHTokComma))
2472 break;
2473 } while (true);
2474 }
John Kessenich5f934b02016-03-13 17:58:25 -06002475
John Kessenich078d7f22016-03-14 10:02:11 -06002476 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002477 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002478 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002479 return false;
2480 }
2481
2482 return true;
2483}
2484
steve-lunarg26d31452016-12-23 18:56:57 -07002485// default_parameter_declaration
2486// : EQUAL conditional_expression
2487// : EQUAL initializer
2488bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2489{
2490 node = nullptr;
2491
2492 // Valid not to have a default_parameter_declaration
2493 if (!acceptTokenClass(EHTokAssign))
2494 return true;
2495
2496 if (!acceptConditionalExpression(node)) {
2497 if (!acceptInitializer(node))
2498 return false;
2499
2500 // For initializer lists, we have to const-fold into a constructor for the type, so build
2501 // that.
John Kessenichc633f642017-04-03 21:48:37 -06002502 TFunction* constructor = parseContext.makeConstructorCall(token.loc, type);
steve-lunarg26d31452016-12-23 18:56:57 -07002503 if (constructor == nullptr) // cannot construct
2504 return false;
2505
2506 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002507 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002508 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002509
steve-lunarg26d31452016-12-23 18:56:57 -07002510 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2511 }
2512
John Kessenichbb79abc2017-10-07 13:23:09 -06002513 if (node == nullptr)
2514 return false;
2515
steve-lunarg26d31452016-12-23 18:56:57 -07002516 // If this is simply a constant, we can use it directly.
2517 if (node->getAsConstantUnion())
2518 return true;
2519
2520 // Otherwise, it has to be const-foldable.
2521 TIntermTyped* origNode = node;
2522
2523 node = intermediate.fold(node->getAsAggregate());
2524
2525 if (node != nullptr && origNode != node)
2526 return true;
2527
2528 parseContext.error(token.loc, "invalid default parameter value", "", "");
2529
2530 return false;
2531}
2532
John Kessenich5f934b02016-03-13 17:58:25 -06002533// parameter_declaration
John Kessenich77ea30b2017-09-30 14:34:50 -06002534// : attributes attributed_declaration
2535//
2536// attributed_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002537// : fully_specified_type post_decls [ = default_parameter_declaration ]
2538// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002539//
2540bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2541{
John Kessenich77ea30b2017-09-30 14:34:50 -06002542 // attributes
2543 TAttributeMap attributes;
2544 acceptAttributes(attributes);
2545
John Kessenich5f934b02016-03-13 17:58:25 -06002546 // fully_specified_type
2547 TType* type = new TType;
John Kessenich046bae02017-12-23 17:29:45 -07002548 if (! acceptFullySpecifiedType(*type, attributes))
John Kessenich5f934b02016-03-13 17:58:25 -06002549 return false;
2550
2551 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002552 HlslToken idToken;
2553 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002554
John Kessenich19b92ff2016-06-19 11:50:34 -06002555 // array_specifier
2556 TArraySizes* arraySizes = nullptr;
2557 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002558 if (arraySizes) {
2559 if (arraySizes->isImplicit()) {
2560 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2561 return false;
2562 }
2563
John Kessenich19b92ff2016-06-19 11:50:34 -06002564 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002565 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002566
2567 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002568 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002569
steve-lunarg26d31452016-12-23 18:56:57 -07002570 TIntermTyped* defaultValue;
2571 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2572 return false;
2573
John Kessenich5aa59e22016-06-17 15:50:47 -06002574 parseContext.paramFix(*type);
2575
steve-lunarg26d31452016-12-23 18:56:57 -07002576 // If any prior parameters have default values, all the parameters after that must as well.
2577 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2578 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2579 return false;
2580 }
2581
2582 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002583 function.addParameter(param);
2584
2585 return true;
2586}
2587
2588// Do the work to create the function definition in addition to
2589// parsing the body (compound_statement).
John Kessenichb16f7e62017-03-11 19:32:47 -07002590//
2591// If 'deferredTokens' are passed in, just get the token stream,
2592// don't process.
2593//
2594bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
2595 TVector<HlslToken>* deferredTokens)
John Kessenich5f934b02016-03-13 17:58:25 -06002596{
John Kessenich088d52b2017-03-11 17:55:28 -07002597 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
John Kessenich5f934b02016-03-13 17:58:25 -06002598
John Kessenichb16f7e62017-03-11 19:32:47 -07002599 if (deferredTokens)
2600 return captureBlockTokens(*deferredTokens);
2601 else
John Kessenich4960baa2017-03-19 18:09:59 -06002602 return acceptFunctionBody(declarator, nodeList);
John Kessenich088d52b2017-03-11 17:55:28 -07002603}
2604
2605bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
2606{
2607 // we might get back an entry-point
John Kessenichca71d942017-03-07 20:44:09 -07002608 TIntermNode* entryPointNode = nullptr;
2609
John Kessenich077e0522016-06-09 02:02:17 -06002610 // This does a pushScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002611 TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function,
2612 declarator.attributes, entryPointNode);
John Kessenich5f934b02016-03-13 17:58:25 -06002613
2614 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002615 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002616 if (! acceptCompoundStatement(functionBody))
2617 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002618
John Kessenich54ee28f2017-03-11 14:13:00 -07002619 // this does a popScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002620 parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode);
John Kessenichca71d942017-03-07 20:44:09 -07002621
2622 // Hook up the 1 or 2 function definitions.
2623 nodeList = intermediate.growAggregate(nodeList, functionNode);
2624 nodeList = intermediate.growAggregate(nodeList, entryPointNode);
John Kessenich02467d82017-01-19 15:41:47 -07002625
2626 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002627}
2628
John Kessenich0d2b6de2016-06-05 11:23:11 -06002629// Accept an expression with parenthesis around it, where
2630// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002631// syntactically required ones like in "if ( expression )".
2632//
2633// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002634//
2635// Note this one is not set up to be speculative; as it gives
2636// errors if not found.
2637//
2638bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2639{
John Kessenich7199a6d2017-11-29 16:32:46 -07002640 expression = nullptr;
2641
John Kessenich0d2b6de2016-06-05 11:23:11 -06002642 // LEFT_PAREN
2643 if (! acceptTokenClass(EHTokLeftParen))
2644 expected("(");
2645
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002646 bool decl = false;
2647 TIntermNode* declNode = nullptr;
2648 decl = acceptControlDeclaration(declNode);
2649 if (decl) {
2650 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2651 expected("initialized declaration");
2652 return false;
2653 } else
2654 expression = declNode->getAsTyped();
2655 } else {
2656 // no declaration
2657 if (! acceptExpression(expression)) {
2658 expected("expression");
2659 return false;
2660 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002661 }
2662
2663 // RIGHT_PAREN
2664 if (! acceptTokenClass(EHTokRightParen))
2665 expected(")");
2666
2667 return true;
2668}
2669
John Kessenich34fb0362016-05-03 23:17:20 -06002670// The top-level full expression recognizer.
2671//
John Kessenich87142c72016-03-12 20:24:24 -07002672// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002673// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002674//
2675bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2676{
LoopDawgef764a22016-06-03 09:17:51 -06002677 node = nullptr;
2678
John Kessenich34fb0362016-05-03 23:17:20 -06002679 // assignment_expression
2680 if (! acceptAssignmentExpression(node))
2681 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002682
John Kessenich34fb0362016-05-03 23:17:20 -06002683 if (! peekTokenClass(EHTokComma))
2684 return true;
2685
2686 do {
2687 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002688 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002689 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002690
John Kessenich34fb0362016-05-03 23:17:20 -06002691 // ... assignment_expression
2692 TIntermTyped* rightNode = nullptr;
2693 if (! acceptAssignmentExpression(rightNode)) {
2694 expected("assignment expression");
2695 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002696 }
2697
John Kessenich34fb0362016-05-03 23:17:20 -06002698 node = intermediate.addComma(node, rightNode, loc);
2699
2700 if (! peekTokenClass(EHTokComma))
2701 return true;
2702 } while (true);
2703}
2704
John Kessenich07354242016-07-01 19:58:06 -06002705// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002706// : LEFT_BRACE RIGHT_BRACE
2707// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002708//
2709// initializer_list
2710// : assignment_expression COMMA assignment_expression COMMA ...
2711//
2712bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2713{
2714 // LEFT_BRACE
2715 if (! acceptTokenClass(EHTokLeftBrace))
2716 return false;
2717
John Kessenich98ad4852016-11-27 17:39:07 -07002718 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002719 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002720 if (acceptTokenClass(EHTokRightBrace)) {
2721 // a zero-length initializer list
2722 node = intermediate.makeAggregate(loc);
2723 return true;
2724 }
2725
2726 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002727 node = nullptr;
2728 do {
2729 // assignment_expression
2730 TIntermTyped* expr;
2731 if (! acceptAssignmentExpression(expr)) {
2732 expected("assignment expression in initializer list");
2733 return false;
2734 }
LoopDawg0fca0ba2017-07-10 15:43:40 -06002735
2736 const bool firstNode = (node == nullptr);
2737
John Kessenich07354242016-07-01 19:58:06 -06002738 node = intermediate.growAggregate(node, expr, loc);
2739
LoopDawg0fca0ba2017-07-10 15:43:40 -06002740 // If every sub-node in the list has qualifier EvqConst, the returned node becomes
2741 // EvqConst. Otherwise, it becomes EvqTemporary. That doesn't happen with e.g.
2742 // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are.
2743 if (firstNode && expr->getQualifier().storage == EvqConst)
2744 node->getQualifier().storage = EvqConst;
2745 else if (expr->getQualifier().storage != EvqConst)
2746 node->getQualifier().storage = EvqTemporary;
2747
John Kessenich07354242016-07-01 19:58:06 -06002748 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002749 if (acceptTokenClass(EHTokComma)) {
2750 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2751 return true;
John Kessenich07354242016-07-01 19:58:06 -06002752 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002753 }
John Kessenich07354242016-07-01 19:58:06 -06002754
2755 // RIGHT_BRACE
2756 if (acceptTokenClass(EHTokRightBrace))
2757 return true;
2758
2759 expected(", or }");
2760 return false;
2761 } while (true);
2762}
2763
John Kessenich34fb0362016-05-03 23:17:20 -06002764// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002765// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002766//
2767// a op (b op (c op d))
2768//
2769// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002770// : initializer
2771// | conditional_expression
2772// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002773//
2774bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2775{
John Kessenich07354242016-07-01 19:58:06 -06002776 // initializer
2777 if (peekTokenClass(EHTokLeftBrace)) {
2778 if (acceptInitializer(node))
2779 return true;
2780
2781 expected("initializer");
2782 return false;
2783 }
2784
John Kessenich00957f82016-07-27 10:39:57 -06002785 // conditional_expression
2786 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002787 return false;
2788
John Kessenich07354242016-07-01 19:58:06 -06002789 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002790 TOperator assignOp = HlslOpMap::assignment(peek());
2791 if (assignOp == EOpNull)
2792 return true;
2793
John Kessenich00957f82016-07-27 10:39:57 -06002794 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002795 TSourceLoc loc = token.loc;
2796 advanceToken();
2797
John Kessenich00957f82016-07-27 10:39:57 -06002798 // conditional_expression assign_op conditional_expression ...
2799 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002800 // gets the right-to-left associativity.
2801 TIntermTyped* rightNode = nullptr;
2802 if (! acceptAssignmentExpression(rightNode)) {
2803 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002804 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002805 }
2806
John Kessenichd21baed2016-09-16 03:05:12 -06002807 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002808 node = parseContext.handleLvalue(loc, "assign", node);
2809
John Kessenichfea226b2016-07-28 17:53:56 -06002810 if (node == nullptr) {
2811 parseContext.error(loc, "could not create assignment", "", "");
2812 return false;
2813 }
John Kessenich34fb0362016-05-03 23:17:20 -06002814
2815 if (! peekTokenClass(EHTokComma))
2816 return true;
2817
2818 return true;
2819}
2820
John Kessenich00957f82016-07-27 10:39:57 -06002821// Accept a conditional expression, which associates right-to-left,
2822// accomplished by the "true" expression calling down to lower
2823// precedence levels than this level.
2824//
2825// conditional_expression
2826// : binary_expression
2827// | binary_expression QUESTION expression COLON assignment_expression
2828//
2829bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2830{
2831 // binary_expression
2832 if (! acceptBinaryExpression(node, PlLogicalOr))
2833 return false;
2834
2835 if (! acceptTokenClass(EHTokQuestion))
2836 return true;
2837
John Kessenich636b62d2017-04-11 19:45:00 -06002838 node = parseContext.convertConditionalExpression(token.loc, node, false);
John Kessenich7e997e22017-03-30 22:09:30 -06002839 if (node == nullptr)
2840 return false;
2841
John Kessenichf6deacd2017-06-06 19:52:55 -06002842 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
2843
John Kessenich00957f82016-07-27 10:39:57 -06002844 TIntermTyped* trueNode = nullptr;
2845 if (! acceptExpression(trueNode)) {
2846 expected("expression after ?");
2847 return false;
2848 }
2849 TSourceLoc loc = token.loc;
2850
2851 if (! acceptTokenClass(EHTokColon)) {
2852 expected(":");
2853 return false;
2854 }
2855
2856 TIntermTyped* falseNode = nullptr;
2857 if (! acceptAssignmentExpression(falseNode)) {
2858 expected("expression after :");
2859 return false;
2860 }
2861
John Kessenichf6deacd2017-06-06 19:52:55 -06002862 --parseContext.controlFlowNestingLevel;
2863
John Kessenich00957f82016-07-27 10:39:57 -06002864 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2865
2866 return true;
2867}
2868
John Kessenich34fb0362016-05-03 23:17:20 -06002869// Accept a binary expression, for binary operations that
2870// associate left-to-right. This is, it is implicit, for example
2871//
2872// ((a op b) op c) op d
2873//
2874// binary_expression
2875// : expression op expression op expression ...
2876//
2877// where 'expression' is the next higher level in precedence.
2878//
2879bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2880{
2881 if (precedenceLevel > PlMul)
2882 return acceptUnaryExpression(node);
2883
2884 // assignment_expression
2885 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2886 return false;
2887
John Kessenich34fb0362016-05-03 23:17:20 -06002888 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002889 TOperator op = HlslOpMap::binary(peek());
2890 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2891 if (tokenLevel < precedenceLevel)
2892 return true;
2893
John Kessenich34fb0362016-05-03 23:17:20 -06002894 // ... op
2895 TSourceLoc loc = token.loc;
2896 advanceToken();
2897
2898 // ... expression
2899 TIntermTyped* rightNode = nullptr;
2900 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2901 expected("expression");
2902 return false;
2903 }
2904
2905 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002906 if (node == nullptr) {
2907 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2908 return false;
2909 }
John Kessenich34fb0362016-05-03 23:17:20 -06002910 } while (true);
2911}
2912
2913// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002914// : (type) unary_expression
2915// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002916// | - unary_expression
2917// | ! unary_expression
2918// | ~ unary_expression
2919// | ++ unary_expression
2920// | -- unary_expression
2921// | postfix_expression
2922//
2923bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2924{
John Kessenich1cc1a282016-06-03 16:55:49 -06002925 // (type) unary_expression
2926 // Have to look two steps ahead, because this could be, e.g., a
2927 // postfix_expression instead, since that also starts with at "(".
2928 if (acceptTokenClass(EHTokLeftParen)) {
2929 TType castType;
2930 if (acceptType(castType)) {
John Kessenich82ae8c32017-06-13 23:13:10 -06002931 // recognize any array_specifier as part of the type
2932 TArraySizes* arraySizes = nullptr;
2933 acceptArraySpecifier(arraySizes);
2934 if (arraySizes != nullptr)
2935 castType.newArraySizes(*arraySizes);
2936 TSourceLoc loc = token.loc;
steve-lunarg5964c642016-07-30 07:38:55 -06002937 if (acceptTokenClass(EHTokRightParen)) {
2938 // We've matched "(type)" now, get the expression to cast
steve-lunarg5964c642016-07-30 07:38:55 -06002939 if (! acceptUnaryExpression(node))
2940 return false;
2941
2942 // Hook it up like a constructor
John Kessenichc633f642017-04-03 21:48:37 -06002943 TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType);
steve-lunarg5964c642016-07-30 07:38:55 -06002944 if (constructorFunction == nullptr) {
2945 expected("type that can be constructed");
2946 return false;
2947 }
2948 TIntermTyped* arguments = nullptr;
2949 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2950 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2951
John Kessenichbb79abc2017-10-07 13:23:09 -06002952 return node != nullptr;
steve-lunarg5964c642016-07-30 07:38:55 -06002953 } else {
2954 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2955 // the '(int' part. We must back up twice.
2956 recedeToken();
2957 recedeToken();
John Kessenich82ae8c32017-06-13 23:13:10 -06002958
2959 // Note, there are no array constructors like
2960 // (float[2](...))
2961 if (arraySizes != nullptr)
2962 parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", "");
John Kessenich1cc1a282016-06-03 16:55:49 -06002963 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002964 } else {
2965 // This isn't a type cast, but it still started "(", so if it is a
2966 // unary expression, it can only be a postfix_expression, so try that.
2967 // Back it up first.
2968 recedeToken();
2969 return acceptPostfixExpression(node);
2970 }
2971 }
2972
2973 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002974 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002975
John Kessenich1cc1a282016-06-03 16:55:49 -06002976 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002977 if (unaryOp == EOpNull)
2978 return acceptPostfixExpression(node);
2979
2980 // op unary_expression
2981 TSourceLoc loc = token.loc;
2982 advanceToken();
2983 if (! acceptUnaryExpression(node))
2984 return false;
2985
2986 // + is a no-op
2987 if (unaryOp == EOpAdd)
2988 return true;
2989
2990 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002991
2992 // These unary ops require lvalues
2993 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2994 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002995
2996 return node != nullptr;
2997}
2998
2999// postfix_expression
3000// : LEFT_PAREN expression RIGHT_PAREN
3001// | literal
3002// | constructor
John Kessenich8f9fdc92017-03-30 16:22:26 -06003003// | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ]
John Kessenich34fb0362016-05-03 23:17:20 -06003004// | function_call
3005// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
3006// | postfix_expression DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07003007// | postfix_expression DOT IDENTIFIER arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06003008// | postfix_expression arguments
John Kessenich34fb0362016-05-03 23:17:20 -06003009// | postfix_expression INC_OP
3010// | postfix_expression DEC_OP
3011//
3012bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
3013{
3014 // Not implemented as self-recursive:
John Kessenich54ee28f2017-03-11 14:13:00 -07003015 // The logical "right recursion" is done with a loop at the end
John Kessenich34fb0362016-05-03 23:17:20 -06003016
3017 // idToken will pick up either a variable or a function name in a function call
3018 HlslToken idToken;
3019
John Kessenich21472ae2016-06-04 11:46:33 -06003020 // Find something before the postfix operations, as they can't operate
3021 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07003022 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06003023 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003024 if (! acceptExpression(node)) {
3025 expected("expression");
3026 return false;
3027 }
3028 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003029 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003030 return false;
3031 }
John Kessenich34fb0362016-05-03 23:17:20 -06003032 } else if (acceptLiteral(node)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003033 // literal (nothing else to do yet)
John Kessenich34fb0362016-05-03 23:17:20 -06003034 } else if (acceptConstructor(node)) {
3035 // constructor (nothing else to do yet)
3036 } else if (acceptIdentifier(idToken)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003037 // user-type, namespace name, variable, or function name
3038 TString* fullName = idToken.string;
3039 while (acceptTokenClass(EHTokColonColon)) {
3040 // user-type or namespace name
3041 fullName = NewPoolTString(fullName->c_str());
3042 fullName->append(parseContext.scopeMangler);
3043 if (acceptIdentifier(idToken))
3044 fullName->append(*idToken.string);
3045 else {
3046 expected("identifier after ::");
John Kessenich54ee28f2017-03-11 14:13:00 -07003047 return false;
3048 }
John Kessenich8f9fdc92017-03-30 16:22:26 -06003049 }
3050 if (! peekTokenClass(EHTokLeftParen)) {
3051 node = parseContext.handleVariable(idToken.loc, fullName);
3052 } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) {
John Kessenich34fb0362016-05-03 23:17:20 -06003053 // function_call (nothing else to do yet)
3054 } else {
3055 expected("function call arguments");
3056 return false;
3057 }
John Kessenich21472ae2016-06-04 11:46:33 -06003058 } else {
3059 // nothing found, can't post operate
3060 return false;
John Kessenich87142c72016-03-12 20:24:24 -07003061 }
3062
John Kessenich21472ae2016-06-04 11:46:33 -06003063 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06003064 do {
3065 TSourceLoc loc = token.loc;
3066 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07003067
John Kessenich34fb0362016-05-03 23:17:20 -06003068 // Consume only a valid post-unary operator, otherwise we are done.
3069 switch (postOp) {
3070 case EOpIndexDirectStruct:
3071 case EOpIndexIndirect:
3072 case EOpPostIncrement:
3073 case EOpPostDecrement:
John Kessenich54ee28f2017-03-11 14:13:00 -07003074 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06003075 advanceToken();
3076 break;
3077 default:
3078 return true;
3079 }
John Kessenich87142c72016-03-12 20:24:24 -07003080
John Kessenich34fb0362016-05-03 23:17:20 -06003081 // We have a valid post-unary operator, process it.
3082 switch (postOp) {
John Kessenich54ee28f2017-03-11 14:13:00 -07003083 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06003084 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06003085 {
John Kessenich19b92ff2016-06-19 11:50:34 -06003086 // DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07003087 // includes swizzles, member variables, and member functions
John Kessenich93a162a2016-06-17 17:16:27 -06003088 HlslToken field;
3089 if (! acceptIdentifier(field)) {
3090 expected("swizzle or member");
3091 return false;
3092 }
LoopDawg4886f692016-06-29 10:58:58 -06003093
John Kessenich516d92d2017-03-08 20:09:03 -07003094 if (peekTokenClass(EHTokLeftParen)) {
3095 // member function
3096 TIntermTyped* thisNode = node;
LoopDawg4886f692016-06-29 10:58:58 -06003097
John Kessenich516d92d2017-03-08 20:09:03 -07003098 // arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06003099 if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) {
LoopDawg4886f692016-06-29 10:58:58 -06003100 expected("function parameters");
3101 return false;
3102 }
John Kessenich516d92d2017-03-08 20:09:03 -07003103 } else
3104 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06003105
John Kessenich34fb0362016-05-03 23:17:20 -06003106 break;
John Kessenich93a162a2016-06-17 17:16:27 -06003107 }
John Kessenich34fb0362016-05-03 23:17:20 -06003108 case EOpIndexIndirect:
3109 {
John Kessenich19b92ff2016-06-19 11:50:34 -06003110 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06003111 TIntermTyped* indexNode = nullptr;
3112 if (! acceptExpression(indexNode) ||
3113 ! peekTokenClass(EHTokRightBracket)) {
3114 expected("expression followed by ']'");
3115 return false;
3116 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003117 advanceToken();
3118 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
steve-lunarg2efd6c62017-04-06 20:22:20 -06003119 if (node == nullptr)
3120 return false;
John Kessenich19b92ff2016-06-19 11:50:34 -06003121 break;
John Kessenich34fb0362016-05-03 23:17:20 -06003122 }
3123 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06003124 // INC_OP
3125 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06003126 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06003127 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06003128 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06003129 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06003130 break;
3131 default:
3132 assert(0);
3133 break;
3134 }
3135 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07003136}
3137
John Kessenichd016be12016-03-13 11:24:20 -06003138// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06003139// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06003140//
3141bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
3142{
3143 // type
3144 TType type;
3145 if (acceptType(type)) {
John Kessenichc633f642017-04-03 21:48:37 -06003146 TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type);
John Kessenichd016be12016-03-13 11:24:20 -06003147 if (constructorFunction == nullptr)
3148 return false;
3149
3150 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06003151 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06003152 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07003153 // It's possible this is a type keyword used as an identifier. Put the token back
3154 // for later use.
3155 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06003156 return false;
3157 }
3158
3159 // hook it up
3160 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
3161
John Kessenichbb79abc2017-10-07 13:23:09 -06003162 return node != nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06003163 }
3164
3165 return false;
3166}
3167
John Kessenich34fb0362016-05-03 23:17:20 -06003168// The function_call identifier was already recognized, and passed in as idToken.
3169//
3170// function_call
3171// : [idToken] arguments
3172//
John Kessenich8f9fdc92017-03-30 16:22:26 -06003173bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject)
John Kessenich34fb0362016-05-03 23:17:20 -06003174{
John Kessenich54ee28f2017-03-11 14:13:00 -07003175 // name
3176 TString* functionName = nullptr;
John Kessenich8f9fdc92017-03-30 16:22:26 -06003177 if (baseObject == nullptr) {
3178 functionName = &name;
3179 } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) {
John Kessenich4960baa2017-03-19 18:09:59 -06003180 // Built-in methods are not in the symbol table as methods, but as global functions
3181 // taking an explicit 'this' as the first argument.
steve-lunarge7d07522017-03-19 18:12:37 -06003182 functionName = NewPoolTString(BUILTIN_PREFIX);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003183 functionName->append(name);
John Kessenich4960baa2017-03-19 18:09:59 -06003184 } else {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003185 if (! baseObject->getType().isStruct()) {
3186 expected("structure");
3187 return false;
3188 }
John Kessenich54ee28f2017-03-11 14:13:00 -07003189 functionName = NewPoolTString("");
John Kessenich8f9fdc92017-03-30 16:22:26 -06003190 functionName->append(baseObject->getType().getTypeName());
John Kessenichf3d88bd2017-03-19 12:24:29 -06003191 parseContext.addScopeMangler(*functionName);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003192 functionName->append(name);
John Kessenich5f12d2f2017-03-11 09:39:55 -07003193 }
LoopDawg4886f692016-06-29 10:58:58 -06003194
John Kessenich54ee28f2017-03-11 14:13:00 -07003195 // function
3196 TFunction* function = new TFunction(functionName, TType(EbtVoid));
3197
3198 // arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07003199 TIntermTyped* arguments = nullptr;
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003200 if (baseObject != nullptr) {
3201 // Non-static member functions have an implicit first argument of the base object.
John Kessenich54ee28f2017-03-11 14:13:00 -07003202 parseContext.handleFunctionArgument(function, arguments, baseObject);
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003203 }
John Kessenich4678ca92016-05-13 09:33:42 -06003204 if (! acceptArguments(function, arguments))
3205 return false;
3206
John Kessenich54ee28f2017-03-11 14:13:00 -07003207 // call
John Kessenich8f9fdc92017-03-30 16:22:26 -06003208 node = parseContext.handleFunctionCall(loc, function, arguments);
John Kessenich4678ca92016-05-13 09:33:42 -06003209
John Kessenichbb79abc2017-10-07 13:23:09 -06003210 return node != nullptr;
John Kessenich34fb0362016-05-03 23:17:20 -06003211}
3212
John Kessenich87142c72016-03-12 20:24:24 -07003213// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06003214// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003215//
John Kessenichd016be12016-03-13 11:24:20 -06003216// The arguments are pushed onto the 'function' argument list and
3217// onto the 'arguments' aggregate.
3218//
John Kessenich4678ca92016-05-13 09:33:42 -06003219bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07003220{
John Kessenich078d7f22016-03-14 10:02:11 -06003221 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003222 if (! acceptTokenClass(EHTokLeftParen))
3223 return false;
3224
John Kessenich2aa12b12017-04-18 14:47:33 -06003225 // RIGHT_PAREN
3226 if (acceptTokenClass(EHTokRightParen))
3227 return true;
3228
3229 // must now be at least one expression...
John Kessenich87142c72016-03-12 20:24:24 -07003230 do {
John Kessenichd016be12016-03-13 11:24:20 -06003231 // expression
John Kessenich87142c72016-03-12 20:24:24 -07003232 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06003233 if (! acceptAssignmentExpression(arg))
John Kessenich2aa12b12017-04-18 14:47:33 -06003234 return false;
John Kessenichd016be12016-03-13 11:24:20 -06003235
3236 // hook it up
3237 parseContext.handleFunctionArgument(function, arguments, arg);
3238
John Kessenich078d7f22016-03-14 10:02:11 -06003239 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07003240 if (! acceptTokenClass(EHTokComma))
3241 break;
3242 } while (true);
3243
John Kessenich078d7f22016-03-14 10:02:11 -06003244 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003245 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003246 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003247 return false;
3248 }
3249
3250 return true;
3251}
3252
3253bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
3254{
3255 switch (token.tokenClass) {
3256 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003257 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003258 break;
steve-lunarg2de32912016-07-28 14:49:48 -06003259 case EHTokUintConstant:
3260 node = intermediate.addConstantUnion(token.u, token.loc, true);
3261 break;
John Kessenich87142c72016-03-12 20:24:24 -07003262 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003263 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003264 break;
3265 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003266 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003267 break;
3268 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003269 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003270 break;
John Kessenich86f71382016-09-19 20:23:18 -06003271 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07003272 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06003273 break;
John Kessenich87142c72016-03-12 20:24:24 -07003274
3275 default:
3276 return false;
3277 }
3278
3279 advanceToken();
3280
3281 return true;
3282}
3283
John Kessenich0e071192017-06-06 11:37:33 -06003284// simple_statement
3285// : SEMICOLON
3286// | declaration_statement
3287// | expression SEMICOLON
3288//
3289bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement)
3290{
3291 // SEMICOLON
3292 if (acceptTokenClass(EHTokSemicolon))
3293 return true;
3294
3295 // declaration
3296 if (acceptDeclaration(statement))
3297 return true;
3298
3299 // expression
3300 TIntermTyped* node;
3301 if (acceptExpression(node))
3302 statement = node;
3303 else
3304 return false;
3305
3306 // SEMICOLON (following an expression)
3307 if (acceptTokenClass(EHTokSemicolon))
3308 return true;
3309 else {
3310 expected(";");
3311 return false;
3312 }
3313}
3314
John Kessenich5f934b02016-03-13 17:58:25 -06003315// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06003316// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003317//
John Kessenich21472ae2016-06-04 11:46:33 -06003318bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07003319{
John Kessenich21472ae2016-06-04 11:46:33 -06003320 TIntermAggregate* compoundStatement = nullptr;
3321
John Kessenich34fb0362016-05-03 23:17:20 -06003322 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003323 if (! acceptTokenClass(EHTokLeftBrace))
3324 return false;
3325
3326 // statement statement ...
3327 TIntermNode* statement = nullptr;
3328 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06003329 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
3330 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
3331 branch->getFlowOp() == EOpDefault)) {
3332 // hook up individual subsequences within a switch statement
3333 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
3334 compoundStatement = nullptr;
3335 } else {
3336 // hook it up to the growing compound statement
3337 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
3338 }
John Kessenich5f934b02016-03-13 17:58:25 -06003339 }
John Kessenich34fb0362016-05-03 23:17:20 -06003340 if (compoundStatement)
3341 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06003342
John Kessenich21472ae2016-06-04 11:46:33 -06003343 retStatement = compoundStatement;
3344
John Kessenich34fb0362016-05-03 23:17:20 -06003345 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003346 return acceptTokenClass(EHTokRightBrace);
3347}
3348
John Kessenich0d2b6de2016-06-05 11:23:11 -06003349bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
3350{
3351 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06003352 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003353 parseContext.popScope();
3354
3355 return result;
3356}
3357
John Kessenich077e0522016-06-09 02:02:17 -06003358bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003359{
John Kessenich077e0522016-06-09 02:02:17 -06003360 parseContext.pushScope();
3361 bool result = acceptCompoundStatement(statement);
3362 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06003363
3364 return result;
3365}
3366
John Kessenich5f934b02016-03-13 17:58:25 -06003367// statement
John Kessenich21472ae2016-06-04 11:46:33 -06003368// : attributes attributed_statement
3369//
3370// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003371// : compound_statement
John Kessenich0e071192017-06-06 11:37:33 -06003372// | simple_statement
John Kessenich21472ae2016-06-04 11:46:33 -06003373// | selection_statement
3374// | switch_statement
3375// | case_label
John Kessenich0e071192017-06-06 11:37:33 -06003376// | default_label
John Kessenich21472ae2016-06-04 11:46:33 -06003377// | iteration_statement
3378// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003379//
3380bool HlslGrammar::acceptStatement(TIntermNode*& statement)
3381{
John Kessenich21472ae2016-06-04 11:46:33 -06003382 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06003383
John Kessenich21472ae2016-06-04 11:46:33 -06003384 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06003385 TAttributeMap attributes;
3386 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003387
John Kessenich21472ae2016-06-04 11:46:33 -06003388 // attributed_statement
3389 switch (peek()) {
3390 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06003391 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06003392
John Kessenich21472ae2016-06-04 11:46:33 -06003393 case EHTokIf:
Rex Xu57e65922017-07-04 23:23:40 +08003394 return acceptSelectionStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003395
John Kessenich21472ae2016-06-04 11:46:33 -06003396 case EHTokSwitch:
Rex Xu57e65922017-07-04 23:23:40 +08003397 return acceptSwitchStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003398
John Kessenich21472ae2016-06-04 11:46:33 -06003399 case EHTokFor:
3400 case EHTokDo:
3401 case EHTokWhile:
steve-lunargf1709e72017-05-02 20:14:50 -06003402 return acceptIterationStatement(statement, attributes);
John Kessenich21472ae2016-06-04 11:46:33 -06003403
3404 case EHTokContinue:
3405 case EHTokBreak:
3406 case EHTokDiscard:
3407 case EHTokReturn:
3408 return acceptJumpStatement(statement);
3409
3410 case EHTokCase:
3411 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003412 case EHTokDefault:
3413 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003414
John Kessenich21472ae2016-06-04 11:46:33 -06003415 case EHTokRightBrace:
3416 // Performance: not strictly necessary, but stops a bunch of hunting early,
3417 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06003418 return false;
3419
John Kessenich21472ae2016-06-04 11:46:33 -06003420 default:
John Kessenich0e071192017-06-06 11:37:33 -06003421 return acceptSimpleStatement(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003422 }
3423
John Kessenich5f934b02016-03-13 17:58:25 -06003424 return true;
John Kessenich87142c72016-03-12 20:24:24 -07003425}
3426
John Kessenich21472ae2016-06-04 11:46:33 -06003427// attributes
John Kessenich77ea30b2017-09-30 14:34:50 -06003428// : [zero or more:] bracketed-attribute
3429//
3430// bracketed-attribute:
3431// : LEFT_BRACKET scoped-attribute RIGHT_BRACKET
3432// : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET
3433//
3434// scoped-attribute:
3435// : attribute
3436// | namespace COLON COLON attribute
John Kessenich21472ae2016-06-04 11:46:33 -06003437//
3438// attribute:
3439// : UNROLL
3440// | UNROLL LEFT_PAREN literal RIGHT_PAREN
3441// | FASTOPT
3442// | ALLOW_UAV_CONDITION
3443// | BRANCH
3444// | FLATTEN
3445// | FORCECASE
3446// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06003447// | DOMAIN
3448// | EARLYDEPTHSTENCIL
3449// | INSTANCE
3450// | MAXTESSFACTOR
3451// | OUTPUTCONTROLPOINTS
3452// | OUTPUTTOPOLOGY
3453// | PARTITIONING
3454// | PATCHCONSTANTFUNC
3455// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06003456//
steve-lunarg1868b142016-10-20 13:07:10 -06003457void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003458{
steve-lunarg1868b142016-10-20 13:07:10 -06003459 // For now, accept the [ XXX(X) ] syntax, but drop all but
3460 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06003461 // TODO: subset to correct set? Pass on?
3462 do {
John Kessenich77ea30b2017-09-30 14:34:50 -06003463 HlslToken attributeToken;
steve-lunarg1868b142016-10-20 13:07:10 -06003464
John Kessenich0d2b6de2016-06-05 11:23:11 -06003465 // LEFT_BRACKET?
3466 if (! acceptTokenClass(EHTokLeftBracket))
3467 return;
John Kessenich77ea30b2017-09-30 14:34:50 -06003468 // another LEFT_BRACKET?
3469 bool doubleBrackets = false;
3470 if (acceptTokenClass(EHTokLeftBracket))
3471 doubleBrackets = true;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003472
John Kessenich77ea30b2017-09-30 14:34:50 -06003473 // attribute? (could be namespace; will adjust later)
3474 if (!acceptIdentifier(attributeToken)) {
3475 if (!peekTokenClass(EHTokRightBracket)) {
3476 expected("namespace or attribute identifier");
3477 advanceToken();
3478 }
3479 }
3480
3481 TString nameSpace;
3482 if (acceptTokenClass(EHTokColonColon)) {
3483 // namespace COLON COLON
3484 nameSpace = *attributeToken.string;
3485 // attribute
3486 if (!acceptIdentifier(attributeToken)) {
3487 expected("attribute identifier");
3488 return;
3489 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003490 }
3491
steve-lunarga22f7db2016-11-11 08:17:44 -07003492 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06003493
3494 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003495 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07003496 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06003497
John Kessenich0d2b6de2016-06-05 11:23:11 -06003498 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07003499 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07003500
steve-lunarga22f7db2016-11-11 08:17:44 -07003501 while (acceptAssignmentExpression(node)) {
3502 expectingExpression = false;
3503 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06003504 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07003505 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06003506 }
3507
steve-lunarga22f7db2016-11-11 08:17:44 -07003508 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06003509 if (! acceptTokenClass(EHTokRightParen))
3510 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07003511
3512 // Error for partial or missing expression
3513 if (expectingExpression || expressions->getSequence().empty())
3514 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06003515 }
3516
3517 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06003518 if (!acceptTokenClass(EHTokRightBracket)) {
3519 expected("]");
3520 return;
3521 }
John Kessenich77ea30b2017-09-30 14:34:50 -06003522 // another RIGHT_BRACKET?
3523 if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) {
3524 expected("]]");
3525 return;
3526 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003527
steve-lunarg1868b142016-10-20 13:07:10 -06003528 // Add any values we found into the attribute map. This accepts
3529 // (and ignores) values not mapping to a known TAttributeType;
John Kessenich77ea30b2017-09-30 14:34:50 -06003530 attributes.setAttribute(nameSpace, attributeToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003531 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06003532}
3533
John Kessenich0d2b6de2016-06-05 11:23:11 -06003534// selection_statement
3535// : IF LEFT_PAREN expression RIGHT_PAREN statement
3536// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
3537//
Rex Xu57e65922017-07-04 23:23:40 +08003538bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003539{
John Kessenich0d2b6de2016-06-05 11:23:11 -06003540 TSourceLoc loc = token.loc;
3541
Rex Xu57e65922017-07-04 23:23:40 +08003542 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3543
John Kessenich0d2b6de2016-06-05 11:23:11 -06003544 // IF
3545 if (! acceptTokenClass(EHTokIf))
3546 return false;
3547
3548 // so that something declared in the condition is scoped to the lifetimes
3549 // of the then-else statements
3550 parseContext.pushScope();
3551
3552 // LEFT_PAREN expression RIGHT_PAREN
3553 TIntermTyped* condition;
3554 if (! acceptParenExpression(condition))
3555 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003556 condition = parseContext.convertConditionalExpression(loc, condition);
3557 if (condition == nullptr)
3558 return false;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003559
3560 // create the child statements
3561 TIntermNodePair thenElse = { nullptr, nullptr };
3562
John Kessenichf6deacd2017-06-06 19:52:55 -06003563 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
3564
John Kessenich0d2b6de2016-06-05 11:23:11 -06003565 // then statement
3566 if (! acceptScopedStatement(thenElse.node1)) {
3567 expected("then statement");
3568 return false;
3569 }
3570
3571 // ELSE
3572 if (acceptTokenClass(EHTokElse)) {
3573 // else statement
3574 if (! acceptScopedStatement(thenElse.node2)) {
3575 expected("else statement");
3576 return false;
3577 }
3578 }
3579
3580 // Put the pieces together
Rex Xu57e65922017-07-04 23:23:40 +08003581 statement = intermediate.addSelection(condition, thenElse, loc, control);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003582 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003583 --parseContext.controlFlowNestingLevel;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003584
3585 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003586}
3587
John Kessenichd02dc5d2016-07-01 00:04:11 -06003588// switch_statement
3589// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
3590//
Rex Xu57e65922017-07-04 23:23:40 +08003591bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003592{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003593 // SWITCH
3594 TSourceLoc loc = token.loc;
Rex Xu57e65922017-07-04 23:23:40 +08003595
3596 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3597
John Kessenichd02dc5d2016-07-01 00:04:11 -06003598 if (! acceptTokenClass(EHTokSwitch))
3599 return false;
3600
3601 // LEFT_PAREN expression RIGHT_PAREN
3602 parseContext.pushScope();
3603 TIntermTyped* switchExpression;
3604 if (! acceptParenExpression(switchExpression)) {
3605 parseContext.popScope();
3606 return false;
3607 }
3608
3609 // compound_statement
3610 parseContext.pushSwitchSequence(new TIntermSequence);
John Kessenichf6deacd2017-06-06 19:52:55 -06003611
3612 ++parseContext.controlFlowNestingLevel;
John Kessenichd02dc5d2016-07-01 00:04:11 -06003613 bool statementOkay = acceptCompoundStatement(statement);
John Kessenichf6deacd2017-06-06 19:52:55 -06003614 --parseContext.controlFlowNestingLevel;
3615
John Kessenichd02dc5d2016-07-01 00:04:11 -06003616 if (statementOkay)
Rex Xu57e65922017-07-04 23:23:40 +08003617 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, control);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003618
3619 parseContext.popSwitchSequence();
3620 parseContext.popScope();
3621
3622 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003623}
3624
John Kessenich119f8f62016-06-05 15:44:07 -06003625// iteration_statement
3626// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3627// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3628// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3629//
3630// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
steve-lunargf1709e72017-05-02 20:14:50 -06003631bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003632{
John Kessenich119f8f62016-06-05 15:44:07 -06003633 TSourceLoc loc = token.loc;
3634 TIntermTyped* condition = nullptr;
3635
3636 EHlslTokenClass loop = peek();
3637 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3638
3639 // WHILE or DO or FOR
3640 advanceToken();
steve-lunargf1709e72017-05-02 20:14:50 -06003641
3642 const TLoopControl control = parseContext.handleLoopControl(attributes);
John Kessenich119f8f62016-06-05 15:44:07 -06003643
3644 switch (loop) {
3645 case EHTokWhile:
3646 // so that something declared in the condition is scoped to the lifetime
3647 // of the while sub-statement
John Kessenichf6deacd2017-06-06 19:52:55 -06003648 parseContext.pushScope(); // this only needs to work right if no errors
John Kessenich119f8f62016-06-05 15:44:07 -06003649 parseContext.nestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003650 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003651
3652 // LEFT_PAREN condition RIGHT_PAREN
3653 if (! acceptParenExpression(condition))
3654 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003655 condition = parseContext.convertConditionalExpression(loc, condition);
3656 if (condition == nullptr)
3657 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003658
3659 // statement
3660 if (! acceptScopedStatement(statement)) {
3661 expected("while sub-statement");
3662 return false;
3663 }
3664
3665 parseContext.unnestLooping();
3666 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003667 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003668
steve-lunargf1709e72017-05-02 20:14:50 -06003669 statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003670
3671 return true;
3672
3673 case EHTokDo:
John Kessenichf6deacd2017-06-06 19:52:55 -06003674 parseContext.nestLooping(); // this only needs to work right if no errors
3675 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003676
John Kessenich119f8f62016-06-05 15:44:07 -06003677 // statement
John Kessenich0c6f9362017-04-20 11:08:24 -06003678 if (! acceptScopedStatement(statement)) {
John Kessenich119f8f62016-06-05 15:44:07 -06003679 expected("do sub-statement");
3680 return false;
3681 }
3682
John Kessenich119f8f62016-06-05 15:44:07 -06003683 // WHILE
3684 if (! acceptTokenClass(EHTokWhile)) {
3685 expected("while");
3686 return false;
3687 }
3688
3689 // LEFT_PAREN condition RIGHT_PAREN
John Kessenich119f8f62016-06-05 15:44:07 -06003690 if (! acceptParenExpression(condition))
3691 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003692 condition = parseContext.convertConditionalExpression(loc, condition);
3693 if (condition == nullptr)
3694 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003695
3696 if (! acceptTokenClass(EHTokSemicolon))
3697 expected(";");
3698
3699 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003700 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003701
steve-lunargf1709e72017-05-02 20:14:50 -06003702 statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003703
3704 return true;
3705
3706 case EHTokFor:
3707 {
3708 // LEFT_PAREN
3709 if (! acceptTokenClass(EHTokLeftParen))
3710 expected("(");
3711
3712 // so that something declared in the condition is scoped to the lifetime
3713 // of the for sub-statement
3714 parseContext.pushScope();
3715
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003716 // initializer
3717 TIntermNode* initNode = nullptr;
John Kessenich0e071192017-06-06 11:37:33 -06003718 if (! acceptSimpleStatement(initNode))
3719 expected("for-loop initializer statement");
John Kessenich119f8f62016-06-05 15:44:07 -06003720
John Kessenichf6deacd2017-06-06 19:52:55 -06003721 parseContext.nestLooping(); // this only needs to work right if no errors
3722 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003723
3724 // condition SEMI_COLON
3725 acceptExpression(condition);
3726 if (! acceptTokenClass(EHTokSemicolon))
3727 expected(";");
John Kessenich7e997e22017-03-30 22:09:30 -06003728 if (condition != nullptr) {
3729 condition = parseContext.convertConditionalExpression(loc, condition);
3730 if (condition == nullptr)
3731 return false;
3732 }
John Kessenich119f8f62016-06-05 15:44:07 -06003733
3734 // iterator SEMI_COLON
3735 TIntermTyped* iterator = nullptr;
3736 acceptExpression(iterator);
3737 if (! acceptTokenClass(EHTokRightParen))
3738 expected(")");
3739
3740 // statement
3741 if (! acceptScopedStatement(statement)) {
3742 expected("for sub-statement");
3743 return false;
3744 }
3745
steve-lunargf1709e72017-05-02 20:14:50 -06003746 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003747
3748 parseContext.popScope();
3749 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003750 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003751
3752 return true;
3753 }
3754
3755 default:
3756 return false;
3757 }
John Kessenich21472ae2016-06-04 11:46:33 -06003758}
3759
3760// jump_statement
3761// : CONTINUE SEMICOLON
3762// | BREAK SEMICOLON
3763// | DISCARD SEMICOLON
3764// | RETURN SEMICOLON
3765// | RETURN expression SEMICOLON
3766//
3767bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3768{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003769 EHlslTokenClass jump = peek();
3770 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003771 case EHTokContinue:
3772 case EHTokBreak:
3773 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003774 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003775 advanceToken();
3776 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003777 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003778 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003779 return false;
3780 }
John Kessenich21472ae2016-06-04 11:46:33 -06003781
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003782 switch (jump) {
3783 case EHTokContinue:
3784 statement = intermediate.addBranch(EOpContinue, token.loc);
3785 break;
3786 case EHTokBreak:
3787 statement = intermediate.addBranch(EOpBreak, token.loc);
3788 break;
3789 case EHTokDiscard:
3790 statement = intermediate.addBranch(EOpKill, token.loc);
3791 break;
3792
3793 case EHTokReturn:
3794 {
3795 // expression
3796 TIntermTyped* node;
3797 if (acceptExpression(node)) {
3798 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003799 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003800 } else
3801 statement = intermediate.addBranch(EOpReturn, token.loc);
3802 break;
3803 }
3804
3805 default:
3806 assert(0);
3807 return false;
3808 }
3809
3810 // SEMICOLON
3811 if (! acceptTokenClass(EHTokSemicolon))
3812 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003813
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003814 return true;
3815}
John Kessenich21472ae2016-06-04 11:46:33 -06003816
John Kessenichd02dc5d2016-07-01 00:04:11 -06003817// case_label
3818// : CASE expression COLON
3819//
John Kessenich21472ae2016-06-04 11:46:33 -06003820bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3821{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003822 TSourceLoc loc = token.loc;
3823 if (! acceptTokenClass(EHTokCase))
3824 return false;
3825
3826 TIntermTyped* expression;
3827 if (! acceptExpression(expression)) {
3828 expected("case expression");
3829 return false;
3830 }
3831
3832 if (! acceptTokenClass(EHTokColon)) {
3833 expected(":");
3834 return false;
3835 }
3836
3837 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3838
3839 return true;
3840}
3841
3842// default_label
3843// : DEFAULT COLON
3844//
3845bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3846{
3847 TSourceLoc loc = token.loc;
3848 if (! acceptTokenClass(EHTokDefault))
3849 return false;
3850
3851 if (! acceptTokenClass(EHTokColon)) {
3852 expected(":");
3853 return false;
3854 }
3855
3856 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3857
3858 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003859}
3860
John Kessenich19b92ff2016-06-19 11:50:34 -06003861// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003862// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3863// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003864//
3865void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3866{
3867 arraySizes = nullptr;
3868
steve-lunarg7b211a32016-10-13 12:26:18 -06003869 // Early-out if there aren't any array dimensions
3870 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003871 return;
3872
steve-lunarg7b211a32016-10-13 12:26:18 -06003873 // 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 -06003874 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003875
3876 // Collect each array dimension.
3877 while (acceptTokenClass(EHTokLeftBracket)) {
3878 TSourceLoc loc = token.loc;
3879 TIntermTyped* sizeExpr = nullptr;
3880
John Kessenich057df292017-03-06 18:18:37 -07003881 // Array sizing expression is optional. If omitted, array will be later sized by initializer list.
steve-lunarg7b211a32016-10-13 12:26:18 -06003882 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3883
3884 if (! acceptTokenClass(EHTokRightBracket)) {
3885 expected("]");
3886 return;
3887 }
3888
3889 if (hasArraySize) {
3890 TArraySize arraySize;
3891 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3892 arraySizes->addInnerSize(arraySize);
3893 } else {
3894 arraySizes->addInnerSize(0); // sized by initializers.
3895 }
steve-lunarg265c0612016-09-27 10:57:35 -06003896 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003897}
3898
John Kessenich630dd7d2016-06-12 23:52:12 -06003899// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003900// : COLON semantic // optional
3901// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3902// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003903// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003904// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003905//
John Kessenich854fe242017-03-02 14:30:59 -07003906// Return true if any tokens were accepted. That is,
3907// false can be returned on successfully recognizing nothing,
3908// not necessarily meaning bad syntax.
3909//
3910bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003911{
John Kessenich854fe242017-03-02 14:30:59 -07003912 bool found = false;
3913
John Kessenich630dd7d2016-06-12 23:52:12 -06003914 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003915 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003916 if (acceptTokenClass(EHTokColon)) {
John Kessenich854fe242017-03-02 14:30:59 -07003917 found = true;
John Kessenich630dd7d2016-06-12 23:52:12 -06003918 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003919 if (peekTokenClass(EHTokLayout))
3920 acceptLayoutQualifierList(qualifier);
3921 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003922 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003923 if (! acceptTokenClass(EHTokLeftParen)) {
3924 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003925 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003926 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003927 HlslToken locationToken;
3928 if (! acceptIdentifier(locationToken)) {
3929 expected("c[subcomponent][.component]");
John Kessenich854fe242017-03-02 14:30:59 -07003930 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003931 }
3932 HlslToken componentToken;
3933 if (acceptTokenClass(EHTokDot)) {
3934 if (! acceptIdentifier(componentToken)) {
3935 expected("component");
John Kessenich854fe242017-03-02 14:30:59 -07003936 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003937 }
3938 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003939 if (! acceptTokenClass(EHTokRightParen)) {
3940 expected(")");
3941 break;
3942 }
John Kessenich7735b942016-09-05 12:40:06 -06003943 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003944 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003945 expected("layout, semantic, packoffset, or register");
John Kessenich854fe242017-03-02 14:30:59 -07003946 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003947 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003948 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3949 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003950 if (! acceptTokenClass(EHTokLeftParen)) {
3951 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003952 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003953 }
John Kessenichb38f0712016-07-30 10:29:54 -06003954 HlslToken registerDesc; // for Type#
3955 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003956 if (! acceptIdentifier(registerDesc)) {
3957 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003958 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003959 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003960 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3961 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003962 // Then we didn't really see the registerDesc yet, it was
3963 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003964 profile = registerDesc;
3965 if (! acceptIdentifier(registerDesc)) {
3966 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003967 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003968 }
3969 }
John Kessenichb38f0712016-07-30 10:29:54 -06003970 int subComponent = 0;
3971 if (acceptTokenClass(EHTokLeftBracket)) {
3972 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3973 if (! peekTokenClass(EHTokIntConstant)) {
3974 expected("literal integer");
John Kessenich854fe242017-03-02 14:30:59 -07003975 return false;
John Kessenichb38f0712016-07-30 10:29:54 -06003976 }
3977 subComponent = token.i;
3978 advanceToken();
3979 if (! acceptTokenClass(EHTokRightBracket)) {
3980 expected("]");
3981 break;
3982 }
3983 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003984 // (COMMA SPACEN)opt
3985 HlslToken spaceDesc;
3986 if (acceptTokenClass(EHTokComma)) {
3987 if (! acceptIdentifier(spaceDesc)) {
3988 expected ("space identifier");
John Kessenich854fe242017-03-02 14:30:59 -07003989 return false;
John Kessenichcfd7ce82016-09-05 16:03:12 -06003990 }
3991 }
3992 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003993 if (! acceptTokenClass(EHTokRightParen)) {
3994 expected(")");
3995 break;
3996 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003997 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003998 } else {
3999 // semantic, in idToken.string
John Kessenich2dd643f2017-03-14 21:50:06 -06004000 TString semanticUpperCase = *idToken.string;
4001 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
4002 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
John Kessenich630dd7d2016-06-12 23:52:12 -06004003 }
John Kessenich854fe242017-03-02 14:30:59 -07004004 } else if (peekTokenClass(EHTokLeftAngle)) {
4005 found = true;
John Kessenicha1e2d492016-09-20 13:22:58 -06004006 acceptAnnotations(qualifier);
John Kessenich854fe242017-03-02 14:30:59 -07004007 } else
John Kessenich630dd7d2016-06-12 23:52:12 -06004008 break;
John Kessenich078d7f22016-03-14 10:02:11 -06004009
John Kessenich630dd7d2016-06-12 23:52:12 -06004010 } while (true);
John Kessenich854fe242017-03-02 14:30:59 -07004011
4012 return found;
John Kessenich078d7f22016-03-14 10:02:11 -06004013}
4014
John Kessenichb16f7e62017-03-11 19:32:47 -07004015//
4016// Get the stream of tokens from the scanner, but skip all syntactic/semantic
4017// processing.
4018//
4019bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
4020{
4021 if (! peekTokenClass(EHTokLeftBrace))
4022 return false;
4023
4024 int braceCount = 0;
4025
4026 do {
4027 switch (peek()) {
4028 case EHTokLeftBrace:
4029 ++braceCount;
4030 break;
4031 case EHTokRightBrace:
4032 --braceCount;
4033 break;
4034 case EHTokNone:
4035 // End of input before balance { } is bad...
4036 return false;
4037 default:
4038 break;
4039 }
4040
4041 tokens.push_back(token);
4042 advanceToken();
4043 } while (braceCount > 0);
4044
4045 return true;
4046}
4047
John Kessenich0320d092017-06-13 22:22:52 -06004048// Return a string for just the types that can also be declared as an identifier.
4049const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const
4050{
4051 switch (tokenClass) {
4052 case EHTokSample: return "sample";
4053 case EHTokHalf: return "half";
4054 case EHTokHalf1x1: return "half1x1";
4055 case EHTokHalf1x2: return "half1x2";
4056 case EHTokHalf1x3: return "half1x3";
4057 case EHTokHalf1x4: return "half1x4";
4058 case EHTokHalf2x1: return "half2x1";
4059 case EHTokHalf2x2: return "half2x2";
4060 case EHTokHalf2x3: return "half2x3";
4061 case EHTokHalf2x4: return "half2x4";
4062 case EHTokHalf3x1: return "half3x1";
4063 case EHTokHalf3x2: return "half3x2";
4064 case EHTokHalf3x3: return "half3x3";
4065 case EHTokHalf3x4: return "half3x4";
4066 case EHTokHalf4x1: return "half4x1";
4067 case EHTokHalf4x2: return "half4x2";
4068 case EHTokHalf4x3: return "half4x3";
4069 case EHTokHalf4x4: return "half4x4";
4070 case EHTokBool: return "bool";
4071 case EHTokFloat: return "float";
4072 case EHTokDouble: return "double";
4073 case EHTokInt: return "int";
4074 case EHTokUint: return "uint";
4075 case EHTokMin16float: return "min16float";
4076 case EHTokMin10float: return "min10float";
4077 case EHTokMin16int: return "min16int";
4078 case EHTokMin12int: return "min12int";
LoopDawg7ee29ba2017-11-27 14:45:36 -07004079 case EHTokConstantBuffer: return "ConstantBuffer";
John Kessenich0320d092017-06-13 22:22:52 -06004080 default:
4081 return nullptr;
4082 }
4083}
4084
John Kesseniche01a9bc2016-03-12 20:11:22 -07004085} // end namespace glslang