blob: 07abf0f7b6d0973f112e071627fd3069b1d7449a [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="");
83 void trace(const char* str);
84 void recover();
85 TIntermNode *getTreeRoot() const { return mTreeRoot; }
86 void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; }
Alexis Hetu407813b2016-02-24 16:46:13 -050087
Nicolas Capens0bac2852016-05-07 06:09:58 -040088 bool getFunctionReturnsValue() const { return mFunctionReturnsValue; }
89 void setFunctionReturnsValue(bool functionReturnsValue)
90 {
91 mFunctionReturnsValue = functionReturnsValue;
92 }
Alexis Hetu407813b2016-02-24 16:46:13 -050093
Nicolas Capens0bac2852016-05-07 06:09:58 -040094 void setLoopNestingLevel(int loopNestintLevel)
95 {
96 mLoopNestingLevel = loopNestintLevel;
97 }
Alexis Hetu407813b2016-02-24 16:46:13 -050098
Nicolas Capens0bac2852016-05-07 06:09:58 -040099 const TType *getCurrentFunctionType() const { return mCurrentFunctionType; }
100 void setCurrentFunctionType(const TType *currentFunctionType)
101 {
102 mCurrentFunctionType = currentFunctionType;
103 }
Alexis Hetu407813b2016-02-24 16:46:13 -0500104
Nicolas Capens0bac2852016-05-07 06:09:58 -0400105 void incrLoopNestingLevel() { ++mLoopNestingLevel; }
106 void decrLoopNestingLevel() { --mLoopNestingLevel; }
Alexis Hetu407813b2016-02-24 16:46:13 -0500107
Nicolas Capens0bac2852016-05-07 06:09:58 -0400108 void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }
109 void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
Alexis Hetu76a343a2015-06-04 17:21:22 -0400110
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400111 // This method is guaranteed to succeed, even if no variable with 'name' exists.
112 const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol);
113
Nicolas Capens0bac2852016-05-07 06:09:58 -0400114 bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line);
John Bauman66b8ab22014-05-06 15:57:45 -0400115
Nicolas Capens0bac2852016-05-07 06:09:58 -0400116 bool reservedErrorCheck(const TSourceLoc &line, const TString& identifier);
117 void assignError(const TSourceLoc &line, const char* op, TString left, TString right);
118 void unaryOpError(const TSourceLoc &line, const char* op, TString operand);
119 void binaryOpError(const TSourceLoc &line, const char* op, TString left, TString right);
120 bool precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type);
121 bool lValueErrorCheck(const TSourceLoc &line, const char* op, TIntermTyped*);
122 bool constErrorCheck(TIntermTyped* node);
123 bool integerErrorCheck(TIntermTyped* node, const char* token);
124 bool globalErrorCheck(const TSourceLoc &line, bool global, const char* token);
125 bool constructorErrorCheck(const TSourceLoc &line, TIntermNode*, TFunction&, TOperator, TType*);
126 bool arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped* expr, int& size);
127 bool arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type);
128 bool arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type);
129 bool voidErrorCheck(const TSourceLoc&, const TString&, const TBasicType&);
130 bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
131 bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
132 bool samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400133 bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400134 bool structQualifierErrorCheck(const TSourceLoc &line, const TPublicType& pType);
135 bool parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType& type);
136 bool nonInitConstErrorCheck(const TSourceLoc &line, TString& identifier, TPublicType& type, bool array);
137 bool nonInitErrorCheck(const TSourceLoc &line, const TString& identifier, TPublicType& type);
138 bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
139 bool extensionErrorCheck(const TSourceLoc &line, const TString&);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400140 bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400141 bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier);
142 bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
Alexis Hetuad527752015-07-07 13:31:44 -0400143 void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation);
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500144 void checkInputOutputTypeIsValidES3(const TQualifier qualifier, const TPublicType &type, const TSourceLoc &qualifierLocation);
John Bauman66b8ab22014-05-06 15:57:45 -0400145
Nicolas Capens0bac2852016-05-07 06:09:58 -0400146 const TExtensionBehavior& extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); }
147 bool supportsExtension(const char* extension);
148 void handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior);
John Bauman66b8ab22014-05-06 15:57:45 -0400149
Nicolas Capens0bac2852016-05-07 06:09:58 -0400150 const TPragma& pragma() const { return mDirectiveHandler.pragma(); }
Alexis Hetue13238e2017-12-15 18:01:07 -0500151 void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value, bool stdgl);
John Bauman66b8ab22014-05-06 15:57:45 -0400152
Nicolas Capens0bac2852016-05-07 06:09:58 -0400153 bool containsSampler(TType& type);
154 const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0);
155 bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType,
156 TIntermTyped *initializer, TIntermNode **intermNode);
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400157
Nicolas Capens0bac2852016-05-07 06:09:58 -0400158 TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier);
159 bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&);
John Bauman66b8ab22014-05-06 15:57:45 -0400160
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400161 TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, const TSourceLoc &identifierOrTypeLocation, const TString &identifier);
162 TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
163 const TSourceLoc &indexLocation, TIntermTyped *indexExpression);
164 TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
165 const TSourceLoc &initLocation, TIntermTyped *initializer);
166
167 // Parse a declaration like "type a[n] = initializer"
168 // Note that this does not apply to declarations like "type[n] a = initializer"
169 TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
170 const TSourceLoc &indexLocation, TIntermTyped *indexExpression,
171 const TSourceLoc &initLocation, TIntermTyped *initializer);
172
173 TIntermAggregate *parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier,
174 const TSymbol *symbol);
175
176 TIntermAggregate *parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
177 const TString &identifier);
178 TIntermAggregate *parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
179 const TString &identifier, const TSourceLoc &arrayLocation, TIntermTyped *indexExpression);
180 TIntermAggregate *parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
181 const TString &identifier, const TSourceLoc &initLocation, TIntermTyped *initializer);
182
183 // Parse a declarator like "a[n] = initializer"
184 TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
185 const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression,
186 const TSourceLoc &initLocation, TIntermTyped *initializer);
187
Nicolas Capens0bac2852016-05-07 06:09:58 -0400188 void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
Alexis Hetu407813b2016-02-24 16:46:13 -0500189 TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location);
190 TIntermAggregate *addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location);
191 void parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut);
192 TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function);
Alexis Hetue5246692015-06-18 12:34:52 -0400193 TFunction *addConstructorFunc(const TPublicType &publicType);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400194 TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
195 TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
196 TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
197 TIntermTyped* addConstMatrixNode(int, TIntermTyped*, const TSourceLoc&);
198 TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line);
199 TIntermTyped* addConstStruct(const TString&, TIntermTyped*, const TSourceLoc&);
200 TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
201 TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation, const TString &fieldString, const TSourceLoc &fieldLocation);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400202
Nicolas Capens0bac2852016-05-07 06:09:58 -0400203 TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
204 TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList);
John Bauman66b8ab22014-05-06 15:57:45 -0400205
Nicolas Capens0bac2852016-05-07 06:09:58 -0400206 TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
207 const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine);
Alexis Hetua35d8232015-06-11 17:11:06 -0400208
Nicolas Capens0bac2852016-05-07 06:09:58 -0400209 TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine);
210 TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine);
211 TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier);
212 TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, const TSourceLoc &storageLoc, TQualifier storageQualifier);
Nicolas Capens7d626792015-02-17 17:58:31 -0500213
Nicolas Capens0bac2852016-05-07 06:09:58 -0400214 // Performs an error check for embedded struct declarations.
215 // Returns true if an error was raised due to the declaration of
216 // this struct.
217 bool enterStructDeclaration(const TSourceLoc &line, const TString& identifier);
218 void exitStructDeclaration();
John Bauman66b8ab22014-05-06 15:57:45 -0400219
Alexis Hetuad6b8752015-06-09 16:15:30 -0400220 bool structNestingErrorCheck(const TSourceLoc &line, const TField &field);
221
Alexis Hetu76a343a2015-06-04 17:21:22 -0400222 TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
223 TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
224 TIntermCase *addDefault(const TSourceLoc &loc);
225
Alexis Hetuad6b8752015-06-09 16:15:30 -0400226 TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
227 TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
Alexis Hetub4769582015-06-16 12:19:50 -0400228 TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
229 TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400230
Alexis Hetue5246692015-06-18 12:34:52 -0400231 TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
232
Alexis Hetu76a343a2015-06-04 17:21:22 -0400233 TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
234 TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
235
Alexis Hetub3ff42c2015-07-03 18:19:57 -0400236 TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError);
237
Alexis Hetueee212e2015-07-07 17:13:30 -0400238 TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line);
239
Alexis Hetuad6b8752015-06-09 16:15:30 -0400240private:
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400241 bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable);
242
Alexis Hetub4769582015-06-16 12:19:50 -0400243 TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetue5246692015-06-18 12:34:52 -0400244 TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetub4769582015-06-16 12:19:50 -0400245
Alexis Hetuad6b8752015-06-09 16:15:30 -0400246 // The funcReturnType parameter is expected to be non-null when the operation is a built-in function.
247 // It is expected to be null for other unary operators.
248 TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType);
249
250 // Return true if the checks pass
251 bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400252
Alexis Hetu407813b2016-02-24 16:46:13 -0500253 // Set to true when the last/current declarator list was started with an empty declaration.
254 bool mDeferredSingleDeclarationErrorCheck;
255
256 GLenum mShaderType; // vertex or fragment language (future: pack or unpack)
257 int mShaderVersion;
258 TIntermNode *mTreeRoot; // root of parse tree being created
259 int mLoopNestingLevel; // 0 if outside all loops
260 int mSwitchNestingLevel; // 0 if outside all switch statements
261 int mStructNestingLevel; // incremented while parsing a struct declaration
262 const TType *mCurrentFunctionType; // the return type of the function that's currently being parsed
263 bool mFunctionReturnsValue; // true if a non-void function has a return
264 bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
265
266 TLayoutMatrixPacking mDefaultMatrixPacking;
267 TLayoutBlockStorage mDefaultBlockStorage;
268 TDiagnostics mDiagnostics;
269 TDirectiveHandler mDirectiveHandler;
270 pp::Preprocessor mPreprocessor;
271 void *mScanner;
272 bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400273 bool mUsesFragColor;
John Bauman66b8ab22014-05-06 15:57:45 -0400274};
275
276int PaParseStrings(int count, const char* const string[], const int length[],
277 TParseContext* context);
278
279#endif // _PARSER_HELPER_INCLUDED_