Implement atomic ops, bit conversions, fix fwidth stage mask, fix saturate dest modifier.
[platform/upstream/glslang.git] / hlsl / hlslParseHelper.h
1 //
2 //Copyright (C) 2016 Google, Inc.
3 //Copyright (C) 2016 LunarG, Inc.
4 //
5 //All rights reserved.
6 //
7 //Redistribution and use in source and binary forms, with or without
8 //modification, are permitted provided that the following conditions
9 //are met:
10 //
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 //
23 //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.
35 //
36 #ifndef HLSL_PARSE_INCLUDED_
37 #define HLSL_PARSE_INCLUDED_
38
39 #include "../glslang/MachineIndependent/parseVersions.h"
40 #include "../glslang/MachineIndependent/ParseHelper.h"
41
42 namespace glslang {
43
44 class HlslParseContext : public TParseContextBase {
45 public:
46     HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins,
47                      int version, EProfile, int spv, int vulkan, EShLanguage, TInfoSink&,
48                      bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
49     virtual ~HlslParseContext();
50     void setLimits(const TBuiltInResource&);
51     bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false);
52     void getPreamble(std::string&);
53
54     void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
55         const char* szExtraInfoFormat, ...);
56     void C_DECL  warn(const TSourceLoc&, const char* szReason, const char* szToken,
57         const char* szExtraInfoFormat, ...);
58     void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
59         const char* szExtraInfoFormat, ...);
60     void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
61         const char* szExtraInfoFormat, ...);
62
63     void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) { }
64     bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) { return true; }
65     bool lineDirectiveShouldSetNextLine() const { return true; }
66     bool builtInName(const TString&);
67
68     void handlePragma(const TSourceLoc&, const TVector<TString>&);
69     TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol,  const TString* string);
70     TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
71     void checkIndex(const TSourceLoc&, const TType&, int& index);
72
73     void makeEditable(TSymbol*&);
74     TVariable* getEditableVariable(const char* name);
75     bool isIoResizeArray(const TType&) const;
76     void fixIoArraySize(const TSourceLoc&, TType&);
77     void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
78     void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
79     int getIoArrayImplicitSize() const;
80     void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
81
82     TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
83     TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
84     TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
85     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
86     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
87     void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg);
88     TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
89     void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
90     TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
91     void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
92     TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
93     void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
94     TFunction* handleConstructorCall(const TSourceLoc&, const TType&);
95     void handleSemantic(TType& type, const TString& semantic);
96
97     bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&);
98     void assignError(const TSourceLoc&, const char* op, TString left, TString right);
99     void unaryOpError(const TSourceLoc&, const char* op, TString operand);
100     void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
101     void variableCheck(TIntermTyped*& nodePtr);
102     void constantValueCheck(TIntermTyped* node, const char* token);
103     void integerCheck(const TIntermTyped* node, const char* token);
104     void globalCheck(const TSourceLoc&, const char* token);
105     bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
106     bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
107     void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&);
108     void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
109     void structArrayCheck(const TSourceLoc&, const TType& structure);
110     void arrayDimMerge(TType& type, const TArraySizes* sizes);
111     bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
112     void boolCheck(const TSourceLoc&, const TIntermTyped*);
113     void globalQualifierFix(const TSourceLoc&, TQualifier&);
114     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
115     void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
116     int computeSamplerTypeIndex(TSampler&);
117     TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&, bool& newDeclaration);
118     void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
119     void paramCheckFix(const TSourceLoc&, const TStorageQualifier&, TType& type);
120     void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
121     void specializationCheck(const TSourceLoc&, const TType&, const char* op);
122
123     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
124     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
125     void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
126     void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
127
128     const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
129     TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
130     TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator);
131     TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
132     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
133     void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
134     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
135     void fixBlockXfbOffsets(TQualifier&, TTypeList&);
136     void fixBlockUniformOffsets(TQualifier&, TTypeList&);
137     void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
138     void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
139     void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
140     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
141     TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
142
143     void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
144
145     void nestLooping()     { ++loopNestingLevel; }
146     void unnestLooping()   { --loopNestingLevel; }
147     void pushScope()       { symbolTable.push(); }
148     void popScope()        { symbolTable.pop(0); }
149
150 protected:
151     void inheritGlobalDefaults(TQualifier& dst) const;
152     TVariable* makeInternalVariable(const char* name, const TType&) const;
153     TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&, bool& newDeclaration);
154     void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
155     TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
156     TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
157     TOperator mapTypeToConstructorOp(const TType&) const;
158     TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage);
159     void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
160                        const char* szExtraInfoFormat, TPrefixType prefix,
161                        va_list args);
162
163     // Current state of parsing
164     struct TPragma contextPragma;
165     int loopNestingLevel;        // 0 if outside all loops
166     int structNestingLevel;      // 0 if outside blocks and structures
167     int controlFlowNestingLevel; // 0 if outside all flow control
168     TList<TIntermSequence*> switchSequenceStack;  // case, node, case, case, node, ...; ensure only one node between cases;   stack of them for nesting
169     TList<int> switchLevel;      // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
170     bool inEntrypoint;           // if inside a function, true if the function is the entry point
171     bool postMainReturn;         // if inside a function, true if the function is the entry point and this is after a return statement
172     const TType* currentFunctionType;  // the return type of the function that's currently being parsed
173     bool functionReturnsValue;   // true if a non-void function has a return
174     const TString* blockName;
175     TQualifier currentBlockQualifier;
176     TBuiltInResource resources;
177     TLimits& limits;
178
179     HlslParseContext(HlslParseContext&);
180     HlslParseContext& operator=(HlslParseContext&);
181
182     TMap<TString, TExtensionBehavior> extensionBehavior;    // for each extension string, what its current behavior is set to
183     static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2)); // see computeSamplerTypeIndex()
184     bool afterEOF;
185     TQualifier globalBufferDefaults;
186     TQualifier globalUniformDefaults;
187     TQualifier globalInputDefaults;
188     TQualifier globalOutputDefaults;
189     TString currentCaller;        // name of last function body entered (not valid when at global scope)
190     TIdSetType inductiveLoopIds;
191     TVector<TIntermTyped*> needsIndexLimitationChecking;
192
193     //
194     // Geometry shader input arrays:
195     //  - array sizing is based on input primitive and/or explicit size
196     //
197     // Tessellation control output arrays:
198     //  - array sizing is based on output layout(vertices=...) and/or explicit size
199     //
200     // Both:
201     //  - array sizing is retroactive
202     //  - built-in block redeclarations interact with this
203     //
204     // Design:
205     //  - use a per-context "resize-list", a list of symbols whose array sizes
206     //    can be fixed
207     //
208     //  - the resize-list starts empty at beginning of user-shader compilation, it does
209     //    not have built-ins in it
210     //
211     //  - on built-in array use: copyUp() symbol and add it to the resize-list
212     //
213     //  - on user array declaration: add it to the resize-list
214     //
215     //  - on block redeclaration: copyUp() symbol and add it to the resize-list
216     //     * note, that appropriately gives an error if redeclaring a block that
217     //       was already used and hence already copied-up
218     //
219     //  - on seeing a layout declaration that sizes the array, fix everything in the 
220     //    resize-list, giving errors for mismatch
221     //
222     //  - on seeing an array size declaration, give errors on mismatch between it and previous
223     //    array-sizing declarations
224     //
225     TVector<TSymbol*> ioArraySymbolResizeList;
226 };
227
228 } // end namespace glslang
229
230 #endif // HLSL_PARSE_INCLUDED_