Some rationalization of TIntermediate (to own it's own tree root) and TParseHelper for better encapsulation. Needed by some upcoming intra-stage link validation.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22914 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-09-03 22:57:27 +00:00
parent 807b8e3b82
commit 2f1eb37d82
8 changed files with 107 additions and 82 deletions

View File

@ -41,6 +41,8 @@
#include "localintermediate.h" #include "localintermediate.h"
#include "QualifierAlive.h" #include "QualifierAlive.h"
#include "RemoveTree.h" #include "RemoveTree.h"
#include "SymbolTable.h"
#include <float.h> #include <float.h>
namespace glslang { namespace glslang {
@ -910,10 +912,10 @@ void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TVari
// //
// This deletes the tree. // This deletes the tree.
// //
void TIntermediate::remove(TIntermNode* root) void TIntermediate::removeTree()
{ {
if (root) if (treeRoot)
RemoveAllTreeNodes(root); RemoveAllTreeNodes(treeRoot);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -35,6 +35,7 @@
// //
#include "ParseHelper.h" #include "ParseHelper.h"
#include "osinclude.h" #include "osinclude.h"
#include <stdarg.h> #include <stdarg.h>
#include <algorithm> #include <algorithm>
@ -47,11 +48,11 @@ namespace glslang {
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb, int v, EProfile p, EShLanguage L, TInfoSink& is, TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb, int v, EProfile p, EShLanguage L, TInfoSink& is,
bool fc, EShMessages m) : bool fc, EShMessages m) :
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0), linkage(0), intermediate(interm), symbolTable(symt), infoSink(is), language(L),
numErrors(0), loopNestingLevel(0),
structNestingLevel(0), inTypeParen(false), parsingBuiltins(pb),
version(v), profile(p), forwardCompatible(fc), messages(m), version(v), profile(p), forwardCompatible(fc), messages(m),
contextPragma(true, false), afterEOF(false), tokensBeforeEOF(false) contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0),
linkage(0), tokensBeforeEOF(false),
parsingBuiltins(pb), numErrors(0), afterEOF(false)
{ {
currentLoc.line = 1; currentLoc.line = 1;
currentLoc.string = 0; currentLoc.string = 0;

View File

@ -69,50 +69,10 @@ public:
TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, EShLanguage, TInfoSink&, TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, EShLanguage, TInfoSink&,
bool forwardCompatible = false, EShMessages messages = EShMsgDefault); bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
TScanContext* scanContext; public:
TPpContext* ppContext;
TIntermediate& intermediate; // to hold and build a parse tree
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
TInfoSink& infoSink;
EShLanguage language; // vertex or fragment language
TIntermNode* treeRoot; // root of parse tree being created
TIntermAggregate *linkage; // aggregate node of objects the linker may need, if not reference by the rest of the AST
int numErrors; // number of compile-time errors encountered
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
bool inTypeParen; // true if in parentheses, looking only for an identifier
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
bool parsingBuiltins; // true if parsing built-in symbols/functions
int version; // version, updated by #version in the shader
EProfile profile; // the declared profile in the shader (core by default)
bool forwardCompatible; // true if errors are to be given for use of deprecated features
EShMessages messages; // errors/warnings
TMap<TString, TBehavior> extensionBehavior; // for each extension string, what it's current enablement is
struct TPragma contextPragma;
TPrecisionQualifier defaultPrecision[EbtNumTypes];
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2)); // see computeSamplerTypeIndex()
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
bool afterEOF;
bool tokensBeforeEOF;
TSourceLoc currentLoc;
const TString* blockName;
TQualifier globalUniformDefaults;
TQualifier globalInputDefaults;
TQualifier globalOutputDefaults;
TQualifier currentBlockDefaults;
void initializeExtensionBehavior();
const char* getPreamble();
bool parseShaderStrings(TPpContext&, char* strings[], int strLen[], int numStrings); bool parseShaderStrings(TPpContext&, char* strings[], int strLen[], int numStrings);
void parserError(const char *s); void initializeExtensionBehavior();
void parserError(const char *s); // for bison's yyerror
void handlePragma(const char **tokens, int numTokens);
TBehavior getExtensionBehavior(const char* behavior);
void updateExtensionBehavior(const char* extName, const char* behavior);
void C_DECL error(TSourceLoc, const char *szReason, const char *szToken, void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...); const char *szExtraInfoFormat, ...);
@ -120,6 +80,8 @@ public:
const char *szExtraInfoFormat, ...); const char *szExtraInfoFormat, ...);
bool reservedErrorCheck(TSourceLoc, const TString& identifier); bool reservedErrorCheck(TSourceLoc, const TString& identifier);
void updateExtensionBehavior(const char* extName, const char* behavior);
void handlePragma(const char **tokens, int numTokens);
TIntermTyped* handleVariable(TSourceLoc, TSymbol* symbol, TString* string); TIntermTyped* handleVariable(TSourceLoc, TSymbol* symbol, TString* string);
TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index); TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field); TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
@ -197,6 +159,59 @@ public:
void requireNotRemoved(TSourceLoc, EProfile callingProfile, int removedVersion, const char *featureDesc); void requireNotRemoved(TSourceLoc, EProfile callingProfile, int removedVersion, const char *featureDesc);
void fullIntegerCheck(TSourceLoc, const char* op); void fullIntegerCheck(TSourceLoc, const char* op);
void doubleCheck(TSourceLoc, const char* op); void doubleCheck(TSourceLoc, const char* op);
void setScanContext(TScanContext* c) { scanContext = c; }
TScanContext* getScanContext() const { return scanContext; }
void setPpContext(TPpContext* c) { ppContext = c; }
TPpContext* getPpContext() const { return ppContext; }
int getNumErrors() const { return numErrors; }
protected:
const char* getPreamble();
TBehavior getExtensionBehavior(const char* behavior);
public:
//
// Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
//
TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
TInfoSink& infoSink;
// compilation mode
EShLanguage language; // vertex or fragment language
int version; // version, updated by #version in the shader
EProfile profile; // the declared profile in the shader (core by default)
bool forwardCompatible; // true if errors are to be given for use of deprecated features
EShMessages messages; // errors/warnings
// Current state of parsing
struct TPragma contextPragma;
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
const TString* blockName;
TQualifier currentBlockDefaults;
TIntermAggregate *linkage; // aggregate node of objects the linker may need, if not referenced by the rest of the AST
TPrecisionQualifier defaultPrecision[EbtNumTypes];
TSourceLoc currentLoc;
bool tokensBeforeEOF;
protected:
TScanContext* scanContext;
TPpContext* ppContext;
int numErrors; // number of compile-time errors encountered
bool parsingBuiltins; // true if parsing built-in symbols/functions
TMap<TString, TBehavior> extensionBehavior; // for each extension string, what it's current enablement is
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2)); // see computeSamplerTypeIndex()
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
bool afterEOF;
TQualifier globalUniformDefaults;
TQualifier globalInputDefaults;
TQualifier globalOutputDefaults;
}; };
} // end namespace glslang } // end namespace glslang

View File

@ -245,7 +245,7 @@ int yylex(YYSTYPE* glslangTokenDesc, glslang::TParseContext& parseContext)
{ {
glslang::TParserToken token(*glslangTokenDesc); glslang::TParserToken token(*glslangTokenDesc);
return parseContext.scanContext->tokenize(parseContext.ppContext, token); return parseContext.getScanContext()->tokenize(parseContext.getPpContext(), token);
} }
namespace { namespace {

View File

@ -108,8 +108,8 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil
TParseContext parseContext(symbolTable, intermediate, true, version, profile, language, infoSink); TParseContext parseContext(symbolTable, intermediate, true, version, profile, language, infoSink);
TPpContext ppContext(parseContext); TPpContext ppContext(parseContext);
TScanContext scanContext(parseContext); TScanContext scanContext(parseContext);
parseContext.scanContext = &scanContext; parseContext.setScanContext(&scanContext);
parseContext.ppContext = &ppContext; parseContext.setPpContext(&ppContext);
// //
// Parse the built-ins. This should only happen once per // Parse the built-ins. This should only happen once per
@ -403,8 +403,8 @@ int __fastcall ShFinalize()
// Do an actual compile on the given strings. The result is left // Do an actual compile on the given strings. The result is left
// in the given compile object. // in the given compile object.
// //
// Return: The return value of ShCompile is really boolean, indicating // Return: The return value is really boolean, indicating
// success or failure. // success (1) or failure (0).
// //
int ShCompile( int ShCompile(
const ShHandle handle, const ShHandle handle,
@ -478,8 +478,8 @@ int ShCompile(
TParseContext parseContext(symbolTable, intermediate, false, version, profile, compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages); TParseContext parseContext(symbolTable, intermediate, false, version, profile, compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
glslang::TScanContext scanContext(parseContext); glslang::TScanContext scanContext(parseContext);
TPpContext ppContext(parseContext); TPpContext ppContext(parseContext);
parseContext.scanContext = &scanContext; parseContext.setScanContext(&scanContext);
parseContext.ppContext = &ppContext; parseContext.setPpContext(&ppContext);
TSourceLoc beginning; TSourceLoc beginning;
beginning.line = 1; beginning.line = 1;
@ -511,38 +511,36 @@ int ShCompile(
bool ret = parseContext.parseShaderStrings(ppContext, const_cast<char**>(shaderStrings), lengths, numStrings); bool ret = parseContext.parseShaderStrings(ppContext, const_cast<char**>(shaderStrings), lengths, numStrings);
if (! ret) if (! ret)
success = false; success = false;
intermediate.addSymbolLinkageNodes(parseContext.treeRoot, parseContext.linkage, parseContext.language, symbolTable); intermediate.addSymbolLinkageNodes(intermediate.getTreeRoot(), parseContext.linkage, parseContext.language, symbolTable);
// Clean up the symbol table before deallocating the pool memory it used. // Clean up the symbol table before deallocating the pool memory it used.
// The AST is self-sufficient now, so it can be done before the rest of compilation/linking. // The AST is self-sufficient now, so it can be done before the rest of compilation/linking.
delete symbolTableMemory; delete symbolTableMemory;
if (success && parseContext.treeRoot) { if (success && intermediate.getTreeRoot()) {
if (optLevel == EShOptNoGeneration) if (optLevel == EShOptNoGeneration)
parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested."); parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested.");
else { else {
success = intermediate.postProcess(parseContext.treeRoot, parseContext.language); success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.language);
if (success) { if (success) {
if (messages & EShMsgAST)
intermediate.outputTree(parseContext.treeRoot, parseContext.infoSink);
// //
// Call the machine dependent compiler // Call the machine dependent compiler
// //
if (! compiler->compile(parseContext.treeRoot, parseContext.version, parseContext.profile)) if (! compiler->compile(intermediate.getTreeRoot(), parseContext.version, parseContext.profile))
success = false; success = false;
} }
} }
} else if (! success) { } else if (! success) {
parseContext.infoSink.info.prefix(EPrefixError); parseContext.infoSink.info.prefix(EPrefixError);
parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n"; parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
success = false; success = false;
if (messages & EShMsgAST)
intermediate.outputTree(parseContext.treeRoot, parseContext.infoSink);
} }
intermediate.remove(parseContext.treeRoot); if (messages & EShMsgAST)
intermediate.outputTree(parseContext.infoSink);
intermediate.removeTree();
// //
// Throw away all the temporary memory used by the compilation process. // Throw away all the temporary memory used by the compilation process.
// //

View File

@ -2438,11 +2438,11 @@ jump_statement
translation_unit translation_unit
: external_declaration { : external_declaration {
$$ = $1; $$ = $1;
parseContext.treeRoot = $$; parseContext.intermediate.setTreeRoot($$);
} }
| translation_unit external_declaration { | translation_unit external_declaration {
$$ = parseContext.intermediate.growAggregate($1, $2); $$ = parseContext.intermediate.growAggregate($1, $2);
parseContext.treeRoot = $$; parseContext.intermediate.setTreeRoot($$);
} }
; ;

View File

@ -35,6 +35,7 @@
// //
#include "localintermediate.h" #include "localintermediate.h"
#include "../Include/InfoSink.h"
namespace glslang { namespace glslang {
@ -567,9 +568,9 @@ bool OutputSwitch(bool /* preVisit */, TIntermSwitch* node, TIntermTraverser* it
// Individual functions can be initialized to 0 to skip processing of that // Individual functions can be initialized to 0 to skip processing of that
// type of node. It's children will still be processed. // type of node. It's children will still be processed.
// //
void TIntermediate::outputTree(TIntermNode* root, TInfoSink& infoSink) void TIntermediate::outputTree(TInfoSink& infoSink)
{ {
if (root == 0) if (treeRoot == 0)
return; return;
TOutputTraverser it(infoSink); TOutputTraverser it(infoSink);
@ -584,7 +585,7 @@ void TIntermediate::outputTree(TIntermNode* root, TInfoSink& infoSink)
it.visitBranch = OutputBranch; it.visitBranch = OutputBranch;
it.visitSwitch = OutputSwitch; it.visitSwitch = OutputSwitch;
root->traverse(&it); treeRoot->traverse(&it);
} }
} // end namespace glslang } // end namespace glslang

View File

@ -37,9 +37,10 @@
#include "../Include/intermediate.h" #include "../Include/intermediate.h"
#include "../Public/ShaderLang.h" #include "../Public/ShaderLang.h"
#include "SymbolTable.h"
#include "Versions.h" #include "Versions.h"
class TInfoSink;
namespace glslang { namespace glslang {
struct TVectorFields { struct TVectorFields {
@ -47,14 +48,19 @@ struct TVectorFields {
int num; int num;
}; };
class TSymbolTable;
class TVariable;
// //
// Set of helper functions to help parse and build the tree. // Set of helper functions to help parse and build the tree.
// //
class TIntermediate { class TIntermediate {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) TIntermediate(int v, EProfile p) : treeRoot(0), profile(p), version(v) { }
void setTreeRoot(TIntermNode* r) { treeRoot = r; }
TIntermNode* getTreeRoot() const { return treeRoot; }
TIntermediate(int v, EProfile p) : version(v), profile(p) { }
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
@ -86,10 +92,12 @@ public:
void addSymbolLinkageNodes(TIntermNode* root, TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); void addSymbolLinkageNodes(TIntermNode* root, TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
void addSymbolLinkageNode(TIntermAggregate*& linkage, const TVariable&); void addSymbolLinkageNode(TIntermAggregate*& linkage, const TVariable&);
void remove(TIntermNode*);
void outputTree(TIntermNode*, TInfoSink&); void outputTree(TInfoSink& infoSink);
void removeTree();
protected: protected:
TIntermNode* treeRoot;
EProfile profile; EProfile profile;
int version; int version;