forked from OSchip/llvm-project
[TableGen] Remove the use of global Record state
This commits removes TableGens reliance on managed static global record state by moving the RecordContext into the RecordKeeper. The RecordKeeper is now treated similarly to a (LLVM|MLIR|etc)Context object and is passed to static construction functions. This is an important step forward in removing TableGens reliance on global state, and in a followup will allow for users that parse tablegen to parse multiple tablegen files without worrying about Record lifetime. Differential Revision: https://reviews.llvm.org/D125276
This commit is contained in:
parent
3ca6328637
commit
2ac3cd20ca
|
@ -39,7 +39,7 @@
|
|||
|
||||
namespace llvm {
|
||||
namespace detail {
|
||||
struct RecordContext;
|
||||
struct RecordKeeperImpl;
|
||||
} // namespace detail
|
||||
|
||||
class ListRecTy;
|
||||
|
@ -69,15 +69,20 @@ public:
|
|||
|
||||
private:
|
||||
RecTyKind Kind;
|
||||
/// The RecordKeeper that uniqued this Type.
|
||||
RecordKeeper &RK;
|
||||
/// ListRecTy of the list that has elements of this type.
|
||||
ListRecTy *ListTy = nullptr;
|
||||
|
||||
public:
|
||||
RecTy(RecTyKind K) : Kind(K) {}
|
||||
RecTy(RecTyKind K, RecordKeeper &RK) : Kind(K), RK(RK) {}
|
||||
virtual ~RecTy() = default;
|
||||
|
||||
RecTyKind getRecTyKind() const { return Kind; }
|
||||
|
||||
/// Return the RecordKeeper that uniqued this Type.
|
||||
RecordKeeper &getRecordKeeper() const { return RK; }
|
||||
|
||||
virtual std::string getAsString() const = 0;
|
||||
void print(raw_ostream &OS) const { OS << getAsString(); }
|
||||
void dump() const;
|
||||
|
@ -101,16 +106,16 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
|
|||
|
||||
/// 'bit' - Represent a single bit
|
||||
class BitRecTy : public RecTy {
|
||||
friend detail::RecordContext;
|
||||
friend detail::RecordKeeperImpl;
|
||||
|
||||
BitRecTy() : RecTy(BitRecTyKind) {}
|
||||
BitRecTy(RecordKeeper &RK) : RecTy(BitRecTyKind, RK) {}
|
||||
|
||||
public:
|
||||
static bool classof(const RecTy *RT) {
|
||||
return RT->getRecTyKind() == BitRecTyKind;
|
||||
}
|
||||
|
||||
static BitRecTy *get();
|
||||
static BitRecTy *get(RecordKeeper &RK);
|
||||
|
||||
std::string getAsString() const override { return "bit"; }
|
||||
|
||||
|
@ -121,14 +126,15 @@ public:
|
|||
class BitsRecTy : public RecTy {
|
||||
unsigned Size;
|
||||
|
||||
explicit BitsRecTy(unsigned Sz) : RecTy(BitsRecTyKind), Size(Sz) {}
|
||||
explicit BitsRecTy(RecordKeeper &RK, unsigned Sz)
|
||||
: RecTy(BitsRecTyKind, RK), Size(Sz) {}
|
||||
|
||||
public:
|
||||
static bool classof(const RecTy *RT) {
|
||||
return RT->getRecTyKind() == BitsRecTyKind;
|
||||
}
|
||||
|
||||
static BitsRecTy *get(unsigned Sz);
|
||||
static BitsRecTy *get(RecordKeeper &RK, unsigned Sz);
|
||||
|
||||
unsigned getNumBits() const { return Size; }
|
||||
|
||||
|
@ -141,16 +147,16 @@ public:
|
|||
|
||||
/// 'int' - Represent an integer value of no particular size
|
||||
class IntRecTy : public RecTy {
|
||||
friend detail::RecordContext;
|
||||
friend detail::RecordKeeperImpl;
|
||||
|
||||
IntRecTy() : RecTy(IntRecTyKind) {}
|
||||
IntRecTy(RecordKeeper &RK) : RecTy(IntRecTyKind, RK) {}
|
||||
|
||||
public:
|
||||
static bool classof(const RecTy *RT) {
|
||||
return RT->getRecTyKind() == IntRecTyKind;
|
||||
}
|
||||
|
||||
static IntRecTy *get();
|
||||
static IntRecTy *get(RecordKeeper &RK);
|
||||
|
||||
std::string getAsString() const override { return "int"; }
|
||||
|
||||
|
@ -159,16 +165,16 @@ public:
|
|||
|
||||
/// 'string' - Represent an string value
|
||||
class StringRecTy : public RecTy {
|
||||
friend detail::RecordContext;
|
||||
friend detail::RecordKeeperImpl;
|
||||
|
||||
StringRecTy() : RecTy(StringRecTyKind) {}
|
||||
StringRecTy(RecordKeeper &RK) : RecTy(StringRecTyKind, RK) {}
|
||||
|
||||
public:
|
||||
static bool classof(const RecTy *RT) {
|
||||
return RT->getRecTyKind() == StringRecTyKind;
|
||||
}
|
||||
|
||||
static StringRecTy *get();
|
||||
static StringRecTy *get(RecordKeeper &RK);
|
||||
|
||||
std::string getAsString() const override;
|
||||
|
||||
|
@ -182,7 +188,8 @@ class ListRecTy : public RecTy {
|
|||
|
||||
RecTy *ElementTy;
|
||||
|
||||
explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), ElementTy(T) {}
|
||||
explicit ListRecTy(RecTy *T)
|
||||
: RecTy(ListRecTyKind, T->getRecordKeeper()), ElementTy(T) {}
|
||||
|
||||
public:
|
||||
static bool classof(const RecTy *RT) {
|
||||
|
@ -201,16 +208,16 @@ public:
|
|||
|
||||
/// 'dag' - Represent a dag fragment
|
||||
class DagRecTy : public RecTy {
|
||||
friend detail::RecordContext;
|
||||
friend detail::RecordKeeperImpl;
|
||||
|
||||
DagRecTy() : RecTy(DagRecTyKind) {}
|
||||
DagRecTy(RecordKeeper &RK) : RecTy(DagRecTyKind, RK) {}
|
||||
|
||||
public:
|
||||
static bool classof(const RecTy *RT) {
|
||||
return RT->getRecTyKind() == DagRecTyKind;
|
||||
}
|
||||
|
||||
static DagRecTy *get();
|
||||
static DagRecTy *get(RecordKeeper &RK);
|
||||
|
||||
std::string getAsString() const override;
|
||||
};
|
||||
|
@ -222,12 +229,12 @@ public:
|
|||
class RecordRecTy final : public RecTy, public FoldingSetNode,
|
||||
public TrailingObjects<RecordRecTy, Record *> {
|
||||
friend class Record;
|
||||
friend detail::RecordContext;
|
||||
friend detail::RecordKeeperImpl;
|
||||
|
||||
unsigned NumClasses;
|
||||
|
||||
explicit RecordRecTy(unsigned Num)
|
||||
: RecTy(RecordRecTyKind), NumClasses(Num) {}
|
||||
explicit RecordRecTy(RecordKeeper &RK, unsigned Num)
|
||||
: RecTy(RecordRecTyKind, RK), NumClasses(Num) {}
|
||||
|
||||
public:
|
||||
RecordRecTy(const RecordRecTy &) = delete;
|
||||
|
@ -241,7 +248,8 @@ public:
|
|||
}
|
||||
|
||||
/// Get the record type with the given non-redundant list of superclasses.
|
||||
static RecordRecTy *get(ArrayRef<Record *> Classes);
|
||||
static RecordRecTy *get(RecordKeeper &RK, ArrayRef<Record *> Classes);
|
||||
static RecordRecTy *get(Record *Class);
|
||||
|
||||
void Profile(FoldingSetNodeID &ID) const;
|
||||
|
||||
|
@ -326,6 +334,9 @@ public:
|
|||
/// Get the kind (type) of the value.
|
||||
InitKind getKind() const { return Kind; }
|
||||
|
||||
/// Get the record keeper that initialized this Init.
|
||||
RecordKeeper &getRecordKeeper() const;
|
||||
|
||||
protected:
|
||||
explicit Init(InitKind K, uint8_t Opc = 0) : Kind(K), Opc(Opc) {}
|
||||
|
||||
|
@ -425,6 +436,9 @@ public:
|
|||
/// Get the type of the Init as a RecTy.
|
||||
RecTy *getType() const { return ValueTy; }
|
||||
|
||||
/// Get the record keeper that initialized this Init.
|
||||
RecordKeeper &getRecordKeeper() const { return ValueTy->getRecordKeeper(); }
|
||||
|
||||
Init *getCastTo(RecTy *Ty) const override;
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
|
@ -439,9 +453,12 @@ public:
|
|||
|
||||
/// '?' - Represents an uninitialized value.
|
||||
class UnsetInit : public Init {
|
||||
friend detail::RecordContext;
|
||||
friend detail::RecordKeeperImpl;
|
||||
|
||||
UnsetInit() : Init(IK_UnsetInit) {}
|
||||
/// The record keeper that initialized this Init.
|
||||
RecordKeeper &RK;
|
||||
|
||||
UnsetInit(RecordKeeper &RK) : Init(IK_UnsetInit), RK(RK) {}
|
||||
|
||||
public:
|
||||
UnsetInit(const UnsetInit &) = delete;
|
||||
|
@ -452,7 +469,10 @@ public:
|
|||
}
|
||||
|
||||
/// Get the singleton unset Init.
|
||||
static UnsetInit *get();
|
||||
static UnsetInit *get(RecordKeeper &RK);
|
||||
|
||||
/// Get the record keeper that initialized this Init.
|
||||
RecordKeeper &getRecordKeeper() const { return RK; }
|
||||
|
||||
Init *getCastTo(RecTy *Ty) const override;
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
@ -472,7 +492,7 @@ public:
|
|||
|
||||
/// 'true'/'false' - Represent a concrete initializer for a bit.
|
||||
class BitInit final : public TypedInit {
|
||||
friend detail::RecordContext;
|
||||
friend detail::RecordKeeperImpl;
|
||||
|
||||
bool Value;
|
||||
|
||||
|
@ -486,7 +506,7 @@ public:
|
|||
return I->getKind() == IK_BitInit;
|
||||
}
|
||||
|
||||
static BitInit *get(bool V);
|
||||
static BitInit *get(RecordKeeper &RK, bool V);
|
||||
|
||||
bool getValue() const { return Value; }
|
||||
|
||||
|
@ -507,8 +527,8 @@ class BitsInit final : public TypedInit, public FoldingSetNode,
|
|||
public TrailingObjects<BitsInit, Init *> {
|
||||
unsigned NumBits;
|
||||
|
||||
BitsInit(unsigned N)
|
||||
: TypedInit(IK_BitsInit, BitsRecTy::get(N)), NumBits(N) {}
|
||||
BitsInit(RecordKeeper &RK, unsigned N)
|
||||
: TypedInit(IK_BitsInit, BitsRecTy::get(RK, N)), NumBits(N) {}
|
||||
|
||||
public:
|
||||
BitsInit(const BitsInit &) = delete;
|
||||
|
@ -521,7 +541,7 @@ public:
|
|||
return I->getKind() == IK_BitsInit;
|
||||
}
|
||||
|
||||
static BitsInit *get(ArrayRef<Init *> Range);
|
||||
static BitsInit *get(RecordKeeper &RK, ArrayRef<Init *> Range);
|
||||
|
||||
void Profile(FoldingSetNodeID &ID) const;
|
||||
|
||||
|
@ -557,8 +577,8 @@ public:
|
|||
class IntInit : public TypedInit {
|
||||
int64_t Value;
|
||||
|
||||
explicit IntInit(int64_t V)
|
||||
: TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {}
|
||||
explicit IntInit(RecordKeeper &RK, int64_t V)
|
||||
: TypedInit(IK_IntInit, IntRecTy::get(RK)), Value(V) {}
|
||||
|
||||
public:
|
||||
IntInit(const IntInit &) = delete;
|
||||
|
@ -568,7 +588,7 @@ public:
|
|||
return I->getKind() == IK_IntInit;
|
||||
}
|
||||
|
||||
static IntInit *get(int64_t V);
|
||||
static IntInit *get(RecordKeeper &RK, int64_t V);
|
||||
|
||||
int64_t getValue() const { return Value; }
|
||||
|
||||
|
@ -579,7 +599,7 @@ public:
|
|||
std::string getAsString() const override;
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
return BitInit::get((Value & (1ULL << Bit)) != 0);
|
||||
return BitInit::get(getRecordKeeper(), (Value & (1ULL << Bit)) != 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -587,8 +607,8 @@ public:
|
|||
class AnonymousNameInit : public TypedInit {
|
||||
unsigned Value;
|
||||
|
||||
explicit AnonymousNameInit(unsigned V)
|
||||
: TypedInit(IK_AnonymousNameInit, StringRecTy::get()), Value(V) {}
|
||||
explicit AnonymousNameInit(RecordKeeper &RK, unsigned V)
|
||||
: TypedInit(IK_AnonymousNameInit, StringRecTy::get(RK)), Value(V) {}
|
||||
|
||||
public:
|
||||
AnonymousNameInit(const AnonymousNameInit &) = delete;
|
||||
|
@ -598,7 +618,7 @@ public:
|
|||
return I->getKind() == IK_AnonymousNameInit;
|
||||
}
|
||||
|
||||
static AnonymousNameInit *get(unsigned);
|
||||
static AnonymousNameInit *get(RecordKeeper &RK, unsigned);
|
||||
|
||||
unsigned getValue() const { return Value; }
|
||||
|
||||
|
@ -625,8 +645,8 @@ private:
|
|||
StringRef Value;
|
||||
StringFormat Format;
|
||||
|
||||
explicit StringInit(StringRef V, StringFormat Fmt)
|
||||
: TypedInit(IK_StringInit, StringRecTy::get()), Value(V), Format(Fmt) {}
|
||||
explicit StringInit(RecordKeeper &RK, StringRef V, StringFormat Fmt)
|
||||
: TypedInit(IK_StringInit, StringRecTy::get(RK)), Value(V), Format(Fmt) {}
|
||||
|
||||
public:
|
||||
StringInit(const StringInit &) = delete;
|
||||
|
@ -636,7 +656,8 @@ public:
|
|||
return I->getKind() == IK_StringInit;
|
||||
}
|
||||
|
||||
static StringInit *get(StringRef, StringFormat Fmt = SF_String);
|
||||
static StringInit *get(RecordKeeper &RK, StringRef,
|
||||
StringFormat Fmt = SF_String);
|
||||
|
||||
static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2) {
|
||||
return (Fmt1 == SF_Code || Fmt2 == SF_Code) ? SF_Code : SF_String;
|
||||
|
@ -677,7 +698,7 @@ public:
|
|||
|
||||
private:
|
||||
explicit ListInit(unsigned N, RecTy *EltTy)
|
||||
: TypedInit(IK_ListInit, ListRecTy::get(EltTy)), NumValues(N) {}
|
||||
: TypedInit(IK_ListInit, ListRecTy::get(EltTy)), NumValues(N) {}
|
||||
|
||||
public:
|
||||
ListInit(const ListInit &) = delete;
|
||||
|
@ -1048,8 +1069,8 @@ private:
|
|||
Init *Expr;
|
||||
|
||||
IsAOpInit(RecTy *CheckType, Init *Expr)
|
||||
: TypedInit(IK_IsAOpInit, IntRecTy::get()), CheckType(CheckType),
|
||||
Expr(Expr) {}
|
||||
: TypedInit(IK_IsAOpInit, IntRecTy::get(CheckType->getRecordKeeper())),
|
||||
CheckType(CheckType), Expr(Expr) {}
|
||||
|
||||
public:
|
||||
IsAOpInit(const IsAOpInit &) = delete;
|
||||
|
@ -1117,7 +1138,8 @@ class VarBitInit final : public TypedInit {
|
|||
unsigned Bit;
|
||||
|
||||
VarBitInit(TypedInit *T, unsigned B)
|
||||
: TypedInit(IK_VarBitInit, BitRecTy::get()), TI(T), Bit(B) {
|
||||
: TypedInit(IK_VarBitInit, BitRecTy::get(T->getRecordKeeper())), TI(T),
|
||||
Bit(B) {
|
||||
assert(T->getType() &&
|
||||
(isa<IntRecTy>(T->getType()) ||
|
||||
(isa<BitsRecTy>(T->getType()) &&
|
||||
|
@ -1222,8 +1244,7 @@ class VarDefInit final : public TypedInit, public FoldingSetNode,
|
|||
DefInit *Def = nullptr; // after instantiation
|
||||
unsigned NumArgs;
|
||||
|
||||
explicit VarDefInit(Record *Class, unsigned N)
|
||||
: TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Class(Class), NumArgs(N) {}
|
||||
explicit VarDefInit(Record *Class, unsigned N);
|
||||
|
||||
DefInit *instantiate();
|
||||
|
||||
|
@ -1320,8 +1341,8 @@ class DagInit final : public TypedInit, public FoldingSetNode,
|
|||
unsigned NumArgNames;
|
||||
|
||||
DagInit(Init *V, StringInit *VN, unsigned NumArgs, unsigned NumArgNames)
|
||||
: TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN),
|
||||
NumArgs(NumArgs), NumArgNames(NumArgNames) {}
|
||||
: TypedInit(IK_DagInit, DagRecTy::get(V->getRecordKeeper())), Val(V),
|
||||
ValName(VN), NumArgs(NumArgs), NumArgNames(NumArgNames) {}
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<Init *>) const { return NumArgs; }
|
||||
|
||||
|
@ -1426,6 +1447,9 @@ public:
|
|||
RecordVal(Init *N, RecTy *T, FieldKind K);
|
||||
RecordVal(Init *N, SMLoc Loc, RecTy *T, FieldKind K);
|
||||
|
||||
/// Get the record keeper used to unique this value.
|
||||
RecordKeeper &getRecordKeeper() const { return Name->getRecordKeeper(); }
|
||||
|
||||
/// Get the name of the field as a StringRef.
|
||||
StringRef getName() const;
|
||||
|
||||
|
@ -1526,13 +1550,14 @@ public:
|
|||
explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
|
||||
bool Anonymous = false, bool Class = false)
|
||||
: Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records),
|
||||
ID(getNewUID()), IsAnonymous(Anonymous), IsClass(Class) {
|
||||
ID(getNewUID(N->getRecordKeeper())), IsAnonymous(Anonymous),
|
||||
IsClass(Class) {
|
||||
checkName();
|
||||
}
|
||||
|
||||
explicit Record(StringRef N, ArrayRef<SMLoc> locs, RecordKeeper &records,
|
||||
bool Class = false)
|
||||
: Record(StringInit::get(N), locs, records, false, Class) {}
|
||||
: Record(StringInit::get(records, N), locs, records, false, Class) {}
|
||||
|
||||
// When copy-constructing a Record, we must still guarantee a globally unique
|
||||
// ID number. Don't copy CorrespondingDefInit either, since it's owned by the
|
||||
|
@ -1541,9 +1566,10 @@ public:
|
|||
: Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
|
||||
Values(O.Values), Assertions(O.Assertions),
|
||||
SuperClasses(O.SuperClasses), TrackedRecords(O.TrackedRecords),
|
||||
ID(getNewUID()), IsAnonymous(O.IsAnonymous), IsClass(O.IsClass) {}
|
||||
ID(getNewUID(O.getRecords())), IsAnonymous(O.IsAnonymous),
|
||||
IsClass(O.IsClass) {}
|
||||
|
||||
static unsigned getNewUID();
|
||||
static unsigned getNewUID(RecordKeeper &RK);
|
||||
|
||||
unsigned getID() const { return ID; }
|
||||
|
||||
|
@ -1599,7 +1625,7 @@ public:
|
|||
}
|
||||
|
||||
const RecordVal *getValue(StringRef Name) const {
|
||||
return getValue(StringInit::get(Name));
|
||||
return getValue(StringInit::get(getRecords(), Name));
|
||||
}
|
||||
|
||||
RecordVal *getValue(const Init *Name) {
|
||||
|
@ -1630,7 +1656,7 @@ public:
|
|||
}
|
||||
|
||||
void removeValue(StringRef Name) {
|
||||
removeValue(StringInit::get(Name));
|
||||
removeValue(StringInit::get(getRecords(), Name));
|
||||
}
|
||||
|
||||
void addAssertion(SMLoc Loc, Init *Condition, Init *Message) {
|
||||
|
@ -1779,26 +1805,16 @@ public:
|
|||
raw_ostream &operator<<(raw_ostream &OS, const Record &R);
|
||||
|
||||
class RecordKeeper {
|
||||
friend class RecordRecTy;
|
||||
|
||||
using RecordMap = std::map<std::string, std::unique_ptr<Record>, std::less<>>;
|
||||
using GlobalMap = std::map<std::string, Init *, std::less<>>;
|
||||
|
||||
std::string InputFilename;
|
||||
RecordMap Classes, Defs;
|
||||
mutable StringMap<std::vector<Record *>> ClassRecordsMap;
|
||||
FoldingSet<RecordRecTy> RecordTypePool;
|
||||
std::map<std::string, Init *, std::less<>> ExtraGlobals;
|
||||
unsigned AnonCounter = 0;
|
||||
|
||||
// These members are for the phase timing feature. We need a timer group,
|
||||
// the last timer started, and a flag to say whether the last timer
|
||||
// is the special "backend overall timer."
|
||||
TimerGroup *TimingGroup = nullptr;
|
||||
Timer *LastTimer = nullptr;
|
||||
bool BackendTimer = false;
|
||||
|
||||
public:
|
||||
RecordKeeper();
|
||||
~RecordKeeper();
|
||||
|
||||
/// Return the internal implementation of the RecordKeeper.
|
||||
detail::RecordKeeperImpl &getImpl() { return *Impl; }
|
||||
|
||||
/// Get the main TableGen input file's name.
|
||||
const std::string getInputFilename() const { return InputFilename; }
|
||||
|
||||
|
@ -1900,6 +1916,27 @@ public:
|
|||
getAllDerivedDefinitionsIfDefined(StringRef ClassName) const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
RecordKeeper(RecordKeeper &&) = delete;
|
||||
RecordKeeper(const RecordKeeper &) = delete;
|
||||
RecordKeeper &operator=(RecordKeeper &&) = delete;
|
||||
RecordKeeper &operator=(const RecordKeeper &) = delete;
|
||||
|
||||
std::string InputFilename;
|
||||
RecordMap Classes, Defs;
|
||||
mutable StringMap<std::vector<Record *>> ClassRecordsMap;
|
||||
GlobalMap ExtraGlobals;
|
||||
|
||||
// These members are for the phase timing feature. We need a timer group,
|
||||
// the last timer started, and a flag to say whether the last timer
|
||||
// is the special "backend overall timer."
|
||||
TimerGroup *TimingGroup = nullptr;
|
||||
Timer *LastTimer = nullptr;
|
||||
bool BackendTimer = false;
|
||||
|
||||
/// The internal uniquer implementation of the RecordKeeper.
|
||||
std::unique_ptr<detail::RecordKeeperImpl> Impl;
|
||||
};
|
||||
|
||||
/// Sorting predicate to sort record pointers by name.
|
||||
|
|
|
@ -157,8 +157,8 @@ void PrintFatalError(const RecordVal *RecVal, const Twine &Msg) {
|
|||
// Check an assertion: Obtain the condition value and be sure it is true.
|
||||
// If not, print a nonfatal error along with the message.
|
||||
void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
|
||||
auto *CondValue = dyn_cast_or_null<IntInit>(
|
||||
Condition->convertInitializerTo(IntRecTy::get()));
|
||||
auto *CondValue = dyn_cast_or_null<IntInit>(Condition->convertInitializerTo(
|
||||
IntRecTy::get(Condition->getRecordKeeper())));
|
||||
if (!CondValue)
|
||||
PrintError(Loc, "assert condition must of type bit, bits, or int.");
|
||||
else if (!CondValue->getValue()) {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/TableGen/Parser.h"
|
||||
#include "RecordContext.h"
|
||||
#include "TGParser.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
|
@ -33,7 +32,6 @@ bool llvm::TableGenParseFile(std::unique_ptr<MemoryBuffer> Buffer,
|
|||
return true;
|
||||
|
||||
// After parsing, reset the tablegen data.
|
||||
detail::resetTablegenRecordContext();
|
||||
SrcMgr = SourceMgr();
|
||||
return false;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,27 +0,0 @@
|
|||
//===- RecordContext.h - RecordContext implementation ---------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains functions for interacting with the tablegen record
|
||||
// context.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace llvm {
|
||||
namespace detail {
|
||||
|
||||
/// Resets the Tablegen record context and all currently parsed record data.
|
||||
/// Tablegen currently relies on a lot of static data to keep track of parsed
|
||||
/// records, which accumulates into static fields. This method resets all of
|
||||
/// that data to enable successive executions of the tablegen parser.
|
||||
/// FIXME: Ideally tablegen would use a properly scoped (non-static) context,
|
||||
/// which would remove any need for managing the context in this way. In that
|
||||
/// case, this method could be removed.
|
||||
void resetTablegenRecordContext();
|
||||
|
||||
} // end namespace detail
|
||||
} // end namespace llvm
|
|
@ -112,14 +112,15 @@ static void checkConcrete(Record &R) {
|
|||
|
||||
/// Return an Init with a qualifier prefix referring
|
||||
/// to CurRec's name.
|
||||
static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
|
||||
Init *Name, StringRef Scoper) {
|
||||
Init *NewName =
|
||||
BinOpInit::getStrConcat(CurRec.getNameInit(), StringInit::get(Scoper));
|
||||
static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass, Init *Name,
|
||||
StringRef Scoper) {
|
||||
RecordKeeper &RK = CurRec.getRecords();
|
||||
Init *NewName = BinOpInit::getStrConcat(CurRec.getNameInit(),
|
||||
StringInit::get(RK, Scoper));
|
||||
NewName = BinOpInit::getStrConcat(NewName, Name);
|
||||
if (CurMultiClass && Scoper != "::") {
|
||||
Init *Prefix = BinOpInit::getStrConcat(CurMultiClass->Rec.getNameInit(),
|
||||
StringInit::get("::"));
|
||||
StringInit::get(RK, "::"));
|
||||
NewName = BinOpInit::getStrConcat(Prefix, NewName);
|
||||
}
|
||||
|
||||
|
@ -131,7 +132,8 @@ static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
|
|||
/// Return the qualified version of the implicit 'NAME' template argument.
|
||||
static Init *QualifiedNameOfImplicitName(Record &Rec,
|
||||
MultiClass *MC = nullptr) {
|
||||
return QualifyName(Rec, MC, StringInit::get("NAME"), MC ? "::" : ":");
|
||||
return QualifyName(Rec, MC, StringInit::get(Rec.getRecords(), "NAME"),
|
||||
MC ? "::" : ":");
|
||||
}
|
||||
|
||||
static Init *QualifiedNameOfImplicitName(MultiClass *MC) {
|
||||
|
@ -187,7 +189,7 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
|
|||
"' is not a bits type");
|
||||
|
||||
// Convert the incoming value to a bits type of the appropriate size...
|
||||
Init *BI = V->getCastTo(BitsRecTy::get(BitList.size()));
|
||||
Init *BI = V->getCastTo(BitsRecTy::get(Records, BitList.size()));
|
||||
if (!BI)
|
||||
return Error(Loc, "Initializer is not compatible with bit range");
|
||||
|
||||
|
@ -206,7 +208,7 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
|
|||
if (!NewBits[i])
|
||||
NewBits[i] = CurVal->getBit(i);
|
||||
|
||||
V = BitsInit::get(NewBits);
|
||||
V = BitsInit::get(Records, NewBits);
|
||||
}
|
||||
|
||||
if (RV->setValue(V, Loc)) {
|
||||
|
@ -262,8 +264,8 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
|
|||
|
||||
Init *Name;
|
||||
if (CurRec->isClass())
|
||||
Name =
|
||||
VarInit::get(QualifiedNameOfImplicitName(*CurRec), StringRecTy::get());
|
||||
Name = VarInit::get(QualifiedNameOfImplicitName(*CurRec),
|
||||
StringRecTy::get(Records));
|
||||
else
|
||||
Name = CurRec->getNameInit();
|
||||
R.set(QualifiedNameOfImplicitName(*SC), Name);
|
||||
|
@ -333,9 +335,9 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC,
|
|||
}
|
||||
}
|
||||
|
||||
TemplateArgs.emplace_back(
|
||||
QualifiedNameOfImplicitName(SMC),
|
||||
VarInit::get(QualifiedNameOfImplicitName(CurMC), StringRecTy::get()));
|
||||
TemplateArgs.emplace_back(QualifiedNameOfImplicitName(SMC),
|
||||
VarInit::get(QualifiedNameOfImplicitName(CurMC),
|
||||
StringRecTy::get(Records)));
|
||||
|
||||
// Add all of the defs in the subclass into the current multiclass.
|
||||
return resolve(SMC->Entries, TemplateArgs, false, &CurMC->Entries);
|
||||
|
@ -540,7 +542,7 @@ Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) {
|
|||
// These are all of the tokens that can begin an object body.
|
||||
// Some of these can also begin values but we disallow those cases
|
||||
// because they are unlikely to be useful.
|
||||
return UnsetInit::get();
|
||||
return UnsetInit::get(Records);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -549,7 +551,7 @@ Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) {
|
|||
if (CurMultiClass)
|
||||
CurRec = &CurMultiClass->Rec;
|
||||
|
||||
Init *Name = ParseValue(CurRec, StringRecTy::get(), ParseNameMode);
|
||||
Init *Name = ParseValue(CurRec, StringRecTy::get(Records), ParseNameMode);
|
||||
if (!Name)
|
||||
return nullptr;
|
||||
|
||||
|
@ -558,8 +560,8 @@ Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) {
|
|||
HasReferenceResolver R(NameStr);
|
||||
Name->resolveReferences(R);
|
||||
if (!R.found())
|
||||
Name = BinOpInit::getStrConcat(VarInit::get(NameStr, StringRecTy::get()),
|
||||
Name);
|
||||
Name = BinOpInit::getStrConcat(
|
||||
VarInit::get(NameStr, StringRecTy::get(Records)), Name);
|
||||
}
|
||||
|
||||
return Name;
|
||||
|
@ -812,12 +814,21 @@ RecTy *TGParser::ParseType() {
|
|||
switch (Lex.getCode()) {
|
||||
default: TokError("Unknown token when expecting a type"); return nullptr;
|
||||
case tgtok::String:
|
||||
case tgtok::Code: Lex.Lex(); return StringRecTy::get();
|
||||
case tgtok::Bit: Lex.Lex(); return BitRecTy::get();
|
||||
case tgtok::Int: Lex.Lex(); return IntRecTy::get();
|
||||
case tgtok::Dag: Lex.Lex(); return DagRecTy::get();
|
||||
case tgtok::Code:
|
||||
Lex.Lex();
|
||||
return StringRecTy::get(Records);
|
||||
case tgtok::Bit:
|
||||
Lex.Lex();
|
||||
return BitRecTy::get(Records);
|
||||
case tgtok::Int:
|
||||
Lex.Lex();
|
||||
return IntRecTy::get(Records);
|
||||
case tgtok::Dag:
|
||||
Lex.Lex();
|
||||
return DagRecTy::get(Records);
|
||||
case tgtok::Id:
|
||||
if (Record *R = ParseClassID()) return RecordRecTy::get(R);
|
||||
if (Record *R = ParseClassID())
|
||||
return RecordRecTy::get(R);
|
||||
TokError("unknown class name");
|
||||
return nullptr;
|
||||
case tgtok::Bits: {
|
||||
|
@ -835,7 +846,7 @@ RecTy *TGParser::ParseType() {
|
|||
return nullptr;
|
||||
}
|
||||
Lex.Lex(); // Eat '>'
|
||||
return BitsRecTy::get(Val);
|
||||
return BitsRecTy::get(Records, Val);
|
||||
}
|
||||
case tgtok::List: {
|
||||
if (Lex.Lex() != tgtok::less) { // Eat 'bits'
|
||||
|
@ -878,7 +889,7 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
|
|||
RV->setUsed(true);
|
||||
return VarInit::get(TemplateArgName, RV->getType());
|
||||
} else if (Name->getValue() == "NAME") {
|
||||
return VarInit::get(TemplateArgName, StringRecTy::get());
|
||||
return VarInit::get(TemplateArgName, StringRecTy::get(Records));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -947,7 +958,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
case tgtok::XNOT:
|
||||
Lex.Lex(); // eat the operation
|
||||
Code = UnOpInit::NOT;
|
||||
Type = IntRecTy::get();
|
||||
Type = IntRecTy::get(Records);
|
||||
break;
|
||||
case tgtok::XHead:
|
||||
Lex.Lex(); // eat the operation
|
||||
|
@ -960,12 +971,12 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
case tgtok::XSize:
|
||||
Lex.Lex();
|
||||
Code = UnOpInit::SIZE;
|
||||
Type = IntRecTy::get();
|
||||
Type = IntRecTy::get(Records);
|
||||
break;
|
||||
case tgtok::XEmpty:
|
||||
Lex.Lex(); // eat the operation
|
||||
Code = UnOpInit::EMPTY;
|
||||
Type = IntRecTy::get();
|
||||
Type = IntRecTy::get(Records);
|
||||
break;
|
||||
case tgtok::XGetDagOp:
|
||||
Lex.Lex(); // eat the operation
|
||||
|
@ -985,7 +996,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
// but keep parsing, to consume the operand
|
||||
}
|
||||
} else {
|
||||
Type = RecordRecTy::get({});
|
||||
Type = RecordRecTy::get(Records, {});
|
||||
}
|
||||
Code = UnOpInit::GETDAGOP;
|
||||
break;
|
||||
|
@ -1143,8 +1154,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
llvm_unreachable("Unhandled code!");
|
||||
case tgtok::XConcat:
|
||||
case tgtok::XSetDagOp:
|
||||
Type = DagRecTy::get();
|
||||
ArgType = DagRecTy::get();
|
||||
Type = DagRecTy::get(Records);
|
||||
ArgType = DagRecTy::get(Records);
|
||||
break;
|
||||
case tgtok::XAND:
|
||||
case tgtok::XOR:
|
||||
|
@ -1155,8 +1166,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
case tgtok::XADD:
|
||||
case tgtok::XSUB:
|
||||
case tgtok::XMUL:
|
||||
Type = IntRecTy::get();
|
||||
ArgType = IntRecTy::get();
|
||||
Type = IntRecTy::get(Records);
|
||||
ArgType = IntRecTy::get(Records);
|
||||
break;
|
||||
case tgtok::XEq:
|
||||
case tgtok::XNe:
|
||||
|
@ -1164,7 +1175,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
case tgtok::XLt:
|
||||
case tgtok::XGe:
|
||||
case tgtok::XGt:
|
||||
Type = BitRecTy::get();
|
||||
Type = BitRecTy::get(Records);
|
||||
// ArgType for the comparison operators is not yet known.
|
||||
break;
|
||||
case tgtok::XListConcat:
|
||||
|
@ -1175,11 +1186,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
// Can't do any typechecking until we parse the first argument.
|
||||
break;
|
||||
case tgtok::XStrConcat:
|
||||
Type = StringRecTy::get();
|
||||
ArgType = StringRecTy::get();
|
||||
Type = StringRecTy::get(Records);
|
||||
ArgType = StringRecTy::get(Records);
|
||||
break;
|
||||
case tgtok::XInterleave:
|
||||
Type = StringRecTy::get();
|
||||
Type = StringRecTy::get(Records);
|
||||
// The first argument type is not yet known.
|
||||
}
|
||||
|
||||
|
@ -1253,9 +1264,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
break;
|
||||
case BinOpInit::EQ:
|
||||
case BinOpInit::NE:
|
||||
if (!ArgType->typeIsConvertibleTo(IntRecTy::get()) &&
|
||||
!ArgType->typeIsConvertibleTo(StringRecTy::get()) &&
|
||||
!ArgType->typeIsConvertibleTo(RecordRecTy::get({}))) {
|
||||
if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&
|
||||
!ArgType->typeIsConvertibleTo(StringRecTy::get(Records)) &&
|
||||
!ArgType->typeIsConvertibleTo(RecordRecTy::get(Records, {}))) {
|
||||
Error(InitLoc, Twine("expected bit, bits, int, string, or record; "
|
||||
"got value of type '") + ArgType->getAsString() +
|
||||
"'");
|
||||
|
@ -1266,8 +1277,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
case BinOpInit::LT:
|
||||
case BinOpInit::GE:
|
||||
case BinOpInit::GT:
|
||||
if (!ArgType->typeIsConvertibleTo(IntRecTy::get()) &&
|
||||
!ArgType->typeIsConvertibleTo(StringRecTy::get())) {
|
||||
if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&
|
||||
!ArgType->typeIsConvertibleTo(StringRecTy::get(Records))) {
|
||||
Error(InitLoc, Twine("expected bit, bits, int, or string; "
|
||||
"got value of type '") + ArgType->getAsString() +
|
||||
"'");
|
||||
|
@ -1277,8 +1288,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
case BinOpInit::INTERLEAVE:
|
||||
switch (InitList.size()) {
|
||||
case 1: // First argument must be a list of strings or integers.
|
||||
if (ArgType != StringRecTy::get()->getListTy() &&
|
||||
!ArgType->typeIsConvertibleTo(IntRecTy::get()->getListTy())) {
|
||||
if (ArgType != StringRecTy::get(Records)->getListTy() &&
|
||||
!ArgType->typeIsConvertibleTo(
|
||||
IntRecTy::get(Records)->getListTy())) {
|
||||
Error(InitLoc, Twine("expected list of string, int, bits, or bit; "
|
||||
"got value of type '") +
|
||||
ArgType->getAsString() + "'");
|
||||
|
@ -1323,7 +1335,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
case BinOpInit::SETDAGOP:
|
||||
// After parsing the first dag argument, switch to expecting
|
||||
// a record, with no restriction on its superclasses.
|
||||
ArgType = RecordRecTy::get({});
|
||||
ArgType = RecordRecTy::get(Records, {});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1383,7 +1395,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
default: llvm_unreachable("Unhandled code!");
|
||||
case tgtok::XDag:
|
||||
Code = TernOpInit::DAG;
|
||||
Type = DagRecTy::get();
|
||||
Type = DagRecTy::get(Records);
|
||||
ItemType = nullptr;
|
||||
break;
|
||||
case tgtok::XIf:
|
||||
|
@ -1445,7 +1457,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
Error(RHSLoc, "could not determine type of the name list in !dag");
|
||||
return nullptr;
|
||||
}
|
||||
if (RHSt && StringRecTy::get()->getListTy() != RHSt->getType()) {
|
||||
if (RHSt && StringRecTy::get(Records)->getListTy() != RHSt->getType()) {
|
||||
Error(RHSLoc, Twine("expected list<string>, got type '") +
|
||||
RHSt->getType()->getAsString() + "'");
|
||||
return nullptr;
|
||||
|
@ -1465,16 +1477,16 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
if (TypedInit *MHSt = dyn_cast<TypedInit>(MHS))
|
||||
MHSTy = MHSt->getType();
|
||||
if (BitsInit *MHSbits = dyn_cast<BitsInit>(MHS))
|
||||
MHSTy = BitsRecTy::get(MHSbits->getNumBits());
|
||||
MHSTy = BitsRecTy::get(Records, MHSbits->getNumBits());
|
||||
if (isa<BitInit>(MHS))
|
||||
MHSTy = BitRecTy::get();
|
||||
MHSTy = BitRecTy::get(Records);
|
||||
|
||||
if (TypedInit *RHSt = dyn_cast<TypedInit>(RHS))
|
||||
RHSTy = RHSt->getType();
|
||||
if (BitsInit *RHSbits = dyn_cast<BitsInit>(RHS))
|
||||
RHSTy = BitsRecTy::get(RHSbits->getNumBits());
|
||||
RHSTy = BitsRecTy::get(Records, RHSbits->getNumBits());
|
||||
if (isa<BitInit>(RHS))
|
||||
RHSTy = BitRecTy::get();
|
||||
RHSTy = BitRecTy::get(Records);
|
||||
|
||||
// For UnsetInit, it's typed from the other hand.
|
||||
if (isa<UnsetInit>(MHS))
|
||||
|
@ -1569,7 +1581,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Init *A = StringInit::get(Lex.getCurStrVal());
|
||||
Init *A = StringInit::get(Records, Lex.getCurStrVal());
|
||||
if (CurRec && CurRec->getValue(A)) {
|
||||
TokError((Twine("left !foldl variable '") + A->getAsString() +
|
||||
"' already defined")
|
||||
|
@ -1587,7 +1599,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Init *B = StringInit::get(Lex.getCurStrVal());
|
||||
Init *B = StringInit::get(Records, Lex.getCurStrVal());
|
||||
if (CurRec && CurRec->getValue(B)) {
|
||||
TokError((Twine("right !foldl variable '") + B->getAsString() +
|
||||
"' already defined")
|
||||
|
@ -1679,7 +1691,7 @@ RecTy *TGParser::ParseOperatorType() {
|
|||
/// Substr ::= !substr(string, start-int [, length-int]) => string
|
||||
Init *TGParser::ParseOperationSubstr(Record *CurRec, RecTy *ItemType) {
|
||||
TernOpInit::TernaryOp Code = TernOpInit::SUBSTR;
|
||||
RecTy *Type = StringRecTy::get();
|
||||
RecTy *Type = StringRecTy::get(Records);
|
||||
|
||||
Lex.Lex(); // eat the operation
|
||||
|
||||
|
@ -1710,7 +1722,7 @@ Init *TGParser::ParseOperationSubstr(Record *CurRec, RecTy *ItemType) {
|
|||
if (!RHS)
|
||||
return nullptr;
|
||||
} else {
|
||||
RHS = IntInit::get(std::numeric_limits<int64_t>::max());
|
||||
RHS = IntInit::get(Records, std::numeric_limits<int64_t>::max());
|
||||
}
|
||||
|
||||
if (!consume(tgtok::r_paren)) {
|
||||
|
@ -1767,7 +1779,7 @@ Init *TGParser::ParseOperationSubstr(Record *CurRec, RecTy *ItemType) {
|
|||
/// Substr ::= !find(string, string [, start-int]) => int
|
||||
Init *TGParser::ParseOperationFind(Record *CurRec, RecTy *ItemType) {
|
||||
TernOpInit::TernaryOp Code = TernOpInit::FIND;
|
||||
RecTy *Type = IntRecTy::get();
|
||||
RecTy *Type = IntRecTy::get(Records);
|
||||
|
||||
Lex.Lex(); // eat the operation
|
||||
|
||||
|
@ -1798,7 +1810,7 @@ Init *TGParser::ParseOperationFind(Record *CurRec, RecTy *ItemType) {
|
|||
if (!RHS)
|
||||
return nullptr;
|
||||
} else {
|
||||
RHS = IntInit::get(0);
|
||||
RHS = IntInit::get(Records, 0);
|
||||
}
|
||||
|
||||
if (!consume(tgtok::r_paren)) {
|
||||
|
@ -1868,7 +1880,7 @@ Init *TGParser::ParseOperationForEachFilter(Record *CurRec, RecTy *ItemType) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Init *LHS = StringInit::get(Lex.getCurStrVal());
|
||||
Init *LHS = StringInit::get(Records, Lex.getCurStrVal());
|
||||
Lex.Lex(); // eat the ID.
|
||||
|
||||
if (CurRec && CurRec->getValue(LHS)) {
|
||||
|
@ -1908,7 +1920,7 @@ Init *TGParser::ParseOperationForEachFilter(Record *CurRec, RecTy *ItemType) {
|
|||
if (ListRecTy *OutListTy = dyn_cast<ListRecTy>(ItemType)) {
|
||||
ExprEltType = (Operation == tgtok::XForEach)
|
||||
? OutListTy->getElementType()
|
||||
: IntRecTy::get();
|
||||
: IntRecTy::get(Records);
|
||||
} else {
|
||||
Error(OpLoc,
|
||||
"expected value of type '" +
|
||||
|
@ -2028,9 +2040,9 @@ Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) {
|
|||
if (TypedInit *Vt = dyn_cast<TypedInit>(V))
|
||||
VTy = Vt->getType();
|
||||
if (BitsInit *Vbits = dyn_cast<BitsInit>(V))
|
||||
VTy = BitsRecTy::get(Vbits->getNumBits());
|
||||
VTy = BitsRecTy::get(Records, Vbits->getNumBits());
|
||||
if (isa<BitInit>(V))
|
||||
VTy = BitRecTy::get();
|
||||
VTy = BitRecTy::get(Records);
|
||||
|
||||
if (Type == nullptr) {
|
||||
if (!isa<UnsetInit>(V))
|
||||
|
@ -2084,23 +2096,23 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
|
|||
default: TokError("Unknown or reserved token when parsing a value"); break;
|
||||
|
||||
case tgtok::TrueVal:
|
||||
R = IntInit::get(1);
|
||||
R = IntInit::get(Records, 1);
|
||||
Lex.Lex();
|
||||
break;
|
||||
case tgtok::FalseVal:
|
||||
R = IntInit::get(0);
|
||||
R = IntInit::get(Records, 0);
|
||||
Lex.Lex();
|
||||
break;
|
||||
case tgtok::IntVal:
|
||||
R = IntInit::get(Lex.getCurIntVal());
|
||||
R = IntInit::get(Records, Lex.getCurIntVal());
|
||||
Lex.Lex();
|
||||
break;
|
||||
case tgtok::BinaryIntVal: {
|
||||
auto BinaryVal = Lex.getCurBinaryIntVal();
|
||||
SmallVector<Init*, 16> Bits(BinaryVal.second);
|
||||
for (unsigned i = 0, e = BinaryVal.second; i != e; ++i)
|
||||
Bits[i] = BitInit::get(BinaryVal.first & (1LL << i));
|
||||
R = BitsInit::get(Bits);
|
||||
Bits[i] = BitInit::get(Records, BinaryVal.first & (1LL << i));
|
||||
R = BitsInit::get(Records, Bits);
|
||||
Lex.Lex();
|
||||
break;
|
||||
}
|
||||
|
@ -2114,20 +2126,20 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
|
|||
Lex.Lex();
|
||||
}
|
||||
|
||||
R = StringInit::get(Val);
|
||||
R = StringInit::get(Records, Val);
|
||||
break;
|
||||
}
|
||||
case tgtok::CodeFragment:
|
||||
R = StringInit::get(Lex.getCurStrVal(), StringInit::SF_Code);
|
||||
R = StringInit::get(Records, Lex.getCurStrVal(), StringInit::SF_Code);
|
||||
Lex.Lex();
|
||||
break;
|
||||
case tgtok::question:
|
||||
R = UnsetInit::get();
|
||||
R = UnsetInit::get(Records);
|
||||
Lex.Lex();
|
||||
break;
|
||||
case tgtok::Id: {
|
||||
SMLoc NameLoc = Lex.getLoc();
|
||||
StringInit *Name = StringInit::get(Lex.getCurStrVal());
|
||||
StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());
|
||||
if (Lex.Lex() != tgtok::less) // consume the Id.
|
||||
return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue
|
||||
|
||||
|
@ -2202,7 +2214,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
|
|||
// Fallthrough to try convert this to a bit.
|
||||
}
|
||||
// All other values must be convertible to just a single bit.
|
||||
Init *Bit = Vals[i]->getCastTo(BitRecTy::get());
|
||||
Init *Bit = Vals[i]->getCastTo(BitRecTy::get(Records));
|
||||
if (!Bit) {
|
||||
Error(BraceLoc, "Element #" + Twine(i) + " (" + Vals[i]->getAsString() +
|
||||
") is not convertable to a bit");
|
||||
|
@ -2211,7 +2223,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
|
|||
NewBits.push_back(Bit);
|
||||
}
|
||||
std::reverse(NewBits.begin(), NewBits.end());
|
||||
return BitsInit::get(NewBits);
|
||||
return BitsInit::get(Records, NewBits);
|
||||
}
|
||||
case tgtok::l_square: { // Value ::= '[' ValueList ']'
|
||||
Lex.Lex(); // eat the '['
|
||||
|
@ -2322,7 +2334,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
|
|||
TokError("expected variable name in dag operator");
|
||||
return nullptr;
|
||||
}
|
||||
OperatorName = StringInit::get(Lex.getCurStrVal());
|
||||
OperatorName = StringInit::get(Records, Lex.getCurStrVal());
|
||||
Lex.Lex(); // eat the VarName.
|
||||
}
|
||||
|
||||
|
@ -2451,7 +2463,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
|
|||
TokError("expected field identifier after '.'");
|
||||
return nullptr;
|
||||
}
|
||||
StringInit *FieldName = StringInit::get(Lex.getCurStrVal());
|
||||
StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());
|
||||
if (!Result->getFieldType(FieldName)) {
|
||||
TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
|
||||
Result->getAsString() + "'");
|
||||
|
@ -2494,9 +2506,9 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
|
|||
|
||||
// Create a !strconcat() operation, first casting each operand to
|
||||
// a string if necessary.
|
||||
if (LHS->getType() != StringRecTy::get()) {
|
||||
if (LHS->getType() != StringRecTy::get(Records)) {
|
||||
auto CastLHS = dyn_cast<TypedInit>(
|
||||
UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get())
|
||||
UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get(Records))
|
||||
->Fold(CurRec));
|
||||
if (!CastLHS) {
|
||||
Error(PasteLoc,
|
||||
|
@ -2518,7 +2530,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
|
|||
// because they are unlikely to be useful.
|
||||
|
||||
// Trailing paste, concat with an empty string.
|
||||
RHS = StringInit::get("");
|
||||
RHS = StringInit::get(Records, "");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2531,9 +2543,9 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (RHS->getType() != StringRecTy::get()) {
|
||||
if (RHS->getType() != StringRecTy::get(Records)) {
|
||||
auto CastRHS = dyn_cast<TypedInit>(
|
||||
UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get())
|
||||
UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get(Records))
|
||||
->Fold(CurRec));
|
||||
if (!CastRHS) {
|
||||
Error(PasteLoc,
|
||||
|
@ -2566,8 +2578,8 @@ void TGParser::ParseDagArgList(
|
|||
// DagArg ::= VARNAME
|
||||
if (Lex.getCode() == tgtok::VarName) {
|
||||
// A missing value is treated like '?'.
|
||||
StringInit *VarName = StringInit::get(Lex.getCurStrVal());
|
||||
Result.emplace_back(UnsetInit::get(), VarName);
|
||||
StringInit *VarName = StringInit::get(Records, Lex.getCurStrVal());
|
||||
Result.emplace_back(UnsetInit::get(Records), VarName);
|
||||
Lex.Lex();
|
||||
} else {
|
||||
// DagArg ::= Value (':' VARNAME)?
|
||||
|
@ -2585,7 +2597,7 @@ void TGParser::ParseDagArgList(
|
|||
Result.clear();
|
||||
return;
|
||||
}
|
||||
VarName = StringInit::get(Lex.getCurStrVal());
|
||||
VarName = StringInit::get(Records, Lex.getCurStrVal());
|
||||
Lex.Lex(); // eat the VarName.
|
||||
}
|
||||
|
||||
|
@ -2692,7 +2704,7 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
|
|||
}
|
||||
|
||||
SMLoc IdLoc = Lex.getLoc();
|
||||
Init *DeclName = StringInit::get(Str);
|
||||
Init *DeclName = StringInit::get(Records, Str);
|
||||
Lex.Lex();
|
||||
|
||||
bool BadField;
|
||||
|
@ -2745,7 +2757,7 @@ VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Init *DeclName = StringInit::get(Lex.getCurStrVal());
|
||||
Init *DeclName = StringInit::get(Records, Lex.getCurStrVal());
|
||||
Lex.Lex();
|
||||
|
||||
// If a value is present, parse it.
|
||||
|
@ -2799,10 +2811,10 @@ VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {
|
|||
|
||||
if (!Ranges.empty()) {
|
||||
assert(!IterType && "Type already initialized?");
|
||||
IterType = IntRecTy::get();
|
||||
IterType = IntRecTy::get(Records);
|
||||
std::vector<Init *> Values;
|
||||
for (unsigned R : Ranges)
|
||||
Values.push_back(IntInit::get(R));
|
||||
Values.push_back(IntInit::get(Records, R));
|
||||
ForeachListValue = ListInit::get(Values, IterType);
|
||||
}
|
||||
|
||||
|
@ -2879,7 +2891,7 @@ bool TGParser::ParseBodyItem(Record *CurRec) {
|
|||
return TokError("expected field identifier after let");
|
||||
|
||||
SMLoc IdLoc = Lex.getLoc();
|
||||
StringInit *FieldName = StringInit::get(Lex.getCurStrVal());
|
||||
StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());
|
||||
Lex.Lex(); // eat the field name.
|
||||
|
||||
SmallVector<unsigned, 16> BitList;
|
||||
|
@ -2898,7 +2910,7 @@ bool TGParser::ParseBodyItem(Record *CurRec) {
|
|||
if (!BitList.empty() && isa<BitsRecTy>(Type)) {
|
||||
// When assigning to a subset of a 'bits' object, expect the RHS to have
|
||||
// the type of that subset instead of the type of the whole object.
|
||||
Type = BitsRecTy::get(BitList.size());
|
||||
Type = BitsRecTy::get(Records, BitList.size());
|
||||
}
|
||||
|
||||
Init *Val = ParseValue(CurRec, Type);
|
||||
|
@ -3056,7 +3068,7 @@ bool TGParser::ParseDefset() {
|
|||
|
||||
if (Lex.getCode() != tgtok::Id)
|
||||
return TokError("expected identifier");
|
||||
StringInit *DeclName = StringInit::get(Lex.getCurStrVal());
|
||||
StringInit *DeclName = StringInit::get(Records, Lex.getCurStrVal());
|
||||
if (Records.getGlobal(DeclName->getValue()))
|
||||
return TokError("def or global variable of this name already exists");
|
||||
|
||||
|
@ -3093,7 +3105,7 @@ bool TGParser::ParseDefvar() {
|
|||
|
||||
if (Lex.getCode() != tgtok::Id)
|
||||
return TokError("expected identifier");
|
||||
StringInit *DeclName = StringInit::get(Lex.getCurStrVal());
|
||||
StringInit *DeclName = StringInit::get(Records, Lex.getCurStrVal());
|
||||
if (CurLocalScope) {
|
||||
if (CurLocalScope->varAlreadyDefined(DeclName->getValue()))
|
||||
return TokError("local variable of this name already exists");
|
||||
|
@ -3201,10 +3213,10 @@ bool TGParser::ParseIf(MultiClass *CurMultiClass) {
|
|||
// loop, over a list of length 0 or 1 depending on the condition, and with no
|
||||
// iteration variable being assigned.
|
||||
|
||||
ListInit *EmptyList = ListInit::get({}, BitRecTy::get());
|
||||
ListInit *EmptyList = ListInit::get({}, BitRecTy::get(Records));
|
||||
ListInit *SingletonList =
|
||||
ListInit::get({BitInit::get(true)}, BitRecTy::get());
|
||||
RecTy *BitListTy = ListRecTy::get(BitRecTy::get());
|
||||
ListInit::get({BitInit::get(Records, true)}, BitRecTy::get(Records));
|
||||
RecTy *BitListTy = ListRecTy::get(BitRecTy::get(Records));
|
||||
|
||||
// The foreach containing the then-clause selects SingletonList if
|
||||
// the condition is true.
|
||||
|
@ -3369,7 +3381,7 @@ void TGParser::ParseLetList(SmallVectorImpl<LetRecord> &Result) {
|
|||
return;
|
||||
}
|
||||
|
||||
StringInit *Name = StringInit::get(Lex.getCurStrVal());
|
||||
StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());
|
||||
SMLoc NameLoc = Lex.getLoc();
|
||||
Lex.Lex(); // Eat the identifier.
|
||||
|
||||
|
@ -3570,7 +3582,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
|
|||
if (CurMultiClass)
|
||||
DefmName = BinOpInit::getStrConcat(
|
||||
VarInit::get(QualifiedNameOfImplicitName(CurMultiClass),
|
||||
StringRecTy::get()),
|
||||
StringRecTy::get(Records)),
|
||||
DefmName);
|
||||
}
|
||||
|
||||
|
|
|
@ -2816,6 +2816,7 @@ void TreePattern::ComputeNamedNodes(TreePatternNode *N) {
|
|||
|
||||
TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
|
||||
StringRef OpName) {
|
||||
RecordKeeper &RK = TheInit->getRecordKeeper();
|
||||
if (DefInit *DI = dyn_cast<DefInit>(TheInit)) {
|
||||
Record *R = DI->getDef();
|
||||
|
||||
|
@ -2854,13 +2855,13 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
|
|||
if (!OpName.empty())
|
||||
error("Constant int or bit argument should not have a name!");
|
||||
if (isa<BitInit>(TheInit))
|
||||
TheInit = TheInit->convertInitializerTo(IntRecTy::get());
|
||||
TheInit = TheInit->convertInitializerTo(IntRecTy::get(RK));
|
||||
return std::make_shared<TreePatternNode>(TheInit, 1);
|
||||
}
|
||||
|
||||
if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) {
|
||||
// Turn this into an IntInit.
|
||||
Init *II = BI->convertInitializerTo(IntRecTy::get());
|
||||
Init *II = BI->convertInitializerTo(IntRecTy::get(RK));
|
||||
if (!II || !isa<IntInit>(II))
|
||||
error("Bits value must be constants!");
|
||||
return ParseTreePattern(II, OpName);
|
||||
|
@ -2959,8 +2960,8 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
|
|||
else // Otherwise, no chain.
|
||||
Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();
|
||||
|
||||
Children.insert(Children.begin(),
|
||||
std::make_shared<TreePatternNode>(IntInit::get(IID), 1));
|
||||
Children.insert(Children.begin(), std::make_shared<TreePatternNode>(
|
||||
IntInit::get(RK, IID), 1));
|
||||
}
|
||||
|
||||
if (Operator->isSubClassOf("ComplexPattern")) {
|
||||
|
@ -4367,7 +4368,7 @@ void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
|
|||
PatternsToMatch.emplace_back(P.getSrcRecord(), P.getPredicates(),
|
||||
std::move(NewSrc), std::move(NewDst),
|
||||
P.getDstRegs(), P.getAddedComplexity(),
|
||||
Record::getNewUID(), Mode, Check);
|
||||
Record::getNewUID(Records), Mode, Check);
|
||||
};
|
||||
|
||||
for (PatternToMatch &P : Copy) {
|
||||
|
@ -4743,7 +4744,7 @@ void CodeGenDAGPatterns::GenerateVariants() {
|
|||
PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(),
|
||||
Variant, PatternsToMatch[i].getDstPatternShared(),
|
||||
PatternsToMatch[i].getDstRegs(),
|
||||
PatternsToMatch[i].getAddedComplexity(), Record::getNewUID(),
|
||||
PatternsToMatch[i].getAddedComplexity(), Record::getNewUID(Records),
|
||||
PatternsToMatch[i].getForceMode(),
|
||||
PatternsToMatch[i].getHwModeFeatures());
|
||||
}
|
||||
|
|
|
@ -632,8 +632,8 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
|
|||
if (!BI->isComplete())
|
||||
return false;
|
||||
// Convert the bits init to an integer and use that for the result.
|
||||
IntInit *II =
|
||||
dyn_cast_or_null<IntInit>(BI->convertInitializerTo(IntRecTy::get()));
|
||||
IntInit *II = dyn_cast_or_null<IntInit>(
|
||||
BI->convertInitializerTo(IntRecTy::get(BI->getRecordKeeper())));
|
||||
if (!II)
|
||||
return false;
|
||||
ResOp = ResultOperand(II->getValue());
|
||||
|
|
|
@ -638,6 +638,7 @@ struct TupleExpander : SetTheory::Expander {
|
|||
Def->getValueAsListOfStrings("RegAsmNames");
|
||||
|
||||
// Zip them up.
|
||||
RecordKeeper &RK = Def->getRecords();
|
||||
for (unsigned n = 0; n != Length; ++n) {
|
||||
std::string Name;
|
||||
Record *Proto = Lists[0][n];
|
||||
|
@ -654,13 +655,13 @@ struct TupleExpander : SetTheory::Expander {
|
|||
SmallVector<Init *, 2> CostPerUse;
|
||||
CostPerUse.insert(CostPerUse.end(), CostList->begin(), CostList->end());
|
||||
|
||||
StringInit *AsmName = StringInit::get("");
|
||||
StringInit *AsmName = StringInit::get(RK, "");
|
||||
if (!RegNames.empty()) {
|
||||
if (RegNames.size() <= n)
|
||||
PrintFatalError(Def->getLoc(),
|
||||
"Register tuple definition missing name for '" +
|
||||
Name + "'.");
|
||||
AsmName = StringInit::get(RegNames[n]);
|
||||
AsmName = StringInit::get(RK, RegNames[n]);
|
||||
}
|
||||
|
||||
// Create a new Record representing the synthesized register. This record
|
||||
|
@ -699,7 +700,7 @@ struct TupleExpander : SetTheory::Expander {
|
|||
|
||||
// Composite registers are always covered by sub-registers.
|
||||
if (Field == "CoveredBySubRegs")
|
||||
RV.setValue(BitInit::get(true));
|
||||
RV.setValue(BitInit::get(RK, true));
|
||||
|
||||
// Copy fields from the RegisterTuples def.
|
||||
if (Field == "SubRegIndices" ||
|
||||
|
|
|
@ -552,7 +552,7 @@ void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
|
|||
NewBits[middle] = BI->getBit(middle);
|
||||
}
|
||||
|
||||
BitsInit *NewBI = BitsInit::get(NewBits);
|
||||
BitsInit *NewBI = BitsInit::get(Records, NewBits);
|
||||
|
||||
// Update the bits in reversed order so that emitInstrOpBits will get the
|
||||
// correct endianness.
|
||||
|
|
|
@ -236,11 +236,11 @@ static BitsInit &getBitsField(const Record &def, StringRef str) {
|
|||
Bits.push_back(const_cast<BitInit *>(BI));
|
||||
} else {
|
||||
for (unsigned Idx = 0U; Idx < SI.BitWidth; ++Idx)
|
||||
Bits.push_back(UnsetInit::get());
|
||||
Bits.push_back(UnsetInit::get(def.getRecords()));
|
||||
}
|
||||
}
|
||||
|
||||
return *BitsInit::get(Bits);
|
||||
return *BitsInit::get(def.getRecords(), Bits);
|
||||
}
|
||||
|
||||
// Representation of the instruction to work on.
|
||||
|
|
|
@ -109,7 +109,8 @@ addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
|
|||
OperandMap[BaseIdx + i].Data.Imm = II->getValue();
|
||||
++OpsAdded;
|
||||
} else if (auto *BI = dyn_cast<BitsInit>(Dag->getArg(i))) {
|
||||
auto *II = cast<IntInit>(BI->convertInitializerTo(IntRecTy::get()));
|
||||
auto *II =
|
||||
cast<IntInit>(BI->convertInitializerTo(IntRecTy::get(Records)));
|
||||
OperandMap[BaseIdx + i].Kind = OpData::Imm;
|
||||
OperandMap[BaseIdx + i].Data.Imm = II->getValue();
|
||||
++OpsAdded;
|
||||
|
|
|
@ -30,7 +30,9 @@ using namespace llvm;
|
|||
namespace {
|
||||
|
||||
int getAsInt(Init *B) {
|
||||
return cast<IntInit>(B->convertInitializerTo(IntRecTy::get()))->getValue();
|
||||
return cast<IntInit>(
|
||||
B->convertInitializerTo(IntRecTy::get(B->getRecordKeeper())))
|
||||
->getValue();
|
||||
}
|
||||
int getInt(Record *R, StringRef Field) {
|
||||
return getAsInt(R->getValueInit(Field));
|
||||
|
|
|
@ -37,8 +37,9 @@ void emitWebAssemblyDisassemblerTables(
|
|||
if (!Def.getValue("Inst"))
|
||||
continue;
|
||||
auto &Inst = *Def.getValueAsBitsInit("Inst");
|
||||
auto Opc = static_cast<unsigned>(
|
||||
reinterpret_cast<IntInit *>(Inst.convertInitializerTo(IntRecTy::get()))
|
||||
RecordKeeper &RK = Inst.getRecordKeeper();
|
||||
unsigned Opc = static_cast<unsigned>(
|
||||
cast<IntInit>(Inst.convertInitializerTo(IntRecTy::get(RK)))
|
||||
->getValue());
|
||||
if (Opc == 0xFFFFFFFF)
|
||||
continue; // No opcode defined.
|
||||
|
@ -55,7 +56,7 @@ void emitWebAssemblyDisassemblerTables(
|
|||
// All wasm instructions have a StackBased field of type string, we only
|
||||
// want the instructions for which this is "true".
|
||||
auto StackString =
|
||||
Def.getValue("StackBased")->getValue()->getCastTo(StringRecTy::get());
|
||||
Def.getValue("StackBased")->getValue()->getCastTo(StringRecTy::get(RK));
|
||||
auto IsStackBased =
|
||||
StackString &&
|
||||
reinterpret_cast<const StringInit *>(StackString)->getValue() == "true";
|
||||
|
|
Loading…
Reference in New Issue