blob: 4b5c0b75f004555b461c357063fdc928ac4370fa [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 3Dlabs Inc. Ltd. 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#ifndef HLSL_PARSE_INCLUDED_
37#define HLSL_PARSE_INCLUDED_
38
39#include "../glslang/MachineIndependent/parseVersions.h"
40#include "../glslang/MachineIndependent/ParseHelper.h"
41
42namespace glslang {
43
steve-lunarg1868b142016-10-20 13:07:10 -060044class TAttributeMap; // forward declare
45
John Kesseniche01a9bc2016-03-12 20:11:22 -070046class HlslParseContext : public TParseContextBase {
47public:
48 HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins,
John Kessenichb901ade2016-06-16 20:59:42 -060049 int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
steve-lunargf1e0c872016-10-31 15:13:43 -060050 const TString sourceEntryPointName,
John Kesseniche01a9bc2016-03-12 20:11:22 -070051 bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
52 virtual ~HlslParseContext();
Henrik Rydgård9a931b32016-12-21 12:48:08 +010053 void initializeExtensionBehavior() override;
LoopDawg62561462016-07-22 20:46:03 -060054
Henrik Rydgård9a931b32016-12-21 12:48:08 +010055 void setLimits(const TBuiltInResource&) override;
56 bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
John Kessenich000c8182017-03-22 23:21:34 -060057 virtual const char* getGlobalUniformBlockName() const override { return "$Global"; }
58 virtual void setUniformBlockDefaults(TType& block) const override
59 {
60 block.getQualifier().layoutPacking = ElpStd140;
61 block.getQualifier().layoutMatrix = ElmRowMajor;
62 }
John Kesseniche01a9bc2016-03-12 20:11:22 -070063
Henrik Rydgård9a931b32016-12-21 12:48:08 +010064 void reservedPpErrorCheck(const TSourceLoc&, const char* /*name*/, const char* /*op*/) override { }
65 bool lineContinuationCheck(const TSourceLoc&, bool /*endOfComment*/) override { return true; }
66 bool lineDirectiveShouldSetNextLine() const override { return true; }
John Kesseniche01a9bc2016-03-12 20:11:22 -070067 bool builtInName(const TString&);
68
Henrik Rydgård9a931b32016-12-21 12:48:08 +010069 void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
John Kessenichf4ba25e2017-03-21 18:35:04 -060070 TIntermTyped* handleVariable(const TSourceLoc&, const TString* string);
John Kesseniche01a9bc2016-03-12 20:11:22 -070071 TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
steve-lunarg6b43d272016-10-06 20:12:24 -060072 TIntermTyped* handleBracketOperator(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
John Kesseniche01a9bc2016-03-12 20:11:22 -070073 void checkIndex(const TSourceLoc&, const TType&, int& index);
74
John Kesseniche01a9bc2016-03-12 20:11:22 -070075 TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
76 TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
77 TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
John Kessenich5f12d2f2017-03-11 09:39:55 -070078 bool isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field);
John Kessenich7dc630f2016-09-16 01:44:43 -060079 void assignLocations(TVariable& variable);
John Kessenich088d52b2017-03-11 17:55:28 -070080 void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
John Kessenich02467d82017-01-19 15:41:47 -070081 TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree);
82 TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&);
steve-lunarge7412492017-03-23 11:56:07 -060083 void handleEntryPointAttributes(const TSourceLoc&, const TAttributeMap&);
John Kessenicha3051662016-09-02 19:13:36 -060084 void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node);
John Kessenich727b3742017-02-03 17:57:55 -070085 void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs);
John Kessenich6fccb3c2016-09-19 16:01:41 -060086 void remapNonEntryPointIO(TFunction& function);
steve-lunargc4a13072016-08-09 11:28:03 -060087 TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
John Kessenich4678ca92016-05-13 09:33:42 -060088 void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg);
John Kessenichfdf63472017-01-13 12:27:52 -070089 TIntermTyped* handleAssign(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
90 TIntermTyped* handleAssignToMatrixSwizzle(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
steve-lunarg26d31452016-12-23 18:56:57 -070091 TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*);
LoopDawg592860c2016-06-09 08:57:35 -060092 void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
LoopDawg4886f692016-06-29 10:58:58 -060093 void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
steve-lunarg5da1f032017-02-12 17:50:28 -070094 void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
steve-lunargf49cdf42016-11-17 15:04:20 -070095 void decomposeGeometryMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
steve-lunarg26d31452016-12-23 18:56:57 -070096 void addInputArgumentConversions(const TFunction&, TIntermTyped*&);
steve-lunargef33ec02016-11-02 12:42:34 -060097 TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&);
John Kesseniche01a9bc2016-03-12 20:11:22 -070098 void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
John Kessenichc633f642017-04-03 21:48:37 -060099 TFunction* makeConstructorCall(const TSourceLoc&, const TType&);
John Kessenich2dd643f2017-03-14 21:50:06 -0600100 void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable, const TString& upperCase);
John Kessenich7735b942016-09-05 12:40:06 -0600101 void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location,
John Kessenichb38f0712016-07-30 10:29:54 -0600102 const glslang::TString* component);
John Kessenich7735b942016-09-05 12:40:06 -0600103 void handleRegister(const TSourceLoc&, TQualifier&, const glslang::TString* profile, const glslang::TString& desc,
John Kessenichcfd7ce82016-09-05 16:03:12 -0600104 int subComponent, const glslang::TString*);
John Kessenich636b62d2017-04-11 19:45:00 -0600105 TIntermTyped* convertConditionalExpression(const TSourceLoc&, TIntermTyped*, bool mustBeScalar = true);
LoopDawga2b79912016-07-14 14:45:14 -0600106 TIntermAggregate* handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, TIntermTyped* argSampler);
107
John Kessenichc142c882017-01-13 19:34:22 -0700108 bool parseMatrixSwizzleSelector(const TSourceLoc&, const TString&, int cols, int rows, TSwizzleSelectors<TMatrixSelector>&);
109 int getMatrixComponentsColumn(int rows, const TSwizzleSelectors<TMatrixSelector>&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700110 void assignError(const TSourceLoc&, const char* op, TString left, TString right);
111 void unaryOpError(const TSourceLoc&, const char* op, TString operand);
112 void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
113 void variableCheck(TIntermTyped*& nodePtr);
114 void constantValueCheck(TIntermTyped* node, const char* token);
115 void integerCheck(const TIntermTyped* node, const char* token);
116 void globalCheck(const TSourceLoc&, const char* token);
117 bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
118 bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
119 void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&);
120 void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
121 void structArrayCheck(const TSourceLoc&, const TType& structure);
122 void arrayDimMerge(TType& type, const TArraySizes* sizes);
123 bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700124 void globalQualifierFix(const TSourceLoc&, TQualifier&);
125 bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
John Kessenich34e7ee72016-09-16 17:10:39 -0600126 void mergeQualifiers(TQualifier& dst, const TQualifier& src);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700127 int computeSamplerTypeIndex(TSampler&);
John Kessenichd3f11222016-11-05 10:15:53 -0600128 TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700129 void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
John Kessenich5aa59e22016-06-17 15:50:47 -0600130 void paramFix(TType& type);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700131 void specializationCheck(const TSourceLoc&, const TType&, const char* op);
132
John Kessenichb9e39122016-08-17 10:22:08 -0600133 void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&);
134 void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&, const TIntermTyped*);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700135 void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
136 void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
137
steve-lunarg26d31452016-12-23 18:56:57 -0700138 const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, TIntermTyped*& args);
John Kessenich4dc835c2017-03-28 23:43:10 -0600139 void declareTypedef(const TSourceLoc&, const TString& identifier, const TType&);
John Kessenich727b3742017-02-03 17:57:55 -0700140 void declareStruct(const TSourceLoc&, TString& structName, TType&);
John Kessenich854fe242017-03-02 14:30:59 -0700141 TSymbol* lookupUserType(const TString&, TType&);
John Kessenich4dc835c2017-03-28 23:43:10 -0600142 TIntermNode* declareVariable(const TSourceLoc&, const TString& identifier, TType&, TIntermTyped* initializer = 0);
John Kessenich82460b52017-04-04 11:47:42 -0600143 void lengthenList(const TSourceLoc&, TIntermSequence& list, int size, TIntermTyped* scalarInit);
John Kessenichc633f642017-04-03 21:48:37 -0600144 TIntermTyped* handleConstructor(const TSourceLoc&, TIntermTyped*, const TType&);
145 TIntermTyped* addConstructor(const TSourceLoc&, TIntermTyped*, const TType&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700146 TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
147 TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
John Kessenich3d157c52016-07-25 16:05:33 -0600148 void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600149 void declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700150 void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
151 void fixBlockXfbOffsets(TQualifier&, TTypeList&);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600152 void fixBlockUniformOffsets(const TQualifier&, TTypeList&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700153 void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
154 void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
155 void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
156 void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
157 TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
158
159 void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
160
John Kessenicha1e2d492016-09-20 13:22:58 -0600161 void nestLooping() { ++loopNestingLevel; }
162 void unnestLooping() { --loopNestingLevel; }
163 void nestAnnotations() { ++annotationNestingLevel; }
164 void unnestAnnotations() { --annotationNestingLevel; }
John Kessenich6dbc0a72016-09-27 19:13:05 -0600165 int getAnnotationNestingLevel() { return annotationNestingLevel; }
John Kessenicha1e2d492016-09-20 13:22:58 -0600166 void pushScope() { symbolTable.push(); }
167 void popScope() { symbolTable.pop(0); }
John Kessenich0d2b6de2016-06-05 11:23:11 -0600168
John Kessenich37789792017-03-21 23:56:40 -0600169 void pushThisScope(const TType&);
170 void popThisScope() { symbolTable.pop(0); }
171
172 void pushImplicitThis(TVariable* thisParameter) { implicitThisStack.push_back(thisParameter); }
173 void popImplicitThis() { implicitThisStack.pop_back(); }
174 TVariable* getImplicitThis(int thisDepth) const { return implicitThisStack[implicitThisStack.size() - thisDepth]; }
175
John Kessenichf3d88bd2017-03-19 12:24:29 -0600176 void pushNamespace(const TString& name);
177 void popNamespace();
John Kessenich4dc835c2017-03-28 23:43:10 -0600178 void getFullNamespaceName(const TString*&) const;
John Kessenichf3d88bd2017-03-19 12:24:29 -0600179 void addScopeMangler(TString&);
John Kessenich54ee28f2017-03-11 14:13:00 -0700180
John Kessenichd02dc5d2016-07-01 00:04:11 -0600181 void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); }
182 void popSwitchSequence() { switchSequenceStack.pop_back(); }
183
John Kessenich4dc835c2017-03-28 23:43:10 -0600184 virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
John Kessenich88c44642017-02-03 14:06:36 -0700185
steve-lunarg90707962016-10-07 19:35:40 -0600186 // Apply L-value conversions. E.g, turning a write to a RWTexture into an ImageStore.
187 TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped* node);
steve-lunarg0de16da2016-10-08 10:54:52 -0600188 bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
steve-lunarg90707962016-10-07 19:35:40 -0600189
steve-lunarg4f2da272016-10-10 15:24:57 -0600190 TLayoutFormat getLayoutFromTxType(const TSourceLoc&, const TType&);
191
steve-lunargf49cdf42016-11-17 15:04:20 -0700192 bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
193 bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
194
steve-lunargf1709e72017-05-02 20:14:50 -0600195 // Determine loop control from attributes
196 TLoopControl handleLoopControl(const TAttributeMap& attributes) const;
197
steve-lunargf1e0c872016-10-31 15:13:43 -0600198 // Potentially rename shader entry point function
John Kessenich4dc835c2017-03-28 23:43:10 -0600199 void renameShaderFunction(const TString*& name) const;
steve-lunargf1e0c872016-10-31 15:13:43 -0600200
steve-lunarga2b01a02016-11-28 17:09:54 -0700201 // Reset data for incrementally built referencing of flattened composite structures
202 void initFlattening() { flattenLevel.push_back(0); flattenOffset.push_back(0); }
203 void finalizeFlattening() { flattenLevel.pop_back(); flattenOffset.pop_back(); }
204
steve-lunargdd8287a2017-02-23 18:04:12 -0700205 // Share struct buffer deep types
206 void shareStructBufferType(TType&);
207
John Kesseniche01a9bc2016-03-12 20:11:22 -0700208protected:
steve-lunarga2b01a02016-11-28 17:09:54 -0700209 struct TFlattenData {
210 TFlattenData() : nextBinding(TQualifier::layoutBindingEnd) { }
211 TFlattenData(int nb) : nextBinding(nb) { }
212
213 TVector<TVariable*> members; // individual flattened variables
214 TVector<int> offsets; // offset to next tree level
215 int nextBinding; // next binding to use.
216 };
217
John Kessenich4dc835c2017-03-28 23:43:10 -0600218 void fixConstInit(const TSourceLoc&, const TString& identifier, TType& type, TIntermTyped*& initializer);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700219 void inheritGlobalDefaults(TQualifier& dst) const;
220 TVariable* makeInternalVariable(const char* name, const TType&) const;
steve-lunarga2e75312016-12-14 15:22:25 -0700221 TVariable* makeInternalVariable(const TString& name, const TType& type) const {
222 return makeInternalVariable(name.c_str(), type);
223 }
John Kessenich82460b52017-04-04 11:47:42 -0600224 TIntermSymbol* makeInternalVariableNode(const TSourceLoc&, const char* name, const TType&) const;
John Kessenich4dc835c2017-03-28 23:43:10 -0600225 TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&, bool track);
226 void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&, bool track);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700227 TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
John Kessenich82460b52017-04-04 11:47:42 -0600228 TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit);
229 bool isScalarConstructor(const TIntermNode*);
LoopDawg58910702016-06-13 09:22:28 -0600230 TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700231
steve-lunarg90707962016-10-07 19:35:40 -0600232 // Return true if this node requires L-value conversion (e.g, to an imageStore).
233 bool shouldConvertLValue(const TIntermNode*) const;
234
steve-lunarge0b9deb2016-09-16 13:26:37 -0600235 // Array and struct flattening
steve-lunarga2e75312016-12-14 15:22:25 -0700236 TIntermTyped* flattenAccess(TIntermTyped* base, int member);
steve-lunarge0b9deb2016-09-16 13:26:37 -0600237 bool shouldFlattenUniform(const TType&) const;
steve-lunarga2b01a02016-11-28 17:09:54 -0700238 bool wasFlattened(const TIntermTyped* node) const;
239 bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); }
240 int addFlattenedMember(const TSourceLoc& loc, const TVariable&, const TType&, TFlattenData&, const TString& name, bool track);
241 bool isFinalFlattening(const TType& type) const { return !(type.isStruct() || type.isArray()); }
242
steve-lunarga2e75312016-12-14 15:22:25 -0700243 // Structure splitting (splits interstage builtin types into its own struct)
steve-lunarg132d3312016-12-19 15:48:01 -0700244 TIntermTyped* splitAccessStruct(const TSourceLoc& loc, TIntermTyped*& base, int& member);
245 void splitAccessArray(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index);
246 TType& split(TType& type, TString name, const TType* outerStructType = nullptr);
steve-lunarga2e75312016-12-14 15:22:25 -0700247 void split(TIntermTyped*);
248 void split(const TVariable&);
249 bool wasSplit(const TIntermTyped* node) const;
250 bool wasSplit(int id) const { return splitIoVars.find(id) != splitIoVars.end(); }
251 TVariable* getSplitIoVar(const TIntermTyped* node) const;
252 TVariable* getSplitIoVar(const TVariable* var) const;
253 TVariable* getSplitIoVar(int id) const;
254 void addInterstageIoToLinkage();
steve-lunarg858c9282017-01-07 08:54:10 -0700255 void addPatchConstantInvocation();
steve-lunargf8203a02017-04-20 09:00:56 -0600256 TIntermTyped* makeIntegerIndex(TIntermTyped*);
steve-lunarga2e75312016-12-14 15:22:25 -0700257
steve-lunargccb076a2017-04-05 11:03:02 -0600258 void fixBuiltInIoType(TType&);
steve-lunarg194f0f32017-03-17 18:51:05 -0600259
steve-lunarge0b9deb2016-09-16 13:26:37 -0600260 void flatten(const TSourceLoc& loc, const TVariable& variable);
steve-lunarga2b01a02016-11-28 17:09:54 -0700261 int flatten(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
262 int flattenStruct(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
263 int flattenArray(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
steve-lunarge0b9deb2016-09-16 13:26:37 -0600264
John Kessenichbf472862017-02-05 20:27:30 -0700265 bool hasUniform(const TQualifier& qualifier) const;
266 void clearUniform(TQualifier& qualifier);
267 bool isInputBuiltIn(const TQualifier& qualifier) const;
268 bool hasInput(const TQualifier& qualifier) const;
269 void correctOutput(TQualifier& qualifier);
270 bool isOutputBuiltIn(const TQualifier& qualifier) const;
271 bool hasOutput(const TQualifier& qualifier) const;
272 void correctInput(TQualifier& qualifier);
273 void correctUniform(TQualifier& qualifier);
274 void clearUniformInputOutput(TQualifier& qualifier);
275
steve-lunarg5da1f032017-02-12 17:50:28 -0700276 // Test method names
steve-lunarg5da1f032017-02-12 17:50:28 -0700277 bool isStructBufferMethod(const TString& name) const;
278
steve-lunargd4d0b292017-04-26 08:31:56 -0600279 // Return standard sample position array
280 TIntermConstantUnion* getSamplePosArray(int count);
281
steve-lunargdd8287a2017-02-23 18:04:12 -0700282 TType* getStructBufferContentType(const TType& type) const;
283 bool isStructBufferType(const TType& type) const { return getStructBufferContentType(type) != nullptr; }
284 TIntermTyped* indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const;
steve-lunarg8e26feb2017-04-10 08:19:21 -0600285 TIntermTyped* getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer);
steve-lunargdd8287a2017-02-23 18:04:12 -0700286
287 // Return true if this type is a reference. This is not currently a type method in case that's
288 // a language specific answer.
289 bool isReference(const TType& type) const { return isStructBufferType(type); }
290
steve-lunarg8e26feb2017-04-10 08:19:21 -0600291 // Return true if this a buffer type that has an associated counter buffer.
292 bool hasStructBuffCounter(const TString& name) const;
293
294 // Finalization step: remove unused buffer blocks from linkage (we don't know until the
295 // shader is entirely compiled)
296 void removeUnusedStructBufferCounters();
297
steve-lunarg858c9282017-01-07 08:54:10 -0700298 // Pass through to base class after remembering builtin mappings.
299 using TParseContextBase::trackLinkage;
300 void trackLinkage(TSymbol& variable) override;
301
Alex Szpakowski7d39ad52017-01-08 17:54:48 -0400302 void finish() override; // post-processing
steve-lunarga2e75312016-12-14 15:22:25 -0700303
steve-lunarge752f462017-03-22 18:39:25 -0600304 // Linkage symbol helpers
305 TIntermSymbol* findLinkageSymbol(TBuiltInVariable biType) const;
306
John Kesseniche01a9bc2016-03-12 20:11:22 -0700307 // Current state of parsing
308 struct TPragma contextPragma;
309 int loopNestingLevel; // 0 if outside all loops
John Kessenicha1e2d492016-09-20 13:22:58 -0600310 int annotationNestingLevel; // 0 if outside all annotations
John Kesseniche01a9bc2016-03-12 20:11:22 -0700311 int structNestingLevel; // 0 if outside blocks and structures
312 int controlFlowNestingLevel; // 0 if outside all flow control
John Kesseniche01a9bc2016-03-12 20:11:22 -0700313 TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
John Kessenich517fe7a2016-11-26 13:31:47 -0700314 bool postEntryPointReturn; // if inside a function, true if the function is the entry point and this is after a return statement
John Kesseniche01a9bc2016-03-12 20:11:22 -0700315 const TType* currentFunctionType; // the return type of the function that's currently being parsed
316 bool functionReturnsValue; // true if a non-void function has a return
John Kesseniche01a9bc2016-03-12 20:11:22 -0700317 TBuiltInResource resources;
318 TLimits& limits;
319
320 HlslParseContext(HlslParseContext&);
321 HlslParseContext& operator=(HlslParseContext&);
322
John Kesseniche01a9bc2016-03-12 20:11:22 -0700323 static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2)); // see computeSamplerTypeIndex()
John Kesseniche01a9bc2016-03-12 20:11:22 -0700324 TQualifier globalBufferDefaults;
325 TQualifier globalUniformDefaults;
326 TQualifier globalInputDefaults;
327 TQualifier globalOutputDefaults;
328 TString currentCaller; // name of last function body entered (not valid when at global scope)
329 TIdSetType inductiveLoopIds;
330 TVector<TIntermTyped*> needsIndexLimitationChecking;
John Kesseniche01a9bc2016-03-12 20:11:22 -0700331
332 //
333 // Geometry shader input arrays:
334 // - array sizing is based on input primitive and/or explicit size
335 //
336 // Tessellation control output arrays:
337 // - array sizing is based on output layout(vertices=...) and/or explicit size
338 //
339 // Both:
340 // - array sizing is retroactive
341 // - built-in block redeclarations interact with this
342 //
343 // Design:
344 // - use a per-context "resize-list", a list of symbols whose array sizes
345 // can be fixed
346 //
347 // - the resize-list starts empty at beginning of user-shader compilation, it does
348 // not have built-ins in it
349 //
350 // - on built-in array use: copyUp() symbol and add it to the resize-list
351 //
352 // - on user array declaration: add it to the resize-list
353 //
354 // - on block redeclaration: copyUp() symbol and add it to the resize-list
355 // * note, that appropriately gives an error if redeclaring a block that
356 // was already used and hence already copied-up
357 //
John Kessenichecba76f2017-01-06 00:34:48 -0700358 // - on seeing a layout declaration that sizes the array, fix everything in the
John Kesseniche01a9bc2016-03-12 20:11:22 -0700359 // resize-list, giving errors for mismatch
360 //
361 // - on seeing an array size declaration, give errors on mismatch between it and previous
362 // array-sizing declarations
363 //
364 TVector<TSymbol*> ioArraySymbolResizeList;
John Kessenichcd0a78a2016-09-09 16:32:09 -0600365
steve-lunarga2b01a02016-11-28 17:09:54 -0700366 TMap<int, TFlattenData> flattenMap;
367 TVector<int> flattenLevel; // nested postfix operator level for flattening
368 TVector<int> flattenOffset; // cumulative offset for flattening
369
John Kessenichbf472862017-02-05 20:27:30 -0700370 // IO-type map. Maps a pure symbol-table form of a structure-member list into
371 // each of the (up to) three kinds of IO, as each as different allowed decorations,
372 // but HLSL allows mixing all in the same structure.
373 struct tIoKinds {
374 TTypeList* input;
375 TTypeList* output;
376 TTypeList* uniform;
377 };
378 TMap<const TTypeList*, tIoKinds> ioTypeMap;
steve-lunarga2e75312016-12-14 15:22:25 -0700379
380 // Structure splitting data:
steve-lunarg132d3312016-12-19 15:48:01 -0700381 TMap<int, TVariable*> splitIoVars; // variables with the builtin interstage IO removed, indexed by unique ID.
382
steve-lunargdd8287a2017-02-23 18:04:12 -0700383 // Structuredbuffer shared types. Typically there are only a few.
384 TVector<TType*> structBufferTypes;
steve-lunarg8e26feb2017-04-10 08:19:21 -0600385
386 TMap<TString, TBuiltInVariable> structBufferBuiltIn;
387 TMap<TString, bool> structBufferCounter;
steve-lunargdd8287a2017-02-23 18:04:12 -0700388
steve-lunarg132d3312016-12-19 15:48:01 -0700389 // The builtin interstage IO map considers e.g, EvqPosition on input and output separately, so that we
390 // can build the linkage correctly if position appears on both sides. Otherwise, multiple positions
391 // are considered identical.
392 struct tInterstageIoData {
steve-lunarg858c9282017-01-07 08:54:10 -0700393 tInterstageIoData(TBuiltInVariable bi, TStorageQualifier q) :
394 builtIn(bi), storage(q) { }
395
steve-lunarg132d3312016-12-19 15:48:01 -0700396 tInterstageIoData(const TType& memberType, const TType& storageType) :
397 builtIn(memberType.getQualifier().builtIn),
398 storage(storageType.getQualifier().storage) { }
399
400 TBuiltInVariable builtIn;
401 TStorageQualifier storage;
402
403 // ordering for maps
404 bool operator<(const tInterstageIoData d) const {
405 return (builtIn != d.builtIn) ? (builtIn < d.builtIn) : (storage < d.storage);
406 }
407 };
408
John Kessenichbf472862017-02-05 20:27:30 -0700409 TMap<tInterstageIoData, TVariable*> interstageBuiltInIo; // individual builtin interstage IO vars, indexed by builtin type.
steve-lunarg067eb9b2017-04-01 15:34:48 -0600410 TVariable* inputPatch;
steve-lunarg132d3312016-12-19 15:48:01 -0700411
412 // We have to move array references to structs containing builtin interstage IO to the split variables.
413 // This is only handled for one level. This stores the index, because we'll need it in the future, since
414 // unlike normal array references, here the index happens before we discover what it applies to.
415 TIntermTyped* builtInIoIndex;
416 TIntermTyped* builtInIoBase;
steve-lunarga2e75312016-12-14 15:22:25 -0700417
John Kessenich7dc630f2016-09-16 01:44:43 -0600418 unsigned int nextInLocation;
419 unsigned int nextOutLocation;
steve-lunargf1e0c872016-10-31 15:13:43 -0600420
steve-lunarg858c9282017-01-07 08:54:10 -0700421 TString sourceEntryPointName;
422 TFunction* entryPointFunction;
423 TIntermNode* entryPointFunctionBody;
424
425 TString patchConstantFunctionName; // hull shader patch constant function name, from function level attribute.
426 TMap<TBuiltInVariable, TSymbol*> builtInLinkageSymbols; // used for tessellation, finding declared builtins
427
John Kessenich37789792017-03-21 23:56:40 -0600428 TVector<TString> currentTypePrefix; // current scoping prefix for nested structures
429 TVector<TVariable*> implicitThisStack; // currently active 'this' variables for nested structures
steve-lunarg08e0c082017-03-29 20:01:13 -0600430
431 TVariable* gsStreamOutput; // geometry shader stream outputs, for emit (Append method)
LoopDawg726bf962017-05-12 17:14:31 -0600432
433 // This tracks the first (mip level) argument to the .mips[][] operator. Since this can be nested as
434 // in tx.mips[tx.mips[0][1].x][2], we need a stack. We also track the TSourceLoc for error reporting
435 // purposes.
436 struct tMipsOperatorData {
437 tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { }
438 TSourceLoc loc;
439 TIntermTyped* mipLevel;
440 };
441
442 TVector<tMipsOperatorData> mipsOperatorMipArg;
John Kesseniche01a9bc2016-03-12 20:11:22 -0700443};
444
steve-lunarge7d07522017-03-19 18:12:37 -0600445// This is the prefix we use for builtin methods to avoid namespace collisions with
446// global scope user functions.
447// TODO: this would be better as a nonparseable character, but that would
448// require changing the scanner.
449#define BUILTIN_PREFIX "__BI_"
450
John Kesseniche01a9bc2016-03-12 20:11:22 -0700451} // end namespace glslang
452
453#endif // HLSL_PARSE_INCLUDED_