Major change to tblgen: instead of resolving values every time a class is

finished up, only resolve fully when the def is defined.  This allows things
to be changed and all uses to be propagated through.  This implements
TableGen/LazyChange.td and fixes TemplateArgRename.td in the process.

None of the .td files used in LLVM backends are changed at all by this
patch.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21344 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2005-04-19 03:36:21 +00:00
parent 6b43c82378
commit 7dda395004
3 changed files with 119 additions and 73 deletions

View File

@ -25,6 +25,7 @@ namespace llvm {
extern int Filelineno; extern int Filelineno;
static Record *CurRec = 0; static Record *CurRec = 0;
static bool ParsingTemplateArgs = false;
typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy; typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
@ -133,6 +134,8 @@ static void setValue(const std::string &ValName,
} }
} }
// addSubClass - Add SC as a subclass to CurRec, resolving TemplateArgs as SC's
// template arguments.
static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) { static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) {
// Add all of the values in the subclass into the current class... // Add all of the values in the subclass into the current class...
const std::vector<RecordVal> &Vals = SC->getValues(); const std::vector<RecordVal> &Vals = SC->getValues();
@ -147,11 +150,19 @@ static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) {
exit(1); exit(1);
} else { // This class expects template arguments... } else { // This class expects template arguments...
// Loop over all of the template arguments, setting them to the specified // Loop over all of the template arguments, setting them to the specified
// value or leaving them as the default as necessary. // value or leaving them as the default if necessary.
for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
if (i < TemplateArgs.size()) { // A value is specified for this temp-arg? if (i < TemplateArgs.size()) { // A value is specified for this temp-arg?
// Set it now. // Set it now.
setValue(TArgs[i], 0, TemplateArgs[i]); setValue(TArgs[i], 0, TemplateArgs[i]);
// Resolve it next.
CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
// Now remove it.
CurRec->removeValue(TArgs[i]);
} else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
err() << "ERROR: Value not specified for template argument #" err() << "ERROR: Value not specified for template argument #"
<< i << " (" << TArgs[i] << ") of subclass '" << SC->getName() << i << " (" << TArgs[i] << ") of subclass '" << SC->getName()
@ -268,6 +279,10 @@ Value : INTVAL {
} | ID { } | ID {
if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) { if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) {
$$ = new VarInit(*$1, RV->getType()); $$ = new VarInit(*$1, RV->getType());
} else if (CurRec && CurRec->isTemplateArg(CurRec->getName()+":"+*$1)) {
const RecordVal *RV = CurRec->getValue(CurRec->getName()+":"+*$1);
assert(RV && "Template arg doesn't exist??");
$$ = new VarInit(CurRec->getName()+":"+*$1, RV->getType());
} else if (Record *D = Records.getDef(*$1)) { } else if (Record *D = Records.getDef(*$1)) {
$$ = new DefInit(D); $$ = new DefInit(D);
} else { } else {
@ -434,9 +449,13 @@ ValueListNE : Value {
}; };
Declaration : OptPrefix Type ID OptValue { Declaration : OptPrefix Type ID OptValue {
addValue(RecordVal(*$3, $2, $1)); std::string DecName = *$3;
setValue(*$3, 0, $4); if (ParsingTemplateArgs)
$$ = $3; DecName = CurRec->getName() + ":" + DecName;
addValue(RecordVal(DecName, $2, $1));
setValue(DecName, 0, $4);
$$ = new std::string(DecName);
}; };
BodyItem : Declaration ';' { BodyItem : Declaration ';' {
@ -492,12 +511,15 @@ ObjectBody : OptID {
*$1 = "anonymous."+utostr(AnonCounter++); *$1 = "anonymous."+utostr(AnonCounter++);
CurRec = new Record(*$1); CurRec = new Record(*$1);
delete $1; delete $1;
ParsingTemplateArgs = true;
} OptTemplateArgList ClassList { } OptTemplateArgList ClassList {
ParsingTemplateArgs = false;
for (unsigned i = 0, e = $4->size(); i != e; ++i) { for (unsigned i = 0, e = $4->size(); i != e; ++i) {
addSubClass((*$4)[i].first, *(*$4)[i].second); addSubClass((*$4)[i].first, *(*$4)[i].second);
// Delete the template arg values for the class // Delete the template arg values for the class
delete (*$4)[i].second; delete (*$4)[i].second;
} }
delete $4; // Delete the class list...
// Process any variables on the set stack... // Process any variables on the set stack...
for (unsigned i = 0, e = LetStack.size(); i != e; ++i) for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
@ -506,22 +528,9 @@ ObjectBody : OptID {
LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0, LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0,
LetStack[i][j].Value); LetStack[i][j].Value);
} Body { } Body {
CurRec->resolveReferences(); $$ = CurRec;
CurRec = 0;
// Now that all of the references have been resolved, we can delete template };
// arguments for superclasses, so they don't pollute our record, and so that
// their names won't conflict with later uses of the name...
for (unsigned i = 0, e = $4->size(); i != e; ++i) {
Record *SuperClass = (*$4)[i].first;
for (unsigned i = 0, e = SuperClass->getTemplateArgs().size(); i != e; ++i)
if (!CurRec->isTemplateArg(SuperClass->getTemplateArgs()[i]))
CurRec->removeValue(SuperClass->getTemplateArgs()[i]);
}
delete $4; // Delete the class list...
$$ = CurRec;
CurRec = 0;
};
ClassInst : CLASS ObjectBody { ClassInst : CLASS ObjectBody {
if (Records.getClass($2->getName())) { if (Records.getClass($2->getName())) {
@ -532,6 +541,8 @@ ClassInst : CLASS ObjectBody {
}; };
DefInst : DEF ObjectBody { DefInst : DEF ObjectBody {
$2->resolveReferences();
if (!$2->getTemplateArgs().empty()) { if (!$2->getTemplateArgs().empty()) {
err() << "Def '" << $2->getName() err() << "Def '" << $2->getName()
<< "' is not permitted to have template arguments!\n"; << "' is not permitted to have template arguments!\n";

View File

@ -275,7 +275,7 @@ bool BitsInit::printAsUnset(std::ostream &OS) const {
// resolveReferences - If there are any field references that refer to fields // resolveReferences - If there are any field references that refer to fields
// that have been filled in, we can propagate the values now. // that have been filled in, we can propagate the values now.
// //
Init *BitsInit::resolveReferences(Record &R) { Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) {
bool Changed = false; bool Changed = false;
BitsInit *New = new BitsInit(getNumBits()); BitsInit *New = new BitsInit(getNumBits());
@ -285,7 +285,7 @@ Init *BitsInit::resolveReferences(Record &R) {
do { do {
B = CurBit; B = CurBit;
CurBit = CurBit->resolveReferences(R); CurBit = CurBit->resolveReferences(R, RV);
Changed |= B != CurBit; Changed |= B != CurBit;
} while (B != CurBit); } while (B != CurBit);
New->setBit(i, CurBit); New->setBit(i, CurBit);
@ -334,7 +334,7 @@ Init *ListInit::convertInitListSlice(const std::vector<unsigned> &Elements) {
return new ListInit(Vals); return new ListInit(Vals);
} }
Init *ListInit::resolveReferences(Record &R) { Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) {
std::vector<Init*> Resolved; std::vector<Init*> Resolved;
Resolved.reserve(getSize()); Resolved.reserve(getSize());
bool Changed = false; bool Changed = false;
@ -345,7 +345,7 @@ Init *ListInit::resolveReferences(Record &R) {
do { do {
E = CurElt; E = CurElt;
CurElt = CurElt->resolveReferences(R); CurElt = CurElt->resolveReferences(R, RV);
Changed |= E != CurElt; Changed |= E != CurElt;
} while (E != CurElt); } while (E != CurElt);
Resolved.push_back(E); Resolved.push_back(E);
@ -396,9 +396,10 @@ Init *TypedInit::convertInitListSlice(const std::vector<unsigned> &Elements) {
} }
Init *VarInit::resolveBitReference(Record &R, unsigned Bit) { Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV,
if (R.isTemplateArg(getName())) unsigned Bit) {
return 0; if (R.isTemplateArg(getName())) return 0;
if (IRV && IRV->getName() != getName()) return 0;
RecordVal *RV = R.getValue(getName()); RecordVal *RV = R.getValue(getName());
assert(RV && "Reference to a non-existant variable?"); assert(RV && "Reference to a non-existant variable?");
@ -413,9 +414,10 @@ Init *VarInit::resolveBitReference(Record &R, unsigned Bit) {
return 0; return 0;
} }
Init *VarInit::resolveListElementReference(Record &R, unsigned Elt) { Init *VarInit::resolveListElementReference(Record &R, const RecordVal *IRV,
if (R.isTemplateArg(getName())) unsigned Elt) {
return 0; if (R.isTemplateArg(getName())) return 0;
if (IRV && IRV->getName() != getName()) return 0;
RecordVal *RV = R.getValue(getName()); RecordVal *RV = R.getValue(getName());
assert(RV && "Reference to a non-existant variable?"); assert(RV && "Reference to a non-existant variable?");
@ -456,33 +458,36 @@ Init *VarInit::getFieldInit(Record &R, const std::string &FieldName) const {
/// If a value is set for the variable later, this method will be called on /// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out. /// users of the value to allow the value to propagate out.
/// ///
Init *VarInit::resolveReferences(Record &R) { Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) {
if (RecordVal *Val = R.getValue(VarName)) if (RecordVal *Val = R.getValue(VarName))
if (!dynamic_cast<UnsetInit*>(Val->getValue())) if (RV == Val || (RV == 0 && !dynamic_cast<UnsetInit*>(Val->getValue())))
return Val->getValue(); return Val->getValue();
return this; return this;
} }
Init *VarBitInit::resolveReferences(Record &R) { Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) {
if (Init *I = getVariable()->resolveBitReference(R, getBitNum())) if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum()))
return I; return I;
return this; return this;
} }
Init *VarListElementInit::resolveReferences(Record &R) { Init *VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) {
if (Init *I = getVariable()->resolveListElementReference(R, getElementNum())) if (Init *I = getVariable()->resolveListElementReference(R, RV,
getElementNum()))
return I; return I;
return this; return this;
} }
Init *VarListElementInit::resolveBitReference(Record &R, unsigned Bit) { Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV,
unsigned Bit) {
// FIXME: This should be implemented, to support references like: // FIXME: This should be implemented, to support references like:
// bit B = AA[0]{1}; // bit B = AA[0]{1};
return 0; return 0;
} }
Init *VarListElementInit::resolveListElementReference(Record &R, unsigned Elt) { Init *VarListElementInit::
resolveListElementReference(Record &R, const RecordVal *RV, unsigned Elt) {
// FIXME: This should be implemented, to support references like: // FIXME: This should be implemented, to support references like:
// int B = AA[0][1]; // int B = AA[0][1];
return 0; return 0;
@ -503,7 +508,8 @@ void DefInit::print(std::ostream &OS) const {
OS << Def->getName(); OS << Def->getName();
} }
Init *FieldInit::resolveBitReference(Record &R, unsigned Bit) { Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV,
unsigned Bit) {
if (Init *BitsVal = Rec->getFieldInit(R, FieldName)) if (Init *BitsVal = Rec->getFieldInit(R, FieldName))
if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) { if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) {
assert(Bit < BI->getNumBits() && "Bit reference out of range!"); assert(Bit < BI->getNumBits() && "Bit reference out of range!");
@ -515,7 +521,8 @@ Init *FieldInit::resolveBitReference(Record &R, unsigned Bit) {
return 0; return 0;
} }
Init *FieldInit::resolveListElementReference(Record &R, unsigned Elt) { Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt) {
if (Init *ListVal = Rec->getFieldInit(R, FieldName)) if (Init *ListVal = Rec->getFieldInit(R, FieldName))
if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) { if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) {
if (Elt >= LI->getSize()) return 0; if (Elt >= LI->getSize()) return 0;
@ -527,12 +534,20 @@ Init *FieldInit::resolveListElementReference(Record &R, unsigned Elt) {
return 0; return 0;
} }
Init *FieldInit::resolveReferences(Record &R) { Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) {
Init *BitsVal = Rec->getFieldInit(R, FieldName); Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec;
Init *BitsVal = NewRec->getFieldInit(R, FieldName);
if (BitsVal) { if (BitsVal) {
Init *BVR = BitsVal->resolveReferences(R); Init *BVR = BitsVal->resolveReferences(R, RV);
return BVR->isComplete() ? BVR : this; return BVR->isComplete() ? BVR : this;
} }
if (NewRec != Rec) {
dump();
NewRec->dump(); std::cerr << "\n";
return new FieldInit(NewRec, FieldName);
}
return this; return this;
} }
@ -566,20 +581,24 @@ void RecordVal::dump() const { std::cerr << *this; }
void RecordVal::print(std::ostream &OS, bool PrintSem) const { void RecordVal::print(std::ostream &OS, bool PrintSem) const {
if (getPrefix()) OS << "field "; if (getPrefix()) OS << "field ";
OS << *getType() << " " << getName(); OS << *getType() << " " << getName();
if (getValue()) {
if (getValue())
OS << " = " << *getValue(); OS << " = " << *getValue();
}
if (PrintSem) OS << ";\n"; if (PrintSem) OS << ";\n";
} }
// resolveReferences - If there are any field references that refer to fields /// resolveReferencesTo - If anything in this record refers to RV, replace the
// that have been filled in, we can propagate the values now. /// reference to RV with the RHS of RV. If RV is null, we resolve all possible
// /// references.
void Record::resolveReferences() { void Record::resolveReferencesTo(const RecordVal *RV) {
for (unsigned i = 0, e = Values.size(); i != e; ++i) for (unsigned i = 0, e = Values.size(); i != e; ++i) {
Values[i].setValue(Values[i].getValue()->resolveReferences(*this)); if (Init *V = Values[i].getValue())
Values[i].setValue(V->resolveReferences(*this, RV));
}
} }
void Record::dump() const { std::cerr << *this; } void Record::dump() const { std::cerr << *this; }
std::ostream &llvm::operator<<(std::ostream &OS, const Record &R) { std::ostream &llvm::operator<<(std::ostream &OS, const Record &R) {

View File

@ -23,7 +23,7 @@
namespace llvm { namespace llvm {
// RecTy subclasses... // RecTy subclasses.
class BitRecTy; class BitRecTy;
class BitsRecTy; class BitsRecTy;
class IntRecTy; class IntRecTy;
@ -33,7 +33,7 @@ class CodeRecTy;
class DagRecTy; class DagRecTy;
class RecordRecTy; class RecordRecTy;
// Init subclasses... // Init subclasses.
struct Init; struct Init;
class UnsetInit; class UnsetInit;
class BitInit; class BitInit;
@ -50,8 +50,9 @@ class FieldInit;
class VarBitInit; class VarBitInit;
class VarListElementInit; class VarListElementInit;
// Other classes... // Other classes.
class Record; class Record;
class RecordVal;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Type Classes // Type Classes
@ -474,7 +475,9 @@ struct Init {
/// If a value is set for the variable later, this method will be called on /// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out. /// users of the value to allow the value to propagate out.
/// ///
virtual Init *resolveReferences(Record &R) { return this; } virtual Init *resolveReferences(Record &R, const RecordVal *RV) {
return this;
}
}; };
inline std::ostream &operator<<(std::ostream &OS, const Init &I) { inline std::ostream &operator<<(std::ostream &OS, const Init &I) {
@ -543,7 +546,7 @@ public:
} }
virtual void print(std::ostream &OS) const; virtual void print(std::ostream &OS) const;
virtual Init *resolveReferences(Record &R); virtual Init *resolveReferences(Record &R, const RecordVal *RV);
// printXX - Print this bitstream with the specified format, returning true if // printXX - Print this bitstream with the specified format, returning true if
// it is not possible. // it is not possible.
@ -631,7 +634,7 @@ public:
/// If a value is set for the variable later, this method will be called on /// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out. /// users of the value to allow the value to propagate out.
/// ///
virtual Init *resolveReferences(Record &R); virtual Init *resolveReferences(Record &R, const RecordVal *RV);
virtual void print(std::ostream &OS) const; virtual void print(std::ostream &OS) const;
}; };
@ -654,12 +657,14 @@ public:
/// VarBitInit::resolveReferences. If the bit is able to be resolved, we /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
/// simply return the resolved value, otherwise we return null. /// simply return the resolved value, otherwise we return null.
/// ///
virtual Init *resolveBitReference(Record &R, unsigned Bit) = 0; virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
unsigned Bit) = 0;
/// resolveListElementReference - This method is used to implement /// resolveListElementReference - This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable /// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null. /// now, we return the resolved value, otherwise we return null.
virtual Init *resolveListElementReference(Record &R, unsigned Elt) = 0; virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt) = 0;
}; };
/// VarInit - 'Opcode' - Represent a reference to an entire variable object. /// VarInit - 'Opcode' - Represent a reference to an entire variable object.
@ -675,8 +680,10 @@ public:
const std::string &getName() const { return VarName; } const std::string &getName() const { return VarName; }
virtual Init *resolveBitReference(Record &R, unsigned Bit); virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
virtual Init *resolveListElementReference(Record &R, unsigned Elt); unsigned Bit);
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt);
virtual RecTy *getFieldType(const std::string &FieldName) const; virtual RecTy *getFieldType(const std::string &FieldName) const;
virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
@ -686,7 +693,7 @@ public:
/// If a value is set for the variable later, this method will be called on /// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out. /// users of the value to allow the value to propagate out.
/// ///
virtual Init *resolveReferences(Record &R); virtual Init *resolveReferences(Record &R, const RecordVal *RV);
virtual void print(std::ostream &OS) const { OS << VarName; } virtual void print(std::ostream &OS) const { OS << VarName; }
}; };
@ -714,7 +721,7 @@ public:
virtual void print(std::ostream &OS) const { virtual void print(std::ostream &OS) const {
TI->print(OS); OS << "{" << Bit << "}"; TI->print(OS); OS << "{" << Bit << "}";
} }
virtual Init *resolveReferences(Record &R); virtual Init *resolveReferences(Record &R, const RecordVal *RV);
}; };
/// VarListElementInit - List[4] - Represent access to one element of a var or /// VarListElementInit - List[4] - Represent access to one element of a var or
@ -737,17 +744,19 @@ public:
TypedInit *getVariable() const { return TI; } TypedInit *getVariable() const { return TI; }
unsigned getElementNum() const { return Element; } unsigned getElementNum() const { return Element; }
virtual Init *resolveBitReference(Record &R, unsigned Bit); virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
unsigned Bit);
/// resolveListElementReference - This method is used to implement /// resolveListElementReference - This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable /// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null. /// now, we return the resolved value, otherwise we return null.
virtual Init *resolveListElementReference(Record &R, unsigned Elt); virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt);
virtual void print(std::ostream &OS) const { virtual void print(std::ostream &OS) const {
TI->print(OS); OS << "[" << Element << "]"; TI->print(OS); OS << "[" << Element << "]";
} }
virtual Init *resolveReferences(Record &R); virtual Init *resolveReferences(Record &R, const RecordVal *RV);
}; };
/// DefInit - AL - Represent a reference to a 'def' in the description /// DefInit - AL - Represent a reference to a 'def' in the description
@ -787,10 +796,12 @@ public:
return Ty->convertValue(this); return Ty->convertValue(this);
} }
virtual Init *resolveBitReference(Record &R, unsigned Bit); virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
virtual Init *resolveListElementReference(Record &R, unsigned Elt); unsigned Bit);
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt);
virtual Init *resolveReferences(Record &R); virtual Init *resolveReferences(Record &R, const RecordVal *RV);
virtual void print(std::ostream &OS) const { virtual void print(std::ostream &OS) const {
Rec->print(OS); OS << "." << FieldName; Rec->print(OS); OS << "." << FieldName;
@ -949,10 +960,15 @@ public:
SuperClasses.push_back(R); SuperClasses.push_back(R);
} }
// resolveReferences - If there are any field references that refer to fields /// resolveReferences - If there are any field references that refer to fields
// that have been filled in, we can propagate the values now. /// that have been filled in, we can propagate the values now.
// ///
void resolveReferences(); void resolveReferences() { resolveReferencesTo(0); }
/// resolveReferencesTo - If anything in this record refers to RV, replace the
/// reference to RV with the RHS of RV. If RV is null, we resolve all
/// possible references.
void resolveReferencesTo(const RecordVal *RV);
void dump() const; void dump() const;