1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | #ifndef _PARSER_HELPER_INCLUDED_ |
15 | #define _PARSER_HELPER_INCLUDED_ |
16 | |
17 | #include "Diagnostics.h" |
18 | #include "DirectiveHandler.h" |
19 | #include "localintermediate.h" |
20 | #include "preprocessor/Preprocessor.h" |
21 | #include "Compiler.h" |
22 | #include "SymbolTable.h" |
23 | |
24 | struct TMatrixFields { |
25 | bool wholeRow; |
26 | bool wholeCol; |
27 | int row; |
28 | int col; |
29 | }; |
30 | |
31 | // |
32 | // The following are extra variables needed during parsing, grouped together so |
33 | // they can be passed to the parser without needing a global. |
34 | // |
35 | class TParseContext { |
36 | public: |
37 | TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, GLenum type, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : |
38 | intermediate(interm), |
39 | symbolTable(symt), |
40 | compileOptions(options), |
41 | sourcePath(sourcePath), |
42 | lexAfterType(false), |
43 | inTypeParen(false), |
44 | AfterEOF(false), |
45 | mDeferredSingleDeclarationErrorCheck(false), |
46 | mShaderType(type), |
47 | mShaderVersion(100), |
48 | mTreeRoot(0), |
49 | mLoopNestingLevel(0), |
50 | mSwitchNestingLevel(0), |
51 | mStructNestingLevel(0), |
52 | mCurrentFunctionType(nullptr), |
53 | mFunctionReturnsValue(false), |
54 | mChecksPrecisionErrors(checksPrecErrors), |
55 | mDefaultMatrixPacking(EmpColumnMajor), |
56 | mDefaultBlockStorage(EbsShared), |
57 | mDiagnostics(is), |
58 | mDirectiveHandler(ext, mDiagnostics, mShaderVersion), |
59 | mPreprocessor(&mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()), |
60 | mScanner(nullptr), |
61 | mUsesFragData(false), |
62 | mUsesFragColor(false) { } |
63 | TIntermediate& intermediate; // to hold and build a parse tree |
64 | TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed |
65 | int compileOptions; |
66 | const char* sourcePath; // Path of source file or null. |
67 | bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier |
68 | bool inTypeParen; // true if in parentheses, looking only for an identifier |
69 | bool AfterEOF; |
70 | |
71 | const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } |
72 | pp::Preprocessor &getPreprocessor() { return mPreprocessor; } |
73 | void *getScanner() const { return mScanner; } |
74 | void setScanner(void *scanner) { mScanner = scanner; } |
75 | int getShaderVersion() const { return mShaderVersion; } |
76 | GLenum getShaderType() const { return mShaderType; } |
77 | int numErrors() const { return mDiagnostics.numErrors(); } |
78 | TInfoSink &infoSink() { return mDiagnostics.infoSink(); } |
79 | void error(const TSourceLoc &loc, const char *reason, const char* token, |
80 | const char* ="" ); |
81 | void warning(const TSourceLoc &loc, const char* reason, const char* token, |
82 | const char* ="" ); |
83 | void info(const TSourceLoc &loc, const char* reason, const char* token, |
84 | const char* ="" ); |
85 | void trace(const char* str); |
86 | void recover(); |
87 | TIntermNode *getTreeRoot() const { return mTreeRoot; } |
88 | void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; } |
89 | |
90 | bool getFunctionReturnsValue() const { return mFunctionReturnsValue; } |
91 | void setFunctionReturnsValue(bool functionReturnsValue) |
92 | { |
93 | mFunctionReturnsValue = functionReturnsValue; |
94 | } |
95 | |
96 | void setLoopNestingLevel(int loopNestintLevel) |
97 | { |
98 | mLoopNestingLevel = loopNestintLevel; |
99 | } |
100 | |
101 | const TType *getCurrentFunctionType() const { return mCurrentFunctionType; } |
102 | void setCurrentFunctionType(const TType *currentFunctionType) |
103 | { |
104 | mCurrentFunctionType = currentFunctionType; |
105 | } |
106 | |
107 | void incrLoopNestingLevel() { ++mLoopNestingLevel; } |
108 | void decrLoopNestingLevel() { --mLoopNestingLevel; } |
109 | |
110 | void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } |
111 | void decrSwitchNestingLevel() { --mSwitchNestingLevel; } |
112 | |
113 | // This method is guaranteed to succeed, even if no variable with 'name' exists. |
114 | const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol); |
115 | |
116 | bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line); |
117 | |
118 | bool reservedErrorCheck(const TSourceLoc &line, const TString& identifier); |
119 | void assignError(const TSourceLoc &line, const char* op, TString left, TString right); |
120 | void unaryOpError(const TSourceLoc &line, const char* op, TString operand); |
121 | void binaryOpError(const TSourceLoc &line, const char* op, TString left, TString right); |
122 | bool precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type); |
123 | bool lValueErrorCheck(const TSourceLoc &line, const char* op, TIntermTyped*); |
124 | bool constErrorCheck(TIntermTyped* node); |
125 | bool integerErrorCheck(TIntermTyped* node, const char* token); |
126 | bool globalErrorCheck(const TSourceLoc &line, bool global, const char* token); |
127 | bool constructorErrorCheck(const TSourceLoc &line, TIntermNode*, TFunction&, TOperator, TType*); |
128 | bool arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped* expr, int& size); |
129 | bool arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type); |
130 | bool arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type); |
131 | bool voidErrorCheck(const TSourceLoc&, const TString&, const TBasicType&); |
132 | bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); |
133 | bool boolErrorCheck(const TSourceLoc&, const TPublicType&); |
134 | bool samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason); |
135 | bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType); |
136 | bool structQualifierErrorCheck(const TSourceLoc &line, const TPublicType& pType); |
137 | bool parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType& type); |
138 | bool nonInitConstErrorCheck(const TSourceLoc &line, TString& identifier, TPublicType& type, bool array); |
139 | bool nonInitErrorCheck(const TSourceLoc &line, const TString& identifier, TPublicType& type); |
140 | bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type); |
141 | bool extensionErrorCheck(const TSourceLoc &line, const TString&); |
142 | bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation); |
143 | bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier); |
144 | bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); |
145 | void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation); |
146 | void checkInputOutputTypeIsValidES3(const TQualifier qualifier, const TPublicType &type, const TSourceLoc &qualifierLocation); |
147 | |
148 | const TExtensionBehavior& extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); } |
149 | bool supportsExtension(const char* extension); |
150 | void handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior); |
151 | |
152 | const TPragma& pragma() const { return mDirectiveHandler.pragma(); } |
153 | void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value, bool stdgl); |
154 | |
155 | bool containsSampler(TType& type); |
156 | const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0); |
157 | bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType, |
158 | TIntermTyped *initializer, TIntermNode **intermNode); |
159 | |
160 | TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier); |
161 | bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&); |
162 | |
163 | TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, const TSourceLoc &identifierOrTypeLocation, const TString &identifier); |
164 | TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier, |
165 | const TSourceLoc &indexLocation, TIntermTyped *indexExpression); |
166 | TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier, |
167 | const TSourceLoc &initLocation, TIntermTyped *initializer); |
168 | |
169 | // Parse a declaration like "type a[n] = initializer" |
170 | // Note that this does not apply to declarations like "type[n] a = initializer" |
171 | TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier, |
172 | const TSourceLoc &indexLocation, TIntermTyped *indexExpression, |
173 | const TSourceLoc &initLocation, TIntermTyped *initializer); |
174 | |
175 | TIntermAggregate *parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier, |
176 | const TSymbol *symbol); |
177 | |
178 | TIntermAggregate *parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation, |
179 | const TString &identifier); |
180 | TIntermAggregate *parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation, |
181 | const TString &identifier, const TSourceLoc &arrayLocation, TIntermTyped *indexExpression); |
182 | TIntermAggregate *parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation, |
183 | const TString &identifier, const TSourceLoc &initLocation, TIntermTyped *initializer); |
184 | |
185 | // Parse a declarator like "a[n] = initializer" |
186 | TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation, |
187 | const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression, |
188 | const TSourceLoc &initLocation, TIntermTyped *initializer); |
189 | |
190 | void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); |
191 | TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location); |
192 | TIntermAggregate *addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location); |
193 | void parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut); |
194 | TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function); |
195 | TFunction *addConstructorFunc(const TPublicType &publicType); |
196 | TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); |
197 | TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); |
198 | TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); |
199 | TIntermTyped* addConstMatrixNode(int, TIntermTyped*, const TSourceLoc&); |
200 | TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line); |
201 | TIntermTyped* addConstStruct(const TString&, TIntermTyped*, const TSourceLoc&); |
202 | TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); |
203 | TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation, const TString &fieldString, const TSourceLoc &fieldLocation); |
204 | |
205 | TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); |
206 | TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList); |
207 | |
208 | TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList, |
209 | const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine); |
210 | |
211 | TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine); |
212 | TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, int intValue, const TSourceLoc& intValueLine); |
213 | TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier); |
214 | TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, const TSourceLoc &storageLoc, TQualifier storageQualifier); |
215 | |
216 | // Performs an error check for embedded struct declarations. |
217 | // Returns true if an error was raised due to the declaration of |
218 | // this struct. |
219 | bool enterStructDeclaration(const TSourceLoc &line, const TString& identifier); |
220 | void exitStructDeclaration(); |
221 | |
222 | bool structNestingErrorCheck(const TSourceLoc &line, const TField &field); |
223 | |
224 | TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc); |
225 | TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); |
226 | TIntermCase *addDefault(const TSourceLoc &loc); |
227 | |
228 | TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); |
229 | TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc); |
230 | TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); |
231 | TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); |
232 | |
233 | TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); |
234 | |
235 | TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); |
236 | TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc); |
237 | |
238 | TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError); |
239 | |
240 | TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line); |
241 | |
242 | private: |
243 | bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable); |
244 | |
245 | TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); |
246 | TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); |
247 | |
248 | // The funcReturnType parameter is expected to be non-null when the operation is a built-in function. |
249 | // It is expected to be null for other unary operators. |
250 | TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType); |
251 | |
252 | // Return true if the checks pass |
253 | bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); |
254 | |
255 | // Set to true when the last/current declarator list was started with an empty declaration. |
256 | bool mDeferredSingleDeclarationErrorCheck; |
257 | |
258 | GLenum mShaderType; // vertex or fragment language (future: pack or unpack) |
259 | int mShaderVersion; |
260 | TIntermNode *mTreeRoot; // root of parse tree being created |
261 | int mLoopNestingLevel; // 0 if outside all loops |
262 | int mSwitchNestingLevel; // 0 if outside all switch statements |
263 | int mStructNestingLevel; // incremented while parsing a struct declaration |
264 | const TType *mCurrentFunctionType; // the return type of the function that's currently being parsed |
265 | bool mFunctionReturnsValue; // true if a non-void function has a return |
266 | bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. |
267 | |
268 | TLayoutMatrixPacking mDefaultMatrixPacking; |
269 | TLayoutBlockStorage mDefaultBlockStorage; |
270 | TDiagnostics mDiagnostics; |
271 | TDirectiveHandler mDirectiveHandler; |
272 | pp::Preprocessor mPreprocessor; |
273 | void *mScanner; |
274 | bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor |
275 | bool mUsesFragColor; |
276 | }; |
277 | |
278 | int PaParseStrings(int count, const char* const string[], const int length[], |
279 | TParseContext* context); |
280 | |
281 | #endif // _PARSER_HELPER_INCLUDED_ |
282 | |