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
24struct 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//
35class TParseContext {
36public:
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* extraInfo="");
81 void warning(const TSourceLoc &loc, const char* reason, const char* token,
82 const char* extraInfo="");
83 void info(const TSourceLoc &loc, const char* reason, const char* token,
84 const char* extraInfo="");
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
242private:
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
278int PaParseStrings(int count, const char* const string[], const int length[],
279 TParseContext* context);
280
281#endif // _PARSER_HELPER_INCLUDED_
282