mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-10 04:20:06 +00:00
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:
parent
807b8e3b82
commit
2f1eb37d82
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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($$);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user