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: TParseContext(TSymbolTable & symt,TExtensionBehavior & ext,TIntermediate & interm,GLenum type,int options,bool checksPrecErrors,const char * sourcePath,TInfoSink & is)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), 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 getPreprocessor()71 const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } getPreprocessor()72 pp::Preprocessor &getPreprocessor() { return mPreprocessor; } getScanner()73 void *getScanner() const { return mScanner; } setScanner(void * scanner)74 void setScanner(void *scanner) { mScanner = scanner; } getShaderVersion()75 int getShaderVersion() const { return mShaderVersion; } getShaderType()76 GLenum getShaderType() const { return mShaderType; } numErrors()77 int numErrors() const { return mDiagnostics.numErrors(); } infoSink()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(); getTreeRoot()85 TIntermNode *getTreeRoot() const { return mTreeRoot; } setTreeRoot(TIntermNode * treeRoot)86 void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; } 87 getFunctionReturnsValue()88 bool getFunctionReturnsValue() const { return mFunctionReturnsValue; } setFunctionReturnsValue(bool functionReturnsValue)89 void setFunctionReturnsValue(bool functionReturnsValue) 90 { 91 mFunctionReturnsValue = functionReturnsValue; 92 } 93 setLoopNestingLevel(int loopNestintLevel)94 void setLoopNestingLevel(int loopNestintLevel) 95 { 96 mLoopNestingLevel = loopNestintLevel; 97 } 98 getCurrentFunctionType()99 const TType *getCurrentFunctionType() const { return mCurrentFunctionType; } setCurrentFunctionType(const TType * currentFunctionType)100 void setCurrentFunctionType(const TType *currentFunctionType) 101 { 102 mCurrentFunctionType = currentFunctionType; 103 } 104 incrLoopNestingLevel()105 void incrLoopNestingLevel() { ++mLoopNestingLevel; } decrLoopNestingLevel()106 void decrLoopNestingLevel() { --mLoopNestingLevel; } 107 incrSwitchNestingLevel()108 void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } decrSwitchNestingLevel()109 void decrSwitchNestingLevel() { --mSwitchNestingLevel; } 110 111 // 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 114 bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line); 115 bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc &line); 116 117 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); 134 bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType); 135 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&); 141 bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation); 142 bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier); 143 bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); 144 void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation); 145 void checkInputOutputTypeIsValidES3(const TQualifier qualifier, const TPublicType &type, const TSourceLoc &qualifierLocation); 146 extensionBehavior()147 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); 150 pragma()151 const TPragma& pragma() const { return mDirectiveHandler.pragma(); } 152 void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value); 153 154 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); 158 159 TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier); 160 bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&); 161 162 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 189 void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); 190 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); 194 TFunction *addConstructorFunc(const TPublicType &publicType); 195 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); 203 204 TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); 205 TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList); 206 207 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); 209 210 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); 214 215 // 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(); 220 221 bool structNestingErrorCheck(const TSourceLoc &line, const TField &field); 222 223 TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc); 224 TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); 225 TIntermCase *addDefault(const TSourceLoc &loc); 226 227 TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); 228 TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc); 229 TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 230 TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 231 232 TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 233 234 TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); 235 TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc); 236 237 TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError); 238 239 TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line); 240 241 private: 242 bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable); 243 244 TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 245 TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 246 247 // 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); 253 254 // 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 274 bool mUsesFragColor; 275 }; 276 277 int PaParseStrings(int count, const char* const string[], const int length[], 278 TParseContext* context); 279 280 #endif // _PARSER_HELPER_INCLUDED_ 281