Create linkage symbol nodes in the AST so a linker has access to all global objects that were declared, for error checking, etc. Use it now for all ins/outs/uniforms as well as gl_VertexID and gl_InstanceID.
Also fixed a confusing name and added more 'const'. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22142 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
b29ba33089
commit
06f8464fb5
@ -34,6 +34,11 @@ uniform barBlockArray {
|
||||
int ni;
|
||||
} insts[4];
|
||||
|
||||
uniform unreferenced {
|
||||
float f;
|
||||
uint u;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
texture(s.sampler, vec3(inst.ni, bv.y, insts[2].nbv.z));
|
||||
|
@ -56,6 +56,7 @@
|
||||
enum TOperator {
|
||||
EOpNull, // if in a node, should only mean a node is still being built
|
||||
EOpSequence, // denotes a list of statements, or parameters, etc.
|
||||
EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST
|
||||
EOpFunctionCall,
|
||||
EOpFunction, // For function definition
|
||||
EOpParameters, // an aggregate listing the parameters to a function
|
||||
@ -353,6 +354,7 @@ public:
|
||||
|
||||
virtual TBasicType getBasicType() const { return type.getBasicType(); }
|
||||
virtual TQualifier& getQualifier() { return type.getQualifier(); }
|
||||
virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
|
||||
virtual void propagatePrecision(TPrecisionQualifier);
|
||||
virtual int getVectorSize() const { return type.getVectorSize(); }
|
||||
virtual int getMatrixCols() const { return type.getMatrixCols(); }
|
||||
@ -431,15 +433,15 @@ public:
|
||||
// if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
|
||||
// per process globalpoolallocator, then it causes increased memory usage per compile
|
||||
// it is essential to use "symbol = sym" to assign to symbol
|
||||
TIntermSymbol(int i, const TString& sym, const TType& t) :
|
||||
TIntermTyped(t), id(i) { symbol = sym;}
|
||||
TIntermSymbol(int i, const TString& n, const TType& t) :
|
||||
TIntermTyped(t), id(i) { name = n;}
|
||||
virtual int getId() const { return id; }
|
||||
virtual const TString& getSymbol() const { return symbol; }
|
||||
virtual const TString& getName() const { return name; }
|
||||
virtual void traverse(TIntermTraverser*);
|
||||
virtual TIntermSymbol* getAsSymbolNode() { return this; }
|
||||
protected:
|
||||
int id;
|
||||
TString symbol;
|
||||
TString name;
|
||||
};
|
||||
|
||||
class TIntermConstantUnion : public TIntermTyped {
|
||||
@ -519,12 +521,14 @@ public:
|
||||
virtual TIntermAggregate* getAsAggregate() { return this; }
|
||||
virtual void setOperator(TOperator o) { op = o; }
|
||||
virtual TIntermSequence& getSequence() { return sequence; }
|
||||
virtual const TIntermSequence& getSequence() const { return sequence; }
|
||||
virtual void setName(const TString& n) { name = n; }
|
||||
virtual const TString& getName() const { return name; }
|
||||
virtual void traverse(TIntermTraverser*);
|
||||
virtual void setUserDefined() { userDefined = true; }
|
||||
virtual bool isUserDefined() { return userDefined; }
|
||||
virtual TQualifierList& getQualifierList() { return qualifier; }
|
||||
virtual const TQualifierList& getQualifierList() const { return qualifier; }
|
||||
void setOptimize(bool o) { optimize = o; }
|
||||
void setDebug(bool d) { debug = d; }
|
||||
bool getOptimize() { return optimize; }
|
||||
|
@ -835,7 +835,7 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres
|
||||
}
|
||||
|
||||
//
|
||||
// This is to be executed once the final root is put on top by the parsing
|
||||
// This is to be executed after the final root is put on top by the parsing
|
||||
// process.
|
||||
//
|
||||
bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
|
||||
@ -843,9 +843,7 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
|
||||
if (root == 0)
|
||||
return true;
|
||||
|
||||
//
|
||||
// First, finish off the top level sequence, if any
|
||||
//
|
||||
// Finish off the top-level sequence
|
||||
TIntermAggregate* aggRoot = root->getAsAggregate();
|
||||
if (aggRoot && aggRoot->getOp() == EOpNull)
|
||||
aggRoot->setOperator(EOpSequence);
|
||||
@ -853,6 +851,58 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
|
||||
return true;
|
||||
}
|
||||
|
||||
void TIntermediate::addSymbolLinkageNodes(TIntermNode* root, TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable)
|
||||
{
|
||||
// Add top-level nodes for declarations that must be checked cross
|
||||
// compilation unit by a linker, yet might not have been referenced
|
||||
// by the AST.
|
||||
//
|
||||
// Almost entirely, translation of symbols is driven by what's present
|
||||
// in the AST traversal, not by translating the symbol table.
|
||||
//
|
||||
// However, there are some special cases:
|
||||
// - From the specification: "Special built-in inputs gl_VertexID and
|
||||
// gl_InstanceID are also considered active vertex attributes."
|
||||
// - Linker-based type mismatch error reporting needs to see all
|
||||
// uniforms/ins/outs variables and blocks.
|
||||
// - ftransform() can make gl_Vertex and gl_ModelViewProjectionMatrix active.
|
||||
//
|
||||
|
||||
//if (ftransformUsed) {
|
||||
// TODO: desktop: track ftransform() usage
|
||||
// addSymbolLinkageNode(root, symbolTable, "gl_Vertex");
|
||||
// addSymbolLinkageNode(root, symbolTable, "gl_ModelViewProjectionMatrix");
|
||||
//}
|
||||
|
||||
if (language == EShLangVertex) {
|
||||
// the names won't be found in the symbol table unless the versions are right,
|
||||
// so version logic does not need to be repeated here
|
||||
addSymbolLinkageNode(linkage, symbolTable, "gl_VertexID");
|
||||
addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID");
|
||||
}
|
||||
|
||||
if (linkage) {
|
||||
// Finish off linkage sequence
|
||||
linkage->setOperator(EOpLinkerObjects);
|
||||
|
||||
// Add a child to the root node for the linker objects
|
||||
growAggregate(root, linkage, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable& symbolTable, const TString& name)
|
||||
{
|
||||
TSymbol* symbol = symbolTable.find(name);
|
||||
if (symbol)
|
||||
addSymbolLinkageNode(linkage, *symbol->getAsVariable());
|
||||
}
|
||||
|
||||
void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TVariable& variable)
|
||||
{
|
||||
TIntermSymbol* node = new TIntermSymbol(variable.getUniqueId(), variable.getName(), variable.getType());
|
||||
linkage = growAggregate(linkage, node, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// This deletes the tree.
|
||||
//
|
||||
|
@ -42,7 +42,7 @@
|
||||
|
||||
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, EProfile p, EShLanguage L, TInfoSink& is,
|
||||
bool fc, EShMessages m) :
|
||||
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
|
||||
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0), linkage(0),
|
||||
numErrors(0), lexAfterType(false), loopNestingLevel(0),
|
||||
structNestingLevel(0), inTypeParen(false),
|
||||
version(v), profile(p), forwardCompatible(fc), messages(m),
|
||||
@ -331,11 +331,11 @@ void TParseContext::variableCheck(TIntermTyped*& nodePtr)
|
||||
return;
|
||||
|
||||
if (symbol->getType().getBasicType() == EbtVoid) {
|
||||
error(symbol->getLine(), "undeclared identifier", symbol->getSymbol().c_str(), "");
|
||||
error(symbol->getLine(), "undeclared identifier", symbol->getName().c_str(), "");
|
||||
|
||||
// Add to symbol table to prevent future error messages on the same name
|
||||
|
||||
TVariable* fakeVariable = new TVariable(&symbol->getSymbol(), TType(EbtFloat));
|
||||
TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat));
|
||||
symbolTable.insert(*fakeVariable);
|
||||
|
||||
// substitute a symbol node for this new variable
|
||||
@ -403,7 +403,7 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
|
||||
|
||||
const char* symbol = 0;
|
||||
if (symNode != 0)
|
||||
symbol = symNode->getSymbol().c_str();
|
||||
symbol = symNode->getName().c_str();
|
||||
|
||||
const char* message = 0;
|
||||
switch (node->getQualifier().storage) {
|
||||
@ -1038,15 +1038,15 @@ void TParseContext::arrayCheck(int line, TString& identifier, const TPublicType&
|
||||
|
||||
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
|
||||
{
|
||||
TSymbol* symbol = symbolTable.find(node->getSymbol());
|
||||
TSymbol* symbol = symbolTable.find(node->getName());
|
||||
if (symbol == 0) {
|
||||
error(line, " undeclared identifier", node->getSymbol().c_str(), "");
|
||||
error(line, " undeclared identifier", node->getName().c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
TVariable* variable = symbol->getAsVariable();
|
||||
if (! variable) {
|
||||
error(0, "array variable name expected", node->getSymbol().c_str(), "");
|
||||
error(0, "array variable name expected", node->getName().c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1055,7 +1055,7 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
|
||||
|
||||
// special casing to test index value of gl_TexCoord. If the accessed index is >= gl_MaxTextureCoords
|
||||
// its an error
|
||||
if (node->getSymbol() == "gl_TexCoord") {
|
||||
if (node->getName() == "gl_TexCoord") {
|
||||
TSymbol* texCoord = symbolTable.find("gl_MaxTextureCoords");
|
||||
if (! texCoord || ! texCoord->getAsVariable()) {
|
||||
infoSink.info.message(EPrefixInternalError, "gl_MaxTextureCoords not defined", line);
|
||||
@ -1111,11 +1111,15 @@ void TParseContext::nonInitCheck(int line, TString& identifier, TPublicType& typ
|
||||
|
||||
TVariable* variable = new TVariable(&identifier, TType(type));
|
||||
|
||||
if (! symbolTable.insert(*variable)) {
|
||||
if (! symbolTable.insert(*variable))
|
||||
error(line, "redefinition", variable->getName().c_str(), "");
|
||||
delete variable;
|
||||
} else
|
||||
else {
|
||||
voidErrorCheck(line, identifier, type);
|
||||
|
||||
// see if it's a linker-level object to track
|
||||
if (type.qualifier.isUniform() || type.qualifier.isPipeInput() || type.qualifier.isPipeOutput())
|
||||
intermediate.addSymbolLinkageNode(linkage, *variable);
|
||||
}
|
||||
}
|
||||
|
||||
void TParseContext::paramCheck(int line, TStorageQualifier qualifier, TType* type)
|
||||
@ -1311,12 +1315,12 @@ bool TParseContext::executeInitializerError(TSourceLoc line, TString& identifier
|
||||
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
|
||||
}
|
||||
} else if (initializer->getAsSymbolNode()) {
|
||||
TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
|
||||
TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getName());
|
||||
if (TVariable* tVar = symbol->getAsVariable()) {
|
||||
constUnion* constArray = tVar->getConstUnionPointer();
|
||||
variable->shareConstPointer(constArray);
|
||||
} else {
|
||||
error(line, "expected variable", initializer->getAsSymbolNode()->getSymbol().c_str(), "");
|
||||
error(line, "expected variable", initializer->getAsSymbolNode()->getName().c_str(), "");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@ -1611,6 +1615,9 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// save it in case there are no references in the AST, so the linker can error test against it
|
||||
intermediate.addSymbolLinkageNode(linkage, *variable);
|
||||
}
|
||||
|
||||
// For an identifier that is already declared, add more qualification to it.
|
||||
|
@ -41,13 +41,6 @@
|
||||
#include "SymbolTable.h"
|
||||
#include "localintermediate.h"
|
||||
|
||||
struct TMatrixFields {
|
||||
bool wholeRow;
|
||||
bool wholeCol;
|
||||
int row;
|
||||
int col;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
EBhRequire,
|
||||
EBhEnable,
|
||||
@ -62,6 +55,8 @@ struct TPragma {
|
||||
TPragmaTable pragmaTable;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The following are extra variables needed during parsing, grouped together so
|
||||
// they can be passed to the parser without needing a global.
|
||||
@ -74,6 +69,7 @@ struct TParseContext {
|
||||
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
|
||||
bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
|
||||
int loopNestingLevel; // 0 if outside all loops
|
||||
|
@ -556,6 +556,7 @@ int ShCompile(
|
||||
int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext, parseContext.getPreamble());
|
||||
if (ret)
|
||||
success = false;
|
||||
intermediate.addSymbolLinkageNodes(parseContext.treeRoot, parseContext.linkage, parseContext.language, symbolTable);
|
||||
|
||||
if (success && parseContext.treeRoot) {
|
||||
if (optLevel == EShOptNoGeneration)
|
||||
@ -564,7 +565,6 @@ int ShCompile(
|
||||
success = intermediate.postProcess(parseContext.treeRoot, parseContext.language);
|
||||
|
||||
if (success) {
|
||||
|
||||
if (debugOptions & EDebugOpIntermediate)
|
||||
intermediate.outputTree(parseContext.treeRoot);
|
||||
|
||||
|
@ -442,6 +442,7 @@ public:
|
||||
*builtIn = level < 2;
|
||||
if (sameScope)
|
||||
*sameScope = level == currentLevel();
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ postfix_expression
|
||||
parseContext.variableCheck($1);
|
||||
if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
|
||||
if ($1->getAsSymbolNode())
|
||||
parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
|
||||
parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getName().c_str(), "");
|
||||
else
|
||||
parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
|
||||
}
|
||||
@ -746,8 +746,8 @@ function_identifier
|
||||
} else {
|
||||
TIntermSymbol* symbol = $1->getAsSymbolNode();
|
||||
if (symbol) {
|
||||
parseContext.reservedErrorCheck(symbol->getLine(), symbol->getSymbol());
|
||||
TFunction *function = new TFunction(&symbol->getSymbol(), TType(EbtVoid));
|
||||
parseContext.reservedErrorCheck(symbol->getLine(), symbol->getName());
|
||||
TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid));
|
||||
$$.function = function;
|
||||
} else
|
||||
parseContext.error($1->getLine(), "function call, method or subroutine call expected", "", "");
|
||||
|
@ -87,7 +87,7 @@ void OutputSymbol(TIntermSymbol* node, TIntermTraverser* it)
|
||||
const int maxSize = GlslangMaxTypeLength + GlslangMaxTokenLength;
|
||||
char buf[maxSize];
|
||||
snprintf(buf, maxSize, "'%s' (%s)\n",
|
||||
node->getSymbol().c_str(),
|
||||
node->getName().c_str(),
|
||||
node->getCompleteString().c_str());
|
||||
|
||||
oit->infoSink.debug << buf;
|
||||
@ -274,6 +274,7 @@ bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTravers
|
||||
|
||||
switch (node->getOp()) {
|
||||
case EOpSequence: out.debug << "Sequence\n"; return true;
|
||||
case EOpLinkerObjects: out.debug << "Linker Objects\n"; return true;
|
||||
case EOpComma: out.debug << "Comma"; break;
|
||||
case EOpFunction: out.debug << "Function Definition: " << node->getName(); break;
|
||||
case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break;
|
||||
|
@ -80,6 +80,9 @@ public:
|
||||
TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
|
||||
TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
|
||||
bool postProcess(TIntermNode*, EShLanguage);
|
||||
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*);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user