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:
John Kessenich 2013-01-24 23:10:51 +00:00
parent 674014bfc4
commit 5521862729
15 changed files with 661 additions and 463 deletions

View File

@ -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_

View File

@ -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

View File

@ -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; }

View File

@ -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)

View File

@ -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;
} }
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -32,4 +32,4 @@
//POSSIBILITY OF SUCH DAMAGE. //POSSIBILITY OF SUCH DAMAGE.
// //
bool QualifierWritten(TIntermNode* root, TQualifier); bool QualifierWritten(TIntermNode* root, TStorageQualifier);

View File

@ -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();
// //

View File

@ -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;
} }
// //

View File

@ -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; }

View File

@ -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

View File

@ -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)

View File

@ -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;
} }