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