// // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_ #define COMPILER_TRANSLATOR_PARSECONTEXT_H_ #include "compiler/translator/Compiler.h" #include "compiler/translator/Diagnostics.h" #include "compiler/translator/DirectiveHandler.h" #include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" #include "compiler/preprocessor/Preprocessor.h" struct TMatrixFields { bool wholeRow; bool wholeCol; int row; int col; }; // // The following are extra variables needed during parsing, grouped together so // they can be passed to the parser without needing a global. // class TParseContext : angle::NonCopyable { public: TParseContext(TSymbolTable &symt, TExtensionBehavior &ext, TIntermediate &interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, TInfoSink &is, const ShBuiltInResources &resources) : intermediate(interm), symbolTable(symt), mDeferredSingleDeclarationErrorCheck(false), mShaderType(type), mShaderSpec(spec), mShaderVersion(100), mTreeRoot(nullptr), mLoopNestingLevel(0), mStructNestingLevel(0), mSwitchNestingLevel(0), mCurrentFunctionType(nullptr), mFunctionReturnsValue(false), mChecksPrecisionErrors(checksPrecErrors), mFragmentPrecisionHighOnESSL1(false), mDefaultMatrixPacking(EmpColumnMajor), mDefaultBlockStorage(EbsShared), mDiagnostics(is), mDirectiveHandler(ext, mDiagnostics, mShaderVersion, mShaderType, resources.WEBGL_debug_shader_precision == 1), mPreprocessor(&mDiagnostics, &mDirectiveHandler), mScanner(nullptr), mUsesFragData(false), mUsesFragColor(false), mUsesSecondaryOutputs(false), mMinProgramTexelOffset(resources.MinProgramTexelOffset), mMaxProgramTexelOffset(resources.MaxProgramTexelOffset) { } const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } pp::Preprocessor &getPreprocessor() { return mPreprocessor; } void *getScanner() const { return mScanner; } void setScanner(void *scanner) { mScanner = scanner; } int getShaderVersion() const { return mShaderVersion; } sh::GLenum getShaderType() const { return mShaderType; } ShShaderSpec getShaderSpec() const { return mShaderSpec; } int numErrors() const { return mDiagnostics.numErrors(); } TInfoSink &infoSink() { return mDiagnostics.infoSink(); } void error(const TSourceLoc &loc, const char *reason, const char *token, const char *extraInfo=""); void warning(const TSourceLoc &loc, const char *reason, const char *token, const char *extraInfo=""); // If isError is false, a warning will be reported instead. void outOfRangeError(bool isError, const TSourceLoc &loc, const char *reason, const char *token, const char *extraInfo = ""); void recover(); TIntermNode *getTreeRoot() const { return mTreeRoot; } void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; } bool getFragmentPrecisionHigh() const { return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300; } void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh) { mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh; } void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; } void incrLoopNestingLevel() { ++mLoopNestingLevel; } void decrLoopNestingLevel() { --mLoopNestingLevel; } void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } void decrSwitchNestingLevel() { --mSwitchNestingLevel; } // This method is guaranteed to succeed, even if no variable with 'name' exists. const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol); TIntermTyped *parseVariableIdentifier(const TSourceLoc &location, const TString *name, const TSymbol *symbol); bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line); bool reservedErrorCheck(const TSourceLoc &line, const TString &identifier); void assignError(const TSourceLoc &line, const char *op, TString left, TString right); void unaryOpError(const TSourceLoc &line, const char *op, TString operand); void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right); bool precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type); bool lValueErrorCheck(const TSourceLoc &line, const char *op, TIntermTyped*); bool constErrorCheck(TIntermTyped *node); bool integerErrorCheck(TIntermTyped *node, const char *token); bool globalErrorCheck(const TSourceLoc &line, bool global, const char *token); bool constructorErrorCheck(const TSourceLoc &line, TIntermNode *argumentsNode, TFunction &function, TOperator op, TType *type); bool arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size); bool arrayQualifierErrorCheck(const TSourceLoc &line, const TPublicType &type); bool arrayTypeErrorCheck(const TSourceLoc &line, const TPublicType &type); bool voidErrorCheck(const TSourceLoc &line, const TString &identifier, const TBasicType &type); bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); bool boolErrorCheck(const TSourceLoc&, const TPublicType&); bool samplerErrorCheck(const TSourceLoc &line, const TPublicType &pType, const char *reason); bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType); bool parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType &type); bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType *type); bool extensionErrorCheck(const TSourceLoc &line, const TString&); bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation); bool layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier); bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation); void es3InputOutputTypeCheck(const TQualifier qualifier, const TPublicType &type, const TSourceLoc &qualifierLocation); const TPragma &pragma() const { return mDirectiveHandler.pragma(); } const TExtensionBehavior &extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); } bool supportsExtension(const char *extension); bool isExtensionEnabled(const char *extension) const; void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior); void handlePragmaDirective(const TSourceLoc &loc, const char *name, const char *value, bool stdgl); bool containsSampler(const TType &type); const TFunction* findFunction( const TSourceLoc &line, TFunction *pfnCall, int inputShaderVersion, bool *builtIn = 0); bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType, TIntermTyped *initializer, TIntermNode **intermNode); TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier); TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, const TSourceLoc &identifierOrTypeLocation, const TString &identifier); TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression); TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier, const TSourceLoc &initLocation, TIntermTyped *initializer); // Parse a declaration like "type a[n] = initializer" // Note that this does not apply to declarations like "type[n] a = initializer" TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression, const TSourceLoc &initLocation, TIntermTyped *initializer); TIntermAggregate *parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier, const TSymbol *symbol); TIntermAggregate *parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation, const TString &identifier); TIntermAggregate *parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation, const TString &identifier, const TSourceLoc &arrayLocation, TIntermTyped *indexExpression); TIntermAggregate *parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation, const TString &identifier, const TSourceLoc &initLocation, TIntermTyped *initializer); // Parse a declarator like "a[n] = initializer" TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation, const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression, const TSourceLoc &initLocation, TIntermTyped *initializer); void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location); TIntermAggregate *addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location); void parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut); TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function); TFunction *addConstructorFunc(const TPublicType &publicType); TIntermTyped *addConstructor(TIntermNode *arguments, TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line); TIntermTyped *addConstVectorNode(TVectorFields &fields, TIntermConstantUnion *node, const TSourceLoc &line, bool outOfRangeIndexIsError); TIntermTyped *addConstMatrixNode(int index, TIntermConstantUnion *node, const TSourceLoc &line, bool outOfRangeIndexIsError); TIntermTyped *addConstArrayNode(int index, TIntermConstantUnion *node, const TSourceLoc &line, bool outOfRangeIndexIsError); TIntermTyped *addConstStruct( const TString &identifier, TIntermTyped *node, const TSourceLoc& line); TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation, const TString &fieldString, const TSourceLoc &fieldLocation); TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList); TIntermAggregate* addInterfaceBlock(const TPublicType &typeQualifier, const TSourceLoc &nameLine, const TString &blockName, TFieldList *fieldList, const TString *instanceName, const TSourceLoc &instanceLine, TIntermTyped *arrayIndex, const TSourceLoc& arrayIndexLine); TLayoutQualifier parseLayoutQualifier( const TString &qualifierType, const TSourceLoc &qualifierTypeLine); TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc &qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc &intValueLine); TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier); TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, const TSourceLoc &storageLoc, TQualifier storageQualifier); // Performs an error check for embedded struct declarations. // Returns true if an error was raised due to the declaration of // this struct. bool enterStructDeclaration(const TSourceLoc &line, const TString &identifier); void exitStructDeclaration(); bool structNestingErrorCheck(const TSourceLoc &line, const TField &field); TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc); TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); TIntermCase *addDefault(const TSourceLoc &loc); TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc); TIntermTyped *addBinaryMath( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TIntermTyped *addBinaryMathBooleanResult( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TIntermTyped *addAssign( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc); void checkTextureOffsetConst(TIntermAggregate *functionCall); TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError); TIntermTyped *addTernarySelection( TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line); // TODO(jmadill): make these private TIntermediate &intermediate; // to hold and build a parse tree TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed private: bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable); bool nonInitErrorCheck(const TSourceLoc &line, const TString &identifier, TPublicType *type); TIntermTyped *addBinaryMathInternal( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TIntermTyped *createAssign( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); // The funcReturnType parameter is expected to be non-null when the operation is a built-in function. // It is expected to be null for other unary operators. TIntermTyped *createUnaryMath( TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType); // Return true if the checks pass bool binaryOpCommonCheck( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); // Set to true when the last/current declarator list was started with an empty declaration. bool mDeferredSingleDeclarationErrorCheck; sh::GLenum mShaderType; // vertex or fragment language (future: pack or unpack) ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. int mShaderVersion; TIntermNode *mTreeRoot; // root of parse tree being created int mLoopNestingLevel; // 0 if outside all loops int mStructNestingLevel; // incremented while parsing a struct declaration int mSwitchNestingLevel; // 0 if outside all switch statements const TType *mCurrentFunctionType; // the return type of the function that's currently being parsed bool mFunctionReturnsValue; // true if a non-void function has a return bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling // ESSL1. TLayoutMatrixPacking mDefaultMatrixPacking; TLayoutBlockStorage mDefaultBlockStorage; TString mHashErrMsg; TDiagnostics mDiagnostics; TDirectiveHandler mDirectiveHandler; pp::Preprocessor mPreprocessor; void *mScanner; bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor bool mUsesFragColor; bool mUsesSecondaryOutputs; // Track if we are using either gl_SecondaryFragData or // gl_Secondary FragColor or both. int mMinProgramTexelOffset; int mMaxProgramTexelOffset; }; int PaParseStrings( size_t count, const char *const string[], const int length[], TParseContext *context); #endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_