Infrastructure: Generalize and broaden per-variable extension checking.

This commit is contained in:
John Kessenich 2018-12-11 17:42:35 -07:00
parent 69932ab47f
commit 28be4543cd
6 changed files with 135 additions and 73 deletions

View file

@ -79,10 +79,12 @@ class TVariable;
class TFunction;
class TAnonMember;
typedef TVector<const char*> TExtensionList;
class TSymbol {
public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
explicit TSymbol(const TString *n) : name(n), numExtensions(0), extensions(0), writable(true) { }
explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { }
virtual TSymbol* clone() const = 0;
virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
@ -104,17 +106,16 @@ public:
virtual TType& getWritableType() = 0;
virtual void setUniqueId(int id) { uniqueId = id; }
virtual int getUniqueId() const { return uniqueId; }
virtual void setExtensions(int num, const char* const exts[])
virtual void setExtensions(int numExts, const char* const exts[])
{
assert(extensions == 0);
assert(num > 0);
numExtensions = num;
extensions = NewPoolObject(exts[0], num);
for (int e = 0; e < num; ++e)
extensions[e] = exts[e];
assert(numExts > 0);
extensions = NewPoolObject(extensions);
for (int e = 0; e < numExts; ++e)
extensions->push_back(exts[e]);
}
virtual int getNumExtensions() const { return numExtensions; }
virtual const char** getExtensions() const { return extensions; }
virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
virtual const char** getExtensions() const { return extensions->data(); }
virtual void dump(TInfoSink &infoSink) const = 0;
virtual bool isReadOnly() const { return ! writable; }
@ -129,8 +130,7 @@ protected:
// For tracking what extensions must be present
// (don't use if correct version/profile is present).
int numExtensions;
const char** extensions; // an array of pointers to existing constant char strings
TExtensionList* extensions; // an array of pointers to existing constant char strings
//
// N.B.: Non-const functions that will be generally used should assert on this,
@ -155,7 +155,9 @@ public:
: TSymbol(name),
userType(uT),
constSubtree(nullptr),
anonId(-1) { type.shallowCopy(t); }
memberExtensions(nullptr),
anonId(-1)
{ type.shallowCopy(t); }
virtual TVariable* clone() const;
virtual ~TVariable() { }
@ -172,6 +174,24 @@ public:
virtual void setAnonId(int i) { anonId = i; }
virtual int getAnonId() const { return anonId; }
virtual void setMemberExtensions(int member, int numExts, const char* const exts[])
{
assert(type.isStruct());
assert(numExts > 0);
if (memberExtensions == nullptr) {
memberExtensions = NewPoolObject(memberExtensions);
memberExtensions->resize(type.getStruct()->size());
}
for (int e = 0; e < numExts; ++e)
(*memberExtensions)[member].push_back(exts[e]);
}
virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; }
virtual int getNumMemberExtensions(int member) const
{
return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size();
}
virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
virtual void dump(TInfoSink &infoSink) const;
protected:
@ -180,15 +200,14 @@ protected:
TType type;
bool userType;
// we are assuming that Pool Allocator will free the memory allocated to unionArray
// when this object is destroyed
// TODO: these two should be a union
// A variable could be a compile-time constant, or a specialization
// constant, or neither, but never both.
TConstUnionArray constArray; // for compile-time constant value
TIntermTyped* constSubtree; // for specialization constant computation
int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
TConstUnionArray constArray; // for compile-time constant value
TIntermTyped* constSubtree; // for specialization constant computation
TVector<TExtensionList>* memberExtensions; // per-member extension list, allocated only when needed
int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
};
//
@ -325,7 +344,7 @@ protected:
//
class TAnonMember : public TSymbol {
public:
TAnonMember(const TString* n, unsigned int m, const TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
virtual TAnonMember* clone() const;
virtual ~TAnonMember() { }
@ -346,6 +365,13 @@ public:
return *types[memberNumber].type;
}
virtual void setExtensions(int numExts, const char* const exts[]) override
{
anonContainer.setMemberExtensions(memberNumber, numExts, exts);
}
virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); }
virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
virtual int getAnonId() const { return anonId; }
virtual void dump(TInfoSink &infoSink) const;
@ -353,7 +379,7 @@ protected:
explicit TAnonMember(const TAnonMember&);
TAnonMember& operator=(const TAnonMember&);
const TVariable& anonContainer;
TVariable& anonContainer;
unsigned int memberNumber;
int anonId;
};
@ -789,11 +815,30 @@ public:
table[level]->setFunctionExtensions(name, num, extensions);
}
void setVariableExtensions(const char* name, int num, const char* const extensions[])
void setVariableExtensions(const char* name, int numExts, const char* const extensions[])
{
TSymbol* symbol = find(TString(name));
if (symbol)
symbol->setExtensions(num, extensions);
if (symbol == nullptr)
return;
symbol->setExtensions(numExts, extensions);
}
void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[])
{
TSymbol* symbol = find(TString(blockName));
if (symbol == nullptr)
return;
TVariable* variable = symbol->getAsVariable();
assert(variable != nullptr);
const TTypeList& structure = *variable->getAsVariable()->getType().getStruct();
for (int member = 0; member < (int)structure.size(); ++member) {
if (structure[member].type->getFieldName().compare(name) == 0) {
variable->setMemberExtensions(member, numExts, extensions);
return;
}
}
}
int getMaxSymbolId() { return uniqueId; }