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

View File

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

View File

@ -69,50 +69,10 @@ public:
TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, EShLanguage, TInfoSink&,
bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
TScanContext* scanContext;
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();
public:
bool parseShaderStrings(TPpContext&, char* strings[], int strLen[], int numStrings);
void parserError(const char *s);
void handlePragma(const char **tokens, int numTokens);
TBehavior getExtensionBehavior(const char* behavior);
void updateExtensionBehavior(const char* extName, const char* behavior);
void initializeExtensionBehavior();
void parserError(const char *s); // for bison's yyerror
void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...);
@ -120,6 +80,8 @@ public:
const char *szExtraInfoFormat, ...);
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* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
@ -197,6 +159,59 @@ public:
void requireNotRemoved(TSourceLoc, EProfile callingProfile, int removedVersion, const char *featureDesc);
void fullIntegerCheck(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

View File

@ -245,7 +245,7 @@ int yylex(YYSTYPE* glslangTokenDesc, glslang::TParseContext& parseContext)
{
glslang::TParserToken token(*glslangTokenDesc);
return parseContext.scanContext->tokenize(parseContext.ppContext, token);
return parseContext.getScanContext()->tokenize(parseContext.getPpContext(), token);
}
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);
TPpContext ppContext(parseContext);
TScanContext scanContext(parseContext);
parseContext.scanContext = &scanContext;
parseContext.ppContext = &ppContext;
parseContext.setScanContext(&scanContext);
parseContext.setPpContext(&ppContext);
//
// 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
// in the given compile object.
//
// Return: The return value of ShCompile is really boolean, indicating
// success or failure.
// Return: The return value is really boolean, indicating
// success (1) or failure (0).
//
int ShCompile(
const ShHandle handle,
@ -478,8 +478,8 @@ int ShCompile(
TParseContext parseContext(symbolTable, intermediate, false, version, profile, compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
glslang::TScanContext scanContext(parseContext);
TPpContext ppContext(parseContext);
parseContext.scanContext = &scanContext;
parseContext.ppContext = &ppContext;
parseContext.setScanContext(&scanContext);
parseContext.setPpContext(&ppContext);
TSourceLoc beginning;
beginning.line = 1;
@ -511,38 +511,36 @@ int ShCompile(
bool ret = parseContext.parseShaderStrings(ppContext, const_cast<char**>(shaderStrings), lengths, numStrings);
if (! ret)
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.
// The AST is self-sufficient now, so it can be done before the rest of compilation/linking.
delete symbolTableMemory;
if (success && parseContext.treeRoot) {
if (success && intermediate.getTreeRoot()) {
if (optLevel == EShOptNoGeneration)
parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested.");
else {
success = intermediate.postProcess(parseContext.treeRoot, parseContext.language);
success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.language);
if (success) {
if (messages & EShMsgAST)
intermediate.outputTree(parseContext.treeRoot, parseContext.infoSink);
//
// 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;
}
}
} else if (! success) {
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;
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.
//

View File

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

View File

@ -35,6 +35,7 @@
//
#include "localintermediate.h"
#include "../Include/InfoSink.h"
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
// 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;
TOutputTraverser it(infoSink);
@ -584,7 +585,7 @@ void TIntermediate::outputTree(TIntermNode* root, TInfoSink& infoSink)
it.visitBranch = OutputBranch;
it.visitSwitch = OutputSwitch;
root->traverse(&it);
treeRoot->traverse(&it);
}
} // end namespace glslang

View File

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