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 "Record.h"
|
||||||
#include "Error.h"
|
#include "Error.h"
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/FoldingSet.h"
|
#include "llvm/ADT/FoldingSet.h"
|
||||||
@ -1638,22 +1639,61 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
|
|||||||
|
|
||||||
unsigned Record::LastID = 0;
|
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() {
|
DefInit *Record::getDefInit() {
|
||||||
if (!TheInit)
|
if (!TheInit)
|
||||||
TheInit = new DefInit(this, new RecordRecTy(this));
|
TheInit = new DefInit(this, new RecordRecTy(this));
|
||||||
return TheInit;
|
return TheInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Record::setName(const std::string &Name) {
|
const std::string &Record::getName() const {
|
||||||
if (TrackedRecords.getDef(getName()) == this) {
|
const StringInit *NameString =
|
||||||
TrackedRecords.removeDef(getName());
|
dynamic_cast<const StringInit *>(Name);
|
||||||
this->Name = 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);
|
TrackedRecords.addDef(this);
|
||||||
} else {
|
} else {
|
||||||
TrackedRecords.removeClass(getName());
|
TrackedRecords.removeClass(Name->getAsUnquotedString());
|
||||||
this->Name = Name;
|
Name = NewName;
|
||||||
TrackedRecords.addClass(this);
|
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
|
/// resolveReferencesTo - If anything in this record refers to RV, replace the
|
||||||
|
@ -1373,7 +1373,7 @@ class Record {
|
|||||||
|
|
||||||
// Unique record ID.
|
// Unique record ID.
|
||||||
unsigned ID;
|
unsigned ID;
|
||||||
std::string Name;
|
Init *Name;
|
||||||
SMLoc Loc;
|
SMLoc Loc;
|
||||||
std::vector<std::string> TemplateArgs;
|
std::vector<std::string> TemplateArgs;
|
||||||
std::vector<RecordVal> Values;
|
std::vector<RecordVal> Values;
|
||||||
@ -1384,11 +1384,13 @@ class Record {
|
|||||||
|
|
||||||
DefInit *TheInit;
|
DefInit *TheInit;
|
||||||
|
|
||||||
|
void checkName();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructs a record.
|
// Constructs a record.
|
||||||
explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) :
|
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() {}
|
~Record() {}
|
||||||
|
|
||||||
|
|
||||||
@ -1397,7 +1399,8 @@ public:
|
|||||||
|
|
||||||
unsigned getID() const { return ID; }
|
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.
|
void setName(const std::string &Name); // Also updates RecordKeeper.
|
||||||
|
|
||||||
SMLoc getLoc() const { return Loc; }
|
SMLoc getLoc() const { return Loc; }
|
||||||
|
@ -1690,6 +1690,9 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
|
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();
|
CurRec->resolveReferences();
|
||||||
|
|
||||||
// If ObjectBody has template arguments, it's an error.
|
// If ObjectBody has template arguments, it's an error.
|
||||||
@ -2102,6 +2105,9 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
|
|||||||
|
|
||||||
if (!CurMultiClass)
|
if (!CurMultiClass)
|
||||||
for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
|
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();
|
NewRecDefs[i]->resolveReferences();
|
||||||
|
|
||||||
if (Lex.getCode() != tgtok::semi)
|
if (Lex.getCode() != tgtok::semi)
|
||||||
|
Loading…
Reference in New Issue
Block a user