mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-21 18:29:46 +00:00
Make Record Name an Init
Use an Init (ultimately a StringInit) to represent the Record name. This allows the name to be composed by standard TableGen operators. This will enable us to get rid of the ugly #NAME# hack processing and naturally replace it with operators. It also increases flexibility and power of the TableGen language by allowing record identifiers to be computed dynamically. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137232 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0b18d59435
commit
0d886401b3
@ -14,6 +14,7 @@
|
||||
#include "Record.h"
|
||||
#include "Error.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
@ -1638,22 +1639,61 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
|
||||
|
||||
unsigned Record::LastID = 0;
|
||||
|
||||
void Record::checkName() {
|
||||
// Ensure the record name has string type.
|
||||
const TypedInit *TypedName = dynamic_cast<const TypedInit *>(Name);
|
||||
assert(TypedName && "Record name is not typed!");
|
||||
RecTy *Type = TypedName->getType();
|
||||
if (dynamic_cast<StringRecTy *>(Type) == 0) {
|
||||
llvm_unreachable("Record name is not a string!");
|
||||
}
|
||||
}
|
||||
|
||||
DefInit *Record::getDefInit() {
|
||||
if (!TheInit)
|
||||
TheInit = new DefInit(this, new RecordRecTy(this));
|
||||
return TheInit;
|
||||
}
|
||||
|
||||
void Record::setName(const std::string &Name) {
|
||||
if (TrackedRecords.getDef(getName()) == this) {
|
||||
TrackedRecords.removeDef(getName());
|
||||
this->Name = Name;
|
||||
const std::string &Record::getName() const {
|
||||
const StringInit *NameString =
|
||||
dynamic_cast<const StringInit *>(Name);
|
||||
assert(NameString && "Record name is not a string!");
|
||||
return NameString->getValue();
|
||||
}
|
||||
|
||||
void Record::setName(Init *NewName) {
|
||||
if (TrackedRecords.getDef(Name->getAsUnquotedString()) == this) {
|
||||
TrackedRecords.removeDef(Name->getAsUnquotedString());
|
||||
Name = NewName;
|
||||
TrackedRecords.addDef(this);
|
||||
} else {
|
||||
TrackedRecords.removeClass(getName());
|
||||
this->Name = Name;
|
||||
TrackedRecords.removeClass(Name->getAsUnquotedString());
|
||||
Name = NewName;
|
||||
TrackedRecords.addClass(this);
|
||||
}
|
||||
checkName();
|
||||
// Since the Init for the name was changed, see if we can resolve
|
||||
// any of it using members of the Record.
|
||||
Init *ComputedName = Name->resolveReferences(*this, 0);
|
||||
if (ComputedName != Name) {
|
||||
setName(ComputedName);
|
||||
}
|
||||
// DO NOT resolve record values to the name at this point because
|
||||
// there might be default values for arguments of this def. Those
|
||||
// arguments might not have been resolved yet so we don't want to
|
||||
// prematurely assume values for those arguments were not passed to
|
||||
// this def.
|
||||
//
|
||||
// Nonetheless, it may be that some of this Record's values
|
||||
// reference the record name. Indeed, the reason for having the
|
||||
// record name be an Init is to provide this flexibility. The extra
|
||||
// resolve steps after completely instantiating defs takes care of
|
||||
// this. See TGParser::ParseDef and TGParser::ParseDefm.
|
||||
}
|
||||
|
||||
void Record::setName(const std::string &Name) {
|
||||
setName(StringInit::get(Name));
|
||||
}
|
||||
|
||||
/// resolveReferencesTo - If anything in this record refers to RV, replace the
|
||||
|
@ -1373,7 +1373,7 @@ class Record {
|
||||
|
||||
// Unique record ID.
|
||||
unsigned ID;
|
||||
std::string Name;
|
||||
Init *Name;
|
||||
SMLoc Loc;
|
||||
std::vector<std::string> TemplateArgs;
|
||||
std::vector<RecordVal> Values;
|
||||
@ -1384,11 +1384,13 @@ class Record {
|
||||
|
||||
DefInit *TheInit;
|
||||
|
||||
void checkName();
|
||||
|
||||
public:
|
||||
|
||||
// Constructs a record.
|
||||
explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) :
|
||||
ID(LastID++), Name(N), Loc(loc), TrackedRecords(records), TheInit(0) {}
|
||||
ID(LastID++), Name(StringInit::get(N)), Loc(loc), TrackedRecords(records), TheInit(0) {}
|
||||
~Record() {}
|
||||
|
||||
|
||||
@ -1397,7 +1399,8 @@ public:
|
||||
|
||||
unsigned getID() const { return ID; }
|
||||
|
||||
const std::string &getName() const { return Name; }
|
||||
const std::string &getName() const;
|
||||
void setName(Init *Name); // Also updates RecordKeeper.
|
||||
void setName(const std::string &Name); // Also updates RecordKeeper.
|
||||
|
||||
SMLoc getLoc() const { return Loc; }
|
||||
|
@ -1690,6 +1690,9 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
|
||||
return true;
|
||||
|
||||
if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
|
||||
// See Record::setName(). This resolve step will see any new name
|
||||
// for the def that might have been created when resolving
|
||||
// inheritance, values and arguments above.
|
||||
CurRec->resolveReferences();
|
||||
|
||||
// If ObjectBody has template arguments, it's an error.
|
||||
@ -2102,6 +2105,9 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
|
||||
|
||||
if (!CurMultiClass)
|
||||
for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
|
||||
// See Record::setName(). This resolve step will see any new
|
||||
// name for the def that might have been created when resolving
|
||||
// inheritance, values and arguments above.
|
||||
NewRecDefs[i]->resolveReferences();
|
||||
|
||||
if (Lex.getCode() != tgtok::semi)
|
||||
|
Loading…
Reference in New Issue
Block a user