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, 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 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 info(const TSourceLoc &loc, const char* reason, const char* token, 84 const char* extraInfo=""); 85 void trace(const char* str); 86 void recover(); getTreeRoot()87 TIntermNode *getTreeRoot() const { return mTreeRoot; } setTreeRoot(TIntermNode * treeRoot)88 void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; } 89 getFunctionReturnsValue()90 bool getFunctionReturnsValue() const { return mFunctionReturnsValue; } setFunctionReturnsValue(bool functionReturnsValue)91 void setFunctionReturnsValue(bool functionReturnsValue) 92 { 93 mFunctionReturnsValue = functionReturnsValue; 94 } 95 setLoopNestingLevel(int loopNestintLevel)96 void setLoopNestingLevel(int loopNestintLevel) 97 { 98 mLoopNestingLevel = loopNestintLevel; 99 } 100 getCurrentFunctionType()101 const TType *getCurrentFunctionType() const { return mCurrentFunctionType; } setCurrentFunctionType(const TType * currentFunctionType)102 void setCurrentFunctionType(const TType *currentFunctionType) 103 { 104 mCurrentFunctionType = currentFunctionType; 105 } 106 incrLoopNestingLevel()107 void incrLoopNestingLevel() { ++mLoopNestingLevel; } decrLoopNestingLevel()108 void decrLoopNestingLevel() { --mLoopNestingLevel; } 109 incrSwitchNestingLevel()110 void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } decrSwitchNestingLevel()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 extensionBehavior()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 pragma()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, 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); 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 242 private: 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 278 int PaParseStrings(int count, const char* const string[], const int length[], 279 TParseContext* context); 280 281 #endif // _PARSER_HELPER_INCLUDED_ 282