blob: d85bdfa22b71f1c74564a9939ac4a7ade24fd02a [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"
John Kesseniche18fd202018-01-30 11:01:39 -070041#include "../glslang/MachineIndependent/attribute.h"
John Kesseniche01a9bc2016-03-12 20:11:22 -070042
LoopDawg307b6502017-07-05 11:33:06 -060043#include <array>
44
John Kesseniche01a9bc2016-03-12 20:11:22 -070045namespace glslang {
46
John Kessenich0a2a0cd2017-05-16 23:16:26 -060047class TFunctionDeclarator;
steve-lunarg1868b142016-10-20 13:07:10 -060048
John Kesseniche01a9bc2016-03-12 20:11:22 -070049class HlslParseContext : public TParseContextBase {
50public:
51 HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins,
John Kessenichb901ade2016-06-16 20:59:42 -060052 int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
steve-lunargf1e0c872016-10-31 15:13:43 -060053 const TString sourceEntryPointName,
John Kesseniche01a9bc2016-03-12 20:11:22 -070054 bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
55 virtual ~HlslParseContext();
Henrik Rydgård9a931b32016-12-21 12:48:08 +010056 void initializeExtensionBehavior() override;
LoopDawg62561462016-07-22 20:46:03 -060057
Henrik Rydgård9a931b32016-12-21 12:48:08 +010058 void setLimits(const TBuiltInResource&) override;
59 bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
John Kessenich000c8182017-03-22 23:21:34 -060060 virtual const char* getGlobalUniformBlockName() const override { return "$Global"; }
61 virtual void setUniformBlockDefaults(TType& block) const override
62 {
63 block.getQualifier().layoutPacking = ElpStd140;
64 block.getQualifier().layoutMatrix = ElmRowMajor;
65 }
John Kesseniche01a9bc2016-03-12 20:11:22 -070066
Henrik Rydgård9a931b32016-12-21 12:48:08 +010067 void reservedPpErrorCheck(const TSourceLoc&, const char* /*name*/, const char* /*op*/) override { }
68 bool lineContinuationCheck(const TSourceLoc&, bool /*endOfComment*/) override { return true; }
69 bool lineDirectiveShouldSetNextLine() const override { return true; }
John Kesseniche01a9bc2016-03-12 20:11:22 -070070 bool builtInName(const TString&);
71
Henrik Rydgård9a931b32016-12-21 12:48:08 +010072 void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
John Kessenichf4ba25e2017-03-21 18:35:04 -060073 TIntermTyped* handleVariable(const TSourceLoc&, const TString* string);
John Kesseniche01a9bc2016-03-12 20:11:22 -070074 TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
steve-lunarg6b43d272016-10-06 20:12:24 -060075 TIntermTyped* handleBracketOperator(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
John Kesseniche01a9bc2016-03-12 20:11:22 -070076
John Kesseniche01a9bc2016-03-12 20:11:22 -070077 TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
78 TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
79 TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
John Kessenich5f12d2f2017-03-11 09:39:55 -070080 bool isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field);
John Kessenich54596ff2017-06-20 03:20:59 -060081 void assignToInterface(TVariable& variable);
John Kessenich088d52b2017-03-11 17:55:28 -070082 void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
John Kesseniche18fd202018-01-30 11:01:39 -070083 TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributes&, TIntermNode*& entryPointTree);
84 TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributes&);
85 void handleEntryPointAttributes(const TSourceLoc&, const TAttributes&);
86 void transferTypeAttributes(const TSourceLoc&, const TAttributes&, TType&, bool allowEntry = false);
John Kessenicha3051662016-09-02 19:13:36 -060087 void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node);
John Kessenich727b3742017-02-03 17:57:55 -070088 void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs);
John Kessenich6fccb3c2016-09-19 16:01:41 -060089 void remapNonEntryPointIO(TFunction& function);
steve-lunargc4a13072016-08-09 11:28:03 -060090 TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
John Kessenich4678ca92016-05-13 09:33:42 -060091 void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg);
John Kessenichfdf63472017-01-13 12:27:52 -070092 TIntermTyped* handleAssign(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
93 TIntermTyped* handleAssignToMatrixSwizzle(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
steve-lunarg26d31452016-12-23 18:56:57 -070094 TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*);
LoopDawg307b6502017-07-05 11:33:06 -060095 TIntermAggregate* assignClipCullDistance(const TSourceLoc&, TOperator, int semanticId, TIntermTyped* left, TIntermTyped* right);
LoopDawgb22c0692017-12-06 16:52:03 -070096 TIntermTyped* assignPosition(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
LoopDawg592860c2016-06-09 08:57:35 -060097 void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
LoopDawg4886f692016-06-29 10:58:58 -060098 void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
steve-lunarg5da1f032017-02-12 17:50:28 -070099 void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
steve-lunargf49cdf42016-11-17 15:04:20 -0700100 void decomposeGeometryMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
John Kessenich0a2a0cd2017-05-16 23:16:26 -0600101 void pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments);
steve-lunarg26d31452016-12-23 18:56:57 -0700102 void addInputArgumentConversions(const TFunction&, TIntermTyped*&);
John Kessenich750c2d02017-05-26 00:01:36 -0600103 void expandArguments(const TSourceLoc&, const TFunction&, TIntermTyped*&);
steve-lunargef33ec02016-11-02 12:42:34 -0600104 TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700105 void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
John Kessenichc633f642017-04-03 21:48:37 -0600106 TFunction* makeConstructorCall(const TSourceLoc&, const TType&);
John Kessenich2dd643f2017-03-14 21:50:06 -0600107 void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable, const TString& upperCase);
John Kessenich7735b942016-09-05 12:40:06 -0600108 void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location,
John Kessenichb38f0712016-07-30 10:29:54 -0600109 const glslang::TString* component);
John Kessenich7735b942016-09-05 12:40:06 -0600110 void handleRegister(const TSourceLoc&, TQualifier&, const glslang::TString* profile, const glslang::TString& desc,
John Kessenichcfd7ce82016-09-05 16:03:12 -0600111 int subComponent, const glslang::TString*);
John Kessenich636b62d2017-04-11 19:45:00 -0600112 TIntermTyped* convertConditionalExpression(const TSourceLoc&, TIntermTyped*, bool mustBeScalar = true);
LoopDawga2b79912016-07-14 14:45:14 -0600113 TIntermAggregate* handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, TIntermTyped* argSampler);
114
John Kessenichc142c882017-01-13 19:34:22 -0700115 bool parseMatrixSwizzleSelector(const TSourceLoc&, const TString&, int cols, int rows, TSwizzleSelectors<TMatrixSelector>&);
116 int getMatrixComponentsColumn(int rows, const TSwizzleSelectors<TMatrixSelector>&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700117 void assignError(const TSourceLoc&, const char* op, TString left, TString right);
118 void unaryOpError(const TSourceLoc&, const char* op, TString operand);
119 void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
120 void variableCheck(TIntermTyped*& nodePtr);
121 void constantValueCheck(TIntermTyped* node, const char* token);
122 void integerCheck(const TIntermTyped* node, const char* token);
123 void globalCheck(const TSourceLoc&, const char* token);
124 bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
125 bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
126 void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&);
127 void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
128 void structArrayCheck(const TSourceLoc&, const TType& structure);
129 void arrayDimMerge(TType& type, const TArraySizes* sizes);
130 bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700131 void globalQualifierFix(const TSourceLoc&, TQualifier&);
132 bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
John Kessenich34e7ee72016-09-16 17:10:39 -0600133 void mergeQualifiers(TQualifier& dst, const TQualifier& src);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700134 int computeSamplerTypeIndex(TSampler&);
John Kessenichd3f11222016-11-05 10:15:53 -0600135 TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
John Kessenich5aa59e22016-06-17 15:50:47 -0600136 void paramFix(TType& type);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700137 void specializationCheck(const TSourceLoc&, const TType&, const char* op);
138
John Kessenichb9e39122016-08-17 10:22:08 -0600139 void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&);
140 void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&, const TIntermTyped*);
John Kessenich046bae02017-12-23 17:29:45 -0700141 void setSpecConstantId(const TSourceLoc&, TQualifier&, int value);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700142 void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
143 void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
144
John Kessenich0a2a0cd2017-05-16 23:16:26 -0600145 const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth, TIntermTyped*& args);
LoopDawg2e629102017-11-22 10:33:34 -0700146 void addGenMulArgumentConversion(const TSourceLoc& loc, TFunction& call, TIntermTyped*& args);
John Kessenich4dc835c2017-03-28 23:43:10 -0600147 void declareTypedef(const TSourceLoc&, const TString& identifier, const TType&);
John Kessenich727b3742017-02-03 17:57:55 -0700148 void declareStruct(const TSourceLoc&, TString& structName, TType&);
John Kessenich854fe242017-03-02 14:30:59 -0700149 TSymbol* lookupUserType(const TString&, TType&);
John Kessenich4dc835c2017-03-28 23:43:10 -0600150 TIntermNode* declareVariable(const TSourceLoc&, const TString& identifier, TType&, TIntermTyped* initializer = 0);
John Kessenich82460b52017-04-04 11:47:42 -0600151 void lengthenList(const TSourceLoc&, TIntermSequence& list, int size, TIntermTyped* scalarInit);
John Kessenichc633f642017-04-03 21:48:37 -0600152 TIntermTyped* handleConstructor(const TSourceLoc&, TIntermTyped*, const TType&);
153 TIntermTyped* addConstructor(const TSourceLoc&, TIntermTyped*, const TType&);
John Kessenich82ae8c32017-06-13 23:13:10 -0600154 TIntermTyped* convertArray(TIntermTyped*, const TType&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700155 TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
156 TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
John Kessenich3d157c52016-07-25 16:05:33 -0600157 void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600158 void declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700159 void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
160 void fixBlockXfbOffsets(TQualifier&, TTypeList&);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600161 void fixBlockUniformOffsets(const TQualifier&, TTypeList&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700162 void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
163 void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
164 void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
165 void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
John Kesseniche18fd202018-01-30 11:01:39 -0700166 TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body, const TAttributes&);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700167
168 void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
169
John Kessenicha1e2d492016-09-20 13:22:58 -0600170 void nestLooping() { ++loopNestingLevel; }
171 void unnestLooping() { --loopNestingLevel; }
172 void nestAnnotations() { ++annotationNestingLevel; }
173 void unnestAnnotations() { --annotationNestingLevel; }
John Kessenich6dbc0a72016-09-27 19:13:05 -0600174 int getAnnotationNestingLevel() { return annotationNestingLevel; }
John Kessenicha1e2d492016-09-20 13:22:58 -0600175 void pushScope() { symbolTable.push(); }
176 void popScope() { symbolTable.pop(0); }
John Kessenich0d2b6de2016-06-05 11:23:11 -0600177
John Kessenich0a2a0cd2017-05-16 23:16:26 -0600178 void pushThisScope(const TType&, const TVector<TFunctionDeclarator>&);
John Kessenich37789792017-03-21 23:56:40 -0600179 void popThisScope() { symbolTable.pop(0); }
180
181 void pushImplicitThis(TVariable* thisParameter) { implicitThisStack.push_back(thisParameter); }
182 void popImplicitThis() { implicitThisStack.pop_back(); }
183 TVariable* getImplicitThis(int thisDepth) const { return implicitThisStack[implicitThisStack.size() - thisDepth]; }
184
John Kessenichf3d88bd2017-03-19 12:24:29 -0600185 void pushNamespace(const TString& name);
186 void popNamespace();
John Kessenich9855bda2017-09-11 21:48:19 -0600187 void getFullNamespaceName(TString*&) const;
John Kessenichf3d88bd2017-03-19 12:24:29 -0600188 void addScopeMangler(TString&);
John Kessenich54ee28f2017-03-11 14:13:00 -0700189
John Kessenichd02dc5d2016-07-01 00:04:11 -0600190 void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); }
191 void popSwitchSequence() { switchSequenceStack.pop_back(); }
192
John Kessenich1b46f132017-10-19 16:54:25 -0600193 virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName,
194 TTypeList* typeList = nullptr) override;
John Kessenich88c44642017-02-03 14:06:36 -0700195
steve-lunarg90707962016-10-07 19:35:40 -0600196 // Apply L-value conversions. E.g, turning a write to a RWTexture into an ImageStore.
John Kessenichf3150742017-06-02 16:28:39 -0600197 TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node);
steve-lunarg0de16da2016-10-08 10:54:52 -0600198 bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
steve-lunarg90707962016-10-07 19:35:40 -0600199
steve-lunarg4f2da272016-10-10 15:24:57 -0600200 TLayoutFormat getLayoutFromTxType(const TSourceLoc&, const TType&);
201
steve-lunargf49cdf42016-11-17 15:04:20 -0700202 bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
203 bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
204
Rex Xu57e65922017-07-04 23:23:40 +0800205 // Determine selection control from attributes
John Kesseniche18fd202018-01-30 11:01:39 -0700206 void handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection*, const TAttributes& attributes);
207 void handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch*, const TAttributes& attributes);
Rex Xu57e65922017-07-04 23:23:40 +0800208
steve-lunargf1709e72017-05-02 20:14:50 -0600209 // Determine loop control from attributes
John Kesseniche18fd202018-01-30 11:01:39 -0700210 void handleLoopAttributes(const TSourceLoc& loc, TIntermLoop*, const TAttributes& attributes);
steve-lunargf1709e72017-05-02 20:14:50 -0600211
steve-lunargdd8287a2017-02-23 18:04:12 -0700212 // Share struct buffer deep types
213 void shareStructBufferType(TType&);
214
LoopDawg5ee05892017-07-31 13:41:42 -0600215 // Set texture return type of the given sampler. Returns success (not all types are valid).
216 bool setTextureReturnType(TSampler& sampler, const TType& retType, const TSourceLoc& loc);
217
218 // Obtain the sampler return type of the given sampler in retType.
219 void getTextureReturnType(const TSampler& sampler, TType& retType) const;
220
John Kesseniche18fd202018-01-30 11:01:39 -0700221 TAttributeType attributeFromName(const TString& nameSpace, const TString& name) const;
222
John Kesseniche01a9bc2016-03-12 20:11:22 -0700223protected:
steve-lunarga2b01a02016-11-28 17:09:54 -0700224 struct TFlattenData {
John Kessenich89f8d1e2017-06-27 15:17:38 -0600225 TFlattenData() : nextBinding(TQualifier::layoutBindingEnd),
226 nextLocation(TQualifier::layoutLocationEnd) { }
227 TFlattenData(int nb, int nl) : nextBinding(nb), nextLocation(nl) { }
steve-lunarga2b01a02016-11-28 17:09:54 -0700228
229 TVector<TVariable*> members; // individual flattened variables
John Kessenich89f8d1e2017-06-27 15:17:38 -0600230 TVector<int> offsets; // offset to next tree level
231 unsigned int nextBinding; // next binding to use.
232 unsigned int nextLocation; // next location to use
steve-lunarga2b01a02016-11-28 17:09:54 -0700233 };
234
John Kessenich4dc835c2017-03-28 23:43:10 -0600235 void fixConstInit(const TSourceLoc&, const TString& identifier, TType& type, TIntermTyped*& initializer);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700236 void inheritGlobalDefaults(TQualifier& dst) const;
237 TVariable* makeInternalVariable(const char* name, const TType&) const;
steve-lunarga2e75312016-12-14 15:22:25 -0700238 TVariable* makeInternalVariable(const TString& name, const TType& type) const {
239 return makeInternalVariable(name.c_str(), type);
240 }
John Kessenich82460b52017-04-04 11:47:42 -0600241 TIntermSymbol* makeInternalVariableNode(const TSourceLoc&, const char* name, const TType&) const;
John Kessenich4dc835c2017-03-28 23:43:10 -0600242 TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&, bool track);
243 void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&, bool track);
John Kessenich092b7d22017-09-30 14:54:18 -0600244 TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
John Kessenich82460b52017-04-04 11:47:42 -0600245 TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit);
246 bool isScalarConstructor(const TIntermNode*);
LoopDawg58910702016-06-13 09:22:28 -0600247 TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700248
steve-lunarg90707962016-10-07 19:35:40 -0600249 // Return true if this node requires L-value conversion (e.g, to an imageStore).
250 bool shouldConvertLValue(const TIntermNode*) const;
251
steve-lunarge0b9deb2016-09-16 13:26:37 -0600252 // Array and struct flattening
steve-lunarga2e75312016-12-14 15:22:25 -0700253 TIntermTyped* flattenAccess(TIntermTyped* base, int member);
John Kessenich41aa1992017-10-11 14:03:45 -0600254 TIntermTyped* flattenAccess(int uniqueId, int member, TStorageQualifier outerStorage, const TType&, int subset = -1);
John Kessenich700bdeb2017-10-04 13:27:43 -0600255 int findSubtreeOffset(const TIntermNode&) const;
256 int findSubtreeOffset(const TType&, int subset, const TVector<int>& offsets) const;
John Kessenich41aa1992017-10-11 14:03:45 -0600257 bool shouldFlatten(const TType&, TStorageQualifier, bool topLevel) const;
steve-lunarga2b01a02016-11-28 17:09:54 -0700258 bool wasFlattened(const TIntermTyped* node) const;
259 bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); }
John Kessenich3322dd82017-08-08 20:02:21 -0600260 int addFlattenedMember(const TVariable&, const TType&, TFlattenData&, const TString& name, bool linkage,
261 const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes);
steve-lunarga2b01a02016-11-28 17:09:54 -0700262
John Kessenich750c2d02017-05-26 00:01:36 -0600263 // Structure splitting (splits interstage built-in types into its own struct)
steve-lunarga2e75312016-12-14 15:22:25 -0700264 void split(const TVariable&);
John Kessenichecd08bc2017-08-07 23:40:05 -0600265 void splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes*, const TQualifier&);
266 const TType& split(const TType& type, const TString& name, const TQualifier&);
steve-lunarga2e75312016-12-14 15:22:25 -0700267 bool wasSplit(const TIntermTyped* node) const;
John Kessenichd5aedc12017-08-06 19:42:42 -0600268 bool wasSplit(int id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); }
269 TVariable* getSplitNonIoVar(int id) const;
steve-lunarg858c9282017-01-07 08:54:10 -0700270 void addPatchConstantInvocation();
LoopDawg195f5842017-09-27 09:12:51 -0600271 void fixTextureShadowModes();
steve-lunargf8203a02017-04-20 09:00:56 -0600272 TIntermTyped* makeIntegerIndex(TIntermTyped*);
steve-lunarga2e75312016-12-14 15:22:25 -0700273
steve-lunargccb076a2017-04-05 11:03:02 -0600274 void fixBuiltInIoType(TType&);
steve-lunarg194f0f32017-03-17 18:51:05 -0600275
John Kessenichd5aedc12017-08-06 19:42:42 -0600276 void flatten(const TVariable& variable, bool linkage);
John Kessenich3322dd82017-08-08 20:02:21 -0600277 int flatten(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage,
278 const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes);
279 int flattenStruct(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage,
280 const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes);
281 int flattenArray(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage,
282 const TQualifier& outerQualifier);
steve-lunarge0b9deb2016-09-16 13:26:37 -0600283
John Kessenichbf472862017-02-05 20:27:30 -0700284 bool hasUniform(const TQualifier& qualifier) const;
285 void clearUniform(TQualifier& qualifier);
286 bool isInputBuiltIn(const TQualifier& qualifier) const;
287 bool hasInput(const TQualifier& qualifier) const;
288 void correctOutput(TQualifier& qualifier);
289 bool isOutputBuiltIn(const TQualifier& qualifier) const;
290 bool hasOutput(const TQualifier& qualifier) const;
291 void correctInput(TQualifier& qualifier);
292 void correctUniform(TQualifier& qualifier);
293 void clearUniformInputOutput(TQualifier& qualifier);
294
steve-lunarg5da1f032017-02-12 17:50:28 -0700295 // Test method names
steve-lunarg5da1f032017-02-12 17:50:28 -0700296 bool isStructBufferMethod(const TString& name) const;
steve-lunarg2bb1f392017-04-27 11:22:32 -0600297 void counterBufferType(const TSourceLoc& loc, TType& type);
steve-lunarg5da1f032017-02-12 17:50:28 -0700298
steve-lunargd4d0b292017-04-26 08:31:56 -0600299 // Return standard sample position array
300 TIntermConstantUnion* getSamplePosArray(int count);
301
steve-lunargdd8287a2017-02-23 18:04:12 -0700302 TType* getStructBufferContentType(const TType& type) const;
303 bool isStructBufferType(const TType& type) const { return getStructBufferContentType(type) != nullptr; }
304 TIntermTyped* indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const;
steve-lunarg8e26feb2017-04-10 08:19:21 -0600305 TIntermTyped* getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer);
steve-lunarg2bb1f392017-04-27 11:22:32 -0600306 TString getStructBuffCounterName(const TString&) const;
307 void addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*&);
308 void addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter&, TIntermAggregate*&);
steve-lunargdd8287a2017-02-23 18:04:12 -0700309
310 // Return true if this type is a reference. This is not currently a type method in case that's
311 // a language specific answer.
312 bool isReference(const TType& type) const { return isStructBufferType(type); }
313
steve-lunarg8e26feb2017-04-10 08:19:21 -0600314 // Return true if this a buffer type that has an associated counter buffer.
steve-lunarga4bfed12017-04-23 19:44:28 -0600315 bool hasStructBuffCounter(const TType&) const;
steve-lunarg8e26feb2017-04-10 08:19:21 -0600316
317 // Finalization step: remove unused buffer blocks from linkage (we don't know until the
318 // shader is entirely compiled)
319 void removeUnusedStructBufferCounters();
LoopDawg307b6502017-07-05 11:33:06 -0600320
321 static bool isClipOrCullDistance(TBuiltInVariable);
322 static bool isClipOrCullDistance(const TQualifier& qual) { return isClipOrCullDistance(qual.builtIn); }
323 static bool isClipOrCullDistance(const TType& type) { return isClipOrCullDistance(type.getQualifier()); }
steve-lunarg8e26feb2017-04-10 08:19:21 -0600324
LoopDawg4a145db2017-09-13 08:44:39 -0600325 // Find the patch constant function (issues error, returns nullptr if not found)
326 const TFunction* findPatchConstantFunction(const TSourceLoc& loc);
327
John Kessenich2b4f77f2017-08-04 13:51:54 -0600328 // Pass through to base class after remembering built-in mappings.
steve-lunarg858c9282017-01-07 08:54:10 -0700329 using TParseContextBase::trackLinkage;
330 void trackLinkage(TSymbol& variable) override;
331
Alex Szpakowski7d39ad52017-01-08 17:54:48 -0400332 void finish() override; // post-processing
steve-lunarga2e75312016-12-14 15:22:25 -0700333
steve-lunarge752f462017-03-22 18:39:25 -0600334 // Linkage symbol helpers
John Kessenich2b4f77f2017-08-04 13:51:54 -0600335 TIntermSymbol* findTessLinkageSymbol(TBuiltInVariable biType) const;
steve-lunarge752f462017-03-22 18:39:25 -0600336
John Kesseniche01a9bc2016-03-12 20:11:22 -0700337 // Current state of parsing
John Kessenicha1e2d492016-09-20 13:22:58 -0600338 int annotationNestingLevel; // 0 if outside all annotations
John Kesseniche01a9bc2016-03-12 20:11:22 -0700339
340 HlslParseContext(HlslParseContext&);
341 HlslParseContext& operator=(HlslParseContext&);
342
John Kesseniche01a9bc2016-03-12 20:11:22 -0700343 static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2)); // see computeSamplerTypeIndex()
John Kesseniche01a9bc2016-03-12 20:11:22 -0700344 TQualifier globalBufferDefaults;
345 TQualifier globalUniformDefaults;
346 TQualifier globalInputDefaults;
347 TQualifier globalOutputDefaults;
348 TString currentCaller; // name of last function body entered (not valid when at global scope)
349 TIdSetType inductiveLoopIds;
350 TVector<TIntermTyped*> needsIndexLimitationChecking;
John Kesseniche01a9bc2016-03-12 20:11:22 -0700351
352 //
353 // Geometry shader input arrays:
354 // - array sizing is based on input primitive and/or explicit size
355 //
356 // Tessellation control output arrays:
357 // - array sizing is based on output layout(vertices=...) and/or explicit size
358 //
359 // Both:
360 // - array sizing is retroactive
361 // - built-in block redeclarations interact with this
362 //
363 // Design:
364 // - use a per-context "resize-list", a list of symbols whose array sizes
365 // can be fixed
366 //
367 // - the resize-list starts empty at beginning of user-shader compilation, it does
368 // not have built-ins in it
369 //
370 // - on built-in array use: copyUp() symbol and add it to the resize-list
371 //
372 // - on user array declaration: add it to the resize-list
373 //
374 // - on block redeclaration: copyUp() symbol and add it to the resize-list
375 // * note, that appropriately gives an error if redeclaring a block that
376 // was already used and hence already copied-up
377 //
John Kessenichecba76f2017-01-06 00:34:48 -0700378 // - on seeing a layout declaration that sizes the array, fix everything in the
John Kesseniche01a9bc2016-03-12 20:11:22 -0700379 // resize-list, giving errors for mismatch
380 //
381 // - on seeing an array size declaration, give errors on mismatch between it and previous
382 // array-sizing declarations
383 //
384 TVector<TSymbol*> ioArraySymbolResizeList;
John Kessenichcd0a78a2016-09-09 16:32:09 -0600385
steve-lunarga2b01a02016-11-28 17:09:54 -0700386 TMap<int, TFlattenData> flattenMap;
steve-lunarga2b01a02016-11-28 17:09:54 -0700387
John Kessenichbf472862017-02-05 20:27:30 -0700388 // IO-type map. Maps a pure symbol-table form of a structure-member list into
389 // each of the (up to) three kinds of IO, as each as different allowed decorations,
390 // but HLSL allows mixing all in the same structure.
391 struct tIoKinds {
392 TTypeList* input;
393 TTypeList* output;
394 TTypeList* uniform;
395 };
396 TMap<const TTypeList*, tIoKinds> ioTypeMap;
steve-lunarga2e75312016-12-14 15:22:25 -0700397
398 // Structure splitting data:
John Kessenichd5aedc12017-08-06 19:42:42 -0600399 TMap<int, TVariable*> splitNonIoVars; // variables with the built-in interstage IO removed, indexed by unique ID.
steve-lunarg132d3312016-12-19 15:48:01 -0700400
steve-lunargdd8287a2017-02-23 18:04:12 -0700401 // Structuredbuffer shared types. Typically there are only a few.
402 TVector<TType*> structBufferTypes;
LoopDawg5ee05892017-07-31 13:41:42 -0600403
404 // This tracks texture sample user structure return types. Only a limited number are supported, as
405 // may fit in TSampler::structReturnIndex.
406 TVector<TTypeList*> textureReturnStruct;
steve-lunarg8e26feb2017-04-10 08:19:21 -0600407
steve-lunarg8e26feb2017-04-10 08:19:21 -0600408 TMap<TString, bool> structBufferCounter;
steve-lunargdd8287a2017-02-23 18:04:12 -0700409
John Kessenich2b4f77f2017-08-04 13:51:54 -0600410 // The built-in interstage IO map considers e.g, EvqPosition on input and output separately, so that we
steve-lunarg132d3312016-12-19 15:48:01 -0700411 // can build the linkage correctly if position appears on both sides. Otherwise, multiple positions
412 // are considered identical.
413 struct tInterstageIoData {
steve-lunarg858c9282017-01-07 08:54:10 -0700414 tInterstageIoData(TBuiltInVariable bi, TStorageQualifier q) :
415 builtIn(bi), storage(q) { }
416
steve-lunarg132d3312016-12-19 15:48:01 -0700417 TBuiltInVariable builtIn;
418 TStorageQualifier storage;
419
420 // ordering for maps
421 bool operator<(const tInterstageIoData d) const {
422 return (builtIn != d.builtIn) ? (builtIn < d.builtIn) : (storage < d.storage);
423 }
424 };
425
John Kessenich2b4f77f2017-08-04 13:51:54 -0600426 TMap<tInterstageIoData, TVariable*> splitBuiltIns; // split built-ins, indexed by built-in type.
LoopDawg4a145db2017-09-13 08:44:39 -0600427 TVariable* inputPatch; // input patch is special for PCF: it's the only non-builtin PCF input,
428 // and is handled as a pseudo-builtin.
steve-lunarg132d3312016-12-19 15:48:01 -0700429
John Kessenich7dc630f2016-09-16 01:44:43 -0600430 unsigned int nextInLocation;
431 unsigned int nextOutLocation;
steve-lunargf1e0c872016-10-31 15:13:43 -0600432
steve-lunarg858c9282017-01-07 08:54:10 -0700433 TFunction* entryPointFunction;
434 TIntermNode* entryPointFunctionBody;
435
436 TString patchConstantFunctionName; // hull shader patch constant function name, from function level attribute.
John Kessenich2b4f77f2017-08-04 13:51:54 -0600437 TMap<TBuiltInVariable, TSymbol*> builtInTessLinkageSymbols; // used for tessellation, finding declared built-ins
steve-lunarg858c9282017-01-07 08:54:10 -0700438
John Kessenich37789792017-03-21 23:56:40 -0600439 TVector<TString> currentTypePrefix; // current scoping prefix for nested structures
440 TVector<TVariable*> implicitThisStack; // currently active 'this' variables for nested structures
steve-lunarg08e0c082017-03-29 20:01:13 -0600441
442 TVariable* gsStreamOutput; // geometry shader stream outputs, for emit (Append method)
LoopDawg726bf962017-05-12 17:14:31 -0600443
LoopDawg5e5b12e2017-08-28 14:02:19 -0600444 TVariable* clipDistanceOutput; // synthesized clip distance out variable (shader might have >1)
445 TVariable* cullDistanceOutput; // synthesized cull distance out variable (shader might have >1)
446 TVariable* clipDistanceInput; // synthesized clip distance in variable (shader might have >1)
447 TVariable* cullDistanceInput; // synthesized cull distance in variable (shader might have >1)
LoopDawg307b6502017-07-05 11:33:06 -0600448
449 static const int maxClipCullRegs = 2;
LoopDawg5e5b12e2017-08-28 14:02:19 -0600450 std::array<int, maxClipCullRegs> clipSemanticNSizeIn; // vector, indexed by clip semantic ID
451 std::array<int, maxClipCullRegs> cullSemanticNSizeIn; // vector, indexed by cull semantic ID
452 std::array<int, maxClipCullRegs> clipSemanticNSizeOut; // vector, indexed by clip semantic ID
453 std::array<int, maxClipCullRegs> cullSemanticNSizeOut; // vector, indexed by cull semantic ID
LoopDawg307b6502017-07-05 11:33:06 -0600454
LoopDawg726bf962017-05-12 17:14:31 -0600455 // This tracks the first (mip level) argument to the .mips[][] operator. Since this can be nested as
456 // in tx.mips[tx.mips[0][1].x][2], we need a stack. We also track the TSourceLoc for error reporting
457 // purposes.
458 struct tMipsOperatorData {
459 tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { }
460 TSourceLoc loc;
461 TIntermTyped* mipLevel;
462 };
463
464 TVector<tMipsOperatorData> mipsOperatorMipArg;
LoopDawg195f5842017-09-27 09:12:51 -0600465
LoopDawg73c57bb2017-10-05 16:25:52 -0600466 // A texture object may be used with shadow and non-shadow samplers, but both may not be
467 // alive post-DCE in the same shader. We do not know at compilation time which are alive: that's
468 // only known post-DCE. If a texture is used both ways, we create two textures, and
469 // leave the elimiation of one to the optimizer. This maps the shader variant to
470 // the shadow variant.
471 //
472 // This can be removed if and when the texture shadow code in
473 // HlslParseContext::handleSamplerTextureCombine is removed.
474 struct tShadowTextureSymbols {
475 tShadowTextureSymbols() { symId.fill(-1); }
476
477 void set(bool shadow, int id) { symId[int(shadow)] = id; }
478 int get(bool shadow) const { return symId[int(shadow)]; }
479
480 // True if this texture has been seen with both shadow and non-shadow modes
481 bool overloaded() const { return symId[0] != -1 && symId[1] != -1; }
482 bool isShadowId(int id) const { return symId[1] == id; }
483
484 private:
485 std::array<int, 2> symId;
486 };
487
488 TMap<int, tShadowTextureSymbols*> textureShadowVariant;
John Kesseniche01a9bc2016-03-12 20:11:22 -0700489};
490
John Kessenich2b4f77f2017-08-04 13:51:54 -0600491// This is the prefix we use for built-in methods to avoid namespace collisions with
steve-lunarge7d07522017-03-19 18:12:37 -0600492// global scope user functions.
493// TODO: this would be better as a nonparseable character, but that would
494// require changing the scanner.
495#define BUILTIN_PREFIX "__BI_"
496
John Kesseniche01a9bc2016-03-12 20:11:22 -0700497} // end namespace glslang
498
499#endif // HLSL_PARSE_INCLUDED_