blob: 10e1895660dfed536321495256d65d2bc2ca7d5e [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman66b8ab22014-05-06 15:57:45 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman66b8ab22014-05-06 15:57:45 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// 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.
John Bauman66b8ab22014-05-06 15:57:45 -040014#ifndef _PARSER_HELPER_INCLUDED_
15#define _PARSER_HELPER_INCLUDED_
16
Nicolas Capenscc863da2015-01-21 15:50:55 -050017#include "Diagnostics.h"
18#include "DirectiveHandler.h"
19#include "localintermediate.h"
20#include "preprocessor/Preprocessor.h"
Nicolas Capensd8cbf392015-02-10 15:35:11 -050021#include "Compiler.h"
Nicolas Capenscc863da2015-01-21 15:50:55 -050022#include "SymbolTable.h"
John Bauman66b8ab22014-05-06 15:57:45 -040023
24struct TMatrixFields {
Nicolas Capens0bac2852016-05-07 06:09:58 -040025 bool wholeRow;
26 bool wholeCol;
27 int row;
28 int col;
John Bauman66b8ab22014-05-06 15:57:45 -040029};
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//
Alexis Hetu0a655842015-06-22 16:52:11 -040035class TParseContext {
36public:
Nicolas Capens0bac2852016-05-07 06:09:58 -040037 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),
Alexis Hetue13238e2017-12-15 18:01:07 -050059 mPreprocessor(&mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
Nicolas Capens0bac2852016-05-07 06:09:58 -040060 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;
John Bauman66b8ab22014-05-06 15:57:45 -040070
Nicolas Capens0bac2852016-05-07 06:09:58 -040071 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="");
Nicolas Capens937e6a52018-05-29 17:11:37 -040083 void info(const TSourceLoc &loc, const char* reason, const char* token,
84 const char* extraInfo="");
Nicolas Capens0bac2852016-05-07 06:09:58 -040085 void trace(const char* str);
86 void recover();
87 TIntermNode *getTreeRoot() const { return mTreeRoot; }
88 void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; }
Alexis Hetu407813b2016-02-24 16:46:13 -050089
Nicolas Capens0bac2852016-05-07 06:09:58 -040090 bool getFunctionReturnsValue() const { return mFunctionReturnsValue; }
91 void setFunctionReturnsValue(bool functionReturnsValue)
92 {
93 mFunctionReturnsValue = functionReturnsValue;
94 }
Alexis Hetu407813b2016-02-24 16:46:13 -050095
Nicolas Capens0bac2852016-05-07 06:09:58 -040096 void setLoopNestingLevel(int loopNestintLevel)
97 {
98 mLoopNestingLevel = loopNestintLevel;
99 }
Alexis Hetu407813b2016-02-24 16:46:13 -0500100
Nicolas Capens0bac2852016-05-07 06:09:58 -0400101 const TType *getCurrentFunctionType() const { return mCurrentFunctionType; }
102 void setCurrentFunctionType(const TType *currentFunctionType)
103 {
104 mCurrentFunctionType = currentFunctionType;
105 }
Alexis Hetu407813b2016-02-24 16:46:13 -0500106
Nicolas Capens0bac2852016-05-07 06:09:58 -0400107 void incrLoopNestingLevel() { ++mLoopNestingLevel; }
108 void decrLoopNestingLevel() { --mLoopNestingLevel; }
Alexis Hetu407813b2016-02-24 16:46:13 -0500109
Nicolas Capens0bac2852016-05-07 06:09:58 -0400110 void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }
111 void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
Alexis Hetu76a343a2015-06-04 17:21:22 -0400112
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400113 // 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
Nicolas Capens0bac2852016-05-07 06:09:58 -0400116 bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line);
John Bauman66b8ab22014-05-06 15:57:45 -0400117
Nicolas Capens0bac2852016-05-07 06:09:58 -0400118 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);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400135 bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400136 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&);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400142 bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400143 bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier);
144 bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
Alexis Hetuad527752015-07-07 13:31:44 -0400145 void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation);
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500146 void checkInputOutputTypeIsValidES3(const TQualifier qualifier, const TPublicType &type, const TSourceLoc &qualifierLocation);
John Bauman66b8ab22014-05-06 15:57:45 -0400147
Nicolas Capens0bac2852016-05-07 06:09:58 -0400148 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);
John Bauman66b8ab22014-05-06 15:57:45 -0400151
Nicolas Capens0bac2852016-05-07 06:09:58 -0400152 const TPragma& pragma() const { return mDirectiveHandler.pragma(); }
Alexis Hetue13238e2017-12-15 18:01:07 -0500153 void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value, bool stdgl);
John Bauman66b8ab22014-05-06 15:57:45 -0400154
Nicolas Capens0bac2852016-05-07 06:09:58 -0400155 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);
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400159
Nicolas Capens0bac2852016-05-07 06:09:58 -0400160 TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier);
161 bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&);
John Bauman66b8ab22014-05-06 15:57:45 -0400162
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400163 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
Nicolas Capens0bac2852016-05-07 06:09:58 -0400190 void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
Alexis Hetu407813b2016-02-24 16:46:13 -0500191 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);
Alexis Hetue5246692015-06-18 12:34:52 -0400195 TFunction *addConstructorFunc(const TPublicType &publicType);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400196 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);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400204
Nicolas Capens0bac2852016-05-07 06:09:58 -0400205 TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
206 TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList);
John Bauman66b8ab22014-05-06 15:57:45 -0400207
Nicolas Capens0bac2852016-05-07 06:09:58 -0400208 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);
Alexis Hetua35d8232015-06-11 17:11:06 -0400210
Nicolas Capens0bac2852016-05-07 06:09:58 -0400211 TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine);
212 TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, 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);
Nicolas Capens7d626792015-02-17 17:58:31 -0500215
Nicolas Capens0bac2852016-05-07 06:09:58 -0400216 // 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();
John Bauman66b8ab22014-05-06 15:57:45 -0400221
Alexis Hetuad6b8752015-06-09 16:15:30 -0400222 bool structNestingErrorCheck(const TSourceLoc &line, const TField &field);
223
Alexis Hetu76a343a2015-06-04 17:21:22 -0400224 TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
225 TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
226 TIntermCase *addDefault(const TSourceLoc &loc);
227
Alexis Hetuad6b8752015-06-09 16:15:30 -0400228 TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
229 TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
Alexis Hetub4769582015-06-16 12:19:50 -0400230 TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
231 TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400232
Alexis Hetue5246692015-06-18 12:34:52 -0400233 TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
234
Alexis Hetu76a343a2015-06-04 17:21:22 -0400235 TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
236 TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
237
Alexis Hetub3ff42c2015-07-03 18:19:57 -0400238 TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError);
239
Alexis Hetueee212e2015-07-07 17:13:30 -0400240 TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line);
241
Alexis Hetuad6b8752015-06-09 16:15:30 -0400242private:
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400243 bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable);
244
Alexis Hetub4769582015-06-16 12:19:50 -0400245 TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetue5246692015-06-18 12:34:52 -0400246 TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetub4769582015-06-16 12:19:50 -0400247
Alexis Hetuad6b8752015-06-09 16:15:30 -0400248 // 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);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400254
Alexis Hetu407813b2016-02-24 16:46:13 -0500255 // 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
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400275 bool mUsesFragColor;
John Bauman66b8ab22014-05-06 15:57:45 -0400276};
277
278int PaParseStrings(int count, const char* const string[], const int length[],
279 TParseContext* context);
280
281#endif // _PARSER_HELPER_INCLUDED_