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: 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 71 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; } 87 88 bool getFunctionReturnsValue() const { return mFunctionReturnsValue; } 89 void setFunctionReturnsValue(bool functionReturnsValue) 90 { 91 mFunctionReturnsValue = functionReturnsValue; 92 } 93 94 void setLoopNestingLevel(int loopNestintLevel) 95 { 96 mLoopNestingLevel = loopNestintLevel; 97 } 98 99 const TType *getCurrentFunctionType() const { return mCurrentFunctionType; } 100 void setCurrentFunctionType(const TType *currentFunctionType) 101 { 102 mCurrentFunctionType = currentFunctionType; 103 } 104 105 void incrLoopNestingLevel() { ++mLoopNestingLevel; } 106 void decrLoopNestingLevel() { --mLoopNestingLevel; } 107 108 void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } 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 146 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); 149 150 const TPragma& pragma() const { return mDirectiveHandler.pragma(); } 151 void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value); 152 153 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); 157 158 TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier); 159 bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&); 160 161 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 188 void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); 189 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); 193 TFunction *addConstructorFunc(const TPublicType &publicType); 194 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); 202 203 TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); 204 TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList); 205 206 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); 208 209 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); 213 214 // 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(); 219 220 bool structNestingErrorCheck(const TSourceLoc &line, const TField &field); 221 222 TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc); 223 TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); 224 TIntermCase *addDefault(const TSourceLoc &loc); 225 226 TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); 227 TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc); 228 TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 229 TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 230 231 TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 232 233 TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); 234 TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc); 235 236 TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError); 237 238 TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line); 239 240 private: 241 bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable); 242 243 TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 244 TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); 245 246 // 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); 252 253 // 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 273 bool mUsesFragColor; 274 }; 275 276 int PaParseStrings(int count, const char* const string[], const int length[], 277 TParseContext* context); 278 279 #endif // _PARSER_HELPER_INCLUDED_ 280