blob: db7397cfda2d7bb84ce5bd4bccffc0fdf034b97c [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 Kessenich54ee28f2017-03-11 14:13:00 -0700379 if (! acceptFullySpecifiedType(declaredType, nodeList))
John Kessenich87142c72016-03-12 20:24:24 -0700380 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600381
John Kessenich77ea30b2017-09-30 14:34:50 -0600382 parseContext.transferTypeAttributes(declarator.attributes, declaredType);
383
John Kessenich2fcdd642017-06-19 15:41:11 -0600384 // cbuffer and tbuffer end with the closing '}'.
385 // No semicolon is included.
386 if (forbidDeclarators)
387 return true;
388
John Kessenich054378d2017-06-19 15:13:26 -0600389 // declarator_list
390 // : declarator
391 // : identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600392 HlslToken idToken;
John Kessenichca71d942017-03-07 20:44:09 -0700393 TIntermAggregate* initializers = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600394 while (acceptIdentifier(idToken)) {
John Kessenich9855bda2017-09-11 21:48:19 -0600395 TString *fullName = idToken.string;
John Kessenich8f9fdc92017-03-30 16:22:26 -0600396 if (parseContext.symbolTable.atGlobalLevel())
397 parseContext.getFullNamespaceName(fullName);
John Kessenich78388722017-03-08 18:53:51 -0700398 if (peekTokenClass(EHTokLeftParen)) {
399 // looks like function parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600400
John Kessenich78388722017-03-08 18:53:51 -0700401 // Potentially rename shader entry point function. No-op most of the time.
John Kessenich8f9fdc92017-03-30 16:22:26 -0600402 parseContext.renameShaderFunction(fullName);
steve-lunargf1e0c872016-10-31 15:13:43 -0600403
John Kessenich78388722017-03-08 18:53:51 -0700404 // function_parameters
John Kessenich8f9fdc92017-03-30 16:22:26 -0600405 declarator.function = new TFunction(fullName, declaredType);
John Kessenich088d52b2017-03-11 17:55:28 -0700406 if (!acceptFunctionParameters(*declarator.function)) {
John Kessenich78388722017-03-08 18:53:51 -0700407 expected("function parameter list");
408 return false;
409 }
410
John Kessenich630dd7d2016-06-12 23:52:12 -0600411 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -0700412 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600413
John Kessenichd5ed0b62016-07-04 17:32:45 -0600414 // compound_statement (function body definition) or just a prototype?
John Kessenich088d52b2017-03-11 17:55:28 -0700415 declarator.loc = token.loc;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600416 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich54ee28f2017-03-11 14:13:00 -0700417 if (declarator_list)
John Kessenichd5ed0b62016-07-04 17:32:45 -0600418 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600419 if (typedefDecl)
420 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenichb16f7e62017-03-11 19:32:47 -0700421 return acceptFunctionDefinition(declarator, nodeList, nullptr);
John Kessenich5e69ec62016-07-05 00:02:40 -0600422 } else {
423 if (typedefDecl)
424 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich088d52b2017-03-11 17:55:28 -0700425 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600426 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600427 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600428 // A variable declaration. Fix the storage qualifier if it's a global.
429 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
430 declaredType.getQualifier().storage = EvqUniform;
431
John Kessenichecba76f2017-01-06 00:34:48 -0700432 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600433 // the number of types can expand when arrayness is different.
434 TType variableType;
435 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600436
John Kesseniche82061d2016-09-27 14:38:57 -0600437 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600438 TArraySizes* arraySizes = nullptr;
439 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600440
John Kesseniche82061d2016-09-27 14:38:57 -0600441 // Fix arrayness in the variableType
442 if (declaredType.isImplicitlySizedArray()) {
443 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
444 // of different sizes, for this case sharing the shallow copy of arrayness
445 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
446 variableType.newArraySizes(declaredType.getArraySizes());
447 }
448 if (arraySizes || variableType.isArray()) {
449 // In the most general case, arrayness is potentially coming both from the
450 // declared type and from the variable: "int[] a[];" or just one or the other.
451 // Merge it all to the variableType, so all arrayness is part of the variableType.
452 parseContext.arrayDimMerge(variableType, arraySizes);
453 }
454
LoopDawg4886f692016-06-29 10:58:58 -0600455 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600456 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600457 if (! acceptSamplerState())
458 return false;
459 }
460
John Kessenichd5ed0b62016-07-04 17:32:45 -0600461 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600462 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600463
464 // EQUAL assignment_expression
465 TIntermTyped* expressionNode = nullptr;
466 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600467 if (typedefDecl)
468 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600469 if (! acceptAssignmentExpression(expressionNode)) {
470 expected("initializer");
471 return false;
472 }
473 }
474
John Kessenich6dbc0a72016-09-27 19:13:05 -0600475 // TODO: things scoped within an annotation need their own name space;
476 // TODO: strings are not yet handled.
477 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
478 if (typedefDecl)
John Kessenich8f9fdc92017-03-30 16:22:26 -0600479 parseContext.declareTypedef(idToken.loc, *fullName, variableType);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600480 else if (variableType.getBasicType() == EbtBlock) {
John Kessenich8116cfc2017-12-09 04:42:42 -0700481 if (expressionNode)
482 parseContext.error(idToken.loc, "buffer aliasing not yet supported", "block initializer", "");
steve-lunarga766b832017-04-25 09:30:28 -0600483 parseContext.declareBlock(idToken.loc, variableType, fullName,
484 variableType.isArray() ? &variableType.getArraySizes() : nullptr);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600485 parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
486 } else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700487 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600488 // this isn't really an individual variable, but a member of the $Global buffer
John Kessenich8f9fdc92017-03-30 16:22:26 -0600489 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600490 } else {
491 // Declare the variable and add any initializer code to the AST.
492 // The top-level node is always made into an aggregate, as that's
493 // historically how the AST has been.
John Kessenichca71d942017-03-07 20:44:09 -0700494 initializers = intermediate.growAggregate(initializers,
John Kessenich8f9fdc92017-03-30 16:22:26 -0600495 parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode),
John Kessenichca71d942017-03-07 20:44:09 -0700496 idToken.loc);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600497 }
498 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600499 }
John Kessenich5f934b02016-03-13 17:58:25 -0600500 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600501
John Kessenich054378d2017-06-19 15:13:26 -0600502 // COMMA
503 if (acceptTokenClass(EHTokComma))
John Kessenich54ee28f2017-03-11 14:13:00 -0700504 declarator_list = true;
John Kessenich2fcdd642017-06-19 15:41:11 -0600505 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600506
John Kessenichca71d942017-03-07 20:44:09 -0700507 // The top-level initializer node is a sequence.
508 if (initializers != nullptr)
509 initializers->setOperator(EOpSequence);
510
511 // Add the initializers' aggregate to the nodeList we were handed.
512 if (nodeList)
513 nodeList = intermediate.growAggregate(nodeList, initializers);
514 else
515 nodeList = initializers;
John Kessenich87142c72016-03-12 20:24:24 -0700516
John Kessenich2fcdd642017-06-19 15:41:11 -0600517 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600518 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich2fcdd642017-06-19 15:41:11 -0600519 // This may have been a false detection of what appeared to be a declaration, but
520 // was actually an assignment such as "float = 4", where "float" is an identifier.
521 // We put the token back to let further parsing happen for cases where that may
522 // happen. This errors on the side of caution, and mostly triggers the error.
John Kessenich13075c62017-04-11 09:51:32 -0600523 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700524 recedeToken();
John Kessenich13075c62017-04-11 09:51:32 -0600525 return false;
John Kessenich13075c62017-04-11 09:51:32 -0600526 } else {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700527 expected(";");
John Kessenich13075c62017-04-11 09:51:32 -0600528 return false;
529 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600530 }
John Kessenichecba76f2017-01-06 00:34:48 -0700531
John Kesseniche01a9bc2016-03-12 20:11:22 -0700532 return true;
533}
534
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600535// control_declaration
536// : fully_specified_type identifier EQUAL expression
537//
538bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
539{
540 node = nullptr;
541
542 // fully_specified_type
543 TType type;
544 if (! acceptFullySpecifiedType(type))
545 return false;
546
John Kessenich057df292017-03-06 18:18:37 -0700547 // filter out type casts
548 if (peekTokenClass(EHTokLeftParen)) {
549 recedeToken();
550 return false;
551 }
552
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600553 // identifier
554 HlslToken idToken;
555 if (! acceptIdentifier(idToken)) {
556 expected("identifier");
557 return false;
558 }
559
560 // EQUAL
561 TIntermTyped* expressionNode = nullptr;
562 if (! acceptTokenClass(EHTokAssign)) {
563 expected("=");
564 return false;
565 }
566
567 // expression
568 if (! acceptExpression(expressionNode)) {
569 expected("initializer");
570 return false;
571 }
572
John Kesseniche82061d2016-09-27 14:38:57 -0600573 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600574
575 return true;
576}
577
John Kessenich87142c72016-03-12 20:24:24 -0700578// fully_specified_type
579// : type_specifier
580// | type_qualifier type_specifier
581//
582bool HlslGrammar::acceptFullySpecifiedType(TType& type)
583{
John Kessenich54ee28f2017-03-11 14:13:00 -0700584 TIntermNode* nodeList = nullptr;
585 return acceptFullySpecifiedType(type, nodeList);
586}
587bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
588{
John Kessenich87142c72016-03-12 20:24:24 -0700589 // type_qualifier
590 TQualifier qualifier;
591 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600592 if (! acceptQualifier(qualifier))
593 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600594 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700595
596 // type_specifier
John Kessenich54ee28f2017-03-11 14:13:00 -0700597 if (! acceptType(type, nodeList)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -0700598 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700599 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700600 // qualifier. Back it out, if we did.
601 if (qualifier.sample)
602 recedeToken();
603
John Kessenich87142c72016-03-12 20:24:24 -0700604 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -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 Kessenich3d157c52016-07-25 16:05:33 -0600609 // further, it can create an anonymous instance of the block
John Kessenich13075c62017-04-11 09:51:32 -0600610 if (peek() != EHTokIdentifier)
John Kessenich3d157c52016-07-25 16:05:33 -0600611 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600612 } else {
613 // Some qualifiers are set when parsing the type. Merge those with
614 // whatever comes from acceptQualifier.
615 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700616
steve-lunargbb0183f2016-10-04 16:58:14 -0600617 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600618 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700619
steve-lunarg08e0c082017-03-29 20:01:13 -0600620 if (type.getQualifier().storage == EvqOut ||
steve-lunarg5da1f032017-02-12 17:50:28 -0700621 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700622 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700623 qualifier.readonly = type.getQualifier().readonly;
624 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700625
John Kessenichecd08bc2017-08-07 23:40:05 -0600626 if (type.isBuiltIn())
steve-lunarg08e0c082017-03-29 20:01:13 -0600627 qualifier.builtIn = type.getQualifier().builtIn;
628
steve-lunargf49cdf42016-11-17 15:04:20 -0700629 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600630 }
John Kessenich87142c72016-03-12 20:24:24 -0700631
632 return true;
633}
634
John Kessenich630dd7d2016-06-12 23:52:12 -0600635// type_qualifier
636// : qualifier qualifier ...
637//
638// Zero or more of these, so this can't return false.
639//
John Kessenichb9e39122016-08-17 10:22:08 -0600640bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700641{
John Kessenich630dd7d2016-06-12 23:52:12 -0600642 do {
643 switch (peek()) {
644 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600645 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600646 break;
647 case EHTokExtern:
648 // TODO: no meaning in glslang?
649 break;
650 case EHTokShared:
651 // TODO: hint
652 break;
653 case EHTokGroupShared:
654 qualifier.storage = EvqShared;
655 break;
656 case EHTokUniform:
657 qualifier.storage = EvqUniform;
658 break;
659 case EHTokConst:
660 qualifier.storage = EvqConst;
661 break;
662 case EHTokVolatile:
663 qualifier.volatil = true;
664 break;
665 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600666 qualifier.smooth = true;
667 break;
668 case EHTokCentroid:
669 qualifier.centroid = true;
670 break;
671 case EHTokNointerpolation:
672 qualifier.flat = true;
673 break;
674 case EHTokNoperspective:
675 qualifier.nopersp = true;
676 break;
677 case EHTokSample:
678 qualifier.sample = true;
679 break;
680 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600681 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600682 break;
683 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600684 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600685 break;
686 case EHTokPrecise:
687 qualifier.noContraction = true;
688 break;
LoopDawg9249c702016-07-12 20:44:32 -0600689 case EHTokIn:
xavierb1d97532017-06-20 07:49:22 +0200690 qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn;
LoopDawg9249c702016-07-12 20:44:32 -0600691 break;
692 case EHTokOut:
xavierb1d97532017-06-20 07:49:22 +0200693 qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut;
LoopDawg9249c702016-07-12 20:44:32 -0600694 break;
695 case EHTokInOut:
696 qualifier.storage = EvqInOut;
697 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600698 case EHTokLayout:
699 if (! acceptLayoutQualifierList(qualifier))
700 return false;
701 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700702 case EHTokGloballyCoherent:
703 qualifier.coherent = true;
704 break;
John Kessenich36b218d2017-03-15 09:05:14 -0600705 case EHTokInline:
706 // TODO: map this to SPIR-V function control
707 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700708
709 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
710 // for output variables.
711 case EHTokPoint:
712 qualifier.storage = EvqIn;
713 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
714 return false;
715 break;
716 case EHTokLine:
717 qualifier.storage = EvqIn;
718 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
719 return false;
720 break;
721 case EHTokTriangle:
722 qualifier.storage = EvqIn;
723 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
724 return false;
725 break;
726 case EHTokLineAdj:
727 qualifier.storage = EvqIn;
728 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
729 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700730 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700731 case EHTokTriangleAdj:
732 qualifier.storage = EvqIn;
733 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
734 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700735 break;
736
John Kessenich630dd7d2016-06-12 23:52:12 -0600737 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600738 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600739 }
740 advanceToken();
741 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700742}
743
John Kessenichb9e39122016-08-17 10:22:08 -0600744// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600745// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600746//
747// layout_qualifier
748// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600749// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600750//
751// Zero or more of these, so this can't return false.
752//
753bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
754{
755 if (! acceptTokenClass(EHTokLayout))
756 return false;
757
758 // LEFT_PAREN
759 if (! acceptTokenClass(EHTokLeftParen))
760 return false;
761
762 do {
763 // identifier
764 HlslToken idToken;
765 if (! acceptIdentifier(idToken))
766 break;
767
768 // EQUAL expression
769 if (acceptTokenClass(EHTokAssign)) {
770 TIntermTyped* expr;
771 if (! acceptConditionalExpression(expr)) {
772 expected("expression");
773 return false;
774 }
775 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
776 } else
777 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
778
779 // COMMA
780 if (! acceptTokenClass(EHTokComma))
781 break;
782 } while (true);
783
784 // RIGHT_PAREN
785 if (! acceptTokenClass(EHTokRightParen)) {
786 expected(")");
787 return false;
788 }
789
790 return true;
791}
792
LoopDawg6daaa4f2016-06-23 19:13:48 -0600793// template_type
794// : FLOAT
795// | DOUBLE
796// | INT
797// | DWORD
798// | UINT
799// | BOOL
800//
steve-lunargf49cdf42016-11-17 15:04:20 -0700801bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600802{
803 switch (peek()) {
804 case EHTokFloat:
805 basicType = EbtFloat;
806 break;
807 case EHTokDouble:
808 basicType = EbtDouble;
809 break;
810 case EHTokInt:
811 case EHTokDword:
812 basicType = EbtInt;
813 break;
814 case EHTokUint:
815 basicType = EbtUint;
816 break;
817 case EHTokBool:
818 basicType = EbtBool;
819 break;
820 default:
821 return false;
822 }
823
824 advanceToken();
825
826 return true;
827}
828
829// vector_template_type
830// : VECTOR
831// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
832//
833bool HlslGrammar::acceptVectorTemplateType(TType& type)
834{
835 if (! acceptTokenClass(EHTokVector))
836 return false;
837
838 if (! acceptTokenClass(EHTokLeftAngle)) {
839 // in HLSL, 'vector' alone means float4.
840 new(&type) TType(EbtFloat, EvqTemporary, 4);
841 return true;
842 }
843
844 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700845 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600846 expected("scalar type");
847 return false;
848 }
849
850 // COMMA
851 if (! acceptTokenClass(EHTokComma)) {
852 expected(",");
853 return false;
854 }
855
856 // integer
857 if (! peekTokenClass(EHTokIntConstant)) {
858 expected("literal integer");
859 return false;
860 }
861
862 TIntermTyped* vecSize;
863 if (! acceptLiteral(vecSize))
864 return false;
865
866 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
867
868 new(&type) TType(basicType, EvqTemporary, vecSizeI);
869
870 if (vecSizeI == 1)
871 type.makeVector();
872
873 if (!acceptTokenClass(EHTokRightAngle)) {
874 expected("right angle bracket");
875 return false;
876 }
877
878 return true;
879}
880
881// matrix_template_type
882// : MATRIX
883// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
884//
885bool HlslGrammar::acceptMatrixTemplateType(TType& type)
886{
887 if (! acceptTokenClass(EHTokMatrix))
888 return false;
889
890 if (! acceptTokenClass(EHTokLeftAngle)) {
891 // in HLSL, 'matrix' alone means float4x4.
892 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
893 return true;
894 }
895
896 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700897 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600898 expected("scalar type");
899 return false;
900 }
901
902 // COMMA
903 if (! acceptTokenClass(EHTokComma)) {
904 expected(",");
905 return false;
906 }
907
908 // integer rows
909 if (! peekTokenClass(EHTokIntConstant)) {
910 expected("literal integer");
911 return false;
912 }
913
914 TIntermTyped* rows;
915 if (! acceptLiteral(rows))
916 return false;
917
918 // COMMA
919 if (! acceptTokenClass(EHTokComma)) {
920 expected(",");
921 return false;
922 }
John Kessenichecba76f2017-01-06 00:34:48 -0700923
LoopDawg6daaa4f2016-06-23 19:13:48 -0600924 // integer cols
925 if (! peekTokenClass(EHTokIntConstant)) {
926 expected("literal integer");
927 return false;
928 }
929
930 TIntermTyped* cols;
931 if (! acceptLiteral(cols))
932 return false;
933
934 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600935 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
936 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600937
938 if (!acceptTokenClass(EHTokRightAngle)) {
939 expected("right angle bracket");
940 return false;
941 }
942
943 return true;
944}
945
steve-lunargf49cdf42016-11-17 15:04:20 -0700946// layout_geometry
947// : LINESTREAM
948// | POINTSTREAM
949// | TRIANGLESTREAM
950//
951bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
952{
953 // read geometry type
954 const EHlslTokenClass geometryType = peek();
955
956 switch (geometryType) {
957 case EHTokPointStream: geometry = ElgPoints; break;
958 case EHTokLineStream: geometry = ElgLineStrip; break;
959 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
960 default:
961 return false; // not a layout geometry
962 }
963
964 advanceToken(); // consume the layout keyword
965 return true;
966}
967
steve-lunarg858c9282017-01-07 08:54:10 -0700968// tessellation_decl_type
969// : INPUTPATCH
970// | OUTPUTPATCH
971//
steve-lunarg067eb9b2017-04-01 15:34:48 -0600972bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType)
steve-lunarg858c9282017-01-07 08:54:10 -0700973{
974 // read geometry type
975 const EHlslTokenClass tessType = peek();
976
977 switch (tessType) {
steve-lunarg067eb9b2017-04-01 15:34:48 -0600978 case EHTokInputPatch: patchType = EbvInputPatch; break;
979 case EHTokOutputPatch: patchType = EbvOutputPatch; break;
steve-lunarg858c9282017-01-07 08:54:10 -0700980 default:
981 return false; // not a tessellation decl
982 }
983
984 advanceToken(); // consume the keyword
985 return true;
986}
987
988// tessellation_patch_template_type
989// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
990//
991bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
992{
steve-lunarg067eb9b2017-04-01 15:34:48 -0600993 TBuiltInVariable patchType;
994
995 if (! acceptTessellationDeclType(patchType))
steve-lunarg858c9282017-01-07 08:54:10 -0700996 return false;
997
998 if (! acceptTokenClass(EHTokLeftAngle))
999 return false;
1000
1001 if (! acceptType(type)) {
1002 expected("tessellation patch type");
1003 return false;
1004 }
1005
1006 if (! acceptTokenClass(EHTokComma))
1007 return false;
1008
1009 // integer size
1010 if (! peekTokenClass(EHTokIntConstant)) {
1011 expected("literal integer");
1012 return false;
1013 }
1014
1015 TIntermTyped* size;
1016 if (! acceptLiteral(size))
1017 return false;
1018
1019 TArraySizes* arraySizes = new TArraySizes;
1020 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
1021 type.newArraySizes(*arraySizes);
steve-lunarg067eb9b2017-04-01 15:34:48 -06001022 type.getQualifier().builtIn = patchType;
steve-lunarg858c9282017-01-07 08:54:10 -07001023
1024 if (! acceptTokenClass(EHTokRightAngle)) {
1025 expected("right angle bracket");
1026 return false;
1027 }
1028
1029 return true;
1030}
1031
steve-lunargf49cdf42016-11-17 15:04:20 -07001032// stream_out_template_type
1033// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
1034//
1035bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
1036{
1037 geometry = ElgNone;
1038
1039 if (! acceptOutputPrimitiveGeometry(geometry))
1040 return false;
1041
1042 if (! acceptTokenClass(EHTokLeftAngle))
1043 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001044
steve-lunargf49cdf42016-11-17 15:04:20 -07001045 if (! acceptType(type)) {
1046 expected("stream output type");
1047 return false;
1048 }
1049
steve-lunarg08e0c082017-03-29 20:01:13 -06001050 type.getQualifier().storage = EvqOut;
1051 type.getQualifier().builtIn = EbvGsOutputStream;
steve-lunargf49cdf42016-11-17 15:04:20 -07001052
1053 if (! acceptTokenClass(EHTokRightAngle)) {
1054 expected("right angle bracket");
1055 return false;
1056 }
1057
1058 return true;
1059}
John Kessenichecba76f2017-01-06 00:34:48 -07001060
John Kessenicha1e2d492016-09-20 13:22:58 -06001061// annotations
1062// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -06001063//
John Kessenicha1e2d492016-09-20 13:22:58 -06001064bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -06001065{
John Kessenicha1e2d492016-09-20 13:22:58 -06001066 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -06001067 return false;
1068
John Kessenicha1e2d492016-09-20 13:22:58 -06001069 // note that we are nesting a name space
1070 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -06001071
1072 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1073 do {
1074 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
1075 while (acceptTokenClass(EHTokSemicolon))
1076 ;
1077
1078 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -06001079 break;
John Kessenich86f71382016-09-19 20:23:18 -06001080
1081 // declaration
John Kessenichca71d942017-03-07 20:44:09 -07001082 TIntermNode* node = nullptr;
John Kessenich86f71382016-09-19 20:23:18 -06001083 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -06001084 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -06001085 return false;
1086 }
1087 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -06001088
1089 parseContext.unnestAnnotations();
1090 return true;
John Kessenich86f71382016-09-19 20:23:18 -06001091}
LoopDawg6daaa4f2016-06-23 19:13:48 -06001092
LoopDawg7f93d562017-09-27 09:04:43 -06001093// subpass input type
1094// : SUBPASSINPUT
1095// | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1096// | SUBPASSINPUTMS
1097// | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1098bool HlslGrammar::acceptSubpassInputType(TType& type)
1099{
1100 // read subpass type
1101 const EHlslTokenClass subpassInputType = peek();
1102
1103 bool multisample;
1104
1105 switch (subpassInputType) {
1106 case EHTokSubpassInput: multisample = false; break;
1107 case EHTokSubpassInputMS: multisample = true; break;
1108 default:
1109 return false; // not a subpass input declaration
1110 }
1111
1112 advanceToken(); // consume the sampler type keyword
1113
1114 TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4
1115
1116 if (acceptTokenClass(EHTokLeftAngle)) {
1117 if (! acceptType(subpassType)) {
1118 expected("scalar or vector type");
1119 return false;
1120 }
1121
1122 const TBasicType basicRetType = subpassType.getBasicType() ;
1123
1124 switch (basicRetType) {
1125 case EbtFloat:
1126 case EbtUint:
1127 case EbtInt:
1128 case EbtStruct:
1129 break;
1130 default:
1131 unimplemented("basic type in subpass input");
1132 return false;
1133 }
1134
1135 if (! acceptTokenClass(EHTokRightAngle)) {
1136 expected("right angle bracket");
1137 return false;
1138 }
1139 }
1140
1141 const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType()
1142 : subpassType.getBasicType();
1143
1144 TSampler sampler;
1145 sampler.setSubpass(subpassBasicType, multisample);
1146
1147 // Remember the declared return type. Function returns false on error.
1148 if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc))
1149 return false;
1150
1151 type.shallowCopy(TType(sampler, EvqUniform));
1152
1153 return true;
1154}
1155
LoopDawg4886f692016-06-29 10:58:58 -06001156// sampler_type
1157// : SAMPLER
1158// | SAMPLER1D
1159// | SAMPLER2D
1160// | SAMPLER3D
1161// | SAMPLERCUBE
1162// | SAMPLERSTATE
1163// | SAMPLERCOMPARISONSTATE
1164bool HlslGrammar::acceptSamplerType(TType& type)
1165{
1166 // read sampler type
1167 const EHlslTokenClass samplerType = peek();
1168
LoopDawga78b0292016-07-19 14:28:05 -06001169 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001170 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001171
LoopDawga78b0292016-07-19 14:28:05 -06001172 bool isShadow = false;
1173
LoopDawg4886f692016-06-29 10:58:58 -06001174 switch (samplerType) {
1175 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001176 case EHTokSampler1d: /*dim = Esd1D*/; break;
1177 case EHTokSampler2d: /*dim = Esd2D*/; break;
1178 case EHTokSampler3d: /*dim = Esd3D*/; break;
1179 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001180 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001181 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001182 default:
1183 return false; // not a sampler declaration
1184 }
1185
1186 advanceToken(); // consume the sampler type keyword
1187
1188 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001189
1190 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001191 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001192
1193 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1194
1195 return true;
1196}
1197
1198// texture_type
1199// | BUFFER
1200// | TEXTURE1D
1201// | TEXTURE1DARRAY
1202// | TEXTURE2D
1203// | TEXTURE2DARRAY
1204// | TEXTURE3D
1205// | TEXTURECUBE
1206// | TEXTURECUBEARRAY
1207// | TEXTURE2DMS
1208// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001209// | RWBUFFER
1210// | RWTEXTURE1D
1211// | RWTEXTURE1DARRAY
1212// | RWTEXTURE2D
1213// | RWTEXTURE2DARRAY
1214// | RWTEXTURE3D
1215
LoopDawg4886f692016-06-29 10:58:58 -06001216bool HlslGrammar::acceptTextureType(TType& type)
1217{
1218 const EHlslTokenClass textureType = peek();
1219
1220 TSamplerDim dim = EsdNone;
1221 bool array = false;
1222 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001223 bool image = false;
steve-lunargbf1537f2017-03-31 17:40:09 -06001224 bool combined = true;
LoopDawg4886f692016-06-29 10:58:58 -06001225
1226 switch (textureType) {
steve-lunargbf1537f2017-03-31 17:40:09 -06001227 case EHTokBuffer: dim = EsdBuffer; combined = false; break;
John Kessenichf36542f2017-03-31 14:39:30 -06001228 case EHTokTexture1d: dim = Esd1D; break;
1229 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1230 case EHTokTexture2d: dim = Esd2D; break;
1231 case EHTokTexture2darray: dim = Esd2D; array = true; break;
1232 case EHTokTexture3d: dim = Esd3D; break;
1233 case EHTokTextureCube: dim = EsdCube; break;
1234 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1235 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1236 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
1237 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1238 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1239 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1240 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1241 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1242 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001243 default:
1244 return false; // not a texture declaration
1245 }
1246
1247 advanceToken(); // consume the texture object keyword
1248
1249 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001250
LoopDawg4886f692016-06-29 10:58:58 -06001251 TIntermTyped* msCount = nullptr;
1252
steve-lunargbb0183f2016-10-04 16:58:14 -06001253 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001254 if (acceptTokenClass(EHTokLeftAngle)) {
1255 if (! acceptType(txType)) {
1256 expected("scalar or vector type");
1257 return false;
1258 }
1259
1260 const TBasicType basicRetType = txType.getBasicType() ;
1261
LoopDawg5ee05892017-07-31 13:41:42 -06001262 switch (basicRetType) {
1263 case EbtFloat:
1264 case EbtUint:
1265 case EbtInt:
1266 case EbtStruct:
1267 break;
1268 default:
LoopDawg4886f692016-06-29 10:58:58 -06001269 unimplemented("basic type in texture");
1270 return false;
1271 }
1272
steve-lunargd53f7172016-07-27 15:46:48 -06001273 // Buffers can handle small mats if they fit in 4 components
1274 if (dim == EsdBuffer && txType.isMatrix()) {
1275 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1276 expected("components < 4 in matrix buffer type");
1277 return false;
1278 }
1279
1280 // TODO: except we don't handle it yet...
1281 unimplemented("matrix type in buffer");
1282 return false;
1283 }
1284
LoopDawg5ee05892017-07-31 13:41:42 -06001285 if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) {
1286 expected("scalar, vector, or struct type");
LoopDawg4886f692016-06-29 10:58:58 -06001287 return false;
1288 }
1289
LoopDawg4886f692016-06-29 10:58:58 -06001290 if (ms && acceptTokenClass(EHTokComma)) {
1291 // read sample count for multisample types, if given
1292 if (! peekTokenClass(EHTokIntConstant)) {
1293 expected("multisample count");
1294 return false;
1295 }
1296
1297 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1298 return false;
1299 }
1300
1301 if (! acceptTokenClass(EHTokRightAngle)) {
1302 expected("right angle bracket");
1303 return false;
1304 }
1305 } else if (ms) {
1306 expected("texture type for multisample");
1307 return false;
John Kessenichf36542f2017-03-31 14:39:30 -06001308 } else if (image) {
steve-lunargbb0183f2016-10-04 16:58:14 -06001309 expected("type for RWTexture/RWBuffer");
1310 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001311 }
1312
1313 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001314 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001315
1316 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001317 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001318
steve-lunarg4f2da272016-10-10 15:24:57 -06001319 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1320 if (image || dim == EsdBuffer)
1321 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001322
LoopDawg5ee05892017-07-31 13:41:42 -06001323 const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType()
1324 : txType.getBasicType();
1325
steve-lunargbb0183f2016-10-04 16:58:14 -06001326 // Non-image Buffers are combined
1327 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001328 sampler.set(txType.getBasicType(), dim, array);
1329 } else {
1330 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001331 if (image) {
LoopDawg5ee05892017-07-31 13:41:42 -06001332 sampler.setImage(txBasicType, dim, array, shadow, ms);
steve-lunargbb0183f2016-10-04 16:58:14 -06001333 } else {
LoopDawg5ee05892017-07-31 13:41:42 -06001334 sampler.setTexture(txBasicType, dim, array, shadow, ms);
steve-lunargbb0183f2016-10-04 16:58:14 -06001335 }
steve-lunargd53f7172016-07-27 15:46:48 -06001336 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001337
LoopDawg5ee05892017-07-31 13:41:42 -06001338 // Remember the declared return type. Function returns false on error.
1339 if (!parseContext.setTextureReturnType(sampler, txType, token.loc))
1340 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001341
steve-lunargbf1537f2017-03-31 17:40:09 -06001342 // Force uncombined, if necessary
1343 if (!combined)
1344 sampler.combined = false;
1345
LoopDawg4886f692016-06-29 10:58:58 -06001346 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001347 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001348
1349 return true;
1350}
1351
John Kessenich87142c72016-03-12 20:24:24 -07001352// If token is for a type, update 'type' with the type information,
1353// and return true and advance.
1354// Otherwise, return false, and don't advance
1355bool HlslGrammar::acceptType(TType& type)
1356{
John Kessenich54ee28f2017-03-11 14:13:00 -07001357 TIntermNode* nodeList = nullptr;
1358 return acceptType(type, nodeList);
1359}
1360bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
1361{
steve-lunarg3226b082016-10-26 19:18:55 -06001362 // Basic types for min* types, broken out here in case of future
1363 // changes, e.g, to use native halfs.
1364 static const TBasicType min16float_bt = EbtFloat;
1365 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001366 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001367 static const TBasicType min16int_bt = EbtInt;
1368 static const TBasicType min12int_bt = EbtInt;
1369 static const TBasicType min16uint_bt = EbtUint;
1370
John Kessenich0320d092017-06-13 22:22:52 -06001371 // Some types might have turned into identifiers. Take the hit for checking
1372 // when this has happened.
1373 if (typeIdentifiers) {
1374 const char* identifierString = getTypeString(peek());
1375 if (identifierString != nullptr) {
1376 TString name = identifierString;
1377 // if it's an identifier, it's not a type
1378 if (parseContext.symbolTable.find(name) != nullptr)
1379 return false;
1380 }
1381 }
1382
LoopDawgfa39cff2017-11-14 14:55:40 -07001383 bool isUnorm = false;
1384 bool isSnorm = false;
1385
1386 // Accept snorm and unorm. Presently, this is ignored, save for an error check below.
1387 switch (peek()) {
1388 case EHTokUnorm:
1389 isUnorm = true;
1390 advanceToken(); // eat the token
1391 break;
1392 case EHTokSNorm:
1393 isSnorm = true;
1394 advanceToken(); // eat the token
1395 break;
1396 default:
1397 break;
1398 }
1399
John Kessenich9c86c6a2016-05-03 22:49:24 -06001400 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001401 case EHTokVector:
1402 return acceptVectorTemplateType(type);
1403 break;
1404
1405 case EHTokMatrix:
1406 return acceptMatrixTemplateType(type);
1407 break;
1408
steve-lunargf49cdf42016-11-17 15:04:20 -07001409 case EHTokPointStream: // fall through
1410 case EHTokLineStream: // ...
1411 case EHTokTriangleStream: // ...
1412 {
1413 TLayoutGeometry geometry;
1414 if (! acceptStreamOutTemplateType(type, geometry))
1415 return false;
1416
1417 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1418 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001419
steve-lunargf49cdf42016-11-17 15:04:20 -07001420 return true;
1421 }
1422
steve-lunarg858c9282017-01-07 08:54:10 -07001423 case EHTokInputPatch: // fall through
1424 case EHTokOutputPatch: // ...
1425 {
1426 if (! acceptTessellationPatchTemplateType(type))
1427 return false;
1428
1429 return true;
1430 }
1431
LoopDawg4886f692016-06-29 10:58:58 -06001432 case EHTokSampler: // fall through
1433 case EHTokSampler1d: // ...
1434 case EHTokSampler2d: // ...
1435 case EHTokSampler3d: // ...
1436 case EHTokSamplerCube: // ...
1437 case EHTokSamplerState: // ...
1438 case EHTokSamplerComparisonState: // ...
1439 return acceptSamplerType(type);
1440 break;
1441
LoopDawg7f93d562017-09-27 09:04:43 -06001442 case EHTokSubpassInput: // fall through
1443 case EHTokSubpassInputMS: // ...
1444 return acceptSubpassInputType(type);
1445 break;
1446
LoopDawg4886f692016-06-29 10:58:58 -06001447 case EHTokBuffer: // fall through
1448 case EHTokTexture1d: // ...
1449 case EHTokTexture1darray: // ...
1450 case EHTokTexture2d: // ...
1451 case EHTokTexture2darray: // ...
1452 case EHTokTexture3d: // ...
1453 case EHTokTextureCube: // ...
1454 case EHTokTextureCubearray: // ...
1455 case EHTokTexture2DMS: // ...
1456 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001457 case EHTokRWTexture1d: // ...
1458 case EHTokRWTexture1darray: // ...
1459 case EHTokRWTexture2d: // ...
1460 case EHTokRWTexture2darray: // ...
1461 case EHTokRWTexture3d: // ...
1462 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001463 return acceptTextureType(type);
1464 break;
1465
steve-lunarg5da1f032017-02-12 17:50:28 -07001466 case EHTokAppendStructuredBuffer:
1467 case EHTokByteAddressBuffer:
1468 case EHTokConsumeStructuredBuffer:
1469 case EHTokRWByteAddressBuffer:
1470 case EHTokRWStructuredBuffer:
1471 case EHTokStructuredBuffer:
1472 return acceptStructBufferType(type);
1473 break;
1474
LoopDawge5530b92017-11-08 19:48:11 -07001475 case EHTokTextureBuffer:
1476 return acceptTextureBufferType(type);
1477 break;
1478
steve-lunarga766b832017-04-25 09:30:28 -06001479 case EHTokConstantBuffer:
1480 return acceptConstantBufferType(type);
1481
John Kessenich27ffb292017-03-03 17:01:01 -07001482 case EHTokClass:
John Kesseniche6e74942016-06-11 16:43:14 -06001483 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001484 case EHTokCBuffer:
1485 case EHTokTBuffer:
John Kessenich54ee28f2017-03-11 14:13:00 -07001486 return acceptStruct(type, nodeList);
John Kesseniche6e74942016-06-11 16:43:14 -06001487
1488 case EHTokIdentifier:
1489 // An identifier could be for a user-defined type.
1490 // Note we cache the symbol table lookup, to save for a later rule
1491 // when this is not a type.
John Kessenichf4ba25e2017-03-21 18:35:04 -06001492 if (parseContext.lookupUserType(*token.string, type) != nullptr) {
John Kesseniche6e74942016-06-11 16:43:14 -06001493 advanceToken();
1494 return true;
1495 } else
1496 return false;
1497
John Kessenich71351de2016-06-08 12:50:56 -06001498 case EHTokVoid:
1499 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001500 break;
John Kessenich71351de2016-06-08 12:50:56 -06001501
John Kessenicha1e2d492016-09-20 13:22:58 -06001502 case EHTokString:
1503 new(&type) TType(EbtString);
1504 break;
1505
John Kessenich87142c72016-03-12 20:24:24 -07001506 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001507 new(&type) TType(EbtFloat);
1508 break;
John Kessenich87142c72016-03-12 20:24:24 -07001509 case EHTokFloat1:
1510 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001511 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001512 break;
John Kessenich87142c72016-03-12 20:24:24 -07001513 case EHTokFloat2:
1514 new(&type) TType(EbtFloat, EvqTemporary, 2);
1515 break;
1516 case EHTokFloat3:
1517 new(&type) TType(EbtFloat, EvqTemporary, 3);
1518 break;
1519 case EHTokFloat4:
1520 new(&type) TType(EbtFloat, EvqTemporary, 4);
1521 break;
1522
John Kessenich71351de2016-06-08 12:50:56 -06001523 case EHTokDouble:
1524 new(&type) TType(EbtDouble);
1525 break;
1526 case EHTokDouble1:
1527 new(&type) TType(EbtDouble);
1528 type.makeVector();
1529 break;
1530 case EHTokDouble2:
1531 new(&type) TType(EbtDouble, EvqTemporary, 2);
1532 break;
1533 case EHTokDouble3:
1534 new(&type) TType(EbtDouble, EvqTemporary, 3);
1535 break;
1536 case EHTokDouble4:
1537 new(&type) TType(EbtDouble, EvqTemporary, 4);
1538 break;
1539
1540 case EHTokInt:
1541 case EHTokDword:
1542 new(&type) TType(EbtInt);
1543 break;
1544 case EHTokInt1:
1545 new(&type) TType(EbtInt);
1546 type.makeVector();
1547 break;
John Kessenich87142c72016-03-12 20:24:24 -07001548 case EHTokInt2:
1549 new(&type) TType(EbtInt, EvqTemporary, 2);
1550 break;
1551 case EHTokInt3:
1552 new(&type) TType(EbtInt, EvqTemporary, 3);
1553 break;
1554 case EHTokInt4:
1555 new(&type) TType(EbtInt, EvqTemporary, 4);
1556 break;
1557
John Kessenich71351de2016-06-08 12:50:56 -06001558 case EHTokUint:
1559 new(&type) TType(EbtUint);
1560 break;
1561 case EHTokUint1:
1562 new(&type) TType(EbtUint);
1563 type.makeVector();
1564 break;
1565 case EHTokUint2:
1566 new(&type) TType(EbtUint, EvqTemporary, 2);
1567 break;
1568 case EHTokUint3:
1569 new(&type) TType(EbtUint, EvqTemporary, 3);
1570 break;
1571 case EHTokUint4:
1572 new(&type) TType(EbtUint, EvqTemporary, 4);
1573 break;
1574
1575 case EHTokBool:
1576 new(&type) TType(EbtBool);
1577 break;
1578 case EHTokBool1:
1579 new(&type) TType(EbtBool);
1580 type.makeVector();
1581 break;
John Kessenich87142c72016-03-12 20:24:24 -07001582 case EHTokBool2:
1583 new(&type) TType(EbtBool, EvqTemporary, 2);
1584 break;
1585 case EHTokBool3:
1586 new(&type) TType(EbtBool, EvqTemporary, 3);
1587 break;
1588 case EHTokBool4:
1589 new(&type) TType(EbtBool, EvqTemporary, 4);
1590 break;
1591
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001592 case EHTokHalf:
John Kessenich96f65522017-06-06 23:35:25 -06001593 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001594 break;
1595 case EHTokHalf1:
John Kessenich96f65522017-06-06 23:35:25 -06001596 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001597 type.makeVector();
1598 break;
1599 case EHTokHalf2:
John Kessenich96f65522017-06-06 23:35:25 -06001600 new(&type) TType(half_bt, EvqTemporary, 2);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001601 break;
1602 case EHTokHalf3:
John Kessenich96f65522017-06-06 23:35:25 -06001603 new(&type) TType(half_bt, EvqTemporary, 3);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001604 break;
1605 case EHTokHalf4:
John Kessenich96f65522017-06-06 23:35:25 -06001606 new(&type) TType(half_bt, EvqTemporary, 4);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001607 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001608
steve-lunarg3226b082016-10-26 19:18:55 -06001609 case EHTokMin16float:
1610 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1611 break;
1612 case EHTokMin16float1:
1613 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1614 type.makeVector();
1615 break;
1616 case EHTokMin16float2:
1617 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1618 break;
1619 case EHTokMin16float3:
1620 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1621 break;
1622 case EHTokMin16float4:
1623 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1624 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001625
steve-lunarg3226b082016-10-26 19:18:55 -06001626 case EHTokMin10float:
1627 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1628 break;
1629 case EHTokMin10float1:
1630 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1631 type.makeVector();
1632 break;
1633 case EHTokMin10float2:
1634 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1635 break;
1636 case EHTokMin10float3:
1637 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1638 break;
1639 case EHTokMin10float4:
1640 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1641 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001642
steve-lunarg3226b082016-10-26 19:18:55 -06001643 case EHTokMin16int:
1644 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1645 break;
1646 case EHTokMin16int1:
1647 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1648 type.makeVector();
1649 break;
1650 case EHTokMin16int2:
1651 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1652 break;
1653 case EHTokMin16int3:
1654 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1655 break;
1656 case EHTokMin16int4:
1657 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1658 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001659
steve-lunarg3226b082016-10-26 19:18:55 -06001660 case EHTokMin12int:
1661 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1662 break;
1663 case EHTokMin12int1:
1664 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1665 type.makeVector();
1666 break;
1667 case EHTokMin12int2:
1668 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1669 break;
1670 case EHTokMin12int3:
1671 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1672 break;
1673 case EHTokMin12int4:
1674 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1675 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001676
steve-lunarg3226b082016-10-26 19:18:55 -06001677 case EHTokMin16uint:
1678 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1679 break;
1680 case EHTokMin16uint1:
1681 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1682 type.makeVector();
1683 break;
1684 case EHTokMin16uint2:
1685 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1686 break;
1687 case EHTokMin16uint3:
1688 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1689 break;
1690 case EHTokMin16uint4:
1691 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1692 break;
1693
John Kessenich0133c122016-05-20 12:17:26 -06001694 case EHTokInt1x1:
1695 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1696 break;
1697 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001698 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001699 break;
1700 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001701 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001702 break;
1703 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001704 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001705 break;
1706 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001707 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001708 break;
1709 case EHTokInt2x2:
1710 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1711 break;
1712 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001713 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001714 break;
1715 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001716 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001717 break;
1718 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001719 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001720 break;
1721 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001722 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001723 break;
1724 case EHTokInt3x3:
1725 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1726 break;
1727 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001728 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001729 break;
1730 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001731 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001732 break;
1733 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001734 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001735 break;
1736 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001737 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001738 break;
1739 case EHTokInt4x4:
1740 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1741 break;
1742
John Kessenich71351de2016-06-08 12:50:56 -06001743 case EHTokUint1x1:
1744 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1745 break;
1746 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001747 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001748 break;
1749 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001750 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001751 break;
1752 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001753 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001754 break;
1755 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001756 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001757 break;
1758 case EHTokUint2x2:
1759 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1760 break;
1761 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001762 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001763 break;
1764 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001765 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001766 break;
1767 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001768 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001769 break;
1770 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001771 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001772 break;
1773 case EHTokUint3x3:
1774 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1775 break;
1776 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001777 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001778 break;
1779 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001780 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001781 break;
1782 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001783 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001784 break;
1785 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001786 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001787 break;
1788 case EHTokUint4x4:
1789 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1790 break;
1791
1792 case EHTokBool1x1:
1793 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1794 break;
1795 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001796 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001797 break;
1798 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001799 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001800 break;
1801 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001802 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001803 break;
1804 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001805 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001806 break;
1807 case EHTokBool2x2:
1808 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1809 break;
1810 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001811 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001812 break;
1813 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001814 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001815 break;
1816 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001817 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001818 break;
1819 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001820 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001821 break;
1822 case EHTokBool3x3:
1823 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1824 break;
1825 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001826 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001827 break;
1828 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001829 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001830 break;
1831 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001832 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001833 break;
1834 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001835 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001836 break;
1837 case EHTokBool4x4:
1838 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1839 break;
1840
John Kessenich0133c122016-05-20 12:17:26 -06001841 case EHTokFloat1x1:
1842 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1843 break;
1844 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001845 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001846 break;
1847 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001848 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001849 break;
1850 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001851 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001852 break;
1853 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001854 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001855 break;
John Kessenich87142c72016-03-12 20:24:24 -07001856 case EHTokFloat2x2:
1857 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1858 break;
1859 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001860 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001861 break;
1862 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001863 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001864 break;
John Kessenich0133c122016-05-20 12:17:26 -06001865 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001866 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001867 break;
John Kessenich87142c72016-03-12 20:24:24 -07001868 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001869 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001870 break;
1871 case EHTokFloat3x3:
1872 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1873 break;
1874 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001875 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001876 break;
John Kessenich0133c122016-05-20 12:17:26 -06001877 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001878 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001879 break;
John Kessenich87142c72016-03-12 20:24:24 -07001880 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001881 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001882 break;
1883 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001884 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001885 break;
1886 case EHTokFloat4x4:
1887 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1888 break;
1889
John Kessenich96f65522017-06-06 23:35:25 -06001890 case EHTokHalf1x1:
1891 new(&type) TType(half_bt, EvqTemporary, 0, 1, 1);
1892 break;
1893 case EHTokHalf1x2:
1894 new(&type) TType(half_bt, EvqTemporary, 0, 1, 2);
1895 break;
1896 case EHTokHalf1x3:
1897 new(&type) TType(half_bt, EvqTemporary, 0, 1, 3);
1898 break;
1899 case EHTokHalf1x4:
1900 new(&type) TType(half_bt, EvqTemporary, 0, 1, 4);
1901 break;
1902 case EHTokHalf2x1:
1903 new(&type) TType(half_bt, EvqTemporary, 0, 2, 1);
1904 break;
1905 case EHTokHalf2x2:
1906 new(&type) TType(half_bt, EvqTemporary, 0, 2, 2);
1907 break;
1908 case EHTokHalf2x3:
1909 new(&type) TType(half_bt, EvqTemporary, 0, 2, 3);
1910 break;
1911 case EHTokHalf2x4:
1912 new(&type) TType(half_bt, EvqTemporary, 0, 2, 4);
1913 break;
1914 case EHTokHalf3x1:
1915 new(&type) TType(half_bt, EvqTemporary, 0, 3, 1);
1916 break;
1917 case EHTokHalf3x2:
1918 new(&type) TType(half_bt, EvqTemporary, 0, 3, 2);
1919 break;
1920 case EHTokHalf3x3:
1921 new(&type) TType(half_bt, EvqTemporary, 0, 3, 3);
1922 break;
1923 case EHTokHalf3x4:
1924 new(&type) TType(half_bt, EvqTemporary, 0, 3, 4);
1925 break;
1926 case EHTokHalf4x1:
1927 new(&type) TType(half_bt, EvqTemporary, 0, 4, 1);
1928 break;
1929 case EHTokHalf4x2:
1930 new(&type) TType(half_bt, EvqTemporary, 0, 4, 2);
1931 break;
1932 case EHTokHalf4x3:
1933 new(&type) TType(half_bt, EvqTemporary, 0, 4, 3);
1934 break;
1935 case EHTokHalf4x4:
1936 new(&type) TType(half_bt, EvqTemporary, 0, 4, 4);
1937 break;
1938
John Kessenich0133c122016-05-20 12:17:26 -06001939 case EHTokDouble1x1:
1940 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1941 break;
1942 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001943 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001944 break;
1945 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001946 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001947 break;
1948 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001949 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001950 break;
1951 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001952 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001953 break;
1954 case EHTokDouble2x2:
1955 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1956 break;
1957 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001958 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001959 break;
1960 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001961 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001962 break;
1963 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001964 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001965 break;
1966 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001967 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001968 break;
1969 case EHTokDouble3x3:
1970 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1971 break;
1972 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001973 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001974 break;
1975 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001976 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001977 break;
1978 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001979 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001980 break;
1981 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001982 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001983 break;
1984 case EHTokDouble4x4:
1985 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1986 break;
1987
John Kessenich87142c72016-03-12 20:24:24 -07001988 default:
1989 return false;
1990 }
1991
1992 advanceToken();
1993
LoopDawgfa39cff2017-11-14 14:55:40 -07001994 if ((isUnorm || isSnorm) && !type.isFloatingDomain()) {
1995 parseContext.error(token.loc, "unorm and snorm only valid in floating point domain", "", "");
1996 return false;
1997 }
1998
John Kessenich87142c72016-03-12 20:24:24 -07001999 return true;
2000}
2001
John Kesseniche6e74942016-06-11 16:43:14 -06002002// struct
John Kessenich3d157c52016-07-25 16:05:33 -06002003// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
2004// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07002005// | struct_type IDENTIFIER // use of previously declared struct type
John Kessenich3d157c52016-07-25 16:05:33 -06002006//
2007// struct_type
2008// : STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07002009// | CLASS
John Kessenich3d157c52016-07-25 16:05:33 -06002010// | CBUFFER
2011// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06002012//
John Kessenich54ee28f2017-03-11 14:13:00 -07002013bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
John Kesseniche6e74942016-06-11 16:43:14 -06002014{
John Kessenichb804de62016-09-05 12:19:18 -06002015 // This storage qualifier will tell us whether it's an AST
2016 // block type or just a generic structure type.
2017 TStorageQualifier storageQualifier = EvqTemporary;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002018 bool readonly = false;
John Kessenich3d157c52016-07-25 16:05:33 -06002019
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002020 if (acceptTokenClass(EHTokCBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06002021 // CBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06002022 storageQualifier = EvqUniform;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002023 } else if (acceptTokenClass(EHTokTBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06002024 // TBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06002025 storageQualifier = EvqBuffer;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002026 readonly = true;
John Kessenich054378d2017-06-19 15:13:26 -06002027 } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) {
2028 // Neither CLASS nor STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06002029 return false;
John Kessenich054378d2017-06-19 15:13:26 -06002030 }
2031
2032 // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06002033
LoopDawg7ee29ba2017-11-27 14:45:36 -07002034
2035 // IDENTIFIER. It might also be a keyword which can double as an identifier.
2036 // For example: 'cbuffer ConstantBuffer' or 'struct ConstantBuffer' is legal.
2037 // 'cbuffer int' is also legal, and 'struct int' appears rejected only because
2038 // it attempts to redefine the 'int' type.
2039 const char* idString = getTypeString(peek());
John Kesseniche6e74942016-06-11 16:43:14 -06002040 TString structName = "";
LoopDawg7ee29ba2017-11-27 14:45:36 -07002041 if (peekTokenClass(EHTokIdentifier) || idString != nullptr) {
2042 if (idString != nullptr)
2043 structName = *idString;
2044 else
2045 structName = *token.string;
John Kesseniche6e74942016-06-11 16:43:14 -06002046 advanceToken();
2047 }
2048
John Kessenich3d157c52016-07-25 16:05:33 -06002049 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002050 TQualifier postDeclQualifier;
2051 postDeclQualifier.clear();
John Kessenich854fe242017-03-02 14:30:59 -07002052 bool postDeclsFound = acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06002053
John Kessenichf3d88bd2017-03-19 12:24:29 -06002054 // LEFT_BRACE, or
John Kessenich854fe242017-03-02 14:30:59 -07002055 // struct_type IDENTIFIER
John Kesseniche6e74942016-06-11 16:43:14 -06002056 if (! acceptTokenClass(EHTokLeftBrace)) {
John Kessenich854fe242017-03-02 14:30:59 -07002057 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
2058 // struct_type IDENTIFIER
2059 return true;
2060 } else {
2061 expected("{");
2062 return false;
2063 }
John Kesseniche6e74942016-06-11 16:43:14 -06002064 }
2065
John Kessenichf3d88bd2017-03-19 12:24:29 -06002066
John Kesseniche6e74942016-06-11 16:43:14 -06002067 // struct_declaration_list
2068 TTypeList* typeList;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002069 // Save each member function so they can be processed after we have a fully formed 'this'.
2070 TVector<TFunctionDeclarator> functionDeclarators;
2071
2072 parseContext.pushNamespace(structName);
John Kessenichaa3c64c2017-03-28 09:52:38 -06002073 bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06002074 parseContext.popNamespace();
2075
2076 if (! acceptedList) {
John Kesseniche6e74942016-06-11 16:43:14 -06002077 expected("struct member declarations");
2078 return false;
2079 }
2080
2081 // RIGHT_BRACE
2082 if (! acceptTokenClass(EHTokRightBrace)) {
2083 expected("}");
2084 return false;
2085 }
2086
2087 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06002088 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06002089 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06002090 else {
John Kessenich7735b942016-09-05 12:40:06 -06002091 postDeclQualifier.storage = storageQualifier;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002092 postDeclQualifier.readonly = readonly;
John Kessenich7735b942016-09-05 12:40:06 -06002093 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06002094 }
John Kesseniche6e74942016-06-11 16:43:14 -06002095
John Kessenich727b3742017-02-03 17:57:55 -07002096 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06002097
John Kessenich4960baa2017-03-19 18:09:59 -06002098 // For member functions: now that we know the type of 'this', go back and
2099 // - add their implicit argument with 'this' (not to the mangling, just the argument list)
2100 // - parse the functions, their tokens were saved for deferred parsing (now)
2101 for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
2102 // update signature
2103 if (functionDeclarators[b].function->hasImplicitThis())
John Kessenich37789792017-03-21 23:56:40 -06002104 functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName);
John Kessenich4960baa2017-03-19 18:09:59 -06002105 }
2106
John Kessenichf3d88bd2017-03-19 12:24:29 -06002107 // All member functions get parsed inside the class/struct namespace and with the
2108 // class/struct members in a symbol-table level.
2109 parseContext.pushNamespace(structName);
John Kessenich0a2a0cd2017-05-16 23:16:26 -06002110 parseContext.pushThisScope(type, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06002111 bool deferredSuccess = true;
2112 for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
2113 // parse body
2114 pushTokenStream(functionDeclarators[b].body);
2115 if (! acceptFunctionBody(functionDeclarators[b], nodeList))
2116 deferredSuccess = false;
2117 popTokenStream();
2118 }
John Kessenich37789792017-03-21 23:56:40 -06002119 parseContext.popThisScope();
John Kessenichf3d88bd2017-03-19 12:24:29 -06002120 parseContext.popNamespace();
2121
2122 return deferredSuccess;
John Kesseniche6e74942016-06-11 16:43:14 -06002123}
2124
steve-lunarga766b832017-04-25 09:30:28 -06002125// constantbuffer
2126// : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE
2127bool HlslGrammar::acceptConstantBufferType(TType& type)
2128{
2129 if (! acceptTokenClass(EHTokConstantBuffer))
2130 return false;
2131
2132 if (! acceptTokenClass(EHTokLeftAngle)) {
2133 expected("left angle bracket");
2134 return false;
2135 }
2136
2137 TType templateType;
2138 if (! acceptType(templateType)) {
2139 expected("type");
2140 return false;
2141 }
2142
2143 if (! acceptTokenClass(EHTokRightAngle)) {
2144 expected("right angle bracket");
2145 return false;
2146 }
2147
2148 TQualifier postDeclQualifier;
2149 postDeclQualifier.clear();
2150 postDeclQualifier.storage = EvqUniform;
2151
2152 if (templateType.isStruct()) {
2153 // Make a block from the type parsed as the template argument
2154 TTypeList* typeList = templateType.getWritableStruct();
2155 new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock
2156
2157 type.getQualifier().storage = EvqUniform;
2158
2159 return true;
2160 } else {
2161 parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", "");
2162 return false;
2163 }
2164}
2165
LoopDawge5530b92017-11-08 19:48:11 -07002166// texture_buffer
2167// : TEXTUREBUFFER LEFT_ANGLE type RIGHT_ANGLE
2168bool HlslGrammar::acceptTextureBufferType(TType& type)
2169{
2170 if (! acceptTokenClass(EHTokTextureBuffer))
2171 return false;
2172
2173 if (! acceptTokenClass(EHTokLeftAngle)) {
2174 expected("left angle bracket");
2175 return false;
2176 }
2177
2178 TType templateType;
2179 if (! acceptType(templateType)) {
2180 expected("type");
2181 return false;
2182 }
2183
2184 if (! acceptTokenClass(EHTokRightAngle)) {
2185 expected("right angle bracket");
2186 return false;
2187 }
2188
2189 templateType.getQualifier().storage = EvqBuffer;
2190 templateType.getQualifier().readonly = true;
2191
2192 TType blockType(templateType.getWritableStruct(), "", templateType.getQualifier());
2193
2194 blockType.getQualifier().storage = EvqBuffer;
2195 blockType.getQualifier().readonly = true;
2196
2197 type.shallowCopy(blockType);
2198
2199 return true;
2200}
2201
2202
steve-lunarg5da1f032017-02-12 17:50:28 -07002203// struct_buffer
2204// : APPENDSTRUCTUREDBUFFER
2205// | BYTEADDRESSBUFFER
2206// | CONSUMESTRUCTUREDBUFFER
2207// | RWBYTEADDRESSBUFFER
2208// | RWSTRUCTUREDBUFFER
2209// | STRUCTUREDBUFFER
2210bool HlslGrammar::acceptStructBufferType(TType& type)
2211{
2212 const EHlslTokenClass structBuffType = peek();
2213
2214 // TODO: globallycoherent
2215 bool hasTemplateType = true;
2216 bool readonly = false;
2217
2218 TStorageQualifier storage = EvqBuffer;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002219 TBuiltInVariable builtinType = EbvNone;
steve-lunarg5da1f032017-02-12 17:50:28 -07002220
2221 switch (structBuffType) {
2222 case EHTokAppendStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002223 builtinType = EbvAppendConsume;
2224 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002225 case EHTokByteAddressBuffer:
2226 hasTemplateType = false;
2227 readonly = true;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002228 builtinType = EbvByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002229 break;
2230 case EHTokConsumeStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002231 builtinType = EbvAppendConsume;
2232 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002233 case EHTokRWByteAddressBuffer:
2234 hasTemplateType = false;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002235 builtinType = EbvRWByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002236 break;
2237 case EHTokRWStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002238 builtinType = EbvRWStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002239 break;
2240 case EHTokStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002241 builtinType = EbvStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002242 readonly = true;
2243 break;
2244 default:
2245 return false; // not a structure buffer type
2246 }
2247
2248 advanceToken(); // consume the structure keyword
2249
2250 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
2251 TType* templateType = new TType;
2252
2253 if (hasTemplateType) {
2254 if (! acceptTokenClass(EHTokLeftAngle)) {
2255 expected("left angle bracket");
2256 return false;
2257 }
2258
2259 if (! acceptType(*templateType)) {
2260 expected("type");
2261 return false;
2262 }
2263 if (! acceptTokenClass(EHTokRightAngle)) {
2264 expected("right angle bracket");
2265 return false;
2266 }
2267 } else {
2268 // byte address buffers have no explicit type.
2269 TType uintType(EbtUint, storage);
2270 templateType->shallowCopy(uintType);
2271 }
2272
2273 // Create an unsized array out of that type.
2274 // TODO: does this work if it's already an array type?
2275 TArraySizes unsizedArray;
2276 unsizedArray.addInnerSize(UnsizedArraySize);
2277 templateType->newArraySizes(unsizedArray);
steve-lunarg40efe5c2017-03-06 12:01:44 -07002278 templateType->getQualifier().storage = storage;
steve-lunargdd8287a2017-02-23 18:04:12 -07002279
2280 // field name is canonical for all structbuffers
2281 templateType->setFieldName("@data");
steve-lunarg5da1f032017-02-12 17:50:28 -07002282
steve-lunarg5da1f032017-02-12 17:50:28 -07002283 TTypeList* blockStruct = new TTypeList;
2284 TTypeLoc member = { templateType, token.loc };
2285 blockStruct->push_back(member);
2286
steve-lunargdd8287a2017-02-23 18:04:12 -07002287 // This is the type of the buffer block (SSBO)
steve-lunarg5da1f032017-02-12 17:50:28 -07002288 TType blockType(blockStruct, "", templateType->getQualifier());
2289
steve-lunargdd8287a2017-02-23 18:04:12 -07002290 blockType.getQualifier().storage = storage;
2291 blockType.getQualifier().readonly = readonly;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002292 blockType.getQualifier().builtIn = builtinType;
steve-lunargdd8287a2017-02-23 18:04:12 -07002293
2294 // We may have created an equivalent type before, in which case we should use its
2295 // deep structure.
2296 parseContext.shareStructBufferType(blockType);
2297
steve-lunarg5da1f032017-02-12 17:50:28 -07002298 type.shallowCopy(blockType);
2299
2300 return true;
2301}
2302
John Kesseniche6e74942016-06-11 16:43:14 -06002303// struct_declaration_list
2304// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
2305//
2306// struct_declaration
John Kessenichcc951f82017-12-06 07:33:36 -07002307// : attributes fully_specified_type struct_declarator COMMA struct_declarator ...
2308// | attributes fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition
John Kesseniche6e74942016-06-11 16:43:14 -06002309//
2310// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06002311// : IDENTIFIER post_decls
2312// | IDENTIFIER array_specifier post_decls
John Kessenich54ee28f2017-03-11 14:13:00 -07002313// | IDENTIFIER function_parameters post_decls // member-function prototype
John Kesseniche6e74942016-06-11 16:43:14 -06002314//
John Kessenichaa3c64c2017-03-28 09:52:38 -06002315bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002316 TVector<TFunctionDeclarator>& declarators)
John Kesseniche6e74942016-06-11 16:43:14 -06002317{
2318 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002319 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06002320
2321 do {
2322 // success on seeing the RIGHT_BRACE coming up
2323 if (peekTokenClass(EHTokRightBrace))
John Kessenichb16f7e62017-03-11 19:32:47 -07002324 break;
John Kesseniche6e74942016-06-11 16:43:14 -06002325
2326 // struct_declaration
John Kessenichcc951f82017-12-06 07:33:36 -07002327
2328 // attributes
2329 TAttributeMap attributes;
2330 acceptAttributes(attributes);
2331
John Kessenich54ee28f2017-03-11 14:13:00 -07002332 bool declarator_list = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002333
2334 // fully_specified_type
2335 TType memberType;
John Kessenich54ee28f2017-03-11 14:13:00 -07002336 if (! acceptFullySpecifiedType(memberType, nodeList)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002337 expected("member type");
2338 return false;
2339 }
2340
John Kessenichcc951f82017-12-06 07:33:36 -07002341 parseContext.transferTypeAttributes(attributes, memberType);
2342
John Kesseniche6e74942016-06-11 16:43:14 -06002343 // struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07002344 bool functionDefinitionAccepted = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002345 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002346 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002347 expected("member name");
2348 return false;
2349 }
2350
John Kessenich54ee28f2017-03-11 14:13:00 -07002351 if (peekTokenClass(EHTokLeftParen)) {
2352 // function_parameters
2353 if (!declarator_list) {
John Kessenichb16f7e62017-03-11 19:32:47 -07002354 declarators.resize(declarators.size() + 1);
2355 // request a token stream for deferred processing
John Kessenichf3d88bd2017-03-19 12:24:29 -06002356 functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
2357 declarators.back());
John Kessenich54ee28f2017-03-11 14:13:00 -07002358 if (functionDefinitionAccepted)
2359 break;
2360 }
2361 expected("member-function definition");
2362 return false;
2363 } else {
2364 // add it to the list of members
2365 TTypeLoc member = { new TType(EbtVoid), token.loc };
2366 member.type->shallowCopy(memberType);
2367 member.type->setFieldName(*idToken.string);
2368 typeList->push_back(member);
John Kesseniche6e74942016-06-11 16:43:14 -06002369
John Kessenich54ee28f2017-03-11 14:13:00 -07002370 // array_specifier
2371 TArraySizes* arraySizes = nullptr;
2372 acceptArraySpecifier(arraySizes);
2373 if (arraySizes)
2374 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06002375
John Kessenich54ee28f2017-03-11 14:13:00 -07002376 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06002377
John Kessenich54ee28f2017-03-11 14:13:00 -07002378 // EQUAL assignment_expression
2379 if (acceptTokenClass(EHTokAssign)) {
2380 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
2381 TIntermTyped* expressionNode = nullptr;
2382 if (! acceptAssignmentExpression(expressionNode)) {
2383 expected("initializer");
2384 return false;
2385 }
John Kessenich18adbdb2017-02-02 15:16:20 -07002386 }
2387 }
John Kesseniche6e74942016-06-11 16:43:14 -06002388 // success on seeing the SEMICOLON coming up
2389 if (peekTokenClass(EHTokSemicolon))
2390 break;
2391
2392 // COMMA
John Kessenich54ee28f2017-03-11 14:13:00 -07002393 if (acceptTokenClass(EHTokComma))
2394 declarator_list = true;
2395 else {
John Kesseniche6e74942016-06-11 16:43:14 -06002396 expected(",");
2397 return false;
2398 }
2399
2400 } while (true);
2401
2402 // SEMI_COLON
John Kessenich54ee28f2017-03-11 14:13:00 -07002403 if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002404 expected(";");
2405 return false;
2406 }
2407
2408 } while (true);
John Kessenichb16f7e62017-03-11 19:32:47 -07002409
John Kessenichb16f7e62017-03-11 19:32:47 -07002410 return true;
John Kesseniche6e74942016-06-11 16:43:14 -06002411}
2412
John Kessenich54ee28f2017-03-11 14:13:00 -07002413// member_function_definition
2414// | function_parameters post_decls compound_statement
2415//
2416// Expects type to have EvqGlobal for a static member and
2417// EvqTemporary for non-static member.
John Kessenich9855bda2017-09-11 21:48:19 -06002418bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, TString& memberName,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002419 TFunctionDeclarator& declarator)
John Kessenich54ee28f2017-03-11 14:13:00 -07002420{
John Kessenich54ee28f2017-03-11 14:13:00 -07002421 bool accepted = false;
2422
John Kessenich9855bda2017-09-11 21:48:19 -06002423 TString* functionName = &memberName;
John Kessenich4dc835c2017-03-28 23:43:10 -06002424 parseContext.getFullNamespaceName(functionName);
John Kessenich088d52b2017-03-11 17:55:28 -07002425 declarator.function = new TFunction(functionName, type);
John Kessenich4960baa2017-03-19 18:09:59 -06002426 if (type.getQualifier().storage == EvqTemporary)
2427 declarator.function->setImplicitThis();
John Kessenich37789792017-03-21 23:56:40 -06002428 else
2429 declarator.function->setIllegalImplicitThis();
John Kessenich54ee28f2017-03-11 14:13:00 -07002430
2431 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -07002432 if (acceptFunctionParameters(*declarator.function)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002433 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -07002434 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich54ee28f2017-03-11 14:13:00 -07002435
2436 // compound_statement (function body definition)
2437 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich088d52b2017-03-11 17:55:28 -07002438 declarator.loc = token.loc;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002439 declarator.body = new TVector<HlslToken>;
2440 accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
John Kessenich54ee28f2017-03-11 14:13:00 -07002441 }
2442 } else
2443 expected("function parameter list");
2444
John Kessenich54ee28f2017-03-11 14:13:00 -07002445 return accepted;
2446}
2447
John Kessenich5f934b02016-03-13 17:58:25 -06002448// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06002449// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06002450// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002451//
2452bool HlslGrammar::acceptFunctionParameters(TFunction& function)
2453{
John Kessenich078d7f22016-03-14 10:02:11 -06002454 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002455 if (! acceptTokenClass(EHTokLeftParen))
2456 return false;
2457
John Kessenich71351de2016-06-08 12:50:56 -06002458 // VOID RIGHT_PAREN
2459 if (! acceptTokenClass(EHTokVoid)) {
2460 do {
2461 // parameter_declaration
2462 if (! acceptParameterDeclaration(function))
2463 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002464
John Kessenich71351de2016-06-08 12:50:56 -06002465 // COMMA
2466 if (! acceptTokenClass(EHTokComma))
2467 break;
2468 } while (true);
2469 }
John Kessenich5f934b02016-03-13 17:58:25 -06002470
John Kessenich078d7f22016-03-14 10:02:11 -06002471 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002472 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002473 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002474 return false;
2475 }
2476
2477 return true;
2478}
2479
steve-lunarg26d31452016-12-23 18:56:57 -07002480// default_parameter_declaration
2481// : EQUAL conditional_expression
2482// : EQUAL initializer
2483bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2484{
2485 node = nullptr;
2486
2487 // Valid not to have a default_parameter_declaration
2488 if (!acceptTokenClass(EHTokAssign))
2489 return true;
2490
2491 if (!acceptConditionalExpression(node)) {
2492 if (!acceptInitializer(node))
2493 return false;
2494
2495 // For initializer lists, we have to const-fold into a constructor for the type, so build
2496 // that.
John Kessenichc633f642017-04-03 21:48:37 -06002497 TFunction* constructor = parseContext.makeConstructorCall(token.loc, type);
steve-lunarg26d31452016-12-23 18:56:57 -07002498 if (constructor == nullptr) // cannot construct
2499 return false;
2500
2501 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002502 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002503 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002504
steve-lunarg26d31452016-12-23 18:56:57 -07002505 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2506 }
2507
John Kessenichbb79abc2017-10-07 13:23:09 -06002508 if (node == nullptr)
2509 return false;
2510
steve-lunarg26d31452016-12-23 18:56:57 -07002511 // If this is simply a constant, we can use it directly.
2512 if (node->getAsConstantUnion())
2513 return true;
2514
2515 // Otherwise, it has to be const-foldable.
2516 TIntermTyped* origNode = node;
2517
2518 node = intermediate.fold(node->getAsAggregate());
2519
2520 if (node != nullptr && origNode != node)
2521 return true;
2522
2523 parseContext.error(token.loc, "invalid default parameter value", "", "");
2524
2525 return false;
2526}
2527
John Kessenich5f934b02016-03-13 17:58:25 -06002528// parameter_declaration
John Kessenich77ea30b2017-09-30 14:34:50 -06002529// : attributes attributed_declaration
2530//
2531// attributed_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002532// : fully_specified_type post_decls [ = default_parameter_declaration ]
2533// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002534//
2535bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2536{
John Kessenich77ea30b2017-09-30 14:34:50 -06002537 // attributes
2538 TAttributeMap attributes;
2539 acceptAttributes(attributes);
2540
John Kessenich5f934b02016-03-13 17:58:25 -06002541 // fully_specified_type
2542 TType* type = new TType;
2543 if (! acceptFullySpecifiedType(*type))
2544 return false;
2545
John Kessenich77ea30b2017-09-30 14:34:50 -06002546 parseContext.transferTypeAttributes(attributes, *type);
2547
John Kessenich5f934b02016-03-13 17:58:25 -06002548 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002549 HlslToken idToken;
2550 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002551
John Kessenich19b92ff2016-06-19 11:50:34 -06002552 // array_specifier
2553 TArraySizes* arraySizes = nullptr;
2554 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002555 if (arraySizes) {
2556 if (arraySizes->isImplicit()) {
2557 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2558 return false;
2559 }
2560
John Kessenich19b92ff2016-06-19 11:50:34 -06002561 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002562 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002563
2564 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002565 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002566
steve-lunarg26d31452016-12-23 18:56:57 -07002567 TIntermTyped* defaultValue;
2568 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2569 return false;
2570
John Kessenich5aa59e22016-06-17 15:50:47 -06002571 parseContext.paramFix(*type);
2572
steve-lunarg26d31452016-12-23 18:56:57 -07002573 // If any prior parameters have default values, all the parameters after that must as well.
2574 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2575 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2576 return false;
2577 }
2578
2579 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002580 function.addParameter(param);
2581
2582 return true;
2583}
2584
2585// Do the work to create the function definition in addition to
2586// parsing the body (compound_statement).
John Kessenichb16f7e62017-03-11 19:32:47 -07002587//
2588// If 'deferredTokens' are passed in, just get the token stream,
2589// don't process.
2590//
2591bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
2592 TVector<HlslToken>* deferredTokens)
John Kessenich5f934b02016-03-13 17:58:25 -06002593{
John Kessenich088d52b2017-03-11 17:55:28 -07002594 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
John Kessenich5f934b02016-03-13 17:58:25 -06002595
John Kessenichb16f7e62017-03-11 19:32:47 -07002596 if (deferredTokens)
2597 return captureBlockTokens(*deferredTokens);
2598 else
John Kessenich4960baa2017-03-19 18:09:59 -06002599 return acceptFunctionBody(declarator, nodeList);
John Kessenich088d52b2017-03-11 17:55:28 -07002600}
2601
2602bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
2603{
2604 // we might get back an entry-point
John Kessenichca71d942017-03-07 20:44:09 -07002605 TIntermNode* entryPointNode = nullptr;
2606
John Kessenich077e0522016-06-09 02:02:17 -06002607 // This does a pushScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002608 TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function,
2609 declarator.attributes, entryPointNode);
John Kessenich5f934b02016-03-13 17:58:25 -06002610
2611 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002612 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002613 if (! acceptCompoundStatement(functionBody))
2614 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002615
John Kessenich54ee28f2017-03-11 14:13:00 -07002616 // this does a popScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002617 parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode);
John Kessenichca71d942017-03-07 20:44:09 -07002618
2619 // Hook up the 1 or 2 function definitions.
2620 nodeList = intermediate.growAggregate(nodeList, functionNode);
2621 nodeList = intermediate.growAggregate(nodeList, entryPointNode);
John Kessenich02467d82017-01-19 15:41:47 -07002622
2623 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002624}
2625
John Kessenich0d2b6de2016-06-05 11:23:11 -06002626// Accept an expression with parenthesis around it, where
2627// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002628// syntactically required ones like in "if ( expression )".
2629//
2630// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002631//
2632// Note this one is not set up to be speculative; as it gives
2633// errors if not found.
2634//
2635bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2636{
John Kessenich7199a6d2017-11-29 16:32:46 -07002637 expression = nullptr;
2638
John Kessenich0d2b6de2016-06-05 11:23:11 -06002639 // LEFT_PAREN
2640 if (! acceptTokenClass(EHTokLeftParen))
2641 expected("(");
2642
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002643 bool decl = false;
2644 TIntermNode* declNode = nullptr;
2645 decl = acceptControlDeclaration(declNode);
2646 if (decl) {
2647 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2648 expected("initialized declaration");
2649 return false;
2650 } else
2651 expression = declNode->getAsTyped();
2652 } else {
2653 // no declaration
2654 if (! acceptExpression(expression)) {
2655 expected("expression");
2656 return false;
2657 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002658 }
2659
2660 // RIGHT_PAREN
2661 if (! acceptTokenClass(EHTokRightParen))
2662 expected(")");
2663
2664 return true;
2665}
2666
John Kessenich34fb0362016-05-03 23:17:20 -06002667// The top-level full expression recognizer.
2668//
John Kessenich87142c72016-03-12 20:24:24 -07002669// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002670// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002671//
2672bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2673{
LoopDawgef764a22016-06-03 09:17:51 -06002674 node = nullptr;
2675
John Kessenich34fb0362016-05-03 23:17:20 -06002676 // assignment_expression
2677 if (! acceptAssignmentExpression(node))
2678 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002679
John Kessenich34fb0362016-05-03 23:17:20 -06002680 if (! peekTokenClass(EHTokComma))
2681 return true;
2682
2683 do {
2684 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002685 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002686 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002687
John Kessenich34fb0362016-05-03 23:17:20 -06002688 // ... assignment_expression
2689 TIntermTyped* rightNode = nullptr;
2690 if (! acceptAssignmentExpression(rightNode)) {
2691 expected("assignment expression");
2692 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002693 }
2694
John Kessenich34fb0362016-05-03 23:17:20 -06002695 node = intermediate.addComma(node, rightNode, loc);
2696
2697 if (! peekTokenClass(EHTokComma))
2698 return true;
2699 } while (true);
2700}
2701
John Kessenich07354242016-07-01 19:58:06 -06002702// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002703// : LEFT_BRACE RIGHT_BRACE
2704// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002705//
2706// initializer_list
2707// : assignment_expression COMMA assignment_expression COMMA ...
2708//
2709bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2710{
2711 // LEFT_BRACE
2712 if (! acceptTokenClass(EHTokLeftBrace))
2713 return false;
2714
John Kessenich98ad4852016-11-27 17:39:07 -07002715 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002716 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002717 if (acceptTokenClass(EHTokRightBrace)) {
2718 // a zero-length initializer list
2719 node = intermediate.makeAggregate(loc);
2720 return true;
2721 }
2722
2723 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002724 node = nullptr;
2725 do {
2726 // assignment_expression
2727 TIntermTyped* expr;
2728 if (! acceptAssignmentExpression(expr)) {
2729 expected("assignment expression in initializer list");
2730 return false;
2731 }
LoopDawg0fca0ba2017-07-10 15:43:40 -06002732
2733 const bool firstNode = (node == nullptr);
2734
John Kessenich07354242016-07-01 19:58:06 -06002735 node = intermediate.growAggregate(node, expr, loc);
2736
LoopDawg0fca0ba2017-07-10 15:43:40 -06002737 // If every sub-node in the list has qualifier EvqConst, the returned node becomes
2738 // EvqConst. Otherwise, it becomes EvqTemporary. That doesn't happen with e.g.
2739 // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are.
2740 if (firstNode && expr->getQualifier().storage == EvqConst)
2741 node->getQualifier().storage = EvqConst;
2742 else if (expr->getQualifier().storage != EvqConst)
2743 node->getQualifier().storage = EvqTemporary;
2744
John Kessenich07354242016-07-01 19:58:06 -06002745 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002746 if (acceptTokenClass(EHTokComma)) {
2747 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2748 return true;
John Kessenich07354242016-07-01 19:58:06 -06002749 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002750 }
John Kessenich07354242016-07-01 19:58:06 -06002751
2752 // RIGHT_BRACE
2753 if (acceptTokenClass(EHTokRightBrace))
2754 return true;
2755
2756 expected(", or }");
2757 return false;
2758 } while (true);
2759}
2760
John Kessenich34fb0362016-05-03 23:17:20 -06002761// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002762// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002763//
2764// a op (b op (c op d))
2765//
2766// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002767// : initializer
2768// | conditional_expression
2769// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002770//
2771bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2772{
John Kessenich07354242016-07-01 19:58:06 -06002773 // initializer
2774 if (peekTokenClass(EHTokLeftBrace)) {
2775 if (acceptInitializer(node))
2776 return true;
2777
2778 expected("initializer");
2779 return false;
2780 }
2781
John Kessenich00957f82016-07-27 10:39:57 -06002782 // conditional_expression
2783 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002784 return false;
2785
John Kessenich07354242016-07-01 19:58:06 -06002786 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002787 TOperator assignOp = HlslOpMap::assignment(peek());
2788 if (assignOp == EOpNull)
2789 return true;
2790
John Kessenich00957f82016-07-27 10:39:57 -06002791 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002792 TSourceLoc loc = token.loc;
2793 advanceToken();
2794
John Kessenich00957f82016-07-27 10:39:57 -06002795 // conditional_expression assign_op conditional_expression ...
2796 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002797 // gets the right-to-left associativity.
2798 TIntermTyped* rightNode = nullptr;
2799 if (! acceptAssignmentExpression(rightNode)) {
2800 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002801 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002802 }
2803
John Kessenichd21baed2016-09-16 03:05:12 -06002804 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002805 node = parseContext.handleLvalue(loc, "assign", node);
2806
John Kessenichfea226b2016-07-28 17:53:56 -06002807 if (node == nullptr) {
2808 parseContext.error(loc, "could not create assignment", "", "");
2809 return false;
2810 }
John Kessenich34fb0362016-05-03 23:17:20 -06002811
2812 if (! peekTokenClass(EHTokComma))
2813 return true;
2814
2815 return true;
2816}
2817
John Kessenich00957f82016-07-27 10:39:57 -06002818// Accept a conditional expression, which associates right-to-left,
2819// accomplished by the "true" expression calling down to lower
2820// precedence levels than this level.
2821//
2822// conditional_expression
2823// : binary_expression
2824// | binary_expression QUESTION expression COLON assignment_expression
2825//
2826bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2827{
2828 // binary_expression
2829 if (! acceptBinaryExpression(node, PlLogicalOr))
2830 return false;
2831
2832 if (! acceptTokenClass(EHTokQuestion))
2833 return true;
2834
John Kessenich636b62d2017-04-11 19:45:00 -06002835 node = parseContext.convertConditionalExpression(token.loc, node, false);
John Kessenich7e997e22017-03-30 22:09:30 -06002836 if (node == nullptr)
2837 return false;
2838
John Kessenichf6deacd2017-06-06 19:52:55 -06002839 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
2840
John Kessenich00957f82016-07-27 10:39:57 -06002841 TIntermTyped* trueNode = nullptr;
2842 if (! acceptExpression(trueNode)) {
2843 expected("expression after ?");
2844 return false;
2845 }
2846 TSourceLoc loc = token.loc;
2847
2848 if (! acceptTokenClass(EHTokColon)) {
2849 expected(":");
2850 return false;
2851 }
2852
2853 TIntermTyped* falseNode = nullptr;
2854 if (! acceptAssignmentExpression(falseNode)) {
2855 expected("expression after :");
2856 return false;
2857 }
2858
John Kessenichf6deacd2017-06-06 19:52:55 -06002859 --parseContext.controlFlowNestingLevel;
2860
John Kessenich00957f82016-07-27 10:39:57 -06002861 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2862
2863 return true;
2864}
2865
John Kessenich34fb0362016-05-03 23:17:20 -06002866// Accept a binary expression, for binary operations that
2867// associate left-to-right. This is, it is implicit, for example
2868//
2869// ((a op b) op c) op d
2870//
2871// binary_expression
2872// : expression op expression op expression ...
2873//
2874// where 'expression' is the next higher level in precedence.
2875//
2876bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2877{
2878 if (precedenceLevel > PlMul)
2879 return acceptUnaryExpression(node);
2880
2881 // assignment_expression
2882 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2883 return false;
2884
John Kessenich34fb0362016-05-03 23:17:20 -06002885 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002886 TOperator op = HlslOpMap::binary(peek());
2887 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2888 if (tokenLevel < precedenceLevel)
2889 return true;
2890
John Kessenich34fb0362016-05-03 23:17:20 -06002891 // ... op
2892 TSourceLoc loc = token.loc;
2893 advanceToken();
2894
2895 // ... expression
2896 TIntermTyped* rightNode = nullptr;
2897 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2898 expected("expression");
2899 return false;
2900 }
2901
2902 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002903 if (node == nullptr) {
2904 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2905 return false;
2906 }
John Kessenich34fb0362016-05-03 23:17:20 -06002907 } while (true);
2908}
2909
2910// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002911// : (type) unary_expression
2912// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002913// | - unary_expression
2914// | ! unary_expression
2915// | ~ unary_expression
2916// | ++ unary_expression
2917// | -- unary_expression
2918// | postfix_expression
2919//
2920bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2921{
John Kessenich1cc1a282016-06-03 16:55:49 -06002922 // (type) unary_expression
2923 // Have to look two steps ahead, because this could be, e.g., a
2924 // postfix_expression instead, since that also starts with at "(".
2925 if (acceptTokenClass(EHTokLeftParen)) {
2926 TType castType;
2927 if (acceptType(castType)) {
John Kessenich82ae8c32017-06-13 23:13:10 -06002928 // recognize any array_specifier as part of the type
2929 TArraySizes* arraySizes = nullptr;
2930 acceptArraySpecifier(arraySizes);
2931 if (arraySizes != nullptr)
2932 castType.newArraySizes(*arraySizes);
2933 TSourceLoc loc = token.loc;
steve-lunarg5964c642016-07-30 07:38:55 -06002934 if (acceptTokenClass(EHTokRightParen)) {
2935 // We've matched "(type)" now, get the expression to cast
steve-lunarg5964c642016-07-30 07:38:55 -06002936 if (! acceptUnaryExpression(node))
2937 return false;
2938
2939 // Hook it up like a constructor
John Kessenichc633f642017-04-03 21:48:37 -06002940 TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType);
steve-lunarg5964c642016-07-30 07:38:55 -06002941 if (constructorFunction == nullptr) {
2942 expected("type that can be constructed");
2943 return false;
2944 }
2945 TIntermTyped* arguments = nullptr;
2946 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2947 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2948
John Kessenichbb79abc2017-10-07 13:23:09 -06002949 return node != nullptr;
steve-lunarg5964c642016-07-30 07:38:55 -06002950 } else {
2951 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2952 // the '(int' part. We must back up twice.
2953 recedeToken();
2954 recedeToken();
John Kessenich82ae8c32017-06-13 23:13:10 -06002955
2956 // Note, there are no array constructors like
2957 // (float[2](...))
2958 if (arraySizes != nullptr)
2959 parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", "");
John Kessenich1cc1a282016-06-03 16:55:49 -06002960 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002961 } else {
2962 // This isn't a type cast, but it still started "(", so if it is a
2963 // unary expression, it can only be a postfix_expression, so try that.
2964 // Back it up first.
2965 recedeToken();
2966 return acceptPostfixExpression(node);
2967 }
2968 }
2969
2970 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002971 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002972
John Kessenich1cc1a282016-06-03 16:55:49 -06002973 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002974 if (unaryOp == EOpNull)
2975 return acceptPostfixExpression(node);
2976
2977 // op unary_expression
2978 TSourceLoc loc = token.loc;
2979 advanceToken();
2980 if (! acceptUnaryExpression(node))
2981 return false;
2982
2983 // + is a no-op
2984 if (unaryOp == EOpAdd)
2985 return true;
2986
2987 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002988
2989 // These unary ops require lvalues
2990 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2991 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002992
2993 return node != nullptr;
2994}
2995
2996// postfix_expression
2997// : LEFT_PAREN expression RIGHT_PAREN
2998// | literal
2999// | constructor
John Kessenich8f9fdc92017-03-30 16:22:26 -06003000// | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ]
John Kessenich34fb0362016-05-03 23:17:20 -06003001// | function_call
3002// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
3003// | postfix_expression DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07003004// | postfix_expression DOT IDENTIFIER arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06003005// | postfix_expression arguments
John Kessenich34fb0362016-05-03 23:17:20 -06003006// | postfix_expression INC_OP
3007// | postfix_expression DEC_OP
3008//
3009bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
3010{
3011 // Not implemented as self-recursive:
John Kessenich54ee28f2017-03-11 14:13:00 -07003012 // The logical "right recursion" is done with a loop at the end
John Kessenich34fb0362016-05-03 23:17:20 -06003013
3014 // idToken will pick up either a variable or a function name in a function call
3015 HlslToken idToken;
3016
John Kessenich21472ae2016-06-04 11:46:33 -06003017 // Find something before the postfix operations, as they can't operate
3018 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07003019 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06003020 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003021 if (! acceptExpression(node)) {
3022 expected("expression");
3023 return false;
3024 }
3025 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003026 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003027 return false;
3028 }
John Kessenich34fb0362016-05-03 23:17:20 -06003029 } else if (acceptLiteral(node)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003030 // literal (nothing else to do yet)
John Kessenich34fb0362016-05-03 23:17:20 -06003031 } else if (acceptConstructor(node)) {
3032 // constructor (nothing else to do yet)
3033 } else if (acceptIdentifier(idToken)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003034 // user-type, namespace name, variable, or function name
3035 TString* fullName = idToken.string;
3036 while (acceptTokenClass(EHTokColonColon)) {
3037 // user-type or namespace name
3038 fullName = NewPoolTString(fullName->c_str());
3039 fullName->append(parseContext.scopeMangler);
3040 if (acceptIdentifier(idToken))
3041 fullName->append(*idToken.string);
3042 else {
3043 expected("identifier after ::");
John Kessenich54ee28f2017-03-11 14:13:00 -07003044 return false;
3045 }
John Kessenich8f9fdc92017-03-30 16:22:26 -06003046 }
3047 if (! peekTokenClass(EHTokLeftParen)) {
3048 node = parseContext.handleVariable(idToken.loc, fullName);
3049 } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) {
John Kessenich34fb0362016-05-03 23:17:20 -06003050 // function_call (nothing else to do yet)
3051 } else {
3052 expected("function call arguments");
3053 return false;
3054 }
John Kessenich21472ae2016-06-04 11:46:33 -06003055 } else {
3056 // nothing found, can't post operate
3057 return false;
John Kessenich87142c72016-03-12 20:24:24 -07003058 }
3059
John Kessenich21472ae2016-06-04 11:46:33 -06003060 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06003061 do {
3062 TSourceLoc loc = token.loc;
3063 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07003064
John Kessenich34fb0362016-05-03 23:17:20 -06003065 // Consume only a valid post-unary operator, otherwise we are done.
3066 switch (postOp) {
3067 case EOpIndexDirectStruct:
3068 case EOpIndexIndirect:
3069 case EOpPostIncrement:
3070 case EOpPostDecrement:
John Kessenich54ee28f2017-03-11 14:13:00 -07003071 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06003072 advanceToken();
3073 break;
3074 default:
3075 return true;
3076 }
John Kessenich87142c72016-03-12 20:24:24 -07003077
John Kessenich34fb0362016-05-03 23:17:20 -06003078 // We have a valid post-unary operator, process it.
3079 switch (postOp) {
John Kessenich54ee28f2017-03-11 14:13:00 -07003080 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06003081 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06003082 {
John Kessenich19b92ff2016-06-19 11:50:34 -06003083 // DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07003084 // includes swizzles, member variables, and member functions
John Kessenich93a162a2016-06-17 17:16:27 -06003085 HlslToken field;
3086 if (! acceptIdentifier(field)) {
3087 expected("swizzle or member");
3088 return false;
3089 }
LoopDawg4886f692016-06-29 10:58:58 -06003090
John Kessenich516d92d2017-03-08 20:09:03 -07003091 if (peekTokenClass(EHTokLeftParen)) {
3092 // member function
3093 TIntermTyped* thisNode = node;
LoopDawg4886f692016-06-29 10:58:58 -06003094
John Kessenich516d92d2017-03-08 20:09:03 -07003095 // arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06003096 if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) {
LoopDawg4886f692016-06-29 10:58:58 -06003097 expected("function parameters");
3098 return false;
3099 }
John Kessenich516d92d2017-03-08 20:09:03 -07003100 } else
3101 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06003102
John Kessenich34fb0362016-05-03 23:17:20 -06003103 break;
John Kessenich93a162a2016-06-17 17:16:27 -06003104 }
John Kessenich34fb0362016-05-03 23:17:20 -06003105 case EOpIndexIndirect:
3106 {
John Kessenich19b92ff2016-06-19 11:50:34 -06003107 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06003108 TIntermTyped* indexNode = nullptr;
3109 if (! acceptExpression(indexNode) ||
3110 ! peekTokenClass(EHTokRightBracket)) {
3111 expected("expression followed by ']'");
3112 return false;
3113 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003114 advanceToken();
3115 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
steve-lunarg2efd6c62017-04-06 20:22:20 -06003116 if (node == nullptr)
3117 return false;
John Kessenich19b92ff2016-06-19 11:50:34 -06003118 break;
John Kessenich34fb0362016-05-03 23:17:20 -06003119 }
3120 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06003121 // INC_OP
3122 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06003123 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06003124 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06003125 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06003126 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06003127 break;
3128 default:
3129 assert(0);
3130 break;
3131 }
3132 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07003133}
3134
John Kessenichd016be12016-03-13 11:24:20 -06003135// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06003136// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06003137//
3138bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
3139{
3140 // type
3141 TType type;
3142 if (acceptType(type)) {
John Kessenichc633f642017-04-03 21:48:37 -06003143 TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type);
John Kessenichd016be12016-03-13 11:24:20 -06003144 if (constructorFunction == nullptr)
3145 return false;
3146
3147 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06003148 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06003149 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07003150 // It's possible this is a type keyword used as an identifier. Put the token back
3151 // for later use.
3152 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06003153 return false;
3154 }
3155
3156 // hook it up
3157 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
3158
John Kessenichbb79abc2017-10-07 13:23:09 -06003159 return node != nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06003160 }
3161
3162 return false;
3163}
3164
John Kessenich34fb0362016-05-03 23:17:20 -06003165// The function_call identifier was already recognized, and passed in as idToken.
3166//
3167// function_call
3168// : [idToken] arguments
3169//
John Kessenich8f9fdc92017-03-30 16:22:26 -06003170bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject)
John Kessenich34fb0362016-05-03 23:17:20 -06003171{
John Kessenich54ee28f2017-03-11 14:13:00 -07003172 // name
3173 TString* functionName = nullptr;
John Kessenich8f9fdc92017-03-30 16:22:26 -06003174 if (baseObject == nullptr) {
3175 functionName = &name;
3176 } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) {
John Kessenich4960baa2017-03-19 18:09:59 -06003177 // Built-in methods are not in the symbol table as methods, but as global functions
3178 // taking an explicit 'this' as the first argument.
steve-lunarge7d07522017-03-19 18:12:37 -06003179 functionName = NewPoolTString(BUILTIN_PREFIX);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003180 functionName->append(name);
John Kessenich4960baa2017-03-19 18:09:59 -06003181 } else {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003182 if (! baseObject->getType().isStruct()) {
3183 expected("structure");
3184 return false;
3185 }
John Kessenich54ee28f2017-03-11 14:13:00 -07003186 functionName = NewPoolTString("");
John Kessenich8f9fdc92017-03-30 16:22:26 -06003187 functionName->append(baseObject->getType().getTypeName());
John Kessenichf3d88bd2017-03-19 12:24:29 -06003188 parseContext.addScopeMangler(*functionName);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003189 functionName->append(name);
John Kessenich5f12d2f2017-03-11 09:39:55 -07003190 }
LoopDawg4886f692016-06-29 10:58:58 -06003191
John Kessenich54ee28f2017-03-11 14:13:00 -07003192 // function
3193 TFunction* function = new TFunction(functionName, TType(EbtVoid));
3194
3195 // arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07003196 TIntermTyped* arguments = nullptr;
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003197 if (baseObject != nullptr) {
3198 // Non-static member functions have an implicit first argument of the base object.
John Kessenich54ee28f2017-03-11 14:13:00 -07003199 parseContext.handleFunctionArgument(function, arguments, baseObject);
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003200 }
John Kessenich4678ca92016-05-13 09:33:42 -06003201 if (! acceptArguments(function, arguments))
3202 return false;
3203
John Kessenich54ee28f2017-03-11 14:13:00 -07003204 // call
John Kessenich8f9fdc92017-03-30 16:22:26 -06003205 node = parseContext.handleFunctionCall(loc, function, arguments);
John Kessenich4678ca92016-05-13 09:33:42 -06003206
John Kessenichbb79abc2017-10-07 13:23:09 -06003207 return node != nullptr;
John Kessenich34fb0362016-05-03 23:17:20 -06003208}
3209
John Kessenich87142c72016-03-12 20:24:24 -07003210// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06003211// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003212//
John Kessenichd016be12016-03-13 11:24:20 -06003213// The arguments are pushed onto the 'function' argument list and
3214// onto the 'arguments' aggregate.
3215//
John Kessenich4678ca92016-05-13 09:33:42 -06003216bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07003217{
John Kessenich078d7f22016-03-14 10:02:11 -06003218 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003219 if (! acceptTokenClass(EHTokLeftParen))
3220 return false;
3221
John Kessenich2aa12b12017-04-18 14:47:33 -06003222 // RIGHT_PAREN
3223 if (acceptTokenClass(EHTokRightParen))
3224 return true;
3225
3226 // must now be at least one expression...
John Kessenich87142c72016-03-12 20:24:24 -07003227 do {
John Kessenichd016be12016-03-13 11:24:20 -06003228 // expression
John Kessenich87142c72016-03-12 20:24:24 -07003229 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06003230 if (! acceptAssignmentExpression(arg))
John Kessenich2aa12b12017-04-18 14:47:33 -06003231 return false;
John Kessenichd016be12016-03-13 11:24:20 -06003232
3233 // hook it up
3234 parseContext.handleFunctionArgument(function, arguments, arg);
3235
John Kessenich078d7f22016-03-14 10:02:11 -06003236 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07003237 if (! acceptTokenClass(EHTokComma))
3238 break;
3239 } while (true);
3240
John Kessenich078d7f22016-03-14 10:02:11 -06003241 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003242 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003243 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003244 return false;
3245 }
3246
3247 return true;
3248}
3249
3250bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
3251{
3252 switch (token.tokenClass) {
3253 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003254 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003255 break;
steve-lunarg2de32912016-07-28 14:49:48 -06003256 case EHTokUintConstant:
3257 node = intermediate.addConstantUnion(token.u, token.loc, true);
3258 break;
John Kessenich87142c72016-03-12 20:24:24 -07003259 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003260 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003261 break;
3262 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003263 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003264 break;
3265 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003266 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003267 break;
John Kessenich86f71382016-09-19 20:23:18 -06003268 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07003269 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06003270 break;
John Kessenich87142c72016-03-12 20:24:24 -07003271
3272 default:
3273 return false;
3274 }
3275
3276 advanceToken();
3277
3278 return true;
3279}
3280
John Kessenich0e071192017-06-06 11:37:33 -06003281// simple_statement
3282// : SEMICOLON
3283// | declaration_statement
3284// | expression SEMICOLON
3285//
3286bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement)
3287{
3288 // SEMICOLON
3289 if (acceptTokenClass(EHTokSemicolon))
3290 return true;
3291
3292 // declaration
3293 if (acceptDeclaration(statement))
3294 return true;
3295
3296 // expression
3297 TIntermTyped* node;
3298 if (acceptExpression(node))
3299 statement = node;
3300 else
3301 return false;
3302
3303 // SEMICOLON (following an expression)
3304 if (acceptTokenClass(EHTokSemicolon))
3305 return true;
3306 else {
3307 expected(";");
3308 return false;
3309 }
3310}
3311
John Kessenich5f934b02016-03-13 17:58:25 -06003312// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06003313// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003314//
John Kessenich21472ae2016-06-04 11:46:33 -06003315bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07003316{
John Kessenich21472ae2016-06-04 11:46:33 -06003317 TIntermAggregate* compoundStatement = nullptr;
3318
John Kessenich34fb0362016-05-03 23:17:20 -06003319 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003320 if (! acceptTokenClass(EHTokLeftBrace))
3321 return false;
3322
3323 // statement statement ...
3324 TIntermNode* statement = nullptr;
3325 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06003326 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
3327 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
3328 branch->getFlowOp() == EOpDefault)) {
3329 // hook up individual subsequences within a switch statement
3330 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
3331 compoundStatement = nullptr;
3332 } else {
3333 // hook it up to the growing compound statement
3334 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
3335 }
John Kessenich5f934b02016-03-13 17:58:25 -06003336 }
John Kessenich34fb0362016-05-03 23:17:20 -06003337 if (compoundStatement)
3338 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06003339
John Kessenich21472ae2016-06-04 11:46:33 -06003340 retStatement = compoundStatement;
3341
John Kessenich34fb0362016-05-03 23:17:20 -06003342 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003343 return acceptTokenClass(EHTokRightBrace);
3344}
3345
John Kessenich0d2b6de2016-06-05 11:23:11 -06003346bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
3347{
3348 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06003349 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003350 parseContext.popScope();
3351
3352 return result;
3353}
3354
John Kessenich077e0522016-06-09 02:02:17 -06003355bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003356{
John Kessenich077e0522016-06-09 02:02:17 -06003357 parseContext.pushScope();
3358 bool result = acceptCompoundStatement(statement);
3359 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06003360
3361 return result;
3362}
3363
John Kessenich5f934b02016-03-13 17:58:25 -06003364// statement
John Kessenich21472ae2016-06-04 11:46:33 -06003365// : attributes attributed_statement
3366//
3367// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003368// : compound_statement
John Kessenich0e071192017-06-06 11:37:33 -06003369// | simple_statement
John Kessenich21472ae2016-06-04 11:46:33 -06003370// | selection_statement
3371// | switch_statement
3372// | case_label
John Kessenich0e071192017-06-06 11:37:33 -06003373// | default_label
John Kessenich21472ae2016-06-04 11:46:33 -06003374// | iteration_statement
3375// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003376//
3377bool HlslGrammar::acceptStatement(TIntermNode*& statement)
3378{
John Kessenich21472ae2016-06-04 11:46:33 -06003379 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06003380
John Kessenich21472ae2016-06-04 11:46:33 -06003381 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06003382 TAttributeMap attributes;
3383 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003384
John Kessenich21472ae2016-06-04 11:46:33 -06003385 // attributed_statement
3386 switch (peek()) {
3387 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06003388 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06003389
John Kessenich21472ae2016-06-04 11:46:33 -06003390 case EHTokIf:
Rex Xu57e65922017-07-04 23:23:40 +08003391 return acceptSelectionStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003392
John Kessenich21472ae2016-06-04 11:46:33 -06003393 case EHTokSwitch:
Rex Xu57e65922017-07-04 23:23:40 +08003394 return acceptSwitchStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003395
John Kessenich21472ae2016-06-04 11:46:33 -06003396 case EHTokFor:
3397 case EHTokDo:
3398 case EHTokWhile:
steve-lunargf1709e72017-05-02 20:14:50 -06003399 return acceptIterationStatement(statement, attributes);
John Kessenich21472ae2016-06-04 11:46:33 -06003400
3401 case EHTokContinue:
3402 case EHTokBreak:
3403 case EHTokDiscard:
3404 case EHTokReturn:
3405 return acceptJumpStatement(statement);
3406
3407 case EHTokCase:
3408 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003409 case EHTokDefault:
3410 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003411
John Kessenich21472ae2016-06-04 11:46:33 -06003412 case EHTokRightBrace:
3413 // Performance: not strictly necessary, but stops a bunch of hunting early,
3414 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06003415 return false;
3416
John Kessenich21472ae2016-06-04 11:46:33 -06003417 default:
John Kessenich0e071192017-06-06 11:37:33 -06003418 return acceptSimpleStatement(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003419 }
3420
John Kessenich5f934b02016-03-13 17:58:25 -06003421 return true;
John Kessenich87142c72016-03-12 20:24:24 -07003422}
3423
John Kessenich21472ae2016-06-04 11:46:33 -06003424// attributes
John Kessenich77ea30b2017-09-30 14:34:50 -06003425// : [zero or more:] bracketed-attribute
3426//
3427// bracketed-attribute:
3428// : LEFT_BRACKET scoped-attribute RIGHT_BRACKET
3429// : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET
3430//
3431// scoped-attribute:
3432// : attribute
3433// | namespace COLON COLON attribute
John Kessenich21472ae2016-06-04 11:46:33 -06003434//
3435// attribute:
3436// : UNROLL
3437// | UNROLL LEFT_PAREN literal RIGHT_PAREN
3438// | FASTOPT
3439// | ALLOW_UAV_CONDITION
3440// | BRANCH
3441// | FLATTEN
3442// | FORCECASE
3443// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06003444// | DOMAIN
3445// | EARLYDEPTHSTENCIL
3446// | INSTANCE
3447// | MAXTESSFACTOR
3448// | OUTPUTCONTROLPOINTS
3449// | OUTPUTTOPOLOGY
3450// | PARTITIONING
3451// | PATCHCONSTANTFUNC
3452// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06003453//
steve-lunarg1868b142016-10-20 13:07:10 -06003454void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003455{
steve-lunarg1868b142016-10-20 13:07:10 -06003456 // For now, accept the [ XXX(X) ] syntax, but drop all but
3457 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06003458 // TODO: subset to correct set? Pass on?
3459 do {
John Kessenich77ea30b2017-09-30 14:34:50 -06003460 HlslToken attributeToken;
steve-lunarg1868b142016-10-20 13:07:10 -06003461
John Kessenich0d2b6de2016-06-05 11:23:11 -06003462 // LEFT_BRACKET?
3463 if (! acceptTokenClass(EHTokLeftBracket))
3464 return;
John Kessenich77ea30b2017-09-30 14:34:50 -06003465 // another LEFT_BRACKET?
3466 bool doubleBrackets = false;
3467 if (acceptTokenClass(EHTokLeftBracket))
3468 doubleBrackets = true;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003469
John Kessenich77ea30b2017-09-30 14:34:50 -06003470 // attribute? (could be namespace; will adjust later)
3471 if (!acceptIdentifier(attributeToken)) {
3472 if (!peekTokenClass(EHTokRightBracket)) {
3473 expected("namespace or attribute identifier");
3474 advanceToken();
3475 }
3476 }
3477
3478 TString nameSpace;
3479 if (acceptTokenClass(EHTokColonColon)) {
3480 // namespace COLON COLON
3481 nameSpace = *attributeToken.string;
3482 // attribute
3483 if (!acceptIdentifier(attributeToken)) {
3484 expected("attribute identifier");
3485 return;
3486 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003487 }
3488
steve-lunarga22f7db2016-11-11 08:17:44 -07003489 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06003490
3491 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003492 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07003493 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06003494
John Kessenich0d2b6de2016-06-05 11:23:11 -06003495 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07003496 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07003497
steve-lunarga22f7db2016-11-11 08:17:44 -07003498 while (acceptAssignmentExpression(node)) {
3499 expectingExpression = false;
3500 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06003501 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07003502 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06003503 }
3504
steve-lunarga22f7db2016-11-11 08:17:44 -07003505 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06003506 if (! acceptTokenClass(EHTokRightParen))
3507 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07003508
3509 // Error for partial or missing expression
3510 if (expectingExpression || expressions->getSequence().empty())
3511 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06003512 }
3513
3514 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06003515 if (!acceptTokenClass(EHTokRightBracket)) {
3516 expected("]");
3517 return;
3518 }
John Kessenich77ea30b2017-09-30 14:34:50 -06003519 // another RIGHT_BRACKET?
3520 if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) {
3521 expected("]]");
3522 return;
3523 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003524
steve-lunarg1868b142016-10-20 13:07:10 -06003525 // Add any values we found into the attribute map. This accepts
3526 // (and ignores) values not mapping to a known TAttributeType;
John Kessenich77ea30b2017-09-30 14:34:50 -06003527 attributes.setAttribute(nameSpace, attributeToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003528 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06003529}
3530
John Kessenich0d2b6de2016-06-05 11:23:11 -06003531// selection_statement
3532// : IF LEFT_PAREN expression RIGHT_PAREN statement
3533// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
3534//
Rex Xu57e65922017-07-04 23:23:40 +08003535bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003536{
John Kessenich0d2b6de2016-06-05 11:23:11 -06003537 TSourceLoc loc = token.loc;
3538
Rex Xu57e65922017-07-04 23:23:40 +08003539 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3540
John Kessenich0d2b6de2016-06-05 11:23:11 -06003541 // IF
3542 if (! acceptTokenClass(EHTokIf))
3543 return false;
3544
3545 // so that something declared in the condition is scoped to the lifetimes
3546 // of the then-else statements
3547 parseContext.pushScope();
3548
3549 // LEFT_PAREN expression RIGHT_PAREN
3550 TIntermTyped* condition;
3551 if (! acceptParenExpression(condition))
3552 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003553 condition = parseContext.convertConditionalExpression(loc, condition);
3554 if (condition == nullptr)
3555 return false;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003556
3557 // create the child statements
3558 TIntermNodePair thenElse = { nullptr, nullptr };
3559
John Kessenichf6deacd2017-06-06 19:52:55 -06003560 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
3561
John Kessenich0d2b6de2016-06-05 11:23:11 -06003562 // then statement
3563 if (! acceptScopedStatement(thenElse.node1)) {
3564 expected("then statement");
3565 return false;
3566 }
3567
3568 // ELSE
3569 if (acceptTokenClass(EHTokElse)) {
3570 // else statement
3571 if (! acceptScopedStatement(thenElse.node2)) {
3572 expected("else statement");
3573 return false;
3574 }
3575 }
3576
3577 // Put the pieces together
Rex Xu57e65922017-07-04 23:23:40 +08003578 statement = intermediate.addSelection(condition, thenElse, loc, control);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003579 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003580 --parseContext.controlFlowNestingLevel;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003581
3582 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003583}
3584
John Kessenichd02dc5d2016-07-01 00:04:11 -06003585// switch_statement
3586// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
3587//
Rex Xu57e65922017-07-04 23:23:40 +08003588bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003589{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003590 // SWITCH
3591 TSourceLoc loc = token.loc;
Rex Xu57e65922017-07-04 23:23:40 +08003592
3593 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3594
John Kessenichd02dc5d2016-07-01 00:04:11 -06003595 if (! acceptTokenClass(EHTokSwitch))
3596 return false;
3597
3598 // LEFT_PAREN expression RIGHT_PAREN
3599 parseContext.pushScope();
3600 TIntermTyped* switchExpression;
3601 if (! acceptParenExpression(switchExpression)) {
3602 parseContext.popScope();
3603 return false;
3604 }
3605
3606 // compound_statement
3607 parseContext.pushSwitchSequence(new TIntermSequence);
John Kessenichf6deacd2017-06-06 19:52:55 -06003608
3609 ++parseContext.controlFlowNestingLevel;
John Kessenichd02dc5d2016-07-01 00:04:11 -06003610 bool statementOkay = acceptCompoundStatement(statement);
John Kessenichf6deacd2017-06-06 19:52:55 -06003611 --parseContext.controlFlowNestingLevel;
3612
John Kessenichd02dc5d2016-07-01 00:04:11 -06003613 if (statementOkay)
Rex Xu57e65922017-07-04 23:23:40 +08003614 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, control);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003615
3616 parseContext.popSwitchSequence();
3617 parseContext.popScope();
3618
3619 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003620}
3621
John Kessenich119f8f62016-06-05 15:44:07 -06003622// iteration_statement
3623// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3624// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3625// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3626//
3627// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
steve-lunargf1709e72017-05-02 20:14:50 -06003628bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003629{
John Kessenich119f8f62016-06-05 15:44:07 -06003630 TSourceLoc loc = token.loc;
3631 TIntermTyped* condition = nullptr;
3632
3633 EHlslTokenClass loop = peek();
3634 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3635
3636 // WHILE or DO or FOR
3637 advanceToken();
steve-lunargf1709e72017-05-02 20:14:50 -06003638
3639 const TLoopControl control = parseContext.handleLoopControl(attributes);
John Kessenich119f8f62016-06-05 15:44:07 -06003640
3641 switch (loop) {
3642 case EHTokWhile:
3643 // so that something declared in the condition is scoped to the lifetime
3644 // of the while sub-statement
John Kessenichf6deacd2017-06-06 19:52:55 -06003645 parseContext.pushScope(); // this only needs to work right if no errors
John Kessenich119f8f62016-06-05 15:44:07 -06003646 parseContext.nestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003647 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003648
3649 // LEFT_PAREN condition RIGHT_PAREN
3650 if (! acceptParenExpression(condition))
3651 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003652 condition = parseContext.convertConditionalExpression(loc, condition);
3653 if (condition == nullptr)
3654 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003655
3656 // statement
3657 if (! acceptScopedStatement(statement)) {
3658 expected("while sub-statement");
3659 return false;
3660 }
3661
3662 parseContext.unnestLooping();
3663 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003664 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003665
steve-lunargf1709e72017-05-02 20:14:50 -06003666 statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003667
3668 return true;
3669
3670 case EHTokDo:
John Kessenichf6deacd2017-06-06 19:52:55 -06003671 parseContext.nestLooping(); // this only needs to work right if no errors
3672 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003673
John Kessenich119f8f62016-06-05 15:44:07 -06003674 // statement
John Kessenich0c6f9362017-04-20 11:08:24 -06003675 if (! acceptScopedStatement(statement)) {
John Kessenich119f8f62016-06-05 15:44:07 -06003676 expected("do sub-statement");
3677 return false;
3678 }
3679
John Kessenich119f8f62016-06-05 15:44:07 -06003680 // WHILE
3681 if (! acceptTokenClass(EHTokWhile)) {
3682 expected("while");
3683 return false;
3684 }
3685
3686 // LEFT_PAREN condition RIGHT_PAREN
John Kessenich119f8f62016-06-05 15:44:07 -06003687 if (! acceptParenExpression(condition))
3688 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003689 condition = parseContext.convertConditionalExpression(loc, condition);
3690 if (condition == nullptr)
3691 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003692
3693 if (! acceptTokenClass(EHTokSemicolon))
3694 expected(";");
3695
3696 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003697 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003698
steve-lunargf1709e72017-05-02 20:14:50 -06003699 statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003700
3701 return true;
3702
3703 case EHTokFor:
3704 {
3705 // LEFT_PAREN
3706 if (! acceptTokenClass(EHTokLeftParen))
3707 expected("(");
3708
3709 // so that something declared in the condition is scoped to the lifetime
3710 // of the for sub-statement
3711 parseContext.pushScope();
3712
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003713 // initializer
3714 TIntermNode* initNode = nullptr;
John Kessenich0e071192017-06-06 11:37:33 -06003715 if (! acceptSimpleStatement(initNode))
3716 expected("for-loop initializer statement");
John Kessenich119f8f62016-06-05 15:44:07 -06003717
John Kessenichf6deacd2017-06-06 19:52:55 -06003718 parseContext.nestLooping(); // this only needs to work right if no errors
3719 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003720
3721 // condition SEMI_COLON
3722 acceptExpression(condition);
3723 if (! acceptTokenClass(EHTokSemicolon))
3724 expected(";");
John Kessenich7e997e22017-03-30 22:09:30 -06003725 if (condition != nullptr) {
3726 condition = parseContext.convertConditionalExpression(loc, condition);
3727 if (condition == nullptr)
3728 return false;
3729 }
John Kessenich119f8f62016-06-05 15:44:07 -06003730
3731 // iterator SEMI_COLON
3732 TIntermTyped* iterator = nullptr;
3733 acceptExpression(iterator);
3734 if (! acceptTokenClass(EHTokRightParen))
3735 expected(")");
3736
3737 // statement
3738 if (! acceptScopedStatement(statement)) {
3739 expected("for sub-statement");
3740 return false;
3741 }
3742
steve-lunargf1709e72017-05-02 20:14:50 -06003743 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003744
3745 parseContext.popScope();
3746 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003747 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003748
3749 return true;
3750 }
3751
3752 default:
3753 return false;
3754 }
John Kessenich21472ae2016-06-04 11:46:33 -06003755}
3756
3757// jump_statement
3758// : CONTINUE SEMICOLON
3759// | BREAK SEMICOLON
3760// | DISCARD SEMICOLON
3761// | RETURN SEMICOLON
3762// | RETURN expression SEMICOLON
3763//
3764bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3765{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003766 EHlslTokenClass jump = peek();
3767 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003768 case EHTokContinue:
3769 case EHTokBreak:
3770 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003771 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003772 advanceToken();
3773 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003774 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003775 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003776 return false;
3777 }
John Kessenich21472ae2016-06-04 11:46:33 -06003778
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003779 switch (jump) {
3780 case EHTokContinue:
3781 statement = intermediate.addBranch(EOpContinue, token.loc);
3782 break;
3783 case EHTokBreak:
3784 statement = intermediate.addBranch(EOpBreak, token.loc);
3785 break;
3786 case EHTokDiscard:
3787 statement = intermediate.addBranch(EOpKill, token.loc);
3788 break;
3789
3790 case EHTokReturn:
3791 {
3792 // expression
3793 TIntermTyped* node;
3794 if (acceptExpression(node)) {
3795 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003796 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003797 } else
3798 statement = intermediate.addBranch(EOpReturn, token.loc);
3799 break;
3800 }
3801
3802 default:
3803 assert(0);
3804 return false;
3805 }
3806
3807 // SEMICOLON
3808 if (! acceptTokenClass(EHTokSemicolon))
3809 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003810
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003811 return true;
3812}
John Kessenich21472ae2016-06-04 11:46:33 -06003813
John Kessenichd02dc5d2016-07-01 00:04:11 -06003814// case_label
3815// : CASE expression COLON
3816//
John Kessenich21472ae2016-06-04 11:46:33 -06003817bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3818{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003819 TSourceLoc loc = token.loc;
3820 if (! acceptTokenClass(EHTokCase))
3821 return false;
3822
3823 TIntermTyped* expression;
3824 if (! acceptExpression(expression)) {
3825 expected("case expression");
3826 return false;
3827 }
3828
3829 if (! acceptTokenClass(EHTokColon)) {
3830 expected(":");
3831 return false;
3832 }
3833
3834 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3835
3836 return true;
3837}
3838
3839// default_label
3840// : DEFAULT COLON
3841//
3842bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3843{
3844 TSourceLoc loc = token.loc;
3845 if (! acceptTokenClass(EHTokDefault))
3846 return false;
3847
3848 if (! acceptTokenClass(EHTokColon)) {
3849 expected(":");
3850 return false;
3851 }
3852
3853 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3854
3855 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003856}
3857
John Kessenich19b92ff2016-06-19 11:50:34 -06003858// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003859// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3860// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003861//
3862void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3863{
3864 arraySizes = nullptr;
3865
steve-lunarg7b211a32016-10-13 12:26:18 -06003866 // Early-out if there aren't any array dimensions
3867 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003868 return;
3869
steve-lunarg7b211a32016-10-13 12:26:18 -06003870 // 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 -06003871 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003872
3873 // Collect each array dimension.
3874 while (acceptTokenClass(EHTokLeftBracket)) {
3875 TSourceLoc loc = token.loc;
3876 TIntermTyped* sizeExpr = nullptr;
3877
John Kessenich057df292017-03-06 18:18:37 -07003878 // Array sizing expression is optional. If omitted, array will be later sized by initializer list.
steve-lunarg7b211a32016-10-13 12:26:18 -06003879 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3880
3881 if (! acceptTokenClass(EHTokRightBracket)) {
3882 expected("]");
3883 return;
3884 }
3885
3886 if (hasArraySize) {
3887 TArraySize arraySize;
3888 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3889 arraySizes->addInnerSize(arraySize);
3890 } else {
3891 arraySizes->addInnerSize(0); // sized by initializers.
3892 }
steve-lunarg265c0612016-09-27 10:57:35 -06003893 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003894}
3895
John Kessenich630dd7d2016-06-12 23:52:12 -06003896// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003897// : COLON semantic // optional
3898// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3899// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003900// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003901// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003902//
John Kessenich854fe242017-03-02 14:30:59 -07003903// Return true if any tokens were accepted. That is,
3904// false can be returned on successfully recognizing nothing,
3905// not necessarily meaning bad syntax.
3906//
3907bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003908{
John Kessenich854fe242017-03-02 14:30:59 -07003909 bool found = false;
3910
John Kessenich630dd7d2016-06-12 23:52:12 -06003911 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003912 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003913 if (acceptTokenClass(EHTokColon)) {
John Kessenich854fe242017-03-02 14:30:59 -07003914 found = true;
John Kessenich630dd7d2016-06-12 23:52:12 -06003915 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003916 if (peekTokenClass(EHTokLayout))
3917 acceptLayoutQualifierList(qualifier);
3918 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003919 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003920 if (! acceptTokenClass(EHTokLeftParen)) {
3921 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003922 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003923 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003924 HlslToken locationToken;
3925 if (! acceptIdentifier(locationToken)) {
3926 expected("c[subcomponent][.component]");
John Kessenich854fe242017-03-02 14:30:59 -07003927 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003928 }
3929 HlslToken componentToken;
3930 if (acceptTokenClass(EHTokDot)) {
3931 if (! acceptIdentifier(componentToken)) {
3932 expected("component");
John Kessenich854fe242017-03-02 14:30:59 -07003933 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003934 }
3935 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003936 if (! acceptTokenClass(EHTokRightParen)) {
3937 expected(")");
3938 break;
3939 }
John Kessenich7735b942016-09-05 12:40:06 -06003940 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003941 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003942 expected("layout, semantic, packoffset, or register");
John Kessenich854fe242017-03-02 14:30:59 -07003943 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003944 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003945 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3946 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003947 if (! acceptTokenClass(EHTokLeftParen)) {
3948 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003949 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003950 }
John Kessenichb38f0712016-07-30 10:29:54 -06003951 HlslToken registerDesc; // for Type#
3952 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003953 if (! acceptIdentifier(registerDesc)) {
3954 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003955 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003956 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003957 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3958 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003959 // Then we didn't really see the registerDesc yet, it was
3960 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003961 profile = registerDesc;
3962 if (! acceptIdentifier(registerDesc)) {
3963 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003964 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003965 }
3966 }
John Kessenichb38f0712016-07-30 10:29:54 -06003967 int subComponent = 0;
3968 if (acceptTokenClass(EHTokLeftBracket)) {
3969 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3970 if (! peekTokenClass(EHTokIntConstant)) {
3971 expected("literal integer");
John Kessenich854fe242017-03-02 14:30:59 -07003972 return false;
John Kessenichb38f0712016-07-30 10:29:54 -06003973 }
3974 subComponent = token.i;
3975 advanceToken();
3976 if (! acceptTokenClass(EHTokRightBracket)) {
3977 expected("]");
3978 break;
3979 }
3980 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003981 // (COMMA SPACEN)opt
3982 HlslToken spaceDesc;
3983 if (acceptTokenClass(EHTokComma)) {
3984 if (! acceptIdentifier(spaceDesc)) {
3985 expected ("space identifier");
John Kessenich854fe242017-03-02 14:30:59 -07003986 return false;
John Kessenichcfd7ce82016-09-05 16:03:12 -06003987 }
3988 }
3989 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003990 if (! acceptTokenClass(EHTokRightParen)) {
3991 expected(")");
3992 break;
3993 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003994 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003995 } else {
3996 // semantic, in idToken.string
John Kessenich2dd643f2017-03-14 21:50:06 -06003997 TString semanticUpperCase = *idToken.string;
3998 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
3999 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
John Kessenich630dd7d2016-06-12 23:52:12 -06004000 }
John Kessenich854fe242017-03-02 14:30:59 -07004001 } else if (peekTokenClass(EHTokLeftAngle)) {
4002 found = true;
John Kessenicha1e2d492016-09-20 13:22:58 -06004003 acceptAnnotations(qualifier);
John Kessenich854fe242017-03-02 14:30:59 -07004004 } else
John Kessenich630dd7d2016-06-12 23:52:12 -06004005 break;
John Kessenich078d7f22016-03-14 10:02:11 -06004006
John Kessenich630dd7d2016-06-12 23:52:12 -06004007 } while (true);
John Kessenich854fe242017-03-02 14:30:59 -07004008
4009 return found;
John Kessenich078d7f22016-03-14 10:02:11 -06004010}
4011
John Kessenichb16f7e62017-03-11 19:32:47 -07004012//
4013// Get the stream of tokens from the scanner, but skip all syntactic/semantic
4014// processing.
4015//
4016bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
4017{
4018 if (! peekTokenClass(EHTokLeftBrace))
4019 return false;
4020
4021 int braceCount = 0;
4022
4023 do {
4024 switch (peek()) {
4025 case EHTokLeftBrace:
4026 ++braceCount;
4027 break;
4028 case EHTokRightBrace:
4029 --braceCount;
4030 break;
4031 case EHTokNone:
4032 // End of input before balance { } is bad...
4033 return false;
4034 default:
4035 break;
4036 }
4037
4038 tokens.push_back(token);
4039 advanceToken();
4040 } while (braceCount > 0);
4041
4042 return true;
4043}
4044
John Kessenich0320d092017-06-13 22:22:52 -06004045// Return a string for just the types that can also be declared as an identifier.
4046const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const
4047{
4048 switch (tokenClass) {
4049 case EHTokSample: return "sample";
4050 case EHTokHalf: return "half";
4051 case EHTokHalf1x1: return "half1x1";
4052 case EHTokHalf1x2: return "half1x2";
4053 case EHTokHalf1x3: return "half1x3";
4054 case EHTokHalf1x4: return "half1x4";
4055 case EHTokHalf2x1: return "half2x1";
4056 case EHTokHalf2x2: return "half2x2";
4057 case EHTokHalf2x3: return "half2x3";
4058 case EHTokHalf2x4: return "half2x4";
4059 case EHTokHalf3x1: return "half3x1";
4060 case EHTokHalf3x2: return "half3x2";
4061 case EHTokHalf3x3: return "half3x3";
4062 case EHTokHalf3x4: return "half3x4";
4063 case EHTokHalf4x1: return "half4x1";
4064 case EHTokHalf4x2: return "half4x2";
4065 case EHTokHalf4x3: return "half4x3";
4066 case EHTokHalf4x4: return "half4x4";
4067 case EHTokBool: return "bool";
4068 case EHTokFloat: return "float";
4069 case EHTokDouble: return "double";
4070 case EHTokInt: return "int";
4071 case EHTokUint: return "uint";
4072 case EHTokMin16float: return "min16float";
4073 case EHTokMin10float: return "min10float";
4074 case EHTokMin16int: return "min16int";
4075 case EHTokMin12int: return "min12int";
LoopDawg7ee29ba2017-11-27 14:45:36 -07004076 case EHTokConstantBuffer: return "ConstantBuffer";
John Kessenich0320d092017-06-13 22:22:52 -06004077 default:
4078 return nullptr;
4079 }
4080}
4081
John Kesseniche01a9bc2016-03-12 20:11:22 -07004082} // end namespace glslang