blob: 314a540b65ea1b888e56d53fb7352a7432d51fe6 [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) {
steve-lunarga766b832017-04-25 09:30:28 -0600481 parseContext.declareBlock(idToken.loc, variableType, fullName,
482 variableType.isArray() ? &variableType.getArraySizes() : nullptr);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600483 parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
484 } else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700485 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600486 // this isn't really an individual variable, but a member of the $Global buffer
John Kessenich8f9fdc92017-03-30 16:22:26 -0600487 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600488 } else {
489 // Declare the variable and add any initializer code to the AST.
490 // The top-level node is always made into an aggregate, as that's
491 // historically how the AST has been.
John Kessenichca71d942017-03-07 20:44:09 -0700492 initializers = intermediate.growAggregate(initializers,
John Kessenich8f9fdc92017-03-30 16:22:26 -0600493 parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode),
John Kessenichca71d942017-03-07 20:44:09 -0700494 idToken.loc);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600495 }
496 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600497 }
John Kessenich5f934b02016-03-13 17:58:25 -0600498 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600499
John Kessenich054378d2017-06-19 15:13:26 -0600500 // COMMA
501 if (acceptTokenClass(EHTokComma))
John Kessenich54ee28f2017-03-11 14:13:00 -0700502 declarator_list = true;
John Kessenich2fcdd642017-06-19 15:41:11 -0600503 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600504
John Kessenichca71d942017-03-07 20:44:09 -0700505 // The top-level initializer node is a sequence.
506 if (initializers != nullptr)
507 initializers->setOperator(EOpSequence);
508
509 // Add the initializers' aggregate to the nodeList we were handed.
510 if (nodeList)
511 nodeList = intermediate.growAggregate(nodeList, initializers);
512 else
513 nodeList = initializers;
John Kessenich87142c72016-03-12 20:24:24 -0700514
John Kessenich2fcdd642017-06-19 15:41:11 -0600515 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600516 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich2fcdd642017-06-19 15:41:11 -0600517 // This may have been a false detection of what appeared to be a declaration, but
518 // was actually an assignment such as "float = 4", where "float" is an identifier.
519 // We put the token back to let further parsing happen for cases where that may
520 // happen. This errors on the side of caution, and mostly triggers the error.
John Kessenich13075c62017-04-11 09:51:32 -0600521 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700522 recedeToken();
John Kessenich13075c62017-04-11 09:51:32 -0600523 return false;
John Kessenich13075c62017-04-11 09:51:32 -0600524 } else {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700525 expected(";");
John Kessenich13075c62017-04-11 09:51:32 -0600526 return false;
527 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600528 }
John Kessenichecba76f2017-01-06 00:34:48 -0700529
John Kesseniche01a9bc2016-03-12 20:11:22 -0700530 return true;
531}
532
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600533// control_declaration
534// : fully_specified_type identifier EQUAL expression
535//
536bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
537{
538 node = nullptr;
539
540 // fully_specified_type
541 TType type;
542 if (! acceptFullySpecifiedType(type))
543 return false;
544
John Kessenich057df292017-03-06 18:18:37 -0700545 // filter out type casts
546 if (peekTokenClass(EHTokLeftParen)) {
547 recedeToken();
548 return false;
549 }
550
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600551 // identifier
552 HlslToken idToken;
553 if (! acceptIdentifier(idToken)) {
554 expected("identifier");
555 return false;
556 }
557
558 // EQUAL
559 TIntermTyped* expressionNode = nullptr;
560 if (! acceptTokenClass(EHTokAssign)) {
561 expected("=");
562 return false;
563 }
564
565 // expression
566 if (! acceptExpression(expressionNode)) {
567 expected("initializer");
568 return false;
569 }
570
John Kesseniche82061d2016-09-27 14:38:57 -0600571 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600572
573 return true;
574}
575
John Kessenich87142c72016-03-12 20:24:24 -0700576// fully_specified_type
577// : type_specifier
578// | type_qualifier type_specifier
579//
580bool HlslGrammar::acceptFullySpecifiedType(TType& type)
581{
John Kessenich54ee28f2017-03-11 14:13:00 -0700582 TIntermNode* nodeList = nullptr;
583 return acceptFullySpecifiedType(type, nodeList);
584}
585bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
586{
John Kessenich87142c72016-03-12 20:24:24 -0700587 // type_qualifier
588 TQualifier qualifier;
589 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600590 if (! acceptQualifier(qualifier))
591 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600592 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700593
594 // type_specifier
John Kessenich54ee28f2017-03-11 14:13:00 -0700595 if (! acceptType(type, nodeList)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -0700596 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700597 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700598 // qualifier. Back it out, if we did.
599 if (qualifier.sample)
600 recedeToken();
601
John Kessenich87142c72016-03-12 20:24:24 -0700602 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700603 }
John Kessenich3d157c52016-07-25 16:05:33 -0600604 if (type.getBasicType() == EbtBlock) {
605 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600606 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600607 // further, it can create an anonymous instance of the block
John Kessenich13075c62017-04-11 09:51:32 -0600608 if (peek() != EHTokIdentifier)
John Kessenich3d157c52016-07-25 16:05:33 -0600609 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600610 } else {
611 // Some qualifiers are set when parsing the type. Merge those with
612 // whatever comes from acceptQualifier.
613 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700614
steve-lunargbb0183f2016-10-04 16:58:14 -0600615 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600616 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700617
steve-lunarg08e0c082017-03-29 20:01:13 -0600618 if (type.getQualifier().storage == EvqOut ||
steve-lunarg5da1f032017-02-12 17:50:28 -0700619 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700620 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700621 qualifier.readonly = type.getQualifier().readonly;
622 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700623
John Kessenichecd08bc2017-08-07 23:40:05 -0600624 if (type.isBuiltIn())
steve-lunarg08e0c082017-03-29 20:01:13 -0600625 qualifier.builtIn = type.getQualifier().builtIn;
626
steve-lunargf49cdf42016-11-17 15:04:20 -0700627 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600628 }
John Kessenich87142c72016-03-12 20:24:24 -0700629
630 return true;
631}
632
John Kessenich630dd7d2016-06-12 23:52:12 -0600633// type_qualifier
634// : qualifier qualifier ...
635//
636// Zero or more of these, so this can't return false.
637//
John Kessenichb9e39122016-08-17 10:22:08 -0600638bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700639{
John Kessenich630dd7d2016-06-12 23:52:12 -0600640 do {
641 switch (peek()) {
642 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600643 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600644 break;
645 case EHTokExtern:
646 // TODO: no meaning in glslang?
647 break;
648 case EHTokShared:
649 // TODO: hint
650 break;
651 case EHTokGroupShared:
652 qualifier.storage = EvqShared;
653 break;
654 case EHTokUniform:
655 qualifier.storage = EvqUniform;
656 break;
657 case EHTokConst:
658 qualifier.storage = EvqConst;
659 break;
660 case EHTokVolatile:
661 qualifier.volatil = true;
662 break;
663 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600664 qualifier.smooth = true;
665 break;
666 case EHTokCentroid:
667 qualifier.centroid = true;
668 break;
669 case EHTokNointerpolation:
670 qualifier.flat = true;
671 break;
672 case EHTokNoperspective:
673 qualifier.nopersp = true;
674 break;
675 case EHTokSample:
676 qualifier.sample = true;
677 break;
678 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600679 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600680 break;
681 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600682 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600683 break;
684 case EHTokPrecise:
685 qualifier.noContraction = true;
686 break;
LoopDawg9249c702016-07-12 20:44:32 -0600687 case EHTokIn:
xavierb1d97532017-06-20 07:49:22 +0200688 qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn;
LoopDawg9249c702016-07-12 20:44:32 -0600689 break;
690 case EHTokOut:
xavierb1d97532017-06-20 07:49:22 +0200691 qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut;
LoopDawg9249c702016-07-12 20:44:32 -0600692 break;
693 case EHTokInOut:
694 qualifier.storage = EvqInOut;
695 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600696 case EHTokLayout:
697 if (! acceptLayoutQualifierList(qualifier))
698 return false;
699 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700700 case EHTokGloballyCoherent:
701 qualifier.coherent = true;
702 break;
John Kessenich36b218d2017-03-15 09:05:14 -0600703 case EHTokInline:
704 // TODO: map this to SPIR-V function control
705 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700706
707 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
708 // for output variables.
709 case EHTokPoint:
710 qualifier.storage = EvqIn;
711 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
712 return false;
713 break;
714 case EHTokLine:
715 qualifier.storage = EvqIn;
716 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
717 return false;
718 break;
719 case EHTokTriangle:
720 qualifier.storage = EvqIn;
721 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
722 return false;
723 break;
724 case EHTokLineAdj:
725 qualifier.storage = EvqIn;
726 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
727 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700728 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700729 case EHTokTriangleAdj:
730 qualifier.storage = EvqIn;
731 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
732 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700733 break;
734
John Kessenich630dd7d2016-06-12 23:52:12 -0600735 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600736 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600737 }
738 advanceToken();
739 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700740}
741
John Kessenichb9e39122016-08-17 10:22:08 -0600742// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600743// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600744//
745// layout_qualifier
746// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600747// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600748//
749// Zero or more of these, so this can't return false.
750//
751bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
752{
753 if (! acceptTokenClass(EHTokLayout))
754 return false;
755
756 // LEFT_PAREN
757 if (! acceptTokenClass(EHTokLeftParen))
758 return false;
759
760 do {
761 // identifier
762 HlslToken idToken;
763 if (! acceptIdentifier(idToken))
764 break;
765
766 // EQUAL expression
767 if (acceptTokenClass(EHTokAssign)) {
768 TIntermTyped* expr;
769 if (! acceptConditionalExpression(expr)) {
770 expected("expression");
771 return false;
772 }
773 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
774 } else
775 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
776
777 // COMMA
778 if (! acceptTokenClass(EHTokComma))
779 break;
780 } while (true);
781
782 // RIGHT_PAREN
783 if (! acceptTokenClass(EHTokRightParen)) {
784 expected(")");
785 return false;
786 }
787
788 return true;
789}
790
LoopDawg6daaa4f2016-06-23 19:13:48 -0600791// template_type
792// : FLOAT
793// | DOUBLE
794// | INT
795// | DWORD
796// | UINT
797// | BOOL
798//
steve-lunargf49cdf42016-11-17 15:04:20 -0700799bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600800{
801 switch (peek()) {
802 case EHTokFloat:
803 basicType = EbtFloat;
804 break;
805 case EHTokDouble:
806 basicType = EbtDouble;
807 break;
808 case EHTokInt:
809 case EHTokDword:
810 basicType = EbtInt;
811 break;
812 case EHTokUint:
813 basicType = EbtUint;
814 break;
815 case EHTokBool:
816 basicType = EbtBool;
817 break;
818 default:
819 return false;
820 }
821
822 advanceToken();
823
824 return true;
825}
826
827// vector_template_type
828// : VECTOR
829// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
830//
831bool HlslGrammar::acceptVectorTemplateType(TType& type)
832{
833 if (! acceptTokenClass(EHTokVector))
834 return false;
835
836 if (! acceptTokenClass(EHTokLeftAngle)) {
837 // in HLSL, 'vector' alone means float4.
838 new(&type) TType(EbtFloat, EvqTemporary, 4);
839 return true;
840 }
841
842 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700843 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600844 expected("scalar type");
845 return false;
846 }
847
848 // COMMA
849 if (! acceptTokenClass(EHTokComma)) {
850 expected(",");
851 return false;
852 }
853
854 // integer
855 if (! peekTokenClass(EHTokIntConstant)) {
856 expected("literal integer");
857 return false;
858 }
859
860 TIntermTyped* vecSize;
861 if (! acceptLiteral(vecSize))
862 return false;
863
864 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
865
866 new(&type) TType(basicType, EvqTemporary, vecSizeI);
867
868 if (vecSizeI == 1)
869 type.makeVector();
870
871 if (!acceptTokenClass(EHTokRightAngle)) {
872 expected("right angle bracket");
873 return false;
874 }
875
876 return true;
877}
878
879// matrix_template_type
880// : MATRIX
881// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
882//
883bool HlslGrammar::acceptMatrixTemplateType(TType& type)
884{
885 if (! acceptTokenClass(EHTokMatrix))
886 return false;
887
888 if (! acceptTokenClass(EHTokLeftAngle)) {
889 // in HLSL, 'matrix' alone means float4x4.
890 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
891 return true;
892 }
893
894 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700895 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600896 expected("scalar type");
897 return false;
898 }
899
900 // COMMA
901 if (! acceptTokenClass(EHTokComma)) {
902 expected(",");
903 return false;
904 }
905
906 // integer rows
907 if (! peekTokenClass(EHTokIntConstant)) {
908 expected("literal integer");
909 return false;
910 }
911
912 TIntermTyped* rows;
913 if (! acceptLiteral(rows))
914 return false;
915
916 // COMMA
917 if (! acceptTokenClass(EHTokComma)) {
918 expected(",");
919 return false;
920 }
John Kessenichecba76f2017-01-06 00:34:48 -0700921
LoopDawg6daaa4f2016-06-23 19:13:48 -0600922 // integer cols
923 if (! peekTokenClass(EHTokIntConstant)) {
924 expected("literal integer");
925 return false;
926 }
927
928 TIntermTyped* cols;
929 if (! acceptLiteral(cols))
930 return false;
931
932 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600933 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
934 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600935
936 if (!acceptTokenClass(EHTokRightAngle)) {
937 expected("right angle bracket");
938 return false;
939 }
940
941 return true;
942}
943
steve-lunargf49cdf42016-11-17 15:04:20 -0700944// layout_geometry
945// : LINESTREAM
946// | POINTSTREAM
947// | TRIANGLESTREAM
948//
949bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
950{
951 // read geometry type
952 const EHlslTokenClass geometryType = peek();
953
954 switch (geometryType) {
955 case EHTokPointStream: geometry = ElgPoints; break;
956 case EHTokLineStream: geometry = ElgLineStrip; break;
957 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
958 default:
959 return false; // not a layout geometry
960 }
961
962 advanceToken(); // consume the layout keyword
963 return true;
964}
965
steve-lunarg858c9282017-01-07 08:54:10 -0700966// tessellation_decl_type
967// : INPUTPATCH
968// | OUTPUTPATCH
969//
steve-lunarg067eb9b2017-04-01 15:34:48 -0600970bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType)
steve-lunarg858c9282017-01-07 08:54:10 -0700971{
972 // read geometry type
973 const EHlslTokenClass tessType = peek();
974
975 switch (tessType) {
steve-lunarg067eb9b2017-04-01 15:34:48 -0600976 case EHTokInputPatch: patchType = EbvInputPatch; break;
977 case EHTokOutputPatch: patchType = EbvOutputPatch; break;
steve-lunarg858c9282017-01-07 08:54:10 -0700978 default:
979 return false; // not a tessellation decl
980 }
981
982 advanceToken(); // consume the keyword
983 return true;
984}
985
986// tessellation_patch_template_type
987// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
988//
989bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
990{
steve-lunarg067eb9b2017-04-01 15:34:48 -0600991 TBuiltInVariable patchType;
992
993 if (! acceptTessellationDeclType(patchType))
steve-lunarg858c9282017-01-07 08:54:10 -0700994 return false;
995
996 if (! acceptTokenClass(EHTokLeftAngle))
997 return false;
998
999 if (! acceptType(type)) {
1000 expected("tessellation patch type");
1001 return false;
1002 }
1003
1004 if (! acceptTokenClass(EHTokComma))
1005 return false;
1006
1007 // integer size
1008 if (! peekTokenClass(EHTokIntConstant)) {
1009 expected("literal integer");
1010 return false;
1011 }
1012
1013 TIntermTyped* size;
1014 if (! acceptLiteral(size))
1015 return false;
1016
1017 TArraySizes* arraySizes = new TArraySizes;
1018 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
1019 type.newArraySizes(*arraySizes);
steve-lunarg067eb9b2017-04-01 15:34:48 -06001020 type.getQualifier().builtIn = patchType;
steve-lunarg858c9282017-01-07 08:54:10 -07001021
1022 if (! acceptTokenClass(EHTokRightAngle)) {
1023 expected("right angle bracket");
1024 return false;
1025 }
1026
1027 return true;
1028}
1029
steve-lunargf49cdf42016-11-17 15:04:20 -07001030// stream_out_template_type
1031// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
1032//
1033bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
1034{
1035 geometry = ElgNone;
1036
1037 if (! acceptOutputPrimitiveGeometry(geometry))
1038 return false;
1039
1040 if (! acceptTokenClass(EHTokLeftAngle))
1041 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001042
steve-lunargf49cdf42016-11-17 15:04:20 -07001043 if (! acceptType(type)) {
1044 expected("stream output type");
1045 return false;
1046 }
1047
steve-lunarg08e0c082017-03-29 20:01:13 -06001048 type.getQualifier().storage = EvqOut;
1049 type.getQualifier().builtIn = EbvGsOutputStream;
steve-lunargf49cdf42016-11-17 15:04:20 -07001050
1051 if (! acceptTokenClass(EHTokRightAngle)) {
1052 expected("right angle bracket");
1053 return false;
1054 }
1055
1056 return true;
1057}
John Kessenichecba76f2017-01-06 00:34:48 -07001058
John Kessenicha1e2d492016-09-20 13:22:58 -06001059// annotations
1060// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -06001061//
John Kessenicha1e2d492016-09-20 13:22:58 -06001062bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -06001063{
John Kessenicha1e2d492016-09-20 13:22:58 -06001064 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -06001065 return false;
1066
John Kessenicha1e2d492016-09-20 13:22:58 -06001067 // note that we are nesting a name space
1068 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -06001069
1070 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1071 do {
1072 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
1073 while (acceptTokenClass(EHTokSemicolon))
1074 ;
1075
1076 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -06001077 break;
John Kessenich86f71382016-09-19 20:23:18 -06001078
1079 // declaration
John Kessenichca71d942017-03-07 20:44:09 -07001080 TIntermNode* node = nullptr;
John Kessenich86f71382016-09-19 20:23:18 -06001081 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -06001082 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -06001083 return false;
1084 }
1085 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -06001086
1087 parseContext.unnestAnnotations();
1088 return true;
John Kessenich86f71382016-09-19 20:23:18 -06001089}
LoopDawg6daaa4f2016-06-23 19:13:48 -06001090
LoopDawg7f93d562017-09-27 09:04:43 -06001091// subpass input type
1092// : SUBPASSINPUT
1093// | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1094// | SUBPASSINPUTMS
1095// | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1096bool HlslGrammar::acceptSubpassInputType(TType& type)
1097{
1098 // read subpass type
1099 const EHlslTokenClass subpassInputType = peek();
1100
1101 bool multisample;
1102
1103 switch (subpassInputType) {
1104 case EHTokSubpassInput: multisample = false; break;
1105 case EHTokSubpassInputMS: multisample = true; break;
1106 default:
1107 return false; // not a subpass input declaration
1108 }
1109
1110 advanceToken(); // consume the sampler type keyword
1111
1112 TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4
1113
1114 if (acceptTokenClass(EHTokLeftAngle)) {
1115 if (! acceptType(subpassType)) {
1116 expected("scalar or vector type");
1117 return false;
1118 }
1119
1120 const TBasicType basicRetType = subpassType.getBasicType() ;
1121
1122 switch (basicRetType) {
1123 case EbtFloat:
1124 case EbtUint:
1125 case EbtInt:
1126 case EbtStruct:
1127 break;
1128 default:
1129 unimplemented("basic type in subpass input");
1130 return false;
1131 }
1132
1133 if (! acceptTokenClass(EHTokRightAngle)) {
1134 expected("right angle bracket");
1135 return false;
1136 }
1137 }
1138
1139 const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType()
1140 : subpassType.getBasicType();
1141
1142 TSampler sampler;
1143 sampler.setSubpass(subpassBasicType, multisample);
1144
1145 // Remember the declared return type. Function returns false on error.
1146 if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc))
1147 return false;
1148
1149 type.shallowCopy(TType(sampler, EvqUniform));
1150
1151 return true;
1152}
1153
LoopDawg4886f692016-06-29 10:58:58 -06001154// sampler_type
1155// : SAMPLER
1156// | SAMPLER1D
1157// | SAMPLER2D
1158// | SAMPLER3D
1159// | SAMPLERCUBE
1160// | SAMPLERSTATE
1161// | SAMPLERCOMPARISONSTATE
1162bool HlslGrammar::acceptSamplerType(TType& type)
1163{
1164 // read sampler type
1165 const EHlslTokenClass samplerType = peek();
1166
LoopDawga78b0292016-07-19 14:28:05 -06001167 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001168 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001169
LoopDawga78b0292016-07-19 14:28:05 -06001170 bool isShadow = false;
1171
LoopDawg4886f692016-06-29 10:58:58 -06001172 switch (samplerType) {
1173 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001174 case EHTokSampler1d: /*dim = Esd1D*/; break;
1175 case EHTokSampler2d: /*dim = Esd2D*/; break;
1176 case EHTokSampler3d: /*dim = Esd3D*/; break;
1177 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001178 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001179 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001180 default:
1181 return false; // not a sampler declaration
1182 }
1183
1184 advanceToken(); // consume the sampler type keyword
1185
1186 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001187
1188 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001189 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001190
1191 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1192
1193 return true;
1194}
1195
1196// texture_type
1197// | BUFFER
1198// | TEXTURE1D
1199// | TEXTURE1DARRAY
1200// | TEXTURE2D
1201// | TEXTURE2DARRAY
1202// | TEXTURE3D
1203// | TEXTURECUBE
1204// | TEXTURECUBEARRAY
1205// | TEXTURE2DMS
1206// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001207// | RWBUFFER
1208// | RWTEXTURE1D
1209// | RWTEXTURE1DARRAY
1210// | RWTEXTURE2D
1211// | RWTEXTURE2DARRAY
1212// | RWTEXTURE3D
1213
LoopDawg4886f692016-06-29 10:58:58 -06001214bool HlslGrammar::acceptTextureType(TType& type)
1215{
1216 const EHlslTokenClass textureType = peek();
1217
1218 TSamplerDim dim = EsdNone;
1219 bool array = false;
1220 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001221 bool image = false;
steve-lunargbf1537f2017-03-31 17:40:09 -06001222 bool combined = true;
LoopDawg4886f692016-06-29 10:58:58 -06001223
1224 switch (textureType) {
steve-lunargbf1537f2017-03-31 17:40:09 -06001225 case EHTokBuffer: dim = EsdBuffer; combined = false; break;
John Kessenichf36542f2017-03-31 14:39:30 -06001226 case EHTokTexture1d: dim = Esd1D; break;
1227 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1228 case EHTokTexture2d: dim = Esd2D; break;
1229 case EHTokTexture2darray: dim = Esd2D; array = true; break;
1230 case EHTokTexture3d: dim = Esd3D; break;
1231 case EHTokTextureCube: dim = EsdCube; break;
1232 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1233 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1234 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
1235 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1236 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1237 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1238 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1239 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1240 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001241 default:
1242 return false; // not a texture declaration
1243 }
1244
1245 advanceToken(); // consume the texture object keyword
1246
1247 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001248
LoopDawg4886f692016-06-29 10:58:58 -06001249 TIntermTyped* msCount = nullptr;
1250
steve-lunargbb0183f2016-10-04 16:58:14 -06001251 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001252 if (acceptTokenClass(EHTokLeftAngle)) {
1253 if (! acceptType(txType)) {
1254 expected("scalar or vector type");
1255 return false;
1256 }
1257
1258 const TBasicType basicRetType = txType.getBasicType() ;
1259
LoopDawg5ee05892017-07-31 13:41:42 -06001260 switch (basicRetType) {
1261 case EbtFloat:
1262 case EbtUint:
1263 case EbtInt:
1264 case EbtStruct:
1265 break;
1266 default:
LoopDawg4886f692016-06-29 10:58:58 -06001267 unimplemented("basic type in texture");
1268 return false;
1269 }
1270
steve-lunargd53f7172016-07-27 15:46:48 -06001271 // Buffers can handle small mats if they fit in 4 components
1272 if (dim == EsdBuffer && txType.isMatrix()) {
1273 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1274 expected("components < 4 in matrix buffer type");
1275 return false;
1276 }
1277
1278 // TODO: except we don't handle it yet...
1279 unimplemented("matrix type in buffer");
1280 return false;
1281 }
1282
LoopDawg5ee05892017-07-31 13:41:42 -06001283 if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) {
1284 expected("scalar, vector, or struct type");
LoopDawg4886f692016-06-29 10:58:58 -06001285 return false;
1286 }
1287
LoopDawg4886f692016-06-29 10:58:58 -06001288 if (ms && acceptTokenClass(EHTokComma)) {
1289 // read sample count for multisample types, if given
1290 if (! peekTokenClass(EHTokIntConstant)) {
1291 expected("multisample count");
1292 return false;
1293 }
1294
1295 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1296 return false;
1297 }
1298
1299 if (! acceptTokenClass(EHTokRightAngle)) {
1300 expected("right angle bracket");
1301 return false;
1302 }
1303 } else if (ms) {
1304 expected("texture type for multisample");
1305 return false;
John Kessenichf36542f2017-03-31 14:39:30 -06001306 } else if (image) {
steve-lunargbb0183f2016-10-04 16:58:14 -06001307 expected("type for RWTexture/RWBuffer");
1308 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001309 }
1310
1311 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001312 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001313
1314 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001315 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001316
steve-lunarg4f2da272016-10-10 15:24:57 -06001317 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1318 if (image || dim == EsdBuffer)
1319 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001320
LoopDawg5ee05892017-07-31 13:41:42 -06001321 const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType()
1322 : txType.getBasicType();
1323
steve-lunargbb0183f2016-10-04 16:58:14 -06001324 // Non-image Buffers are combined
1325 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001326 sampler.set(txType.getBasicType(), dim, array);
1327 } else {
1328 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001329 if (image) {
LoopDawg5ee05892017-07-31 13:41:42 -06001330 sampler.setImage(txBasicType, dim, array, shadow, ms);
steve-lunargbb0183f2016-10-04 16:58:14 -06001331 } else {
LoopDawg5ee05892017-07-31 13:41:42 -06001332 sampler.setTexture(txBasicType, dim, array, shadow, ms);
steve-lunargbb0183f2016-10-04 16:58:14 -06001333 }
steve-lunargd53f7172016-07-27 15:46:48 -06001334 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001335
LoopDawg5ee05892017-07-31 13:41:42 -06001336 // Remember the declared return type. Function returns false on error.
1337 if (!parseContext.setTextureReturnType(sampler, txType, token.loc))
1338 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001339
steve-lunargbf1537f2017-03-31 17:40:09 -06001340 // Force uncombined, if necessary
1341 if (!combined)
1342 sampler.combined = false;
1343
LoopDawg4886f692016-06-29 10:58:58 -06001344 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001345 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001346
1347 return true;
1348}
1349
John Kessenich87142c72016-03-12 20:24:24 -07001350// If token is for a type, update 'type' with the type information,
1351// and return true and advance.
1352// Otherwise, return false, and don't advance
1353bool HlslGrammar::acceptType(TType& type)
1354{
John Kessenich54ee28f2017-03-11 14:13:00 -07001355 TIntermNode* nodeList = nullptr;
1356 return acceptType(type, nodeList);
1357}
1358bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
1359{
steve-lunarg3226b082016-10-26 19:18:55 -06001360 // Basic types for min* types, broken out here in case of future
1361 // changes, e.g, to use native halfs.
1362 static const TBasicType min16float_bt = EbtFloat;
1363 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001364 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001365 static const TBasicType min16int_bt = EbtInt;
1366 static const TBasicType min12int_bt = EbtInt;
1367 static const TBasicType min16uint_bt = EbtUint;
1368
John Kessenich0320d092017-06-13 22:22:52 -06001369 // Some types might have turned into identifiers. Take the hit for checking
1370 // when this has happened.
1371 if (typeIdentifiers) {
1372 const char* identifierString = getTypeString(peek());
1373 if (identifierString != nullptr) {
1374 TString name = identifierString;
1375 // if it's an identifier, it's not a type
1376 if (parseContext.symbolTable.find(name) != nullptr)
1377 return false;
1378 }
1379 }
1380
LoopDawgfa39cff2017-11-14 14:55:40 -07001381 bool isUnorm = false;
1382 bool isSnorm = false;
1383
1384 // Accept snorm and unorm. Presently, this is ignored, save for an error check below.
1385 switch (peek()) {
1386 case EHTokUnorm:
1387 isUnorm = true;
1388 advanceToken(); // eat the token
1389 break;
1390 case EHTokSNorm:
1391 isSnorm = true;
1392 advanceToken(); // eat the token
1393 break;
1394 default:
1395 break;
1396 }
1397
John Kessenich9c86c6a2016-05-03 22:49:24 -06001398 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001399 case EHTokVector:
1400 return acceptVectorTemplateType(type);
1401 break;
1402
1403 case EHTokMatrix:
1404 return acceptMatrixTemplateType(type);
1405 break;
1406
steve-lunargf49cdf42016-11-17 15:04:20 -07001407 case EHTokPointStream: // fall through
1408 case EHTokLineStream: // ...
1409 case EHTokTriangleStream: // ...
1410 {
1411 TLayoutGeometry geometry;
1412 if (! acceptStreamOutTemplateType(type, geometry))
1413 return false;
1414
1415 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1416 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001417
steve-lunargf49cdf42016-11-17 15:04:20 -07001418 return true;
1419 }
1420
steve-lunarg858c9282017-01-07 08:54:10 -07001421 case EHTokInputPatch: // fall through
1422 case EHTokOutputPatch: // ...
1423 {
1424 if (! acceptTessellationPatchTemplateType(type))
1425 return false;
1426
1427 return true;
1428 }
1429
LoopDawg4886f692016-06-29 10:58:58 -06001430 case EHTokSampler: // fall through
1431 case EHTokSampler1d: // ...
1432 case EHTokSampler2d: // ...
1433 case EHTokSampler3d: // ...
1434 case EHTokSamplerCube: // ...
1435 case EHTokSamplerState: // ...
1436 case EHTokSamplerComparisonState: // ...
1437 return acceptSamplerType(type);
1438 break;
1439
LoopDawg7f93d562017-09-27 09:04:43 -06001440 case EHTokSubpassInput: // fall through
1441 case EHTokSubpassInputMS: // ...
1442 return acceptSubpassInputType(type);
1443 break;
1444
LoopDawg4886f692016-06-29 10:58:58 -06001445 case EHTokBuffer: // fall through
1446 case EHTokTexture1d: // ...
1447 case EHTokTexture1darray: // ...
1448 case EHTokTexture2d: // ...
1449 case EHTokTexture2darray: // ...
1450 case EHTokTexture3d: // ...
1451 case EHTokTextureCube: // ...
1452 case EHTokTextureCubearray: // ...
1453 case EHTokTexture2DMS: // ...
1454 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001455 case EHTokRWTexture1d: // ...
1456 case EHTokRWTexture1darray: // ...
1457 case EHTokRWTexture2d: // ...
1458 case EHTokRWTexture2darray: // ...
1459 case EHTokRWTexture3d: // ...
1460 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001461 return acceptTextureType(type);
1462 break;
1463
steve-lunarg5da1f032017-02-12 17:50:28 -07001464 case EHTokAppendStructuredBuffer:
1465 case EHTokByteAddressBuffer:
1466 case EHTokConsumeStructuredBuffer:
1467 case EHTokRWByteAddressBuffer:
1468 case EHTokRWStructuredBuffer:
1469 case EHTokStructuredBuffer:
1470 return acceptStructBufferType(type);
1471 break;
1472
LoopDawge5530b92017-11-08 19:48:11 -07001473 case EHTokTextureBuffer:
1474 return acceptTextureBufferType(type);
1475 break;
1476
steve-lunarga766b832017-04-25 09:30:28 -06001477 case EHTokConstantBuffer:
1478 return acceptConstantBufferType(type);
1479
John Kessenich27ffb292017-03-03 17:01:01 -07001480 case EHTokClass:
John Kesseniche6e74942016-06-11 16:43:14 -06001481 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001482 case EHTokCBuffer:
1483 case EHTokTBuffer:
John Kessenich54ee28f2017-03-11 14:13:00 -07001484 return acceptStruct(type, nodeList);
John Kesseniche6e74942016-06-11 16:43:14 -06001485
1486 case EHTokIdentifier:
1487 // An identifier could be for a user-defined type.
1488 // Note we cache the symbol table lookup, to save for a later rule
1489 // when this is not a type.
John Kessenichf4ba25e2017-03-21 18:35:04 -06001490 if (parseContext.lookupUserType(*token.string, type) != nullptr) {
John Kesseniche6e74942016-06-11 16:43:14 -06001491 advanceToken();
1492 return true;
1493 } else
1494 return false;
1495
John Kessenich71351de2016-06-08 12:50:56 -06001496 case EHTokVoid:
1497 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001498 break;
John Kessenich71351de2016-06-08 12:50:56 -06001499
John Kessenicha1e2d492016-09-20 13:22:58 -06001500 case EHTokString:
1501 new(&type) TType(EbtString);
1502 break;
1503
John Kessenich87142c72016-03-12 20:24:24 -07001504 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001505 new(&type) TType(EbtFloat);
1506 break;
John Kessenich87142c72016-03-12 20:24:24 -07001507 case EHTokFloat1:
1508 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001509 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001510 break;
John Kessenich87142c72016-03-12 20:24:24 -07001511 case EHTokFloat2:
1512 new(&type) TType(EbtFloat, EvqTemporary, 2);
1513 break;
1514 case EHTokFloat3:
1515 new(&type) TType(EbtFloat, EvqTemporary, 3);
1516 break;
1517 case EHTokFloat4:
1518 new(&type) TType(EbtFloat, EvqTemporary, 4);
1519 break;
1520
John Kessenich71351de2016-06-08 12:50:56 -06001521 case EHTokDouble:
1522 new(&type) TType(EbtDouble);
1523 break;
1524 case EHTokDouble1:
1525 new(&type) TType(EbtDouble);
1526 type.makeVector();
1527 break;
1528 case EHTokDouble2:
1529 new(&type) TType(EbtDouble, EvqTemporary, 2);
1530 break;
1531 case EHTokDouble3:
1532 new(&type) TType(EbtDouble, EvqTemporary, 3);
1533 break;
1534 case EHTokDouble4:
1535 new(&type) TType(EbtDouble, EvqTemporary, 4);
1536 break;
1537
1538 case EHTokInt:
1539 case EHTokDword:
1540 new(&type) TType(EbtInt);
1541 break;
1542 case EHTokInt1:
1543 new(&type) TType(EbtInt);
1544 type.makeVector();
1545 break;
John Kessenich87142c72016-03-12 20:24:24 -07001546 case EHTokInt2:
1547 new(&type) TType(EbtInt, EvqTemporary, 2);
1548 break;
1549 case EHTokInt3:
1550 new(&type) TType(EbtInt, EvqTemporary, 3);
1551 break;
1552 case EHTokInt4:
1553 new(&type) TType(EbtInt, EvqTemporary, 4);
1554 break;
1555
John Kessenich71351de2016-06-08 12:50:56 -06001556 case EHTokUint:
1557 new(&type) TType(EbtUint);
1558 break;
1559 case EHTokUint1:
1560 new(&type) TType(EbtUint);
1561 type.makeVector();
1562 break;
1563 case EHTokUint2:
1564 new(&type) TType(EbtUint, EvqTemporary, 2);
1565 break;
1566 case EHTokUint3:
1567 new(&type) TType(EbtUint, EvqTemporary, 3);
1568 break;
1569 case EHTokUint4:
1570 new(&type) TType(EbtUint, EvqTemporary, 4);
1571 break;
1572
1573 case EHTokBool:
1574 new(&type) TType(EbtBool);
1575 break;
1576 case EHTokBool1:
1577 new(&type) TType(EbtBool);
1578 type.makeVector();
1579 break;
John Kessenich87142c72016-03-12 20:24:24 -07001580 case EHTokBool2:
1581 new(&type) TType(EbtBool, EvqTemporary, 2);
1582 break;
1583 case EHTokBool3:
1584 new(&type) TType(EbtBool, EvqTemporary, 3);
1585 break;
1586 case EHTokBool4:
1587 new(&type) TType(EbtBool, EvqTemporary, 4);
1588 break;
1589
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001590 case EHTokHalf:
John Kessenich96f65522017-06-06 23:35:25 -06001591 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001592 break;
1593 case EHTokHalf1:
John Kessenich96f65522017-06-06 23:35:25 -06001594 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001595 type.makeVector();
1596 break;
1597 case EHTokHalf2:
John Kessenich96f65522017-06-06 23:35:25 -06001598 new(&type) TType(half_bt, EvqTemporary, 2);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001599 break;
1600 case EHTokHalf3:
John Kessenich96f65522017-06-06 23:35:25 -06001601 new(&type) TType(half_bt, EvqTemporary, 3);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001602 break;
1603 case EHTokHalf4:
John Kessenich96f65522017-06-06 23:35:25 -06001604 new(&type) TType(half_bt, EvqTemporary, 4);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001605 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001606
steve-lunarg3226b082016-10-26 19:18:55 -06001607 case EHTokMin16float:
1608 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1609 break;
1610 case EHTokMin16float1:
1611 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1612 type.makeVector();
1613 break;
1614 case EHTokMin16float2:
1615 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1616 break;
1617 case EHTokMin16float3:
1618 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1619 break;
1620 case EHTokMin16float4:
1621 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1622 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001623
steve-lunarg3226b082016-10-26 19:18:55 -06001624 case EHTokMin10float:
1625 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1626 break;
1627 case EHTokMin10float1:
1628 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1629 type.makeVector();
1630 break;
1631 case EHTokMin10float2:
1632 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1633 break;
1634 case EHTokMin10float3:
1635 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1636 break;
1637 case EHTokMin10float4:
1638 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1639 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001640
steve-lunarg3226b082016-10-26 19:18:55 -06001641 case EHTokMin16int:
1642 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1643 break;
1644 case EHTokMin16int1:
1645 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1646 type.makeVector();
1647 break;
1648 case EHTokMin16int2:
1649 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1650 break;
1651 case EHTokMin16int3:
1652 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1653 break;
1654 case EHTokMin16int4:
1655 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1656 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001657
steve-lunarg3226b082016-10-26 19:18:55 -06001658 case EHTokMin12int:
1659 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1660 break;
1661 case EHTokMin12int1:
1662 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1663 type.makeVector();
1664 break;
1665 case EHTokMin12int2:
1666 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1667 break;
1668 case EHTokMin12int3:
1669 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1670 break;
1671 case EHTokMin12int4:
1672 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1673 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001674
steve-lunarg3226b082016-10-26 19:18:55 -06001675 case EHTokMin16uint:
1676 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1677 break;
1678 case EHTokMin16uint1:
1679 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1680 type.makeVector();
1681 break;
1682 case EHTokMin16uint2:
1683 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1684 break;
1685 case EHTokMin16uint3:
1686 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1687 break;
1688 case EHTokMin16uint4:
1689 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1690 break;
1691
John Kessenich0133c122016-05-20 12:17:26 -06001692 case EHTokInt1x1:
1693 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1694 break;
1695 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001696 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001697 break;
1698 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001699 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001700 break;
1701 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001702 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001703 break;
1704 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001705 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001706 break;
1707 case EHTokInt2x2:
1708 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1709 break;
1710 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001711 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001712 break;
1713 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001714 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001715 break;
1716 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001717 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001718 break;
1719 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001720 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001721 break;
1722 case EHTokInt3x3:
1723 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1724 break;
1725 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001726 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001727 break;
1728 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001729 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001730 break;
1731 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001732 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001733 break;
1734 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001735 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001736 break;
1737 case EHTokInt4x4:
1738 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1739 break;
1740
John Kessenich71351de2016-06-08 12:50:56 -06001741 case EHTokUint1x1:
1742 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1743 break;
1744 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001745 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001746 break;
1747 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001748 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001749 break;
1750 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001751 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001752 break;
1753 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001754 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001755 break;
1756 case EHTokUint2x2:
1757 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1758 break;
1759 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001760 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001761 break;
1762 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001763 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001764 break;
1765 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001766 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001767 break;
1768 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001769 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001770 break;
1771 case EHTokUint3x3:
1772 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1773 break;
1774 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001775 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001776 break;
1777 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001778 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001779 break;
1780 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001781 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001782 break;
1783 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001784 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001785 break;
1786 case EHTokUint4x4:
1787 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1788 break;
1789
1790 case EHTokBool1x1:
1791 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1792 break;
1793 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001794 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001795 break;
1796 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001797 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001798 break;
1799 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001800 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001801 break;
1802 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001803 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001804 break;
1805 case EHTokBool2x2:
1806 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1807 break;
1808 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001809 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001810 break;
1811 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001812 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001813 break;
1814 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001815 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001816 break;
1817 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001818 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001819 break;
1820 case EHTokBool3x3:
1821 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1822 break;
1823 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001824 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001825 break;
1826 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001827 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001828 break;
1829 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001830 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001831 break;
1832 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001833 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001834 break;
1835 case EHTokBool4x4:
1836 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1837 break;
1838
John Kessenich0133c122016-05-20 12:17:26 -06001839 case EHTokFloat1x1:
1840 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1841 break;
1842 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001843 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001844 break;
1845 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001846 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001847 break;
1848 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001849 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001850 break;
1851 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001852 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001853 break;
John Kessenich87142c72016-03-12 20:24:24 -07001854 case EHTokFloat2x2:
1855 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1856 break;
1857 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001858 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001859 break;
1860 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001861 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001862 break;
John Kessenich0133c122016-05-20 12:17:26 -06001863 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001864 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001865 break;
John Kessenich87142c72016-03-12 20:24:24 -07001866 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001867 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001868 break;
1869 case EHTokFloat3x3:
1870 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1871 break;
1872 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001873 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001874 break;
John Kessenich0133c122016-05-20 12:17:26 -06001875 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001876 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001877 break;
John Kessenich87142c72016-03-12 20:24:24 -07001878 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001879 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001880 break;
1881 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001882 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001883 break;
1884 case EHTokFloat4x4:
1885 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1886 break;
1887
John Kessenich96f65522017-06-06 23:35:25 -06001888 case EHTokHalf1x1:
1889 new(&type) TType(half_bt, EvqTemporary, 0, 1, 1);
1890 break;
1891 case EHTokHalf1x2:
1892 new(&type) TType(half_bt, EvqTemporary, 0, 1, 2);
1893 break;
1894 case EHTokHalf1x3:
1895 new(&type) TType(half_bt, EvqTemporary, 0, 1, 3);
1896 break;
1897 case EHTokHalf1x4:
1898 new(&type) TType(half_bt, EvqTemporary, 0, 1, 4);
1899 break;
1900 case EHTokHalf2x1:
1901 new(&type) TType(half_bt, EvqTemporary, 0, 2, 1);
1902 break;
1903 case EHTokHalf2x2:
1904 new(&type) TType(half_bt, EvqTemporary, 0, 2, 2);
1905 break;
1906 case EHTokHalf2x3:
1907 new(&type) TType(half_bt, EvqTemporary, 0, 2, 3);
1908 break;
1909 case EHTokHalf2x4:
1910 new(&type) TType(half_bt, EvqTemporary, 0, 2, 4);
1911 break;
1912 case EHTokHalf3x1:
1913 new(&type) TType(half_bt, EvqTemporary, 0, 3, 1);
1914 break;
1915 case EHTokHalf3x2:
1916 new(&type) TType(half_bt, EvqTemporary, 0, 3, 2);
1917 break;
1918 case EHTokHalf3x3:
1919 new(&type) TType(half_bt, EvqTemporary, 0, 3, 3);
1920 break;
1921 case EHTokHalf3x4:
1922 new(&type) TType(half_bt, EvqTemporary, 0, 3, 4);
1923 break;
1924 case EHTokHalf4x1:
1925 new(&type) TType(half_bt, EvqTemporary, 0, 4, 1);
1926 break;
1927 case EHTokHalf4x2:
1928 new(&type) TType(half_bt, EvqTemporary, 0, 4, 2);
1929 break;
1930 case EHTokHalf4x3:
1931 new(&type) TType(half_bt, EvqTemporary, 0, 4, 3);
1932 break;
1933 case EHTokHalf4x4:
1934 new(&type) TType(half_bt, EvqTemporary, 0, 4, 4);
1935 break;
1936
John Kessenich0133c122016-05-20 12:17:26 -06001937 case EHTokDouble1x1:
1938 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1939 break;
1940 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001941 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001942 break;
1943 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001944 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001945 break;
1946 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001947 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001948 break;
1949 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001950 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001951 break;
1952 case EHTokDouble2x2:
1953 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1954 break;
1955 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001956 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001957 break;
1958 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001959 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001960 break;
1961 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001962 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001963 break;
1964 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001965 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001966 break;
1967 case EHTokDouble3x3:
1968 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1969 break;
1970 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001971 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001972 break;
1973 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001974 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001975 break;
1976 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001977 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001978 break;
1979 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001980 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001981 break;
1982 case EHTokDouble4x4:
1983 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1984 break;
1985
John Kessenich87142c72016-03-12 20:24:24 -07001986 default:
1987 return false;
1988 }
1989
1990 advanceToken();
1991
LoopDawgfa39cff2017-11-14 14:55:40 -07001992 if ((isUnorm || isSnorm) && !type.isFloatingDomain()) {
1993 parseContext.error(token.loc, "unorm and snorm only valid in floating point domain", "", "");
1994 return false;
1995 }
1996
John Kessenich87142c72016-03-12 20:24:24 -07001997 return true;
1998}
1999
John Kesseniche6e74942016-06-11 16:43:14 -06002000// struct
John Kessenich3d157c52016-07-25 16:05:33 -06002001// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
2002// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07002003// | struct_type IDENTIFIER // use of previously declared struct type
John Kessenich3d157c52016-07-25 16:05:33 -06002004//
2005// struct_type
2006// : STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07002007// | CLASS
John Kessenich3d157c52016-07-25 16:05:33 -06002008// | CBUFFER
2009// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06002010//
John Kessenich54ee28f2017-03-11 14:13:00 -07002011bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
John Kesseniche6e74942016-06-11 16:43:14 -06002012{
John Kessenichb804de62016-09-05 12:19:18 -06002013 // This storage qualifier will tell us whether it's an AST
2014 // block type or just a generic structure type.
2015 TStorageQualifier storageQualifier = EvqTemporary;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002016 bool readonly = false;
John Kessenich3d157c52016-07-25 16:05:33 -06002017
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002018 if (acceptTokenClass(EHTokCBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06002019 // CBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06002020 storageQualifier = EvqUniform;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002021 } else if (acceptTokenClass(EHTokTBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06002022 // TBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06002023 storageQualifier = EvqBuffer;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002024 readonly = true;
John Kessenich054378d2017-06-19 15:13:26 -06002025 } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) {
2026 // Neither CLASS nor STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06002027 return false;
John Kessenich054378d2017-06-19 15:13:26 -06002028 }
2029
2030 // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06002031
LoopDawg7ee29ba2017-11-27 14:45:36 -07002032
2033 // IDENTIFIER. It might also be a keyword which can double as an identifier.
2034 // For example: 'cbuffer ConstantBuffer' or 'struct ConstantBuffer' is legal.
2035 // 'cbuffer int' is also legal, and 'struct int' appears rejected only because
2036 // it attempts to redefine the 'int' type.
2037 const char* idString = getTypeString(peek());
John Kesseniche6e74942016-06-11 16:43:14 -06002038 TString structName = "";
LoopDawg7ee29ba2017-11-27 14:45:36 -07002039 if (peekTokenClass(EHTokIdentifier) || idString != nullptr) {
2040 if (idString != nullptr)
2041 structName = *idString;
2042 else
2043 structName = *token.string;
John Kesseniche6e74942016-06-11 16:43:14 -06002044 advanceToken();
2045 }
2046
John Kessenich3d157c52016-07-25 16:05:33 -06002047 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002048 TQualifier postDeclQualifier;
2049 postDeclQualifier.clear();
John Kessenich854fe242017-03-02 14:30:59 -07002050 bool postDeclsFound = acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06002051
John Kessenichf3d88bd2017-03-19 12:24:29 -06002052 // LEFT_BRACE, or
John Kessenich854fe242017-03-02 14:30:59 -07002053 // struct_type IDENTIFIER
John Kesseniche6e74942016-06-11 16:43:14 -06002054 if (! acceptTokenClass(EHTokLeftBrace)) {
John Kessenich854fe242017-03-02 14:30:59 -07002055 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
2056 // struct_type IDENTIFIER
2057 return true;
2058 } else {
2059 expected("{");
2060 return false;
2061 }
John Kesseniche6e74942016-06-11 16:43:14 -06002062 }
2063
John Kessenichf3d88bd2017-03-19 12:24:29 -06002064
John Kesseniche6e74942016-06-11 16:43:14 -06002065 // struct_declaration_list
2066 TTypeList* typeList;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002067 // Save each member function so they can be processed after we have a fully formed 'this'.
2068 TVector<TFunctionDeclarator> functionDeclarators;
2069
2070 parseContext.pushNamespace(structName);
John Kessenichaa3c64c2017-03-28 09:52:38 -06002071 bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06002072 parseContext.popNamespace();
2073
2074 if (! acceptedList) {
John Kesseniche6e74942016-06-11 16:43:14 -06002075 expected("struct member declarations");
2076 return false;
2077 }
2078
2079 // RIGHT_BRACE
2080 if (! acceptTokenClass(EHTokRightBrace)) {
2081 expected("}");
2082 return false;
2083 }
2084
2085 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06002086 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06002087 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06002088 else {
John Kessenich7735b942016-09-05 12:40:06 -06002089 postDeclQualifier.storage = storageQualifier;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002090 postDeclQualifier.readonly = readonly;
John Kessenich7735b942016-09-05 12:40:06 -06002091 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06002092 }
John Kesseniche6e74942016-06-11 16:43:14 -06002093
John Kessenich727b3742017-02-03 17:57:55 -07002094 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06002095
John Kessenich4960baa2017-03-19 18:09:59 -06002096 // For member functions: now that we know the type of 'this', go back and
2097 // - add their implicit argument with 'this' (not to the mangling, just the argument list)
2098 // - parse the functions, their tokens were saved for deferred parsing (now)
2099 for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
2100 // update signature
2101 if (functionDeclarators[b].function->hasImplicitThis())
John Kessenich37789792017-03-21 23:56:40 -06002102 functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName);
John Kessenich4960baa2017-03-19 18:09:59 -06002103 }
2104
John Kessenichf3d88bd2017-03-19 12:24:29 -06002105 // All member functions get parsed inside the class/struct namespace and with the
2106 // class/struct members in a symbol-table level.
2107 parseContext.pushNamespace(structName);
John Kessenich0a2a0cd2017-05-16 23:16:26 -06002108 parseContext.pushThisScope(type, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06002109 bool deferredSuccess = true;
2110 for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
2111 // parse body
2112 pushTokenStream(functionDeclarators[b].body);
2113 if (! acceptFunctionBody(functionDeclarators[b], nodeList))
2114 deferredSuccess = false;
2115 popTokenStream();
2116 }
John Kessenich37789792017-03-21 23:56:40 -06002117 parseContext.popThisScope();
John Kessenichf3d88bd2017-03-19 12:24:29 -06002118 parseContext.popNamespace();
2119
2120 return deferredSuccess;
John Kesseniche6e74942016-06-11 16:43:14 -06002121}
2122
steve-lunarga766b832017-04-25 09:30:28 -06002123// constantbuffer
2124// : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE
2125bool HlslGrammar::acceptConstantBufferType(TType& type)
2126{
2127 if (! acceptTokenClass(EHTokConstantBuffer))
2128 return false;
2129
2130 if (! acceptTokenClass(EHTokLeftAngle)) {
2131 expected("left angle bracket");
2132 return false;
2133 }
2134
2135 TType templateType;
2136 if (! acceptType(templateType)) {
2137 expected("type");
2138 return false;
2139 }
2140
2141 if (! acceptTokenClass(EHTokRightAngle)) {
2142 expected("right angle bracket");
2143 return false;
2144 }
2145
2146 TQualifier postDeclQualifier;
2147 postDeclQualifier.clear();
2148 postDeclQualifier.storage = EvqUniform;
2149
2150 if (templateType.isStruct()) {
2151 // Make a block from the type parsed as the template argument
2152 TTypeList* typeList = templateType.getWritableStruct();
2153 new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock
2154
2155 type.getQualifier().storage = EvqUniform;
2156
2157 return true;
2158 } else {
2159 parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", "");
2160 return false;
2161 }
2162}
2163
LoopDawge5530b92017-11-08 19:48:11 -07002164// texture_buffer
2165// : TEXTUREBUFFER LEFT_ANGLE type RIGHT_ANGLE
2166bool HlslGrammar::acceptTextureBufferType(TType& type)
2167{
2168 if (! acceptTokenClass(EHTokTextureBuffer))
2169 return false;
2170
2171 if (! acceptTokenClass(EHTokLeftAngle)) {
2172 expected("left angle bracket");
2173 return false;
2174 }
2175
2176 TType templateType;
2177 if (! acceptType(templateType)) {
2178 expected("type");
2179 return false;
2180 }
2181
2182 if (! acceptTokenClass(EHTokRightAngle)) {
2183 expected("right angle bracket");
2184 return false;
2185 }
2186
2187 templateType.getQualifier().storage = EvqBuffer;
2188 templateType.getQualifier().readonly = true;
2189
2190 TType blockType(templateType.getWritableStruct(), "", templateType.getQualifier());
2191
2192 blockType.getQualifier().storage = EvqBuffer;
2193 blockType.getQualifier().readonly = true;
2194
2195 type.shallowCopy(blockType);
2196
2197 return true;
2198}
2199
2200
steve-lunarg5da1f032017-02-12 17:50:28 -07002201// struct_buffer
2202// : APPENDSTRUCTUREDBUFFER
2203// | BYTEADDRESSBUFFER
2204// | CONSUMESTRUCTUREDBUFFER
2205// | RWBYTEADDRESSBUFFER
2206// | RWSTRUCTUREDBUFFER
2207// | STRUCTUREDBUFFER
2208bool HlslGrammar::acceptStructBufferType(TType& type)
2209{
2210 const EHlslTokenClass structBuffType = peek();
2211
2212 // TODO: globallycoherent
2213 bool hasTemplateType = true;
2214 bool readonly = false;
2215
2216 TStorageQualifier storage = EvqBuffer;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002217 TBuiltInVariable builtinType = EbvNone;
steve-lunarg5da1f032017-02-12 17:50:28 -07002218
2219 switch (structBuffType) {
2220 case EHTokAppendStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002221 builtinType = EbvAppendConsume;
2222 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002223 case EHTokByteAddressBuffer:
2224 hasTemplateType = false;
2225 readonly = true;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002226 builtinType = EbvByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002227 break;
2228 case EHTokConsumeStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002229 builtinType = EbvAppendConsume;
2230 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002231 case EHTokRWByteAddressBuffer:
2232 hasTemplateType = false;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002233 builtinType = EbvRWByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002234 break;
2235 case EHTokRWStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002236 builtinType = EbvRWStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002237 break;
2238 case EHTokStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002239 builtinType = EbvStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002240 readonly = true;
2241 break;
2242 default:
2243 return false; // not a structure buffer type
2244 }
2245
2246 advanceToken(); // consume the structure keyword
2247
2248 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
2249 TType* templateType = new TType;
2250
2251 if (hasTemplateType) {
2252 if (! acceptTokenClass(EHTokLeftAngle)) {
2253 expected("left angle bracket");
2254 return false;
2255 }
2256
2257 if (! acceptType(*templateType)) {
2258 expected("type");
2259 return false;
2260 }
2261 if (! acceptTokenClass(EHTokRightAngle)) {
2262 expected("right angle bracket");
2263 return false;
2264 }
2265 } else {
2266 // byte address buffers have no explicit type.
2267 TType uintType(EbtUint, storage);
2268 templateType->shallowCopy(uintType);
2269 }
2270
2271 // Create an unsized array out of that type.
2272 // TODO: does this work if it's already an array type?
2273 TArraySizes unsizedArray;
2274 unsizedArray.addInnerSize(UnsizedArraySize);
2275 templateType->newArraySizes(unsizedArray);
steve-lunarg40efe5c2017-03-06 12:01:44 -07002276 templateType->getQualifier().storage = storage;
steve-lunargdd8287a2017-02-23 18:04:12 -07002277
2278 // field name is canonical for all structbuffers
2279 templateType->setFieldName("@data");
steve-lunarg5da1f032017-02-12 17:50:28 -07002280
steve-lunarg5da1f032017-02-12 17:50:28 -07002281 TTypeList* blockStruct = new TTypeList;
2282 TTypeLoc member = { templateType, token.loc };
2283 blockStruct->push_back(member);
2284
steve-lunargdd8287a2017-02-23 18:04:12 -07002285 // This is the type of the buffer block (SSBO)
steve-lunarg5da1f032017-02-12 17:50:28 -07002286 TType blockType(blockStruct, "", templateType->getQualifier());
2287
steve-lunargdd8287a2017-02-23 18:04:12 -07002288 blockType.getQualifier().storage = storage;
2289 blockType.getQualifier().readonly = readonly;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002290 blockType.getQualifier().builtIn = builtinType;
steve-lunargdd8287a2017-02-23 18:04:12 -07002291
2292 // We may have created an equivalent type before, in which case we should use its
2293 // deep structure.
2294 parseContext.shareStructBufferType(blockType);
2295
steve-lunarg5da1f032017-02-12 17:50:28 -07002296 type.shallowCopy(blockType);
2297
2298 return true;
2299}
2300
John Kesseniche6e74942016-06-11 16:43:14 -06002301// struct_declaration_list
2302// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
2303//
2304// struct_declaration
John Kessenichcc951f82017-12-06 07:33:36 -07002305// : attributes fully_specified_type struct_declarator COMMA struct_declarator ...
2306// | attributes fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition
John Kesseniche6e74942016-06-11 16:43:14 -06002307//
2308// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06002309// : IDENTIFIER post_decls
2310// | IDENTIFIER array_specifier post_decls
John Kessenich54ee28f2017-03-11 14:13:00 -07002311// | IDENTIFIER function_parameters post_decls // member-function prototype
John Kesseniche6e74942016-06-11 16:43:14 -06002312//
John Kessenichaa3c64c2017-03-28 09:52:38 -06002313bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002314 TVector<TFunctionDeclarator>& declarators)
John Kesseniche6e74942016-06-11 16:43:14 -06002315{
2316 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002317 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06002318
2319 do {
2320 // success on seeing the RIGHT_BRACE coming up
2321 if (peekTokenClass(EHTokRightBrace))
John Kessenichb16f7e62017-03-11 19:32:47 -07002322 break;
John Kesseniche6e74942016-06-11 16:43:14 -06002323
2324 // struct_declaration
John Kessenichcc951f82017-12-06 07:33:36 -07002325
2326 // attributes
2327 TAttributeMap attributes;
2328 acceptAttributes(attributes);
2329
John Kessenich54ee28f2017-03-11 14:13:00 -07002330 bool declarator_list = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002331
2332 // fully_specified_type
2333 TType memberType;
John Kessenich54ee28f2017-03-11 14:13:00 -07002334 if (! acceptFullySpecifiedType(memberType, nodeList)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002335 expected("member type");
2336 return false;
2337 }
2338
John Kessenichcc951f82017-12-06 07:33:36 -07002339 parseContext.transferTypeAttributes(attributes, memberType);
2340
John Kesseniche6e74942016-06-11 16:43:14 -06002341 // struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07002342 bool functionDefinitionAccepted = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002343 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002344 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002345 expected("member name");
2346 return false;
2347 }
2348
John Kessenich54ee28f2017-03-11 14:13:00 -07002349 if (peekTokenClass(EHTokLeftParen)) {
2350 // function_parameters
2351 if (!declarator_list) {
John Kessenichb16f7e62017-03-11 19:32:47 -07002352 declarators.resize(declarators.size() + 1);
2353 // request a token stream for deferred processing
John Kessenichf3d88bd2017-03-19 12:24:29 -06002354 functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
2355 declarators.back());
John Kessenich54ee28f2017-03-11 14:13:00 -07002356 if (functionDefinitionAccepted)
2357 break;
2358 }
2359 expected("member-function definition");
2360 return false;
2361 } else {
2362 // add it to the list of members
2363 TTypeLoc member = { new TType(EbtVoid), token.loc };
2364 member.type->shallowCopy(memberType);
2365 member.type->setFieldName(*idToken.string);
2366 typeList->push_back(member);
John Kesseniche6e74942016-06-11 16:43:14 -06002367
John Kessenich54ee28f2017-03-11 14:13:00 -07002368 // array_specifier
2369 TArraySizes* arraySizes = nullptr;
2370 acceptArraySpecifier(arraySizes);
2371 if (arraySizes)
2372 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06002373
John Kessenich54ee28f2017-03-11 14:13:00 -07002374 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06002375
John Kessenich54ee28f2017-03-11 14:13:00 -07002376 // EQUAL assignment_expression
2377 if (acceptTokenClass(EHTokAssign)) {
2378 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
2379 TIntermTyped* expressionNode = nullptr;
2380 if (! acceptAssignmentExpression(expressionNode)) {
2381 expected("initializer");
2382 return false;
2383 }
John Kessenich18adbdb2017-02-02 15:16:20 -07002384 }
2385 }
John Kesseniche6e74942016-06-11 16:43:14 -06002386 // success on seeing the SEMICOLON coming up
2387 if (peekTokenClass(EHTokSemicolon))
2388 break;
2389
2390 // COMMA
John Kessenich54ee28f2017-03-11 14:13:00 -07002391 if (acceptTokenClass(EHTokComma))
2392 declarator_list = true;
2393 else {
John Kesseniche6e74942016-06-11 16:43:14 -06002394 expected(",");
2395 return false;
2396 }
2397
2398 } while (true);
2399
2400 // SEMI_COLON
John Kessenich54ee28f2017-03-11 14:13:00 -07002401 if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002402 expected(";");
2403 return false;
2404 }
2405
2406 } while (true);
John Kessenichb16f7e62017-03-11 19:32:47 -07002407
John Kessenichb16f7e62017-03-11 19:32:47 -07002408 return true;
John Kesseniche6e74942016-06-11 16:43:14 -06002409}
2410
John Kessenich54ee28f2017-03-11 14:13:00 -07002411// member_function_definition
2412// | function_parameters post_decls compound_statement
2413//
2414// Expects type to have EvqGlobal for a static member and
2415// EvqTemporary for non-static member.
John Kessenich9855bda2017-09-11 21:48:19 -06002416bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, TString& memberName,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002417 TFunctionDeclarator& declarator)
John Kessenich54ee28f2017-03-11 14:13:00 -07002418{
John Kessenich54ee28f2017-03-11 14:13:00 -07002419 bool accepted = false;
2420
John Kessenich9855bda2017-09-11 21:48:19 -06002421 TString* functionName = &memberName;
John Kessenich4dc835c2017-03-28 23:43:10 -06002422 parseContext.getFullNamespaceName(functionName);
John Kessenich088d52b2017-03-11 17:55:28 -07002423 declarator.function = new TFunction(functionName, type);
John Kessenich4960baa2017-03-19 18:09:59 -06002424 if (type.getQualifier().storage == EvqTemporary)
2425 declarator.function->setImplicitThis();
John Kessenich37789792017-03-21 23:56:40 -06002426 else
2427 declarator.function->setIllegalImplicitThis();
John Kessenich54ee28f2017-03-11 14:13:00 -07002428
2429 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -07002430 if (acceptFunctionParameters(*declarator.function)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002431 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -07002432 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich54ee28f2017-03-11 14:13:00 -07002433
2434 // compound_statement (function body definition)
2435 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich088d52b2017-03-11 17:55:28 -07002436 declarator.loc = token.loc;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002437 declarator.body = new TVector<HlslToken>;
2438 accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
John Kessenich54ee28f2017-03-11 14:13:00 -07002439 }
2440 } else
2441 expected("function parameter list");
2442
John Kessenich54ee28f2017-03-11 14:13:00 -07002443 return accepted;
2444}
2445
John Kessenich5f934b02016-03-13 17:58:25 -06002446// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06002447// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06002448// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002449//
2450bool HlslGrammar::acceptFunctionParameters(TFunction& function)
2451{
John Kessenich078d7f22016-03-14 10:02:11 -06002452 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002453 if (! acceptTokenClass(EHTokLeftParen))
2454 return false;
2455
John Kessenich71351de2016-06-08 12:50:56 -06002456 // VOID RIGHT_PAREN
2457 if (! acceptTokenClass(EHTokVoid)) {
2458 do {
2459 // parameter_declaration
2460 if (! acceptParameterDeclaration(function))
2461 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002462
John Kessenich71351de2016-06-08 12:50:56 -06002463 // COMMA
2464 if (! acceptTokenClass(EHTokComma))
2465 break;
2466 } while (true);
2467 }
John Kessenich5f934b02016-03-13 17:58:25 -06002468
John Kessenich078d7f22016-03-14 10:02:11 -06002469 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002470 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002471 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002472 return false;
2473 }
2474
2475 return true;
2476}
2477
steve-lunarg26d31452016-12-23 18:56:57 -07002478// default_parameter_declaration
2479// : EQUAL conditional_expression
2480// : EQUAL initializer
2481bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2482{
2483 node = nullptr;
2484
2485 // Valid not to have a default_parameter_declaration
2486 if (!acceptTokenClass(EHTokAssign))
2487 return true;
2488
2489 if (!acceptConditionalExpression(node)) {
2490 if (!acceptInitializer(node))
2491 return false;
2492
2493 // For initializer lists, we have to const-fold into a constructor for the type, so build
2494 // that.
John Kessenichc633f642017-04-03 21:48:37 -06002495 TFunction* constructor = parseContext.makeConstructorCall(token.loc, type);
steve-lunarg26d31452016-12-23 18:56:57 -07002496 if (constructor == nullptr) // cannot construct
2497 return false;
2498
2499 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002500 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002501 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002502
steve-lunarg26d31452016-12-23 18:56:57 -07002503 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2504 }
2505
John Kessenichbb79abc2017-10-07 13:23:09 -06002506 if (node == nullptr)
2507 return false;
2508
steve-lunarg26d31452016-12-23 18:56:57 -07002509 // If this is simply a constant, we can use it directly.
2510 if (node->getAsConstantUnion())
2511 return true;
2512
2513 // Otherwise, it has to be const-foldable.
2514 TIntermTyped* origNode = node;
2515
2516 node = intermediate.fold(node->getAsAggregate());
2517
2518 if (node != nullptr && origNode != node)
2519 return true;
2520
2521 parseContext.error(token.loc, "invalid default parameter value", "", "");
2522
2523 return false;
2524}
2525
John Kessenich5f934b02016-03-13 17:58:25 -06002526// parameter_declaration
John Kessenich77ea30b2017-09-30 14:34:50 -06002527// : attributes attributed_declaration
2528//
2529// attributed_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002530// : fully_specified_type post_decls [ = default_parameter_declaration ]
2531// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002532//
2533bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2534{
John Kessenich77ea30b2017-09-30 14:34:50 -06002535 // attributes
2536 TAttributeMap attributes;
2537 acceptAttributes(attributes);
2538
John Kessenich5f934b02016-03-13 17:58:25 -06002539 // fully_specified_type
2540 TType* type = new TType;
2541 if (! acceptFullySpecifiedType(*type))
2542 return false;
2543
John Kessenich77ea30b2017-09-30 14:34:50 -06002544 parseContext.transferTypeAttributes(attributes, *type);
2545
John Kessenich5f934b02016-03-13 17:58:25 -06002546 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002547 HlslToken idToken;
2548 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002549
John Kessenich19b92ff2016-06-19 11:50:34 -06002550 // array_specifier
2551 TArraySizes* arraySizes = nullptr;
2552 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002553 if (arraySizes) {
2554 if (arraySizes->isImplicit()) {
2555 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2556 return false;
2557 }
2558
John Kessenich19b92ff2016-06-19 11:50:34 -06002559 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002560 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002561
2562 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002563 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002564
steve-lunarg26d31452016-12-23 18:56:57 -07002565 TIntermTyped* defaultValue;
2566 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2567 return false;
2568
John Kessenich5aa59e22016-06-17 15:50:47 -06002569 parseContext.paramFix(*type);
2570
steve-lunarg26d31452016-12-23 18:56:57 -07002571 // If any prior parameters have default values, all the parameters after that must as well.
2572 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2573 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2574 return false;
2575 }
2576
2577 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002578 function.addParameter(param);
2579
2580 return true;
2581}
2582
2583// Do the work to create the function definition in addition to
2584// parsing the body (compound_statement).
John Kessenichb16f7e62017-03-11 19:32:47 -07002585//
2586// If 'deferredTokens' are passed in, just get the token stream,
2587// don't process.
2588//
2589bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
2590 TVector<HlslToken>* deferredTokens)
John Kessenich5f934b02016-03-13 17:58:25 -06002591{
John Kessenich088d52b2017-03-11 17:55:28 -07002592 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
John Kessenich5f934b02016-03-13 17:58:25 -06002593
John Kessenichb16f7e62017-03-11 19:32:47 -07002594 if (deferredTokens)
2595 return captureBlockTokens(*deferredTokens);
2596 else
John Kessenich4960baa2017-03-19 18:09:59 -06002597 return acceptFunctionBody(declarator, nodeList);
John Kessenich088d52b2017-03-11 17:55:28 -07002598}
2599
2600bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
2601{
2602 // we might get back an entry-point
John Kessenichca71d942017-03-07 20:44:09 -07002603 TIntermNode* entryPointNode = nullptr;
2604
John Kessenich077e0522016-06-09 02:02:17 -06002605 // This does a pushScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002606 TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function,
2607 declarator.attributes, entryPointNode);
John Kessenich5f934b02016-03-13 17:58:25 -06002608
2609 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002610 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002611 if (! acceptCompoundStatement(functionBody))
2612 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002613
John Kessenich54ee28f2017-03-11 14:13:00 -07002614 // this does a popScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002615 parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode);
John Kessenichca71d942017-03-07 20:44:09 -07002616
2617 // Hook up the 1 or 2 function definitions.
2618 nodeList = intermediate.growAggregate(nodeList, functionNode);
2619 nodeList = intermediate.growAggregate(nodeList, entryPointNode);
John Kessenich02467d82017-01-19 15:41:47 -07002620
2621 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002622}
2623
John Kessenich0d2b6de2016-06-05 11:23:11 -06002624// Accept an expression with parenthesis around it, where
2625// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002626// syntactically required ones like in "if ( expression )".
2627//
2628// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002629//
2630// Note this one is not set up to be speculative; as it gives
2631// errors if not found.
2632//
2633bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2634{
John Kessenich7199a6d2017-11-29 16:32:46 -07002635 expression = nullptr;
2636
John Kessenich0d2b6de2016-06-05 11:23:11 -06002637 // LEFT_PAREN
2638 if (! acceptTokenClass(EHTokLeftParen))
2639 expected("(");
2640
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002641 bool decl = false;
2642 TIntermNode* declNode = nullptr;
2643 decl = acceptControlDeclaration(declNode);
2644 if (decl) {
2645 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2646 expected("initialized declaration");
2647 return false;
2648 } else
2649 expression = declNode->getAsTyped();
2650 } else {
2651 // no declaration
2652 if (! acceptExpression(expression)) {
2653 expected("expression");
2654 return false;
2655 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002656 }
2657
2658 // RIGHT_PAREN
2659 if (! acceptTokenClass(EHTokRightParen))
2660 expected(")");
2661
2662 return true;
2663}
2664
John Kessenich34fb0362016-05-03 23:17:20 -06002665// The top-level full expression recognizer.
2666//
John Kessenich87142c72016-03-12 20:24:24 -07002667// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002668// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002669//
2670bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2671{
LoopDawgef764a22016-06-03 09:17:51 -06002672 node = nullptr;
2673
John Kessenich34fb0362016-05-03 23:17:20 -06002674 // assignment_expression
2675 if (! acceptAssignmentExpression(node))
2676 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002677
John Kessenich34fb0362016-05-03 23:17:20 -06002678 if (! peekTokenClass(EHTokComma))
2679 return true;
2680
2681 do {
2682 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002683 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002684 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002685
John Kessenich34fb0362016-05-03 23:17:20 -06002686 // ... assignment_expression
2687 TIntermTyped* rightNode = nullptr;
2688 if (! acceptAssignmentExpression(rightNode)) {
2689 expected("assignment expression");
2690 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002691 }
2692
John Kessenich34fb0362016-05-03 23:17:20 -06002693 node = intermediate.addComma(node, rightNode, loc);
2694
2695 if (! peekTokenClass(EHTokComma))
2696 return true;
2697 } while (true);
2698}
2699
John Kessenich07354242016-07-01 19:58:06 -06002700// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002701// : LEFT_BRACE RIGHT_BRACE
2702// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002703//
2704// initializer_list
2705// : assignment_expression COMMA assignment_expression COMMA ...
2706//
2707bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2708{
2709 // LEFT_BRACE
2710 if (! acceptTokenClass(EHTokLeftBrace))
2711 return false;
2712
John Kessenich98ad4852016-11-27 17:39:07 -07002713 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002714 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002715 if (acceptTokenClass(EHTokRightBrace)) {
2716 // a zero-length initializer list
2717 node = intermediate.makeAggregate(loc);
2718 return true;
2719 }
2720
2721 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002722 node = nullptr;
2723 do {
2724 // assignment_expression
2725 TIntermTyped* expr;
2726 if (! acceptAssignmentExpression(expr)) {
2727 expected("assignment expression in initializer list");
2728 return false;
2729 }
LoopDawg0fca0ba2017-07-10 15:43:40 -06002730
2731 const bool firstNode = (node == nullptr);
2732
John Kessenich07354242016-07-01 19:58:06 -06002733 node = intermediate.growAggregate(node, expr, loc);
2734
LoopDawg0fca0ba2017-07-10 15:43:40 -06002735 // If every sub-node in the list has qualifier EvqConst, the returned node becomes
2736 // EvqConst. Otherwise, it becomes EvqTemporary. That doesn't happen with e.g.
2737 // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are.
2738 if (firstNode && expr->getQualifier().storage == EvqConst)
2739 node->getQualifier().storage = EvqConst;
2740 else if (expr->getQualifier().storage != EvqConst)
2741 node->getQualifier().storage = EvqTemporary;
2742
John Kessenich07354242016-07-01 19:58:06 -06002743 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002744 if (acceptTokenClass(EHTokComma)) {
2745 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2746 return true;
John Kessenich07354242016-07-01 19:58:06 -06002747 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002748 }
John Kessenich07354242016-07-01 19:58:06 -06002749
2750 // RIGHT_BRACE
2751 if (acceptTokenClass(EHTokRightBrace))
2752 return true;
2753
2754 expected(", or }");
2755 return false;
2756 } while (true);
2757}
2758
John Kessenich34fb0362016-05-03 23:17:20 -06002759// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002760// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002761//
2762// a op (b op (c op d))
2763//
2764// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002765// : initializer
2766// | conditional_expression
2767// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002768//
2769bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2770{
John Kessenich07354242016-07-01 19:58:06 -06002771 // initializer
2772 if (peekTokenClass(EHTokLeftBrace)) {
2773 if (acceptInitializer(node))
2774 return true;
2775
2776 expected("initializer");
2777 return false;
2778 }
2779
John Kessenich00957f82016-07-27 10:39:57 -06002780 // conditional_expression
2781 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002782 return false;
2783
John Kessenich07354242016-07-01 19:58:06 -06002784 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002785 TOperator assignOp = HlslOpMap::assignment(peek());
2786 if (assignOp == EOpNull)
2787 return true;
2788
John Kessenich00957f82016-07-27 10:39:57 -06002789 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002790 TSourceLoc loc = token.loc;
2791 advanceToken();
2792
John Kessenich00957f82016-07-27 10:39:57 -06002793 // conditional_expression assign_op conditional_expression ...
2794 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002795 // gets the right-to-left associativity.
2796 TIntermTyped* rightNode = nullptr;
2797 if (! acceptAssignmentExpression(rightNode)) {
2798 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002799 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002800 }
2801
John Kessenichd21baed2016-09-16 03:05:12 -06002802 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002803 node = parseContext.handleLvalue(loc, "assign", node);
2804
John Kessenichfea226b2016-07-28 17:53:56 -06002805 if (node == nullptr) {
2806 parseContext.error(loc, "could not create assignment", "", "");
2807 return false;
2808 }
John Kessenich34fb0362016-05-03 23:17:20 -06002809
2810 if (! peekTokenClass(EHTokComma))
2811 return true;
2812
2813 return true;
2814}
2815
John Kessenich00957f82016-07-27 10:39:57 -06002816// Accept a conditional expression, which associates right-to-left,
2817// accomplished by the "true" expression calling down to lower
2818// precedence levels than this level.
2819//
2820// conditional_expression
2821// : binary_expression
2822// | binary_expression QUESTION expression COLON assignment_expression
2823//
2824bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2825{
2826 // binary_expression
2827 if (! acceptBinaryExpression(node, PlLogicalOr))
2828 return false;
2829
2830 if (! acceptTokenClass(EHTokQuestion))
2831 return true;
2832
John Kessenich636b62d2017-04-11 19:45:00 -06002833 node = parseContext.convertConditionalExpression(token.loc, node, false);
John Kessenich7e997e22017-03-30 22:09:30 -06002834 if (node == nullptr)
2835 return false;
2836
John Kessenichf6deacd2017-06-06 19:52:55 -06002837 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
2838
John Kessenich00957f82016-07-27 10:39:57 -06002839 TIntermTyped* trueNode = nullptr;
2840 if (! acceptExpression(trueNode)) {
2841 expected("expression after ?");
2842 return false;
2843 }
2844 TSourceLoc loc = token.loc;
2845
2846 if (! acceptTokenClass(EHTokColon)) {
2847 expected(":");
2848 return false;
2849 }
2850
2851 TIntermTyped* falseNode = nullptr;
2852 if (! acceptAssignmentExpression(falseNode)) {
2853 expected("expression after :");
2854 return false;
2855 }
2856
John Kessenichf6deacd2017-06-06 19:52:55 -06002857 --parseContext.controlFlowNestingLevel;
2858
John Kessenich00957f82016-07-27 10:39:57 -06002859 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2860
2861 return true;
2862}
2863
John Kessenich34fb0362016-05-03 23:17:20 -06002864// Accept a binary expression, for binary operations that
2865// associate left-to-right. This is, it is implicit, for example
2866//
2867// ((a op b) op c) op d
2868//
2869// binary_expression
2870// : expression op expression op expression ...
2871//
2872// where 'expression' is the next higher level in precedence.
2873//
2874bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2875{
2876 if (precedenceLevel > PlMul)
2877 return acceptUnaryExpression(node);
2878
2879 // assignment_expression
2880 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2881 return false;
2882
John Kessenich34fb0362016-05-03 23:17:20 -06002883 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002884 TOperator op = HlslOpMap::binary(peek());
2885 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2886 if (tokenLevel < precedenceLevel)
2887 return true;
2888
John Kessenich34fb0362016-05-03 23:17:20 -06002889 // ... op
2890 TSourceLoc loc = token.loc;
2891 advanceToken();
2892
2893 // ... expression
2894 TIntermTyped* rightNode = nullptr;
2895 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2896 expected("expression");
2897 return false;
2898 }
2899
2900 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002901 if (node == nullptr) {
2902 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2903 return false;
2904 }
John Kessenich34fb0362016-05-03 23:17:20 -06002905 } while (true);
2906}
2907
2908// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002909// : (type) unary_expression
2910// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002911// | - unary_expression
2912// | ! unary_expression
2913// | ~ unary_expression
2914// | ++ unary_expression
2915// | -- unary_expression
2916// | postfix_expression
2917//
2918bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2919{
John Kessenich1cc1a282016-06-03 16:55:49 -06002920 // (type) unary_expression
2921 // Have to look two steps ahead, because this could be, e.g., a
2922 // postfix_expression instead, since that also starts with at "(".
2923 if (acceptTokenClass(EHTokLeftParen)) {
2924 TType castType;
2925 if (acceptType(castType)) {
John Kessenich82ae8c32017-06-13 23:13:10 -06002926 // recognize any array_specifier as part of the type
2927 TArraySizes* arraySizes = nullptr;
2928 acceptArraySpecifier(arraySizes);
2929 if (arraySizes != nullptr)
2930 castType.newArraySizes(*arraySizes);
2931 TSourceLoc loc = token.loc;
steve-lunarg5964c642016-07-30 07:38:55 -06002932 if (acceptTokenClass(EHTokRightParen)) {
2933 // We've matched "(type)" now, get the expression to cast
steve-lunarg5964c642016-07-30 07:38:55 -06002934 if (! acceptUnaryExpression(node))
2935 return false;
2936
2937 // Hook it up like a constructor
John Kessenichc633f642017-04-03 21:48:37 -06002938 TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType);
steve-lunarg5964c642016-07-30 07:38:55 -06002939 if (constructorFunction == nullptr) {
2940 expected("type that can be constructed");
2941 return false;
2942 }
2943 TIntermTyped* arguments = nullptr;
2944 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2945 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2946
John Kessenichbb79abc2017-10-07 13:23:09 -06002947 return node != nullptr;
steve-lunarg5964c642016-07-30 07:38:55 -06002948 } else {
2949 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2950 // the '(int' part. We must back up twice.
2951 recedeToken();
2952 recedeToken();
John Kessenich82ae8c32017-06-13 23:13:10 -06002953
2954 // Note, there are no array constructors like
2955 // (float[2](...))
2956 if (arraySizes != nullptr)
2957 parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", "");
John Kessenich1cc1a282016-06-03 16:55:49 -06002958 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002959 } else {
2960 // This isn't a type cast, but it still started "(", so if it is a
2961 // unary expression, it can only be a postfix_expression, so try that.
2962 // Back it up first.
2963 recedeToken();
2964 return acceptPostfixExpression(node);
2965 }
2966 }
2967
2968 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002969 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002970
John Kessenich1cc1a282016-06-03 16:55:49 -06002971 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002972 if (unaryOp == EOpNull)
2973 return acceptPostfixExpression(node);
2974
2975 // op unary_expression
2976 TSourceLoc loc = token.loc;
2977 advanceToken();
2978 if (! acceptUnaryExpression(node))
2979 return false;
2980
2981 // + is a no-op
2982 if (unaryOp == EOpAdd)
2983 return true;
2984
2985 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002986
2987 // These unary ops require lvalues
2988 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2989 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002990
2991 return node != nullptr;
2992}
2993
2994// postfix_expression
2995// : LEFT_PAREN expression RIGHT_PAREN
2996// | literal
2997// | constructor
John Kessenich8f9fdc92017-03-30 16:22:26 -06002998// | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ]
John Kessenich34fb0362016-05-03 23:17:20 -06002999// | function_call
3000// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
3001// | postfix_expression DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07003002// | postfix_expression DOT IDENTIFIER arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06003003// | postfix_expression arguments
John Kessenich34fb0362016-05-03 23:17:20 -06003004// | postfix_expression INC_OP
3005// | postfix_expression DEC_OP
3006//
3007bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
3008{
3009 // Not implemented as self-recursive:
John Kessenich54ee28f2017-03-11 14:13:00 -07003010 // The logical "right recursion" is done with a loop at the end
John Kessenich34fb0362016-05-03 23:17:20 -06003011
3012 // idToken will pick up either a variable or a function name in a function call
3013 HlslToken idToken;
3014
John Kessenich21472ae2016-06-04 11:46:33 -06003015 // Find something before the postfix operations, as they can't operate
3016 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07003017 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06003018 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003019 if (! acceptExpression(node)) {
3020 expected("expression");
3021 return false;
3022 }
3023 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003024 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003025 return false;
3026 }
John Kessenich34fb0362016-05-03 23:17:20 -06003027 } else if (acceptLiteral(node)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003028 // literal (nothing else to do yet)
John Kessenich34fb0362016-05-03 23:17:20 -06003029 } else if (acceptConstructor(node)) {
3030 // constructor (nothing else to do yet)
3031 } else if (acceptIdentifier(idToken)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003032 // user-type, namespace name, variable, or function name
3033 TString* fullName = idToken.string;
3034 while (acceptTokenClass(EHTokColonColon)) {
3035 // user-type or namespace name
3036 fullName = NewPoolTString(fullName->c_str());
3037 fullName->append(parseContext.scopeMangler);
3038 if (acceptIdentifier(idToken))
3039 fullName->append(*idToken.string);
3040 else {
3041 expected("identifier after ::");
John Kessenich54ee28f2017-03-11 14:13:00 -07003042 return false;
3043 }
John Kessenich8f9fdc92017-03-30 16:22:26 -06003044 }
3045 if (! peekTokenClass(EHTokLeftParen)) {
3046 node = parseContext.handleVariable(idToken.loc, fullName);
3047 } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) {
John Kessenich34fb0362016-05-03 23:17:20 -06003048 // function_call (nothing else to do yet)
3049 } else {
3050 expected("function call arguments");
3051 return false;
3052 }
John Kessenich21472ae2016-06-04 11:46:33 -06003053 } else {
3054 // nothing found, can't post operate
3055 return false;
John Kessenich87142c72016-03-12 20:24:24 -07003056 }
3057
John Kessenich21472ae2016-06-04 11:46:33 -06003058 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06003059 do {
3060 TSourceLoc loc = token.loc;
3061 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07003062
John Kessenich34fb0362016-05-03 23:17:20 -06003063 // Consume only a valid post-unary operator, otherwise we are done.
3064 switch (postOp) {
3065 case EOpIndexDirectStruct:
3066 case EOpIndexIndirect:
3067 case EOpPostIncrement:
3068 case EOpPostDecrement:
John Kessenich54ee28f2017-03-11 14:13:00 -07003069 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06003070 advanceToken();
3071 break;
3072 default:
3073 return true;
3074 }
John Kessenich87142c72016-03-12 20:24:24 -07003075
John Kessenich34fb0362016-05-03 23:17:20 -06003076 // We have a valid post-unary operator, process it.
3077 switch (postOp) {
John Kessenich54ee28f2017-03-11 14:13:00 -07003078 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06003079 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06003080 {
John Kessenich19b92ff2016-06-19 11:50:34 -06003081 // DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07003082 // includes swizzles, member variables, and member functions
John Kessenich93a162a2016-06-17 17:16:27 -06003083 HlslToken field;
3084 if (! acceptIdentifier(field)) {
3085 expected("swizzle or member");
3086 return false;
3087 }
LoopDawg4886f692016-06-29 10:58:58 -06003088
John Kessenich516d92d2017-03-08 20:09:03 -07003089 if (peekTokenClass(EHTokLeftParen)) {
3090 // member function
3091 TIntermTyped* thisNode = node;
LoopDawg4886f692016-06-29 10:58:58 -06003092
John Kessenich516d92d2017-03-08 20:09:03 -07003093 // arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06003094 if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) {
LoopDawg4886f692016-06-29 10:58:58 -06003095 expected("function parameters");
3096 return false;
3097 }
John Kessenich516d92d2017-03-08 20:09:03 -07003098 } else
3099 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06003100
John Kessenich34fb0362016-05-03 23:17:20 -06003101 break;
John Kessenich93a162a2016-06-17 17:16:27 -06003102 }
John Kessenich34fb0362016-05-03 23:17:20 -06003103 case EOpIndexIndirect:
3104 {
John Kessenich19b92ff2016-06-19 11:50:34 -06003105 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06003106 TIntermTyped* indexNode = nullptr;
3107 if (! acceptExpression(indexNode) ||
3108 ! peekTokenClass(EHTokRightBracket)) {
3109 expected("expression followed by ']'");
3110 return false;
3111 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003112 advanceToken();
3113 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
steve-lunarg2efd6c62017-04-06 20:22:20 -06003114 if (node == nullptr)
3115 return false;
John Kessenich19b92ff2016-06-19 11:50:34 -06003116 break;
John Kessenich34fb0362016-05-03 23:17:20 -06003117 }
3118 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06003119 // INC_OP
3120 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06003121 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06003122 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06003123 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06003124 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06003125 break;
3126 default:
3127 assert(0);
3128 break;
3129 }
3130 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07003131}
3132
John Kessenichd016be12016-03-13 11:24:20 -06003133// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06003134// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06003135//
3136bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
3137{
3138 // type
3139 TType type;
3140 if (acceptType(type)) {
John Kessenichc633f642017-04-03 21:48:37 -06003141 TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type);
John Kessenichd016be12016-03-13 11:24:20 -06003142 if (constructorFunction == nullptr)
3143 return false;
3144
3145 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06003146 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06003147 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07003148 // It's possible this is a type keyword used as an identifier. Put the token back
3149 // for later use.
3150 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06003151 return false;
3152 }
3153
3154 // hook it up
3155 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
3156
John Kessenichbb79abc2017-10-07 13:23:09 -06003157 return node != nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06003158 }
3159
3160 return false;
3161}
3162
John Kessenich34fb0362016-05-03 23:17:20 -06003163// The function_call identifier was already recognized, and passed in as idToken.
3164//
3165// function_call
3166// : [idToken] arguments
3167//
John Kessenich8f9fdc92017-03-30 16:22:26 -06003168bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject)
John Kessenich34fb0362016-05-03 23:17:20 -06003169{
John Kessenich54ee28f2017-03-11 14:13:00 -07003170 // name
3171 TString* functionName = nullptr;
John Kessenich8f9fdc92017-03-30 16:22:26 -06003172 if (baseObject == nullptr) {
3173 functionName = &name;
3174 } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) {
John Kessenich4960baa2017-03-19 18:09:59 -06003175 // Built-in methods are not in the symbol table as methods, but as global functions
3176 // taking an explicit 'this' as the first argument.
steve-lunarge7d07522017-03-19 18:12:37 -06003177 functionName = NewPoolTString(BUILTIN_PREFIX);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003178 functionName->append(name);
John Kessenich4960baa2017-03-19 18:09:59 -06003179 } else {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003180 if (! baseObject->getType().isStruct()) {
3181 expected("structure");
3182 return false;
3183 }
John Kessenich54ee28f2017-03-11 14:13:00 -07003184 functionName = NewPoolTString("");
John Kessenich8f9fdc92017-03-30 16:22:26 -06003185 functionName->append(baseObject->getType().getTypeName());
John Kessenichf3d88bd2017-03-19 12:24:29 -06003186 parseContext.addScopeMangler(*functionName);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003187 functionName->append(name);
John Kessenich5f12d2f2017-03-11 09:39:55 -07003188 }
LoopDawg4886f692016-06-29 10:58:58 -06003189
John Kessenich54ee28f2017-03-11 14:13:00 -07003190 // function
3191 TFunction* function = new TFunction(functionName, TType(EbtVoid));
3192
3193 // arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07003194 TIntermTyped* arguments = nullptr;
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003195 if (baseObject != nullptr) {
3196 // Non-static member functions have an implicit first argument of the base object.
John Kessenich54ee28f2017-03-11 14:13:00 -07003197 parseContext.handleFunctionArgument(function, arguments, baseObject);
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003198 }
John Kessenich4678ca92016-05-13 09:33:42 -06003199 if (! acceptArguments(function, arguments))
3200 return false;
3201
John Kessenich54ee28f2017-03-11 14:13:00 -07003202 // call
John Kessenich8f9fdc92017-03-30 16:22:26 -06003203 node = parseContext.handleFunctionCall(loc, function, arguments);
John Kessenich4678ca92016-05-13 09:33:42 -06003204
John Kessenichbb79abc2017-10-07 13:23:09 -06003205 return node != nullptr;
John Kessenich34fb0362016-05-03 23:17:20 -06003206}
3207
John Kessenich87142c72016-03-12 20:24:24 -07003208// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06003209// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003210//
John Kessenichd016be12016-03-13 11:24:20 -06003211// The arguments are pushed onto the 'function' argument list and
3212// onto the 'arguments' aggregate.
3213//
John Kessenich4678ca92016-05-13 09:33:42 -06003214bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07003215{
John Kessenich078d7f22016-03-14 10:02:11 -06003216 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003217 if (! acceptTokenClass(EHTokLeftParen))
3218 return false;
3219
John Kessenich2aa12b12017-04-18 14:47:33 -06003220 // RIGHT_PAREN
3221 if (acceptTokenClass(EHTokRightParen))
3222 return true;
3223
3224 // must now be at least one expression...
John Kessenich87142c72016-03-12 20:24:24 -07003225 do {
John Kessenichd016be12016-03-13 11:24:20 -06003226 // expression
John Kessenich87142c72016-03-12 20:24:24 -07003227 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06003228 if (! acceptAssignmentExpression(arg))
John Kessenich2aa12b12017-04-18 14:47:33 -06003229 return false;
John Kessenichd016be12016-03-13 11:24:20 -06003230
3231 // hook it up
3232 parseContext.handleFunctionArgument(function, arguments, arg);
3233
John Kessenich078d7f22016-03-14 10:02:11 -06003234 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07003235 if (! acceptTokenClass(EHTokComma))
3236 break;
3237 } while (true);
3238
John Kessenich078d7f22016-03-14 10:02:11 -06003239 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003240 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003241 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003242 return false;
3243 }
3244
3245 return true;
3246}
3247
3248bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
3249{
3250 switch (token.tokenClass) {
3251 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003252 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003253 break;
steve-lunarg2de32912016-07-28 14:49:48 -06003254 case EHTokUintConstant:
3255 node = intermediate.addConstantUnion(token.u, token.loc, true);
3256 break;
John Kessenich87142c72016-03-12 20:24:24 -07003257 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003258 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003259 break;
3260 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003261 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003262 break;
3263 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003264 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003265 break;
John Kessenich86f71382016-09-19 20:23:18 -06003266 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07003267 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06003268 break;
John Kessenich87142c72016-03-12 20:24:24 -07003269
3270 default:
3271 return false;
3272 }
3273
3274 advanceToken();
3275
3276 return true;
3277}
3278
John Kessenich0e071192017-06-06 11:37:33 -06003279// simple_statement
3280// : SEMICOLON
3281// | declaration_statement
3282// | expression SEMICOLON
3283//
3284bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement)
3285{
3286 // SEMICOLON
3287 if (acceptTokenClass(EHTokSemicolon))
3288 return true;
3289
3290 // declaration
3291 if (acceptDeclaration(statement))
3292 return true;
3293
3294 // expression
3295 TIntermTyped* node;
3296 if (acceptExpression(node))
3297 statement = node;
3298 else
3299 return false;
3300
3301 // SEMICOLON (following an expression)
3302 if (acceptTokenClass(EHTokSemicolon))
3303 return true;
3304 else {
3305 expected(";");
3306 return false;
3307 }
3308}
3309
John Kessenich5f934b02016-03-13 17:58:25 -06003310// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06003311// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003312//
John Kessenich21472ae2016-06-04 11:46:33 -06003313bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07003314{
John Kessenich21472ae2016-06-04 11:46:33 -06003315 TIntermAggregate* compoundStatement = nullptr;
3316
John Kessenich34fb0362016-05-03 23:17:20 -06003317 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003318 if (! acceptTokenClass(EHTokLeftBrace))
3319 return false;
3320
3321 // statement statement ...
3322 TIntermNode* statement = nullptr;
3323 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06003324 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
3325 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
3326 branch->getFlowOp() == EOpDefault)) {
3327 // hook up individual subsequences within a switch statement
3328 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
3329 compoundStatement = nullptr;
3330 } else {
3331 // hook it up to the growing compound statement
3332 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
3333 }
John Kessenich5f934b02016-03-13 17:58:25 -06003334 }
John Kessenich34fb0362016-05-03 23:17:20 -06003335 if (compoundStatement)
3336 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06003337
John Kessenich21472ae2016-06-04 11:46:33 -06003338 retStatement = compoundStatement;
3339
John Kessenich34fb0362016-05-03 23:17:20 -06003340 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003341 return acceptTokenClass(EHTokRightBrace);
3342}
3343
John Kessenich0d2b6de2016-06-05 11:23:11 -06003344bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
3345{
3346 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06003347 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003348 parseContext.popScope();
3349
3350 return result;
3351}
3352
John Kessenich077e0522016-06-09 02:02:17 -06003353bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003354{
John Kessenich077e0522016-06-09 02:02:17 -06003355 parseContext.pushScope();
3356 bool result = acceptCompoundStatement(statement);
3357 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06003358
3359 return result;
3360}
3361
John Kessenich5f934b02016-03-13 17:58:25 -06003362// statement
John Kessenich21472ae2016-06-04 11:46:33 -06003363// : attributes attributed_statement
3364//
3365// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003366// : compound_statement
John Kessenich0e071192017-06-06 11:37:33 -06003367// | simple_statement
John Kessenich21472ae2016-06-04 11:46:33 -06003368// | selection_statement
3369// | switch_statement
3370// | case_label
John Kessenich0e071192017-06-06 11:37:33 -06003371// | default_label
John Kessenich21472ae2016-06-04 11:46:33 -06003372// | iteration_statement
3373// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003374//
3375bool HlslGrammar::acceptStatement(TIntermNode*& statement)
3376{
John Kessenich21472ae2016-06-04 11:46:33 -06003377 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06003378
John Kessenich21472ae2016-06-04 11:46:33 -06003379 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06003380 TAttributeMap attributes;
3381 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003382
John Kessenich21472ae2016-06-04 11:46:33 -06003383 // attributed_statement
3384 switch (peek()) {
3385 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06003386 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06003387
John Kessenich21472ae2016-06-04 11:46:33 -06003388 case EHTokIf:
Rex Xu57e65922017-07-04 23:23:40 +08003389 return acceptSelectionStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003390
John Kessenich21472ae2016-06-04 11:46:33 -06003391 case EHTokSwitch:
Rex Xu57e65922017-07-04 23:23:40 +08003392 return acceptSwitchStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003393
John Kessenich21472ae2016-06-04 11:46:33 -06003394 case EHTokFor:
3395 case EHTokDo:
3396 case EHTokWhile:
steve-lunargf1709e72017-05-02 20:14:50 -06003397 return acceptIterationStatement(statement, attributes);
John Kessenich21472ae2016-06-04 11:46:33 -06003398
3399 case EHTokContinue:
3400 case EHTokBreak:
3401 case EHTokDiscard:
3402 case EHTokReturn:
3403 return acceptJumpStatement(statement);
3404
3405 case EHTokCase:
3406 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003407 case EHTokDefault:
3408 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003409
John Kessenich21472ae2016-06-04 11:46:33 -06003410 case EHTokRightBrace:
3411 // Performance: not strictly necessary, but stops a bunch of hunting early,
3412 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06003413 return false;
3414
John Kessenich21472ae2016-06-04 11:46:33 -06003415 default:
John Kessenich0e071192017-06-06 11:37:33 -06003416 return acceptSimpleStatement(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003417 }
3418
John Kessenich5f934b02016-03-13 17:58:25 -06003419 return true;
John Kessenich87142c72016-03-12 20:24:24 -07003420}
3421
John Kessenich21472ae2016-06-04 11:46:33 -06003422// attributes
John Kessenich77ea30b2017-09-30 14:34:50 -06003423// : [zero or more:] bracketed-attribute
3424//
3425// bracketed-attribute:
3426// : LEFT_BRACKET scoped-attribute RIGHT_BRACKET
3427// : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET
3428//
3429// scoped-attribute:
3430// : attribute
3431// | namespace COLON COLON attribute
John Kessenich21472ae2016-06-04 11:46:33 -06003432//
3433// attribute:
3434// : UNROLL
3435// | UNROLL LEFT_PAREN literal RIGHT_PAREN
3436// | FASTOPT
3437// | ALLOW_UAV_CONDITION
3438// | BRANCH
3439// | FLATTEN
3440// | FORCECASE
3441// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06003442// | DOMAIN
3443// | EARLYDEPTHSTENCIL
3444// | INSTANCE
3445// | MAXTESSFACTOR
3446// | OUTPUTCONTROLPOINTS
3447// | OUTPUTTOPOLOGY
3448// | PARTITIONING
3449// | PATCHCONSTANTFUNC
3450// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06003451//
steve-lunarg1868b142016-10-20 13:07:10 -06003452void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003453{
steve-lunarg1868b142016-10-20 13:07:10 -06003454 // For now, accept the [ XXX(X) ] syntax, but drop all but
3455 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06003456 // TODO: subset to correct set? Pass on?
3457 do {
John Kessenich77ea30b2017-09-30 14:34:50 -06003458 HlslToken attributeToken;
steve-lunarg1868b142016-10-20 13:07:10 -06003459
John Kessenich0d2b6de2016-06-05 11:23:11 -06003460 // LEFT_BRACKET?
3461 if (! acceptTokenClass(EHTokLeftBracket))
3462 return;
John Kessenich77ea30b2017-09-30 14:34:50 -06003463 // another LEFT_BRACKET?
3464 bool doubleBrackets = false;
3465 if (acceptTokenClass(EHTokLeftBracket))
3466 doubleBrackets = true;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003467
John Kessenich77ea30b2017-09-30 14:34:50 -06003468 // attribute? (could be namespace; will adjust later)
3469 if (!acceptIdentifier(attributeToken)) {
3470 if (!peekTokenClass(EHTokRightBracket)) {
3471 expected("namespace or attribute identifier");
3472 advanceToken();
3473 }
3474 }
3475
3476 TString nameSpace;
3477 if (acceptTokenClass(EHTokColonColon)) {
3478 // namespace COLON COLON
3479 nameSpace = *attributeToken.string;
3480 // attribute
3481 if (!acceptIdentifier(attributeToken)) {
3482 expected("attribute identifier");
3483 return;
3484 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003485 }
3486
steve-lunarga22f7db2016-11-11 08:17:44 -07003487 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06003488
3489 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003490 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07003491 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06003492
John Kessenich0d2b6de2016-06-05 11:23:11 -06003493 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07003494 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07003495
steve-lunarga22f7db2016-11-11 08:17:44 -07003496 while (acceptAssignmentExpression(node)) {
3497 expectingExpression = false;
3498 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06003499 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07003500 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06003501 }
3502
steve-lunarga22f7db2016-11-11 08:17:44 -07003503 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06003504 if (! acceptTokenClass(EHTokRightParen))
3505 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07003506
3507 // Error for partial or missing expression
3508 if (expectingExpression || expressions->getSequence().empty())
3509 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06003510 }
3511
3512 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06003513 if (!acceptTokenClass(EHTokRightBracket)) {
3514 expected("]");
3515 return;
3516 }
John Kessenich77ea30b2017-09-30 14:34:50 -06003517 // another RIGHT_BRACKET?
3518 if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) {
3519 expected("]]");
3520 return;
3521 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003522
steve-lunarg1868b142016-10-20 13:07:10 -06003523 // Add any values we found into the attribute map. This accepts
3524 // (and ignores) values not mapping to a known TAttributeType;
John Kessenich77ea30b2017-09-30 14:34:50 -06003525 attributes.setAttribute(nameSpace, attributeToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003526 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06003527}
3528
John Kessenich0d2b6de2016-06-05 11:23:11 -06003529// selection_statement
3530// : IF LEFT_PAREN expression RIGHT_PAREN statement
3531// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
3532//
Rex Xu57e65922017-07-04 23:23:40 +08003533bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003534{
John Kessenich0d2b6de2016-06-05 11:23:11 -06003535 TSourceLoc loc = token.loc;
3536
Rex Xu57e65922017-07-04 23:23:40 +08003537 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3538
John Kessenich0d2b6de2016-06-05 11:23:11 -06003539 // IF
3540 if (! acceptTokenClass(EHTokIf))
3541 return false;
3542
3543 // so that something declared in the condition is scoped to the lifetimes
3544 // of the then-else statements
3545 parseContext.pushScope();
3546
3547 // LEFT_PAREN expression RIGHT_PAREN
3548 TIntermTyped* condition;
3549 if (! acceptParenExpression(condition))
3550 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003551 condition = parseContext.convertConditionalExpression(loc, condition);
3552 if (condition == nullptr)
3553 return false;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003554
3555 // create the child statements
3556 TIntermNodePair thenElse = { nullptr, nullptr };
3557
John Kessenichf6deacd2017-06-06 19:52:55 -06003558 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
3559
John Kessenich0d2b6de2016-06-05 11:23:11 -06003560 // then statement
3561 if (! acceptScopedStatement(thenElse.node1)) {
3562 expected("then statement");
3563 return false;
3564 }
3565
3566 // ELSE
3567 if (acceptTokenClass(EHTokElse)) {
3568 // else statement
3569 if (! acceptScopedStatement(thenElse.node2)) {
3570 expected("else statement");
3571 return false;
3572 }
3573 }
3574
3575 // Put the pieces together
Rex Xu57e65922017-07-04 23:23:40 +08003576 statement = intermediate.addSelection(condition, thenElse, loc, control);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003577 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003578 --parseContext.controlFlowNestingLevel;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003579
3580 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003581}
3582
John Kessenichd02dc5d2016-07-01 00:04:11 -06003583// switch_statement
3584// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
3585//
Rex Xu57e65922017-07-04 23:23:40 +08003586bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003587{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003588 // SWITCH
3589 TSourceLoc loc = token.loc;
Rex Xu57e65922017-07-04 23:23:40 +08003590
3591 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3592
John Kessenichd02dc5d2016-07-01 00:04:11 -06003593 if (! acceptTokenClass(EHTokSwitch))
3594 return false;
3595
3596 // LEFT_PAREN expression RIGHT_PAREN
3597 parseContext.pushScope();
3598 TIntermTyped* switchExpression;
3599 if (! acceptParenExpression(switchExpression)) {
3600 parseContext.popScope();
3601 return false;
3602 }
3603
3604 // compound_statement
3605 parseContext.pushSwitchSequence(new TIntermSequence);
John Kessenichf6deacd2017-06-06 19:52:55 -06003606
3607 ++parseContext.controlFlowNestingLevel;
John Kessenichd02dc5d2016-07-01 00:04:11 -06003608 bool statementOkay = acceptCompoundStatement(statement);
John Kessenichf6deacd2017-06-06 19:52:55 -06003609 --parseContext.controlFlowNestingLevel;
3610
John Kessenichd02dc5d2016-07-01 00:04:11 -06003611 if (statementOkay)
Rex Xu57e65922017-07-04 23:23:40 +08003612 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, control);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003613
3614 parseContext.popSwitchSequence();
3615 parseContext.popScope();
3616
3617 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003618}
3619
John Kessenich119f8f62016-06-05 15:44:07 -06003620// iteration_statement
3621// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3622// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3623// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3624//
3625// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
steve-lunargf1709e72017-05-02 20:14:50 -06003626bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003627{
John Kessenich119f8f62016-06-05 15:44:07 -06003628 TSourceLoc loc = token.loc;
3629 TIntermTyped* condition = nullptr;
3630
3631 EHlslTokenClass loop = peek();
3632 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3633
3634 // WHILE or DO or FOR
3635 advanceToken();
steve-lunargf1709e72017-05-02 20:14:50 -06003636
3637 const TLoopControl control = parseContext.handleLoopControl(attributes);
John Kessenich119f8f62016-06-05 15:44:07 -06003638
3639 switch (loop) {
3640 case EHTokWhile:
3641 // so that something declared in the condition is scoped to the lifetime
3642 // of the while sub-statement
John Kessenichf6deacd2017-06-06 19:52:55 -06003643 parseContext.pushScope(); // this only needs to work right if no errors
John Kessenich119f8f62016-06-05 15:44:07 -06003644 parseContext.nestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003645 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003646
3647 // LEFT_PAREN condition RIGHT_PAREN
3648 if (! acceptParenExpression(condition))
3649 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003650 condition = parseContext.convertConditionalExpression(loc, condition);
3651 if (condition == nullptr)
3652 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003653
3654 // statement
3655 if (! acceptScopedStatement(statement)) {
3656 expected("while sub-statement");
3657 return false;
3658 }
3659
3660 parseContext.unnestLooping();
3661 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003662 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003663
steve-lunargf1709e72017-05-02 20:14:50 -06003664 statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003665
3666 return true;
3667
3668 case EHTokDo:
John Kessenichf6deacd2017-06-06 19:52:55 -06003669 parseContext.nestLooping(); // this only needs to work right if no errors
3670 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003671
John Kessenich119f8f62016-06-05 15:44:07 -06003672 // statement
John Kessenich0c6f9362017-04-20 11:08:24 -06003673 if (! acceptScopedStatement(statement)) {
John Kessenich119f8f62016-06-05 15:44:07 -06003674 expected("do sub-statement");
3675 return false;
3676 }
3677
John Kessenich119f8f62016-06-05 15:44:07 -06003678 // WHILE
3679 if (! acceptTokenClass(EHTokWhile)) {
3680 expected("while");
3681 return false;
3682 }
3683
3684 // LEFT_PAREN condition RIGHT_PAREN
John Kessenich119f8f62016-06-05 15:44:07 -06003685 if (! acceptParenExpression(condition))
3686 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003687 condition = parseContext.convertConditionalExpression(loc, condition);
3688 if (condition == nullptr)
3689 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003690
3691 if (! acceptTokenClass(EHTokSemicolon))
3692 expected(";");
3693
3694 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003695 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003696
steve-lunargf1709e72017-05-02 20:14:50 -06003697 statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003698
3699 return true;
3700
3701 case EHTokFor:
3702 {
3703 // LEFT_PAREN
3704 if (! acceptTokenClass(EHTokLeftParen))
3705 expected("(");
3706
3707 // so that something declared in the condition is scoped to the lifetime
3708 // of the for sub-statement
3709 parseContext.pushScope();
3710
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003711 // initializer
3712 TIntermNode* initNode = nullptr;
John Kessenich0e071192017-06-06 11:37:33 -06003713 if (! acceptSimpleStatement(initNode))
3714 expected("for-loop initializer statement");
John Kessenich119f8f62016-06-05 15:44:07 -06003715
John Kessenichf6deacd2017-06-06 19:52:55 -06003716 parseContext.nestLooping(); // this only needs to work right if no errors
3717 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003718
3719 // condition SEMI_COLON
3720 acceptExpression(condition);
3721 if (! acceptTokenClass(EHTokSemicolon))
3722 expected(";");
John Kessenich7e997e22017-03-30 22:09:30 -06003723 if (condition != nullptr) {
3724 condition = parseContext.convertConditionalExpression(loc, condition);
3725 if (condition == nullptr)
3726 return false;
3727 }
John Kessenich119f8f62016-06-05 15:44:07 -06003728
3729 // iterator SEMI_COLON
3730 TIntermTyped* iterator = nullptr;
3731 acceptExpression(iterator);
3732 if (! acceptTokenClass(EHTokRightParen))
3733 expected(")");
3734
3735 // statement
3736 if (! acceptScopedStatement(statement)) {
3737 expected("for sub-statement");
3738 return false;
3739 }
3740
steve-lunargf1709e72017-05-02 20:14:50 -06003741 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003742
3743 parseContext.popScope();
3744 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003745 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003746
3747 return true;
3748 }
3749
3750 default:
3751 return false;
3752 }
John Kessenich21472ae2016-06-04 11:46:33 -06003753}
3754
3755// jump_statement
3756// : CONTINUE SEMICOLON
3757// | BREAK SEMICOLON
3758// | DISCARD SEMICOLON
3759// | RETURN SEMICOLON
3760// | RETURN expression SEMICOLON
3761//
3762bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3763{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003764 EHlslTokenClass jump = peek();
3765 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003766 case EHTokContinue:
3767 case EHTokBreak:
3768 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003769 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003770 advanceToken();
3771 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003772 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003773 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003774 return false;
3775 }
John Kessenich21472ae2016-06-04 11:46:33 -06003776
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003777 switch (jump) {
3778 case EHTokContinue:
3779 statement = intermediate.addBranch(EOpContinue, token.loc);
3780 break;
3781 case EHTokBreak:
3782 statement = intermediate.addBranch(EOpBreak, token.loc);
3783 break;
3784 case EHTokDiscard:
3785 statement = intermediate.addBranch(EOpKill, token.loc);
3786 break;
3787
3788 case EHTokReturn:
3789 {
3790 // expression
3791 TIntermTyped* node;
3792 if (acceptExpression(node)) {
3793 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003794 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003795 } else
3796 statement = intermediate.addBranch(EOpReturn, token.loc);
3797 break;
3798 }
3799
3800 default:
3801 assert(0);
3802 return false;
3803 }
3804
3805 // SEMICOLON
3806 if (! acceptTokenClass(EHTokSemicolon))
3807 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003808
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003809 return true;
3810}
John Kessenich21472ae2016-06-04 11:46:33 -06003811
John Kessenichd02dc5d2016-07-01 00:04:11 -06003812// case_label
3813// : CASE expression COLON
3814//
John Kessenich21472ae2016-06-04 11:46:33 -06003815bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3816{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003817 TSourceLoc loc = token.loc;
3818 if (! acceptTokenClass(EHTokCase))
3819 return false;
3820
3821 TIntermTyped* expression;
3822 if (! acceptExpression(expression)) {
3823 expected("case expression");
3824 return false;
3825 }
3826
3827 if (! acceptTokenClass(EHTokColon)) {
3828 expected(":");
3829 return false;
3830 }
3831
3832 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3833
3834 return true;
3835}
3836
3837// default_label
3838// : DEFAULT COLON
3839//
3840bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3841{
3842 TSourceLoc loc = token.loc;
3843 if (! acceptTokenClass(EHTokDefault))
3844 return false;
3845
3846 if (! acceptTokenClass(EHTokColon)) {
3847 expected(":");
3848 return false;
3849 }
3850
3851 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3852
3853 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003854}
3855
John Kessenich19b92ff2016-06-19 11:50:34 -06003856// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003857// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3858// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003859//
3860void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3861{
3862 arraySizes = nullptr;
3863
steve-lunarg7b211a32016-10-13 12:26:18 -06003864 // Early-out if there aren't any array dimensions
3865 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003866 return;
3867
steve-lunarg7b211a32016-10-13 12:26:18 -06003868 // 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 -06003869 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003870
3871 // Collect each array dimension.
3872 while (acceptTokenClass(EHTokLeftBracket)) {
3873 TSourceLoc loc = token.loc;
3874 TIntermTyped* sizeExpr = nullptr;
3875
John Kessenich057df292017-03-06 18:18:37 -07003876 // Array sizing expression is optional. If omitted, array will be later sized by initializer list.
steve-lunarg7b211a32016-10-13 12:26:18 -06003877 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3878
3879 if (! acceptTokenClass(EHTokRightBracket)) {
3880 expected("]");
3881 return;
3882 }
3883
3884 if (hasArraySize) {
3885 TArraySize arraySize;
3886 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3887 arraySizes->addInnerSize(arraySize);
3888 } else {
3889 arraySizes->addInnerSize(0); // sized by initializers.
3890 }
steve-lunarg265c0612016-09-27 10:57:35 -06003891 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003892}
3893
John Kessenich630dd7d2016-06-12 23:52:12 -06003894// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003895// : COLON semantic // optional
3896// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3897// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003898// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003899// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003900//
John Kessenich854fe242017-03-02 14:30:59 -07003901// Return true if any tokens were accepted. That is,
3902// false can be returned on successfully recognizing nothing,
3903// not necessarily meaning bad syntax.
3904//
3905bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003906{
John Kessenich854fe242017-03-02 14:30:59 -07003907 bool found = false;
3908
John Kessenich630dd7d2016-06-12 23:52:12 -06003909 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003910 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003911 if (acceptTokenClass(EHTokColon)) {
John Kessenich854fe242017-03-02 14:30:59 -07003912 found = true;
John Kessenich630dd7d2016-06-12 23:52:12 -06003913 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003914 if (peekTokenClass(EHTokLayout))
3915 acceptLayoutQualifierList(qualifier);
3916 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003917 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003918 if (! acceptTokenClass(EHTokLeftParen)) {
3919 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003920 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003921 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003922 HlslToken locationToken;
3923 if (! acceptIdentifier(locationToken)) {
3924 expected("c[subcomponent][.component]");
John Kessenich854fe242017-03-02 14:30:59 -07003925 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003926 }
3927 HlslToken componentToken;
3928 if (acceptTokenClass(EHTokDot)) {
3929 if (! acceptIdentifier(componentToken)) {
3930 expected("component");
John Kessenich854fe242017-03-02 14:30:59 -07003931 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003932 }
3933 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003934 if (! acceptTokenClass(EHTokRightParen)) {
3935 expected(")");
3936 break;
3937 }
John Kessenich7735b942016-09-05 12:40:06 -06003938 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003939 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003940 expected("layout, semantic, packoffset, or register");
John Kessenich854fe242017-03-02 14:30:59 -07003941 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003942 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003943 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3944 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003945 if (! acceptTokenClass(EHTokLeftParen)) {
3946 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003947 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003948 }
John Kessenichb38f0712016-07-30 10:29:54 -06003949 HlslToken registerDesc; // for Type#
3950 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003951 if (! acceptIdentifier(registerDesc)) {
3952 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003953 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003954 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003955 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3956 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003957 // Then we didn't really see the registerDesc yet, it was
3958 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003959 profile = registerDesc;
3960 if (! acceptIdentifier(registerDesc)) {
3961 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003962 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003963 }
3964 }
John Kessenichb38f0712016-07-30 10:29:54 -06003965 int subComponent = 0;
3966 if (acceptTokenClass(EHTokLeftBracket)) {
3967 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3968 if (! peekTokenClass(EHTokIntConstant)) {
3969 expected("literal integer");
John Kessenich854fe242017-03-02 14:30:59 -07003970 return false;
John Kessenichb38f0712016-07-30 10:29:54 -06003971 }
3972 subComponent = token.i;
3973 advanceToken();
3974 if (! acceptTokenClass(EHTokRightBracket)) {
3975 expected("]");
3976 break;
3977 }
3978 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003979 // (COMMA SPACEN)opt
3980 HlslToken spaceDesc;
3981 if (acceptTokenClass(EHTokComma)) {
3982 if (! acceptIdentifier(spaceDesc)) {
3983 expected ("space identifier");
John Kessenich854fe242017-03-02 14:30:59 -07003984 return false;
John Kessenichcfd7ce82016-09-05 16:03:12 -06003985 }
3986 }
3987 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003988 if (! acceptTokenClass(EHTokRightParen)) {
3989 expected(")");
3990 break;
3991 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003992 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003993 } else {
3994 // semantic, in idToken.string
John Kessenich2dd643f2017-03-14 21:50:06 -06003995 TString semanticUpperCase = *idToken.string;
3996 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
3997 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
John Kessenich630dd7d2016-06-12 23:52:12 -06003998 }
John Kessenich854fe242017-03-02 14:30:59 -07003999 } else if (peekTokenClass(EHTokLeftAngle)) {
4000 found = true;
John Kessenicha1e2d492016-09-20 13:22:58 -06004001 acceptAnnotations(qualifier);
John Kessenich854fe242017-03-02 14:30:59 -07004002 } else
John Kessenich630dd7d2016-06-12 23:52:12 -06004003 break;
John Kessenich078d7f22016-03-14 10:02:11 -06004004
John Kessenich630dd7d2016-06-12 23:52:12 -06004005 } while (true);
John Kessenich854fe242017-03-02 14:30:59 -07004006
4007 return found;
John Kessenich078d7f22016-03-14 10:02:11 -06004008}
4009
John Kessenichb16f7e62017-03-11 19:32:47 -07004010//
4011// Get the stream of tokens from the scanner, but skip all syntactic/semantic
4012// processing.
4013//
4014bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
4015{
4016 if (! peekTokenClass(EHTokLeftBrace))
4017 return false;
4018
4019 int braceCount = 0;
4020
4021 do {
4022 switch (peek()) {
4023 case EHTokLeftBrace:
4024 ++braceCount;
4025 break;
4026 case EHTokRightBrace:
4027 --braceCount;
4028 break;
4029 case EHTokNone:
4030 // End of input before balance { } is bad...
4031 return false;
4032 default:
4033 break;
4034 }
4035
4036 tokens.push_back(token);
4037 advanceToken();
4038 } while (braceCount > 0);
4039
4040 return true;
4041}
4042
John Kessenich0320d092017-06-13 22:22:52 -06004043// Return a string for just the types that can also be declared as an identifier.
4044const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const
4045{
4046 switch (tokenClass) {
4047 case EHTokSample: return "sample";
4048 case EHTokHalf: return "half";
4049 case EHTokHalf1x1: return "half1x1";
4050 case EHTokHalf1x2: return "half1x2";
4051 case EHTokHalf1x3: return "half1x3";
4052 case EHTokHalf1x4: return "half1x4";
4053 case EHTokHalf2x1: return "half2x1";
4054 case EHTokHalf2x2: return "half2x2";
4055 case EHTokHalf2x3: return "half2x3";
4056 case EHTokHalf2x4: return "half2x4";
4057 case EHTokHalf3x1: return "half3x1";
4058 case EHTokHalf3x2: return "half3x2";
4059 case EHTokHalf3x3: return "half3x3";
4060 case EHTokHalf3x4: return "half3x4";
4061 case EHTokHalf4x1: return "half4x1";
4062 case EHTokHalf4x2: return "half4x2";
4063 case EHTokHalf4x3: return "half4x3";
4064 case EHTokHalf4x4: return "half4x4";
4065 case EHTokBool: return "bool";
4066 case EHTokFloat: return "float";
4067 case EHTokDouble: return "double";
4068 case EHTokInt: return "int";
4069 case EHTokUint: return "uint";
4070 case EHTokMin16float: return "min16float";
4071 case EHTokMin10float: return "min10float";
4072 case EHTokMin16int: return "min16int";
4073 case EHTokMin12int: return "min12int";
LoopDawg7ee29ba2017-11-27 14:45:36 -07004074 case EHTokConstantBuffer: return "ConstantBuffer";
John Kessenich0320d092017-06-13 22:22:52 -06004075 default:
4076 return nullptr;
4077 }
4078}
4079
John Kesseniche01a9bc2016-03-12 20:11:22 -07004080} // end namespace glslang