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_
...@@ -63,6 +63,13 @@ inline TTypeList* NewPoolTTypeList() ...@@ -63,6 +63,13 @@ inline TTypeList* NewPoolTTypeList()
// 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)
{ {
qualifier = p.qualifier;
if (p.userDef) { if (p.userDef) {
structure = p.userDef->getStruct(); structure = p.userDef->getStruct();
typeName = NewPoolTString(p.userDef->getTypeName().c_str()); 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() {}
...@@ -206,8 +230,8 @@ public: ...@@ -206,8 +230,8 @@ public:
} }
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; }
...@@ -251,7 +275,8 @@ public: ...@@ -251,7 +275,8 @@ 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
...@@ -304,11 +329,12 @@ protected: ...@@ -304,11 +329,12 @@ 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;
} }
} }
......
...@@ -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;
...@@ -93,6 +88,7 @@ struct TParseContext { ...@@ -93,6 +88,7 @@ struct TParseContext {
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;
TPrecisionQualifier defaultPrecision[EbtNumTypes];
TString HashErrMsg; TString HashErrMsg;
bool AfterEOF; bool AfterEOF;
...@@ -125,11 +121,12 @@ struct TParseContext { ...@@ -125,11 +121,12 @@ 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);
......
...@@ -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;
} }
// //
......
...@@ -103,7 +103,7 @@ public: ...@@ -103,7 +103,7 @@ public:
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; }
...@@ -201,7 +201,7 @@ protected: ...@@ -201,7 +201,7 @@ 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)
...@@ -224,6 +224,32 @@ public: ...@@ -224,6 +224,32 @@ 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;
...@@ -235,6 +261,7 @@ protected: ...@@ -235,6 +261,7 @@ protected:
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,11 +297,15 @@ public: ...@@ -270,11 +297,15 @@ 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)
{
table[currentLevel()]->getPreviousDefaultPrecisions(p);
delete table[currentLevel()]; delete table[currentLevel()];
table.pop_back(); table.pop_back();
} }
...@@ -307,6 +338,8 @@ public: ...@@ -307,6 +338,8 @@ public:
void dump(TInfoSink &infoSink) const; void dump(TInfoSink &infoSink) const;
void copyTable(const TSymbolTable& copyOf); void copyTable(const TSymbolTable& copyOf);
void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
protected: 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