Implement the full scheme for ES precision qualifiers, generalizing existing storage qualifiers to be able to include multiple independent kinds of qualifiers.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@20317 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
674014bfc4
commit
5521862729
@ -55,7 +55,7 @@ enum TBasicType {
|
|||||||
EbtSamplerRectShadow, // ARB_texture_rectangle
|
EbtSamplerRectShadow, // ARB_texture_rectangle
|
||||||
EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
|
EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
|
||||||
EbtStruct,
|
EbtStruct,
|
||||||
EbtAddress, // should be deprecated??
|
EbtNumTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
__inline bool IsSampler(TBasicType type)
|
__inline bool IsSampler(TBasicType type)
|
||||||
@ -69,7 +69,7 @@ __inline bool IsSampler(TBasicType type)
|
|||||||
// to allocate variables in. Since built-ins tend to go to different registers
|
// to allocate variables in. Since built-ins tend to go to different registers
|
||||||
// than varying or uniform, it makes sense they are peers, not sub-classes.
|
// than varying or uniform, it makes sense they are peers, not sub-classes.
|
||||||
//
|
//
|
||||||
enum TQualifier {
|
enum TStorageQualifier {
|
||||||
EvqTemporary, // For temporaries (within a function), read/write
|
EvqTemporary, // For temporaries (within a function), read/write
|
||||||
EvqGlobal, // For globals read/write
|
EvqGlobal, // For globals read/write
|
||||||
EvqConst, // User defined constants and non-output parameters in functions
|
EvqConst, // User defined constants and non-output parameters in functions
|
||||||
@ -104,7 +104,7 @@ enum TQualifier {
|
|||||||
//
|
//
|
||||||
// This is just for debug print out, carried along with the definitions above.
|
// This is just for debug print out, carried along with the definitions above.
|
||||||
//
|
//
|
||||||
__inline const char* getQualifierString(TQualifier q)
|
__inline const char* getStorageQualifierString(TStorageQualifier q)
|
||||||
{
|
{
|
||||||
switch (q) {
|
switch (q) {
|
||||||
case EvqTemporary: return "Temporary"; break;
|
case EvqTemporary: return "Temporary"; break;
|
||||||
@ -129,4 +129,22 @@ __inline const char* getQualifierString(TQualifier q)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TPrecisionQualifier {
|
||||||
|
EpqNone,
|
||||||
|
EpqLow,
|
||||||
|
EpqMedium,
|
||||||
|
EpqHigh
|
||||||
|
};
|
||||||
|
|
||||||
|
__inline const char* getPrecisionQualifierString(TPrecisionQualifier p)
|
||||||
|
{
|
||||||
|
switch(p) {
|
||||||
|
case EpqNone: return ""; break;
|
||||||
|
case EpqLow: return "lowp"; break;
|
||||||
|
case EpqMedium: return "mediump"; break;
|
||||||
|
case EpqHigh: return "highp"; break;
|
||||||
|
default: return "unknown precision qualifier";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _BASICTYPES_INCLUDED_
|
#endif // _BASICTYPES_INCLUDED_
|
||||||
|
@ -56,13 +56,20 @@ inline TTypeList* NewPoolTTypeList()
|
|||||||
|
|
||||||
//
|
//
|
||||||
// This is a workaround for a problem with the yacc stack, It can't have
|
// This is a workaround for a problem with the yacc stack, It can't have
|
||||||
// types that it thinks have non-trivial constructors. It should
|
// types that it thinks have non-trivial constructors. It should
|
||||||
// just be used while recognizing the grammar, not anything else. Pointers
|
// just be used while recognizing the grammar, not anything else. Pointers
|
||||||
// could be used, but also trying to avoid lots of memory management overhead.
|
// could be used, but also trying to avoid lots of memory management overhead.
|
||||||
//
|
//
|
||||||
// Not as bad as it looks, there is no actual assumption that the fields
|
// Not as bad as it looks, there is no actual assumption that the fields
|
||||||
// match up or are name the same or anything like that.
|
// match up or are name the same or anything like that.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
class TQualifier {
|
||||||
|
public:
|
||||||
|
TStorageQualifier storage : 7;
|
||||||
|
TPrecisionQualifier precision : 3;
|
||||||
|
};
|
||||||
|
|
||||||
class TPublicType {
|
class TPublicType {
|
||||||
public:
|
public:
|
||||||
TBasicType type;
|
TBasicType type;
|
||||||
@ -74,10 +81,9 @@ public:
|
|||||||
TType* userDef;
|
TType* userDef;
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
void setBasic(TBasicType bt, TQualifier q, int ln = 0)
|
void initType(int ln = 0)
|
||||||
{
|
{
|
||||||
type = bt;
|
type = EbtVoid;
|
||||||
qualifier = q;
|
|
||||||
size = 1;
|
size = 1;
|
||||||
matrix = false;
|
matrix = false;
|
||||||
array = false;
|
array = false;
|
||||||
@ -86,6 +92,18 @@ public:
|
|||||||
line = ln;
|
line = ln;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initQualifiers(bool global = false)
|
||||||
|
{
|
||||||
|
qualifier.storage = global ? EvqGlobal : EvqTemporary;
|
||||||
|
qualifier.precision = EpqNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(int line = 0, bool global = false)
|
||||||
|
{
|
||||||
|
initType(line);
|
||||||
|
initQualifiers(global);
|
||||||
|
}
|
||||||
|
|
||||||
void setAggregate(int s, bool m = false)
|
void setAggregate(int s, bool m = false)
|
||||||
{
|
{
|
||||||
size = s;
|
size = s;
|
||||||
@ -107,22 +125,28 @@ typedef std::map<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
|
|||||||
class TType {
|
class TType {
|
||||||
public:
|
public:
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||||
explicit TType(TBasicType t, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
|
explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
|
||||||
type(t), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
|
type(t), size(s), matrix(m), array(a), arraySize(0),
|
||||||
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
|
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
|
||||||
{ }
|
fieldName(0), mangled(0), typeName(0) {
|
||||||
|
qualifier.storage = q;
|
||||||
|
qualifier.precision = EpqNone;
|
||||||
|
}
|
||||||
explicit TType(const TPublicType &p) :
|
explicit TType(const TPublicType &p) :
|
||||||
type(p.type), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
|
type(p.type), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
|
||||||
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
|
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
|
||||||
{
|
{
|
||||||
if (p.userDef) {
|
qualifier = p.qualifier;
|
||||||
structure = p.userDef->getStruct();
|
if (p.userDef) {
|
||||||
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
|
structure = p.userDef->getStruct();
|
||||||
}
|
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
explicit TType(TTypeList* userDef, const TString& n) :
|
explicit TType(TTypeList* userDef, const TString& n) :
|
||||||
type(EbtStruct), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
|
type(EbtStruct), size(1), matrix(false), array(false), arraySize(0),
|
||||||
structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) {
|
structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) {
|
||||||
|
qualifier.storage = EvqTemporary;
|
||||||
|
qualifier.precision = EpqNone;
|
||||||
typeName = NewPoolTString(n.c_str());
|
typeName = NewPoolTString(n.c_str());
|
||||||
}
|
}
|
||||||
explicit TType() {}
|
explicit TType() {}
|
||||||
@ -180,47 +204,47 @@ public:
|
|||||||
|
|
||||||
return newType;
|
return newType;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setType(TBasicType t, int s, bool m, bool a, int aS = 0)
|
virtual void setType(TBasicType t, int s, bool m, bool a, int aS = 0)
|
||||||
{ type = t; size = s; matrix = m; array = a; arraySize = aS; }
|
{ type = t; size = s; matrix = m; array = a; arraySize = aS; }
|
||||||
virtual void setType(TBasicType t, int s, bool m, TType* userDef = 0)
|
virtual void setType(TBasicType t, int s, bool m, TType* userDef = 0)
|
||||||
{ type = t;
|
{ type = t;
|
||||||
size = s;
|
size = s;
|
||||||
matrix = m;
|
matrix = m;
|
||||||
if (userDef)
|
if (userDef)
|
||||||
structure = userDef->getStruct();
|
structure = userDef->getStruct();
|
||||||
// leave array information intact.
|
// leave array information intact.
|
||||||
}
|
}
|
||||||
virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); }
|
virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); }
|
||||||
virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
|
virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
|
||||||
virtual const TString& getTypeName() const
|
virtual const TString& getTypeName() const
|
||||||
{
|
{
|
||||||
assert(typeName);
|
assert(typeName);
|
||||||
return *typeName;
|
return *typeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const TString& getFieldName() const
|
virtual const TString& getFieldName() const
|
||||||
{
|
{
|
||||||
assert(fieldName);
|
assert(fieldName);
|
||||||
return *fieldName;
|
return *fieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual TBasicType getBasicType() const { return type; }
|
virtual TBasicType getBasicType() const { return type; }
|
||||||
virtual TQualifier getQualifier() const { return qualifier; }
|
virtual TQualifier& getQualifier() { return qualifier; }
|
||||||
virtual void changeQualifier(TQualifier q) { qualifier = q; }
|
virtual const TQualifier& getQualifier() const { return qualifier; }
|
||||||
|
|
||||||
// One-dimensional size of single instance type
|
// One-dimensional size of single instance type
|
||||||
virtual int getNominalSize() const { return size; }
|
virtual int getNominalSize() const { return size; }
|
||||||
|
|
||||||
// Full-dimensional size of single instance of type
|
// Full-dimensional size of single instance of type
|
||||||
virtual int getInstanceSize() const
|
virtual int getInstanceSize() const
|
||||||
{
|
{
|
||||||
if (matrix)
|
if (matrix)
|
||||||
return size * size;
|
return size * size;
|
||||||
else
|
else
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool isMatrix() const { return matrix ? true : false; }
|
virtual bool isMatrix() const { return matrix ? true : false; }
|
||||||
virtual bool isArray() const { return array ? true : false; }
|
virtual bool isArray() const { return array ? true : false; }
|
||||||
int getArraySize() const { return arraySize; }
|
int getArraySize() const { return arraySize; }
|
||||||
@ -251,18 +275,19 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const char* getBasicString() const { return TType::getBasicString(type); }
|
const char* getBasicString() const { return TType::getBasicString(type); }
|
||||||
const char* getQualifierString() const { return ::getQualifierString(qualifier); }
|
const char* getStorageQualifierString() const { return ::getStorageQualifierString(qualifier.storage); }
|
||||||
|
const char* getPrecisionQualifierString() const { return ::getPrecisionQualifierString(qualifier.precision); }
|
||||||
TTypeList* getStruct() { return structure; }
|
TTypeList* getStruct() { return structure; }
|
||||||
|
|
||||||
int getObjectSize() const
|
int getObjectSize() const
|
||||||
{
|
{
|
||||||
int totalSize;
|
int totalSize;
|
||||||
|
|
||||||
if (getBasicType() == EbtStruct)
|
if (getBasicType() == EbtStruct)
|
||||||
totalSize = getStructSize();
|
totalSize = getStructSize();
|
||||||
else if (matrix)
|
else if (matrix)
|
||||||
totalSize = size * size;
|
totalSize = size * size;
|
||||||
else
|
else
|
||||||
totalSize = size;
|
totalSize = size;
|
||||||
|
|
||||||
if (isArray())
|
if (isArray())
|
||||||
@ -275,10 +300,10 @@ public:
|
|||||||
TString& getMangledName() {
|
TString& getMangledName() {
|
||||||
if (!mangled) {
|
if (!mangled) {
|
||||||
mangled = NewPoolTString("");
|
mangled = NewPoolTString("");
|
||||||
buildMangledName(*mangled);
|
buildMangledName(*mangled);
|
||||||
*mangled += ';' ;
|
*mangled += ';' ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *mangled;
|
return *mangled;
|
||||||
}
|
}
|
||||||
bool sameElementType(const TType& right) const {
|
bool sameElementType(const TType& right) const {
|
||||||
@ -299,16 +324,17 @@ public:
|
|||||||
return !operator==(right);
|
return !operator==(right);
|
||||||
}
|
}
|
||||||
TString getCompleteString() const;
|
TString getCompleteString() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void buildMangledName(TString&);
|
void buildMangledName(TString&);
|
||||||
int getStructSize() const;
|
int getStructSize() const;
|
||||||
|
|
||||||
TBasicType type : 6;
|
TBasicType type : 8;
|
||||||
TQualifier qualifier : 7;
|
|
||||||
int size : 8; // size of vector or matrix, not size of array
|
int size : 8; // size of vector or matrix, not size of array
|
||||||
unsigned int matrix : 1;
|
unsigned int matrix : 1;
|
||||||
unsigned int array : 1;
|
unsigned int array : 1;
|
||||||
|
TQualifier qualifier;
|
||||||
|
|
||||||
int arraySize;
|
int arraySize;
|
||||||
|
|
||||||
TTypeList* structure; // 0 unless this is a struct
|
TTypeList* structure; // 0 unless this is a struct
|
||||||
|
@ -285,14 +285,14 @@ public:
|
|||||||
virtual TType* getTypePointer() { return &type; }
|
virtual TType* getTypePointer() { return &type; }
|
||||||
|
|
||||||
virtual TBasicType getBasicType() const { return type.getBasicType(); }
|
virtual TBasicType getBasicType() const { return type.getBasicType(); }
|
||||||
virtual TQualifier getQualifier() const { return type.getQualifier(); }
|
virtual TQualifier& getQualifier() { return type.getQualifier(); }
|
||||||
virtual int getNominalSize() const { return type.getNominalSize(); }
|
virtual int getNominalSize() const { return type.getNominalSize(); }
|
||||||
virtual int getSize() const { return type.getInstanceSize(); }
|
virtual int getSize() const { return type.getInstanceSize(); }
|
||||||
virtual bool isMatrix() const { return type.isMatrix(); }
|
virtual bool isMatrix() const { return type.isMatrix(); }
|
||||||
virtual bool isArray() const { return type.isArray(); }
|
virtual bool isArray() const { return type.isArray(); }
|
||||||
virtual bool isVector() const { return type.isVector(); }
|
virtual bool isVector() const { return type.isVector(); }
|
||||||
const char* getBasicString() const { return type.getBasicString(); }
|
const char* getBasicString() const { return type.getBasicString(); }
|
||||||
const char* getQualifierString() const { return type.getQualifierString(); }
|
const char* getStorageQualifierString() const { return type.getStorageQualifierString(); }
|
||||||
TString getCompleteString() const { return type.getCompleteString(); }
|
TString getCompleteString() const { return type.getCompleteString(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -451,7 +451,7 @@ public:
|
|||||||
virtual void traverse(TIntermTraverser*);
|
virtual void traverse(TIntermTraverser*);
|
||||||
virtual void setUserDefined() { userDefined = true; }
|
virtual void setUserDefined() { userDefined = true; }
|
||||||
virtual bool isUserDefined() { return userDefined; }
|
virtual bool isUserDefined() { return userDefined; }
|
||||||
virtual TQualifierList& getQualifier() { return qualifier; }
|
virtual TQualifierList& getQualifierList() { return qualifier; }
|
||||||
void setOptimize(bool o) { optimize = o; }
|
void setOptimize(bool o) { optimize = o; }
|
||||||
void setDebug(bool d) { debug = d; }
|
void setDebug(bool d) { debug = d; }
|
||||||
bool getOptimize() { return optimize; }
|
bool getOptimize() { return optimize; }
|
||||||
|
@ -546,13 +546,14 @@ TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nod
|
|||||||
|
|
||||||
TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
|
TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
|
||||||
{
|
{
|
||||||
if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
|
if (left->getType().getQualifier().storage == EvqConst &&
|
||||||
|
right->getType().getQualifier().storage == EvqConst) {
|
||||||
return right;
|
return right;
|
||||||
} else {
|
} else {
|
||||||
TIntermTyped *commaAggregate = growAggregate(left, right, line);
|
TIntermTyped *commaAggregate = growAggregate(left, right, line);
|
||||||
commaAggregate->getAsAggregate()->setOperator(EOpComma);
|
commaAggregate->getAsAggregate()->setOperator(EOpComma);
|
||||||
commaAggregate->setType(right->getType());
|
commaAggregate->setType(right->getType());
|
||||||
commaAggregate->getTypePointer()->changeQualifier(EvqTemporary);
|
commaAggregate->getTypePointer()->getQualifier().storage = EvqTemporary;
|
||||||
return commaAggregate;
|
return commaAggregate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -830,7 +831,11 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
|
|||||||
// operand. Then only deviations from this need be coded.
|
// operand. Then only deviations from this need be coded.
|
||||||
//
|
//
|
||||||
setType(left->getType());
|
setType(left->getType());
|
||||||
type.changeQualifier(EvqTemporary);
|
type.getQualifier().storage = EvqTemporary;
|
||||||
|
|
||||||
|
// Fix precision qualifiers
|
||||||
|
if (right->getQualifier().precision > getQualifier().precision)
|
||||||
|
getQualifier().precision = right->getQualifier().precision;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Array operations.
|
// Array operations.
|
||||||
@ -1510,7 +1515,8 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
|
|||||||
|
|
||||||
const TType& t = node->getType();
|
const TType& t = node->getType();
|
||||||
|
|
||||||
return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
|
return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getNominalSize(), t.isMatrix(),
|
||||||
|
t.isArray()), node->getLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
|
void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
|
||||||
|
@ -44,6 +44,25 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) :
|
||||||
|
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
|
||||||
|
recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
|
||||||
|
switchNestingLevel(0), inTypeParen(false),
|
||||||
|
version(110), profile(ENoProfile), futureCompatibility(false),
|
||||||
|
contextPragma(true, false)
|
||||||
|
{
|
||||||
|
// Default precisions for version 110, to be overridden for
|
||||||
|
// other versions/profiles/stage combinations
|
||||||
|
for (int type = 0; type < EbtNumTypes; ++type)
|
||||||
|
defaultPrecision[type] = EpqHigh;
|
||||||
|
|
||||||
|
defaultPrecision[EbtVoid] = EpqNone;
|
||||||
|
defaultPrecision[EbtDouble] = EpqNone;
|
||||||
|
defaultPrecision[EbtBool] = EpqNone;
|
||||||
|
defaultPrecision[EbtVoid] = EpqNone;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Look at a '.' field selector string and change it into offsets
|
// Look at a '.' field selector string and change it into offsets
|
||||||
// for a vector.
|
// for a vector.
|
||||||
@ -331,7 +350,7 @@ bool TParseContext::lValueErrorCheck(int line, char* op, TIntermTyped* node)
|
|||||||
symbol = symNode->getSymbol().c_str();
|
symbol = symNode->getSymbol().c_str();
|
||||||
|
|
||||||
char* message = 0;
|
char* message = 0;
|
||||||
switch (node->getQualifier()) {
|
switch (node->getQualifier().storage) {
|
||||||
case EvqConst: message = "can't modify a const"; break;
|
case EvqConst: message = "can't modify a const"; break;
|
||||||
case EvqConstReadOnly: message = "can't modify a const"; break;
|
case EvqConstReadOnly: message = "can't modify a const"; break;
|
||||||
case EvqAttribute: message = "can't modify an attribute"; break;
|
case EvqAttribute: message = "can't modify an attribute"; break;
|
||||||
@ -395,7 +414,7 @@ bool TParseContext::lValueErrorCheck(int line, char* op, TIntermTyped* node)
|
|||||||
//
|
//
|
||||||
bool TParseContext::constErrorCheck(TIntermTyped* node)
|
bool TParseContext::constErrorCheck(TIntermTyped* node)
|
||||||
{
|
{
|
||||||
if (node->getQualifier() == EvqConst)
|
if (node->getQualifier().storage == EvqConst)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
error(node->getLine(), "constant expression required", "", "");
|
error(node->getLine(), "constant expression required", "", "");
|
||||||
@ -503,14 +522,14 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
|
|||||||
overFull = true;
|
overFull = true;
|
||||||
if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
|
if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
|
||||||
full = true;
|
full = true;
|
||||||
if (function[i].type->getQualifier() != EvqConst)
|
if (function[i].type->getQualifier().storage != EvqConst)
|
||||||
constType = false;
|
constType = false;
|
||||||
if (function[i].type->isArray())
|
if (function[i].type->isArray())
|
||||||
arrayArg = true;
|
arrayArg = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constType)
|
if (constType)
|
||||||
type->changeQualifier(EvqConst);
|
type->getQualifier().storage = EvqConst;
|
||||||
|
|
||||||
if (type->isArray() && type->getArraySize() != function.getParamCount()) {
|
if (type->isArray() && type->getArraySize() != function.getParamCount()) {
|
||||||
error(line, "array constructor needs one argument per array element", "constructor", "");
|
error(line, "array constructor needs one argument per array element", "constructor", "");
|
||||||
@ -623,19 +642,19 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
|
|||||||
|
|
||||||
bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualifier)
|
bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualifier)
|
||||||
{
|
{
|
||||||
switch (qualifier) {
|
switch (qualifier.storage) {
|
||||||
case EvqIn:
|
case EvqIn:
|
||||||
profileRequires(line, ENoProfile, 130, 0, "in for stage inputs");
|
profileRequires(line, ENoProfile, 130, 0, "in for stage inputs");
|
||||||
profileRequires(line, EEsProfile, 300, 0, "in for stage inputs");
|
profileRequires(line, EEsProfile, 300, 0, "in for stage inputs");
|
||||||
qualifier = EvqVaryingIn;
|
qualifier.storage = EvqVaryingIn;
|
||||||
break;
|
break;
|
||||||
case EvqOut:
|
case EvqOut:
|
||||||
profileRequires(line, ENoProfile, 130, 0, "out for stage outputs");
|
profileRequires(line, ENoProfile, 130, 0, "out for stage outputs");
|
||||||
profileRequires(line, EEsProfile, 300, 0, "out for stage outputs");
|
profileRequires(line, EEsProfile, 300, 0, "out for stage outputs");
|
||||||
qualifier = EvqVaryingOut;
|
qualifier.storage = EvqVaryingOut;
|
||||||
break;
|
break;
|
||||||
case EvqInOut:
|
case EvqInOut:
|
||||||
qualifier = EvqVaryingIn;
|
qualifier.storage = EvqVaryingIn;
|
||||||
error(line, "cannot use 'inout' at global scope", "", "");
|
error(line, "cannot use 'inout' at global scope", "", "");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -646,20 +665,34 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
|
|||||||
|
|
||||||
bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
|
bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
|
||||||
{
|
{
|
||||||
if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
|
if ((pType.qualifier.storage == EvqVaryingIn ||
|
||||||
|
pType.qualifier.storage == EvqVaryingOut ||
|
||||||
|
pType.qualifier.storage == EvqAttribute) &&
|
||||||
pType.type == EbtStruct) {
|
pType.type == EbtStruct) {
|
||||||
error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), "");
|
|
||||||
|
error(line, "cannot be used with a structure", getStorageQualifierString(pType.qualifier.storage), "");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
|
if (pType.qualifier.storage != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
|
void TParseContext::setDefaultPrecision(int line, TBasicType type, TPrecisionQualifier qualifier)
|
||||||
|
{
|
||||||
|
// TODO: push and pop for nested scopes
|
||||||
|
if (IsSampler(type) || type == EbtInt || type == EbtFloat) {
|
||||||
|
defaultPrecision[type] = qualifier;
|
||||||
|
} else {
|
||||||
|
error(line, "cannot apply precision statement to this type", TType::getBasicString(type), "");
|
||||||
|
recover();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TParseContext::parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type)
|
||||||
{
|
{
|
||||||
if ((qualifier == EvqOut || qualifier == EvqInOut) &&
|
if ((qualifier == EvqOut || qualifier == EvqInOut) &&
|
||||||
type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
|
type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
|
||||||
@ -741,12 +774,12 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
|
|||||||
//
|
//
|
||||||
bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
|
bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
|
||||||
{
|
{
|
||||||
if (type.qualifier == EvqAttribute) {
|
if (type.qualifier.storage == EvqAttribute) {
|
||||||
error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
|
error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.qualifier == EvqConst)
|
if (type.qualifier.storage == EvqConst)
|
||||||
profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array");
|
profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -899,8 +932,8 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
|
|||||||
//
|
//
|
||||||
// Make the qualifier make sense.
|
// Make the qualifier make sense.
|
||||||
//
|
//
|
||||||
if (type.qualifier == EvqConst) {
|
if (type.qualifier.storage == EvqConst) {
|
||||||
type.qualifier = EvqTemporary;
|
type.qualifier.storage = EvqTemporary;
|
||||||
error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
|
error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -933,24 +966,24 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TType* type)
|
bool TParseContext::paramErrorCheck(int line, TStorageQualifier qualifier, TType* type)
|
||||||
{
|
{
|
||||||
switch (qualifier) {
|
switch (qualifier) {
|
||||||
case EvqConst:
|
case EvqConst:
|
||||||
case EvqConstReadOnly:
|
case EvqConstReadOnly:
|
||||||
type->changeQualifier(EvqConstReadOnly);
|
type->getQualifier().storage = EvqConstReadOnly;
|
||||||
return false;
|
return false;
|
||||||
case EvqIn:
|
case EvqIn:
|
||||||
case EvqOut:
|
case EvqOut:
|
||||||
case EvqInOut:
|
case EvqInOut:
|
||||||
type->changeQualifier(qualifier);
|
type->getQualifier().storage = qualifier;
|
||||||
return false;
|
return false;
|
||||||
case EvqTemporary:
|
case EvqTemporary:
|
||||||
type->changeQualifier(EvqIn);
|
type->getQualifier().storage = EvqIn;
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
type->changeQualifier(EvqIn);
|
type->getQualifier().storage = EvqIn;
|
||||||
error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
|
error(line, "qualifier not allowed on function parameter", getStorageQualifierString(qualifier), "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1016,9 +1049,9 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
|
|||||||
//
|
//
|
||||||
// identifier must be of type constant, a global, or a temporary
|
// identifier must be of type constant, a global, or a temporary
|
||||||
//
|
//
|
||||||
TQualifier qualifier = variable->getType().getQualifier();
|
TStorageQualifier qualifier = variable->getType().getQualifier().storage;
|
||||||
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
|
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
|
||||||
error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), "");
|
error(line, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@ -1026,15 +1059,15 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
|
|||||||
//
|
//
|
||||||
|
|
||||||
if (qualifier == EvqConst) {
|
if (qualifier == EvqConst) {
|
||||||
if (qualifier != initializer->getType().getQualifier()) {
|
if (qualifier != initializer->getType().getQualifier().storage) {
|
||||||
error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
||||||
variable->getType().changeQualifier(EvqTemporary);
|
variable->getType().getQualifier().storage = EvqTemporary;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (type != initializer->getType()) {
|
if (type != initializer->getType()) {
|
||||||
error(line, " non-matching types for const initializer ",
|
error(line, " non-matching types for const initializer ",
|
||||||
variable->getType().getQualifierString(), "");
|
variable->getType().getStorageQualifierString(), "");
|
||||||
variable->getType().changeQualifier(EvqTemporary);
|
variable->getType().getQualifier().storage = EvqTemporary;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (initializer->getAsConstantUnion()) {
|
if (initializer->getAsConstantUnion()) {
|
||||||
@ -1053,7 +1086,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
|
|||||||
variable->shareConstPointer(constArray);
|
variable->shareConstPointer(constArray);
|
||||||
} else {
|
} else {
|
||||||
error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
||||||
variable->getType().changeQualifier(EvqTemporary);
|
variable->getType().getQualifier().storage = EvqTemporary;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ struct TMatrixFields {
|
|||||||
bool wholeRow;
|
bool wholeRow;
|
||||||
bool wholeCol;
|
bool wholeCol;
|
||||||
int row;
|
int row;
|
||||||
int col;
|
int col;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -67,12 +67,7 @@ struct TPragma {
|
|||||||
// they can be passed to the parser without needing a global.
|
// they can be passed to the parser without needing a global.
|
||||||
//
|
//
|
||||||
struct TParseContext {
|
struct TParseContext {
|
||||||
TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) :
|
TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is);
|
||||||
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
|
|
||||||
recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
|
|
||||||
switchNestingLevel(0), inTypeParen(false),
|
|
||||||
version(110), profile(ENoProfile), futureCompatibility(false),
|
|
||||||
contextPragma(true, false) { }
|
|
||||||
TIntermediate& intermediate; // to hold and build a parse tree
|
TIntermediate& intermediate; // to hold and build a parse tree
|
||||||
TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
|
TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
|
||||||
TInfoSink& infoSink;
|
TInfoSink& infoSink;
|
||||||
@ -91,18 +86,19 @@ struct TParseContext {
|
|||||||
EProfile profile; // the declared profile in the shader (core by default)
|
EProfile profile; // the declared profile in the shader (core by default)
|
||||||
bool futureCompatibility; // true if requesting errors for future compatibility (false by default)
|
bool futureCompatibility; // true if requesting errors for future compatibility (false by default)
|
||||||
TMap<TString, TBehavior> extensionBehavior; // for each extension string, what it's current enablement is
|
TMap<TString, TBehavior> extensionBehavior; // for each extension string, what it's current enablement is
|
||||||
|
|
||||||
struct TPragma contextPragma;
|
struct TPragma contextPragma;
|
||||||
TString HashErrMsg;
|
TPrecisionQualifier defaultPrecision[EbtNumTypes];
|
||||||
|
TString HashErrMsg;
|
||||||
bool AfterEOF;
|
bool AfterEOF;
|
||||||
|
|
||||||
void initializeExtensionBehavior();
|
void initializeExtensionBehavior();
|
||||||
|
|
||||||
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, ...);
|
||||||
bool reservedErrorCheck(int line, const TString& identifier);
|
bool reservedErrorCheck(int line, const TString& identifier);
|
||||||
void recover();
|
void recover();
|
||||||
|
|
||||||
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
|
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
|
||||||
bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
|
bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
|
||||||
void assignError(int line, const char* op, TString left, TString right);
|
void assignError(int line, const char* op, TString left, TString right);
|
||||||
@ -125,13 +121,14 @@ struct TParseContext {
|
|||||||
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
|
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
|
||||||
bool globalQualifierFixAndErrorCheck(int line, TQualifier&);
|
bool globalQualifierFixAndErrorCheck(int line, TQualifier&);
|
||||||
bool structQualifierErrorCheck(int line, const TPublicType& pType);
|
bool structQualifierErrorCheck(int line, const TPublicType& pType);
|
||||||
bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
|
void setDefaultPrecision(int line, TBasicType, TPrecisionQualifier);
|
||||||
|
bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type);
|
||||||
bool containsSampler(TType& type);
|
bool containsSampler(TType& type);
|
||||||
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
|
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
|
||||||
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
|
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
|
||||||
bool paramErrorCheck(int line, TQualifier qualifier, TType* type);
|
bool paramErrorCheck(int line, TStorageQualifier qualifier, TType* type);
|
||||||
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
|
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
|
||||||
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
|
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
|
||||||
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
|
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
|
||||||
bool areAllChildConst(TIntermAggregate* aggrNode);
|
bool areAllChildConst(TIntermAggregate* aggrNode);
|
||||||
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
|
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
class TAliveTraverser : public TIntermTraverser {
|
class TAliveTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TAliveTraverser(TQualifier q) : TIntermTraverser(), found(false), qualifier(q)
|
TAliveTraverser(TStorageQualifier q) : TIntermTraverser(), found(false), qualifier(q)
|
||||||
{
|
{
|
||||||
visitSymbol = AliveSymbol;
|
visitSymbol = AliveSymbol;
|
||||||
visitSelection = AliveSelection;
|
visitSelection = AliveSelection;
|
||||||
@ -45,7 +45,7 @@ public:
|
|||||||
bool wasFound() { return found; }
|
bool wasFound() { return found; }
|
||||||
protected:
|
protected:
|
||||||
bool found;
|
bool found;
|
||||||
TQualifier qualifier;
|
TStorageQualifier qualifier;
|
||||||
|
|
||||||
friend void AliveSymbol(TIntermSymbol*, TIntermTraverser*);
|
friend void AliveSymbol(TIntermSymbol*, TIntermTraverser*);
|
||||||
friend bool AliveSelection(bool, TIntermSelection*, TIntermTraverser*);
|
friend bool AliveSelection(bool, TIntermSelection*, TIntermTraverser*);
|
||||||
@ -59,7 +59,7 @@ protected:
|
|||||||
// ?? It does not do this well yet, this is just a place holder
|
// ?? It does not do this well yet, this is just a place holder
|
||||||
// that simply determines if it was reference at all, anywhere.
|
// that simply determines if it was reference at all, anywhere.
|
||||||
//
|
//
|
||||||
bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
|
bool QualifierWritten(TIntermNode* node, TStorageQualifier qualifier)
|
||||||
{
|
{
|
||||||
TAliveTraverser it(qualifier);
|
TAliveTraverser it(qualifier);
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ void AliveSymbol(TIntermSymbol* node, TIntermTraverser* it)
|
|||||||
//
|
//
|
||||||
// If it's what we're looking for, record it.
|
// If it's what we're looking for, record it.
|
||||||
//
|
//
|
||||||
if (node->getQualifier() == lit->qualifier)
|
if (node->getQualifier().storage == lit->qualifier)
|
||||||
lit->found = true;
|
lit->found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,4 +32,4 @@
|
|||||||
//POSSIBILITY OF SUCH DAMAGE.
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
|
|
||||||
bool QualifierWritten(TIntermNode* root, TQualifier);
|
bool QualifierWritten(TIntermNode* root, TStorageQualifier);
|
||||||
|
@ -92,12 +92,11 @@ int ShInitialize()
|
|||||||
|
|
||||||
SetGlobalPoolAllocatorPtr(gPoolAllocator);
|
SetGlobalPoolAllocatorPtr(gPoolAllocator);
|
||||||
|
|
||||||
symTables[EShLangVertex].pop();
|
symTables[EShLangVertex].pop(0);
|
||||||
symTables[EShLangFragment].pop();
|
symTables[EShLangFragment].pop(0);
|
||||||
|
|
||||||
builtInPoolAllocator->popAll();
|
builtInPoolAllocator->popAll();
|
||||||
delete builtInPoolAllocator;
|
delete builtInPoolAllocator;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret ? 1 : 0;
|
return ret ? 1 : 0;
|
||||||
@ -343,7 +342,7 @@ int ShCompile(
|
|||||||
// throwing away all but the built-ins.
|
// throwing away all but the built-ins.
|
||||||
//
|
//
|
||||||
while (! symbolTable.atSharedBuiltInLevel())
|
while (! symbolTable.atSharedBuiltInLevel())
|
||||||
symbolTable.pop();
|
symbolTable.pop(0);
|
||||||
|
|
||||||
FinalizePreprocessor();
|
FinalizePreprocessor();
|
||||||
//
|
//
|
||||||
|
@ -111,7 +111,7 @@ int TType::getStructSize() const
|
|||||||
|
|
||||||
void TVariable::dump(TInfoSink& infoSink) const
|
void TVariable::dump(TInfoSink& infoSink) const
|
||||||
{
|
{
|
||||||
infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getBasicString();
|
infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " " << type.getBasicString();
|
||||||
if (type.isArray()) {
|
if (type.isArray()) {
|
||||||
infoSink.debug << "[0]";
|
infoSink.debug << "[0]";
|
||||||
}
|
}
|
||||||
@ -154,6 +154,8 @@ TSymbolTableLevel::~TSymbolTableLevel()
|
|||||||
{
|
{
|
||||||
for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
|
for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
|
||||||
delete (*it).second;
|
delete (*it).second;
|
||||||
|
|
||||||
|
delete [] defaultPrecision;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
// so that symbol table lookups are never ambiguous. This allows
|
// so that symbol table lookups are never ambiguous. This allows
|
||||||
// a simpler symbol table structure.
|
// a simpler symbol table structure.
|
||||||
//
|
//
|
||||||
// * Pushing and popping of scope, so symbol table will really be a stack
|
// * Pushing and popping of scope, so symbol table will really be a stack
|
||||||
// of symbol tables. Searched from the top, with new inserts going into
|
// of symbol tables. Searched from the top, with new inserts going into
|
||||||
// the top.
|
// the top.
|
||||||
//
|
//
|
||||||
@ -61,11 +61,11 @@
|
|||||||
#include "../Include/Common.h"
|
#include "../Include/Common.h"
|
||||||
#include "../Include/intermediate.h"
|
#include "../Include/intermediate.h"
|
||||||
#include "../Include/InfoSink.h"
|
#include "../Include/InfoSink.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Symbol base class. (Can build functions or variables out of these...)
|
// Symbol base class. (Can build functions or variables out of these...)
|
||||||
//
|
//
|
||||||
class TSymbol {
|
class TSymbol {
|
||||||
public:
|
public:
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||||
TSymbol(const TString *n) : name(n) { }
|
TSymbol(const TString *n) : name(n) { }
|
||||||
@ -87,29 +87,29 @@ protected:
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Variable class, meaning a symbol that's not a function.
|
// Variable class, meaning a symbol that's not a function.
|
||||||
//
|
//
|
||||||
// There could be a separate class heirarchy for Constant variables;
|
// There could be a separate class heirarchy for Constant variables;
|
||||||
// Only one of int, bool, or float, (or none) is correct for
|
// Only one of int, bool, or float, (or none) is correct for
|
||||||
// any particular use, but it's easy to do this way, and doesn't
|
// any particular use, but it's easy to do this way, and doesn't
|
||||||
// seem worth having separate classes, and "getConst" can't simply return
|
// seem worth having separate classes, and "getConst" can't simply return
|
||||||
// different values for different types polymorphically, so this is
|
// different values for different types polymorphically, so this is
|
||||||
// just simple and pragmatic.
|
// just simple and pragmatic.
|
||||||
//
|
//
|
||||||
class TVariable : public TSymbol {
|
class TVariable : public TSymbol {
|
||||||
public:
|
public:
|
||||||
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
|
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
|
||||||
virtual ~TVariable() { }
|
virtual ~TVariable() { }
|
||||||
virtual bool isVariable() const { return true; }
|
virtual bool isVariable() const { return true; }
|
||||||
TType& getType() { return type; }
|
TType& getType() { return type; }
|
||||||
const TType& getType() const { return type; }
|
const TType& getType() const { return type; }
|
||||||
bool isUserType() const { return userType; }
|
bool isUserType() const { return userType; }
|
||||||
void changeQualifier(TQualifier qualifier) { type.changeQualifier(qualifier); }
|
void setStorageQualifier(TStorageQualifier qualifier) { type.getQualifier().storage = qualifier; }
|
||||||
void updateArrayInformationType(TType *t) { arrayInformationType = t; }
|
void updateArrayInformationType(TType *t) { arrayInformationType = t; }
|
||||||
TType* getArrayInformationType() { return arrayInformationType; }
|
TType* getArrayInformationType() { return arrayInformationType; }
|
||||||
|
|
||||||
virtual void dump(TInfoSink &infoSink) const;
|
virtual void dump(TInfoSink &infoSink) const;
|
||||||
|
|
||||||
constUnion* getConstPointer() {
|
constUnion* getConstPointer() {
|
||||||
if (!unionArray)
|
if (!unionArray)
|
||||||
unionArray = new constUnion[type.getObjectSize()];
|
unionArray = new constUnion[type.getObjectSize()];
|
||||||
|
|
||||||
@ -121,11 +121,11 @@ public:
|
|||||||
void shareConstPointer( constUnion *constArray)
|
void shareConstPointer( constUnion *constArray)
|
||||||
{
|
{
|
||||||
delete unionArray;
|
delete unionArray;
|
||||||
unionArray = constArray;
|
unionArray = constArray;
|
||||||
}
|
}
|
||||||
TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
|
TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
|
||||||
virtual TVariable* clone(TStructureMap& remapper);
|
virtual TVariable* clone(TStructureMap& remapper);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TType type;
|
TType type;
|
||||||
bool userType;
|
bool userType;
|
||||||
@ -149,7 +149,7 @@ struct TParameter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// The function sub-class of a symbol.
|
// The function sub-class of a symbol.
|
||||||
//
|
//
|
||||||
class TFunction : public TSymbol {
|
class TFunction : public TSymbol {
|
||||||
public:
|
public:
|
||||||
@ -158,21 +158,21 @@ public:
|
|||||||
returnType(TType(EbtVoid)),
|
returnType(TType(EbtVoid)),
|
||||||
op(o),
|
op(o),
|
||||||
defined(false) { }
|
defined(false) { }
|
||||||
TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) :
|
TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) :
|
||||||
TSymbol(name),
|
TSymbol(name),
|
||||||
returnType(retType),
|
returnType(retType),
|
||||||
mangledName(*name + '('),
|
mangledName(*name + '('),
|
||||||
op(tOp),
|
op(tOp),
|
||||||
defined(false) { }
|
defined(false) { }
|
||||||
virtual ~TFunction();
|
virtual ~TFunction();
|
||||||
virtual bool isFunction() const { return true; }
|
virtual bool isFunction() const { return true; }
|
||||||
|
|
||||||
void addParameter(TParameter& p)
|
void addParameter(TParameter& p)
|
||||||
{
|
{
|
||||||
parameters.push_back(p);
|
parameters.push_back(p);
|
||||||
mangledName = mangledName + p.type->getMangledName();
|
mangledName = mangledName + p.type->getMangledName();
|
||||||
}
|
}
|
||||||
|
|
||||||
const TString& getMangledName() const { return mangledName; }
|
const TString& getMangledName() const { return mangledName; }
|
||||||
const TType& getReturnType() const { return returnType; }
|
const TType& getReturnType() const { return returnType; }
|
||||||
void relateToOperator(TOperator o) { op = o; }
|
void relateToOperator(TOperator o) { op = o; }
|
||||||
@ -180,14 +180,14 @@ public:
|
|||||||
void setDefined() { defined = true; }
|
void setDefined() { defined = true; }
|
||||||
bool isDefined() { return defined; }
|
bool isDefined() { return defined; }
|
||||||
|
|
||||||
int getParamCount() const { return static_cast<int>(parameters.size()); }
|
int getParamCount() const { return static_cast<int>(parameters.size()); }
|
||||||
TParameter& operator [](int i) { return parameters[i]; }
|
TParameter& operator [](int i) { return parameters[i]; }
|
||||||
const TParameter& operator [](int i) const { return parameters[i]; }
|
const TParameter& operator [](int i) const { return parameters[i]; }
|
||||||
|
|
||||||
virtual void dump(TInfoSink &infoSink) const;
|
virtual void dump(TInfoSink &infoSink) const;
|
||||||
TFunction(const TFunction&, TStructureMap& remapper);
|
TFunction(const TFunction&, TStructureMap& remapper);
|
||||||
virtual TFunction* clone(TStructureMap& remapper);
|
virtual TFunction* clone(TStructureMap& remapper);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef TVector<TParameter> TParamList;
|
typedef TVector<TParameter> TParamList;
|
||||||
TParamList parameters;
|
TParamList parameters;
|
||||||
@ -201,17 +201,17 @@ protected:
|
|||||||
class TSymbolTableLevel {
|
class TSymbolTableLevel {
|
||||||
public:
|
public:
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||||
TSymbolTableLevel() { }
|
TSymbolTableLevel() : defaultPrecision (0) { }
|
||||||
~TSymbolTableLevel();
|
~TSymbolTableLevel();
|
||||||
|
|
||||||
bool insert(TSymbol& symbol)
|
bool insert(TSymbol& symbol)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// returning true means symbol was added to the table
|
// returning true means symbol was added to the table
|
||||||
//
|
//
|
||||||
tInsertResult result;
|
tInsertResult result;
|
||||||
result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
|
result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
|
||||||
|
|
||||||
return result.second;
|
return result.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,17 +224,44 @@ public:
|
|||||||
return (*it).second;
|
return (*it).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use this to do a lazy 'push' of precision defaults the first time
|
||||||
|
// a precision statement is seen in a new scope. Leave it at 0 for
|
||||||
|
// when no push was needed. Thus, it is not the current defaults,
|
||||||
|
// it is what to restore the defaults to when popping a level.
|
||||||
|
void setPreviousDefaultPrecisions(const TPrecisionQualifier *p)
|
||||||
|
{
|
||||||
|
// can call multiple times at one scope, will only latch on first call,
|
||||||
|
// as we're tracking the previous scope's values, not the current values
|
||||||
|
if (defaultPrecision != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
defaultPrecision = new TPrecisionQualifier[EbtNumTypes];
|
||||||
|
for (int t = 0; t < EbtNumTypes; ++t)
|
||||||
|
defaultPrecision[t] = p[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
void getPreviousDefaultPrecisions(TPrecisionQualifier *p)
|
||||||
|
{
|
||||||
|
// can be called for table level pops that didn't set the
|
||||||
|
// defaults
|
||||||
|
if (defaultPrecision == 0 || p == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int t = 0; t < EbtNumTypes; ++t)
|
||||||
|
p[t] = defaultPrecision[t];
|
||||||
|
}
|
||||||
|
|
||||||
void relateToOperator(const char* name, TOperator op);
|
void relateToOperator(const char* name, TOperator op);
|
||||||
void dump(TInfoSink &infoSink) const;
|
void dump(TInfoSink &infoSink) const;
|
||||||
TSymbolTableLevel* clone(TStructureMap& remapper);
|
TSymbolTableLevel* clone(TStructureMap& remapper);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
|
typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
|
||||||
typedef const tLevel::value_type tLevelPair;
|
typedef const tLevel::value_type tLevelPair;
|
||||||
typedef std::pair<tLevel::iterator, bool> tInsertResult;
|
typedef std::pair<tLevel::iterator, bool> tInsertResult;
|
||||||
|
|
||||||
tLevel level;
|
tLevel level;
|
||||||
|
TPrecisionQualifier *defaultPrecision;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TSymbolTable {
|
class TSymbolTable {
|
||||||
@ -258,7 +285,7 @@ public:
|
|||||||
{
|
{
|
||||||
// level 0 is always built In symbols, so we never pop that out
|
// level 0 is always built In symbols, so we never pop that out
|
||||||
while (table.size() > 1)
|
while (table.size() > 1)
|
||||||
pop();
|
pop(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -270,13 +297,17 @@ public:
|
|||||||
bool atBuiltInLevel() { return atSharedBuiltInLevel() || atDynamicBuiltInLevel(); }
|
bool atBuiltInLevel() { return atSharedBuiltInLevel() || atDynamicBuiltInLevel(); }
|
||||||
bool atSharedBuiltInLevel() { return table.size() == 1; }
|
bool atSharedBuiltInLevel() { return table.size() == 1; }
|
||||||
bool atGlobalLevel() { return table.size() <= 3; }
|
bool atGlobalLevel() { return table.size() <= 3; }
|
||||||
void push() {
|
|
||||||
|
void push()
|
||||||
|
{
|
||||||
table.push_back(new TSymbolTableLevel);
|
table.push_back(new TSymbolTableLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop() {
|
void pop(TPrecisionQualifier *p)
|
||||||
delete table[currentLevel()];
|
{
|
||||||
table.pop_back();
|
table[currentLevel()]->getPreviousDefaultPrecisions(p);
|
||||||
|
delete table[currentLevel()];
|
||||||
|
table.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert(TSymbol& symbol)
|
bool insert(TSymbol& symbol)
|
||||||
@ -284,8 +315,8 @@ public:
|
|||||||
symbol.setUniqueId(++uniqueId);
|
symbol.setUniqueId(++uniqueId);
|
||||||
return table[currentLevel()]->insert(symbol);
|
return table[currentLevel()]->insert(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0)
|
TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0)
|
||||||
{
|
{
|
||||||
int level = currentLevel();
|
int level = currentLevel();
|
||||||
TSymbol* symbol;
|
TSymbol* symbol;
|
||||||
@ -307,7 +338,9 @@ public:
|
|||||||
void dump(TInfoSink &infoSink) const;
|
void dump(TInfoSink &infoSink) const;
|
||||||
void copyTable(const TSymbolTable& copyOf);
|
void copyTable(const TSymbolTable& copyOf);
|
||||||
|
|
||||||
protected:
|
void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
|
||||||
|
|
||||||
|
protected:
|
||||||
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
|
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
|
||||||
bool atDynamicBuiltInLevel() { return table.size() == 2; }
|
bool atDynamicBuiltInLevel() { return table.size() == 2; }
|
||||||
|
|
||||||
|
@ -732,6 +732,24 @@ void SetVersion(int version)
|
|||||||
{
|
{
|
||||||
TParseContext& parseContext = *((TParseContext *)cpp->pC);
|
TParseContext& parseContext = *((TParseContext *)cpp->pC);
|
||||||
parseContext.version = version;
|
parseContext.version = version;
|
||||||
|
|
||||||
|
if (version == 100 || version == 300) {
|
||||||
|
for (int type = 0; type < EbtNumTypes; ++type)
|
||||||
|
parseContext.defaultPrecision[type] = EpqNone;
|
||||||
|
|
||||||
|
if (parseContext.language == EShLangVertex) {
|
||||||
|
parseContext.defaultPrecision[EbtInt] = EpqHigh;
|
||||||
|
parseContext.defaultPrecision[EbtFloat] = EpqHigh;
|
||||||
|
parseContext.defaultPrecision[EbtSampler2D] = EpqLow;
|
||||||
|
parseContext.defaultPrecision[EbtSamplerCube] = EpqLow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parseContext.language == EShLangFragment) {
|
||||||
|
parseContext.defaultPrecision[EbtInt] = EpqMedium;
|
||||||
|
parseContext.defaultPrecision[EbtSampler2D] = EpqLow;
|
||||||
|
parseContext.defaultPrecision[EbtSamplerCube] = EpqLow;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FirstProfileVersion = 150;
|
const int FirstProfileVersion = 150;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -60,10 +60,12 @@ TString TType::getCompleteString() const
|
|||||||
char *p = &buf[0];
|
char *p = &buf[0];
|
||||||
char *end = &buf[maxSize];
|
char *end = &buf[maxSize];
|
||||||
|
|
||||||
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
|
if (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal)
|
||||||
p += sprintf_s(p, end - p, "%s ", getQualifierString());
|
p += sprintf_s(p, end - p, "%s ", getStorageQualifierString());
|
||||||
if (array)
|
if (array)
|
||||||
p += sprintf_s(p, end - p, "array of ");
|
p += sprintf_s(p, end - p, "array of ");
|
||||||
|
if (qualifier.precision != EpqNone)
|
||||||
|
p += sprintf_s(p, end - p, "%s ", getPrecisionQualifierString());
|
||||||
if (matrix)
|
if (matrix)
|
||||||
p += sprintf_s(p, end - p, "%dX%d matrix of ", size, size);
|
p += sprintf_s(p, end - p, "%dX%d matrix of ", size, size);
|
||||||
else if (size > 1)
|
else if (size > 1)
|
||||||
|
@ -69,15 +69,15 @@ void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
|
|||||||
{
|
{
|
||||||
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
||||||
oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
|
oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
|
||||||
return;
|
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
||||||
{
|
{
|
||||||
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
||||||
|
|
||||||
TQualifier qualifier = node->getType().getQualifier();
|
TStorageQualifier qualifier = node->getType().getQualifier().storage;
|
||||||
|
|
||||||
if (qualifier != EvqConst) {
|
if (qualifier != EvqConst) {
|
||||||
const int maxSize = 200;
|
const int maxSize = 200;
|
||||||
@ -85,6 +85,7 @@ bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
|||||||
sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
|
sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
|
||||||
oit->infoSink.info.message(EPrefixError, buf, node->getLine());
|
oit->infoSink.info.message(EPrefixError, buf, node->getLine());
|
||||||
oit->error = true;
|
oit->error = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +103,7 @@ bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
|
|||||||
sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
|
sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
|
||||||
oit->infoSink.info.message(EPrefixError, buf, node->getLine());
|
oit->infoSink.info.message(EPrefixError, buf, node->getLine());
|
||||||
oit->error = true;
|
oit->error = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,11 +117,13 @@ bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverse
|
|||||||
sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
|
sprintf_s(buf, maxSize, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
|
||||||
oit->infoSink.info.message(EPrefixError, buf, node->getLine());
|
oit->infoSink.info.message(EPrefixError, buf, node->getLine());
|
||||||
oit->error = true;
|
oit->error = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->getSequence().size() == 0) {
|
if (node->getSequence().size() == 0) {
|
||||||
oit->error = true;
|
oit->error = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +156,7 @@ bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverse
|
|||||||
oit->isMatrix = false;
|
oit->isMatrix = false;
|
||||||
oit->matrixSize = 0;
|
oit->matrixSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +234,7 @@ bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
|
|||||||
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
||||||
oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
|
oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
|
||||||
oit->error = true;
|
oit->error = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +243,7 @@ bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
|
|||||||
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
||||||
oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
|
oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
|
||||||
oit->error = true;
|
oit->error = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user