blob: ea613ebc800d77869f1a87c8521e9d82c6155814 [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),
59 mPreprocessor(&mDiagnostics, &mDirectiveHandler),
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;
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);
115 bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc &line);
John Bauman66b8ab22014-05-06 15:57:45 -0400116
Nicolas Capens0bac2852016-05-07 06:09:58 -0400117 bool reservedErrorCheck(const TSourceLoc &line, const TString& identifier);
118 void assignError(const TSourceLoc &line, const char* op, TString left, TString right);
119 void unaryOpError(const TSourceLoc &line, const char* op, TString operand);
120 void binaryOpError(const TSourceLoc &line, const char* op, TString left, TString right);
121 bool precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type);
122 bool lValueErrorCheck(const TSourceLoc &line, const char* op, TIntermTyped*);
123 bool constErrorCheck(TIntermTyped* node);
124 bool integerErrorCheck(TIntermTyped* node, const char* token);
125 bool globalErrorCheck(const TSourceLoc &line, bool global, const char* token);
126 bool constructorErrorCheck(const TSourceLoc &line, TIntermNode*, TFunction&, TOperator, TType*);
127 bool arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped* expr, int& size);
128 bool arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type);
129 bool arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type);
130 bool voidErrorCheck(const TSourceLoc&, const TString&, const TBasicType&);
131 bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
132 bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
133 bool samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400134 bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400135 bool structQualifierErrorCheck(const TSourceLoc &line, const TPublicType& pType);
136 bool parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType& type);
137 bool nonInitConstErrorCheck(const TSourceLoc &line, TString& identifier, TPublicType& type, bool array);
138 bool nonInitErrorCheck(const TSourceLoc &line, const TString& identifier, TPublicType& type);
139 bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
140 bool extensionErrorCheck(const TSourceLoc &line, const TString&);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400141 bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400142 bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier);
143 bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
Alexis Hetuad527752015-07-07 13:31:44 -0400144 void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation);
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500145 void checkInputOutputTypeIsValidES3(const TQualifier qualifier, const TPublicType &type, const TSourceLoc &qualifierLocation);
John Bauman66b8ab22014-05-06 15:57:45 -0400146
Nicolas Capens0bac2852016-05-07 06:09:58 -0400147 const TExtensionBehavior& extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); }
148 bool supportsExtension(const char* extension);
149 void handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior);
John Bauman66b8ab22014-05-06 15:57:45 -0400150
Nicolas Capens0bac2852016-05-07 06:09:58 -0400151 const TPragma& pragma() const { return mDirectiveHandler.pragma(); }
152 void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value);
John Bauman66b8ab22014-05-06 15:57:45 -0400153
Nicolas Capens0bac2852016-05-07 06:09:58 -0400154 bool containsSampler(TType& type);
155 const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0);
156 bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType,
157 TIntermTyped *initializer, TIntermNode **intermNode);
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400158
Nicolas Capens0bac2852016-05-07 06:09:58 -0400159 TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier);
160 bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&);
John Bauman66b8ab22014-05-06 15:57:45 -0400161
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400162 TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, const TSourceLoc &identifierOrTypeLocation, const TString &identifier);
163 TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
164 const TSourceLoc &indexLocation, TIntermTyped *indexExpression);
165 TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
166 const TSourceLoc &initLocation, TIntermTyped *initializer);
167
168 // Parse a declaration like "type a[n] = initializer"
169 // Note that this does not apply to declarations like "type[n] a = initializer"
170 TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
171 const TSourceLoc &indexLocation, TIntermTyped *indexExpression,
172 const TSourceLoc &initLocation, TIntermTyped *initializer);
173
174 TIntermAggregate *parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier,
175 const TSymbol *symbol);
176
177 TIntermAggregate *parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
178 const TString &identifier);
179 TIntermAggregate *parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
180 const TString &identifier, const TSourceLoc &arrayLocation, TIntermTyped *indexExpression);
181 TIntermAggregate *parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
182 const TString &identifier, const TSourceLoc &initLocation, TIntermTyped *initializer);
183
184 // Parse a declarator like "a[n] = initializer"
185 TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
186 const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression,
187 const TSourceLoc &initLocation, TIntermTyped *initializer);
188
Nicolas Capens0bac2852016-05-07 06:09:58 -0400189 void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
Alexis Hetu407813b2016-02-24 16:46:13 -0500190 TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location);
191 TIntermAggregate *addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location);
192 void parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut);
193 TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function);
Alexis Hetue5246692015-06-18 12:34:52 -0400194 TFunction *addConstructorFunc(const TPublicType &publicType);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400195 TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
196 TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
197 TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
198 TIntermTyped* addConstMatrixNode(int, TIntermTyped*, const TSourceLoc&);
199 TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line);
200 TIntermTyped* addConstStruct(const TString&, TIntermTyped*, const TSourceLoc&);
201 TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
202 TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation, const TString &fieldString, const TSourceLoc &fieldLocation);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400203
Nicolas Capens0bac2852016-05-07 06:09:58 -0400204 TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
205 TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList);
John Bauman66b8ab22014-05-06 15:57:45 -0400206
Nicolas Capens0bac2852016-05-07 06:09:58 -0400207 TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
208 const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine);
Alexis Hetua35d8232015-06-11 17:11:06 -0400209
Nicolas Capens0bac2852016-05-07 06:09:58 -0400210 TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine);
211 TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine);
212 TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier);
213 TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, const TSourceLoc &storageLoc, TQualifier storageQualifier);
Nicolas Capens7d626792015-02-17 17:58:31 -0500214
Nicolas Capens0bac2852016-05-07 06:09:58 -0400215 // Performs an error check for embedded struct declarations.
216 // Returns true if an error was raised due to the declaration of
217 // this struct.
218 bool enterStructDeclaration(const TSourceLoc &line, const TString& identifier);
219 void exitStructDeclaration();
John Bauman66b8ab22014-05-06 15:57:45 -0400220
Alexis Hetuad6b8752015-06-09 16:15:30 -0400221 bool structNestingErrorCheck(const TSourceLoc &line, const TField &field);
222
Alexis Hetu76a343a2015-06-04 17:21:22 -0400223 TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
224 TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
225 TIntermCase *addDefault(const TSourceLoc &loc);
226
Alexis Hetuad6b8752015-06-09 16:15:30 -0400227 TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
228 TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
Alexis Hetub4769582015-06-16 12:19:50 -0400229 TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
230 TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400231
Alexis Hetue5246692015-06-18 12:34:52 -0400232 TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
233
Alexis Hetu76a343a2015-06-04 17:21:22 -0400234 TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
235 TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
236
Alexis Hetub3ff42c2015-07-03 18:19:57 -0400237 TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError);
238
Alexis Hetueee212e2015-07-07 17:13:30 -0400239 TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line);
240
Alexis Hetuad6b8752015-06-09 16:15:30 -0400241private:
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400242 bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable);
243
Alexis Hetub4769582015-06-16 12:19:50 -0400244 TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetue5246692015-06-18 12:34:52 -0400245 TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetub4769582015-06-16 12:19:50 -0400246
Alexis Hetuad6b8752015-06-09 16:15:30 -0400247 // The funcReturnType parameter is expected to be non-null when the operation is a built-in function.
248 // It is expected to be null for other unary operators.
249 TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType);
250
251 // Return true if the checks pass
252 bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400253
Alexis Hetu407813b2016-02-24 16:46:13 -0500254 // Set to true when the last/current declarator list was started with an empty declaration.
255 bool mDeferredSingleDeclarationErrorCheck;
256
257 GLenum mShaderType; // vertex or fragment language (future: pack or unpack)
258 int mShaderVersion;
259 TIntermNode *mTreeRoot; // root of parse tree being created
260 int mLoopNestingLevel; // 0 if outside all loops
261 int mSwitchNestingLevel; // 0 if outside all switch statements
262 int mStructNestingLevel; // incremented while parsing a struct declaration
263 const TType *mCurrentFunctionType; // the return type of the function that's currently being parsed
264 bool mFunctionReturnsValue; // true if a non-void function has a return
265 bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
266
267 TLayoutMatrixPacking mDefaultMatrixPacking;
268 TLayoutBlockStorage mDefaultBlockStorage;
269 TDiagnostics mDiagnostics;
270 TDirectiveHandler mDirectiveHandler;
271 pp::Preprocessor mPreprocessor;
272 void *mScanner;
273 bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400274 bool mUsesFragColor;
John Bauman66b8ab22014-05-06 15:57:45 -0400275};
276
277int PaParseStrings(int count, const char* const string[], const int length[],
278 TParseContext* context);
279
280#endif // _PARSER_HELPER_INCLUDED_