Commit 55218627 by John Kessenich

Implement the full scheme for ES precision qualifiers, generalizing existing…

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
parent 674014bf
...@@ -55,7 +55,7 @@ enum TBasicType { ...@@ -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) ...@@ -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 { ...@@ -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) ...@@ -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() ...@@ -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: ...@@ -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: ...@@ -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; ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 ...@@ -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) ...@@ -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 ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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: ...@@ -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: ...@@ -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) ...@@ -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 @@ ...@@ -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() ...@@ -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( ...@@ -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 ...@@ -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() ...@@ -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 @@ ...@@ -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 @@ ...@@ -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: ...@@ -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: ...@@ -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 { ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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) ...@@ -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;
......
...@@ -60,10 +60,12 @@ TString TType::getCompleteString() const ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment