mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
IR: Introduce GenericDwarfNode
As part of PR22235, introduce `DwarfNode` and `GenericDwarfNode`. The former is a metadata node with a DWARF tag. The latter matches our current (generic) schema of a header with string (and stringified integer) data and an arbitrary number of operands. This doesn't move it into place yet; that change will require a large number of testcase updates. llvm-svn: 226529
This commit is contained in:
parent
c1c7b46705
commit
0973b855f5
@ -49,6 +49,8 @@ HANDLE_METADATA_LEAF(LocalAsMetadata)
|
|||||||
HANDLE_MDNODE_BRANCH(MDNode)
|
HANDLE_MDNODE_BRANCH(MDNode)
|
||||||
HANDLE_MDNODE_LEAF(MDTuple)
|
HANDLE_MDNODE_LEAF(MDTuple)
|
||||||
HANDLE_MDNODE_LEAF(MDLocation)
|
HANDLE_MDNODE_LEAF(MDLocation)
|
||||||
|
HANDLE_MDNODE_BRANCH(DwarfNode)
|
||||||
|
HANDLE_MDNODE_LEAF(GenericDwarfNode)
|
||||||
|
|
||||||
#undef HANDLE_METADATA
|
#undef HANDLE_METADATA
|
||||||
#undef HANDLE_METADATA_LEAF
|
#undef HANDLE_METADATA_LEAF
|
||||||
|
@ -61,6 +61,7 @@ public:
|
|||||||
enum MetadataKind {
|
enum MetadataKind {
|
||||||
MDTupleKind,
|
MDTupleKind,
|
||||||
MDLocationKind,
|
MDLocationKind,
|
||||||
|
GenericDwarfNodeKind,
|
||||||
ConstantAsMetadataKind,
|
ConstantAsMetadataKind,
|
||||||
LocalAsMetadataKind,
|
LocalAsMetadataKind,
|
||||||
MDStringKind
|
MDStringKind
|
||||||
@ -704,7 +705,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
|
MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
|
||||||
ArrayRef<Metadata *> MDs);
|
ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None);
|
||||||
~MDNode() {}
|
~MDNode() {}
|
||||||
|
|
||||||
void dropAllReferences();
|
void dropAllReferences();
|
||||||
@ -847,7 +848,8 @@ public:
|
|||||||
/// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
|
/// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
static bool classof(const Metadata *MD) {
|
static bool classof(const Metadata *MD) {
|
||||||
return MD->getMetadataID() == MDTupleKind ||
|
return MD->getMetadataID() == MDTupleKind ||
|
||||||
MD->getMetadataID() == MDLocationKind;
|
MD->getMetadataID() == MDLocationKind ||
|
||||||
|
MD->getMetadataID() == GenericDwarfNodeKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Check whether MDNode is a vtable access.
|
/// \brief Check whether MDNode is a vtable access.
|
||||||
@ -989,6 +991,104 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Tagged dwarf node.
|
||||||
|
///
|
||||||
|
/// A metadata node with a DWARF tag.
|
||||||
|
class DwarfNode : public MDNode {
|
||||||
|
friend class LLVMContextImpl;
|
||||||
|
friend class MDNode;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DwarfNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
|
||||||
|
ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None)
|
||||||
|
: MDNode(C, ID, Storage, Ops1, Ops2) {
|
||||||
|
assert(Tag < 1u << 16);
|
||||||
|
SubclassData16 = Tag;
|
||||||
|
}
|
||||||
|
~DwarfNode() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned getTag() const { return SubclassData16; }
|
||||||
|
|
||||||
|
static bool classof(const Metadata *MD) {
|
||||||
|
return MD->getMetadataID() == GenericDwarfNodeKind;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Generic tagged dwarf node.
|
||||||
|
///
|
||||||
|
/// A generic metadata node with a DWARF tag that doesn't have special
|
||||||
|
/// handling.
|
||||||
|
class GenericDwarfNode : public DwarfNode {
|
||||||
|
friend class LLVMContextImpl;
|
||||||
|
friend class MDNode;
|
||||||
|
|
||||||
|
GenericDwarfNode(LLVMContext &C, StorageType Storage, unsigned Hash,
|
||||||
|
unsigned Tag, ArrayRef<Metadata *> Ops1,
|
||||||
|
ArrayRef<Metadata *> Ops2)
|
||||||
|
: DwarfNode(C, GenericDwarfNodeKind, Storage, Tag, Ops1, Ops2) {
|
||||||
|
setHash(Hash);
|
||||||
|
}
|
||||||
|
~GenericDwarfNode() { dropAllReferences(); }
|
||||||
|
|
||||||
|
void setHash(unsigned Hash) { SubclassData32 = Hash; }
|
||||||
|
void recalculateHash();
|
||||||
|
|
||||||
|
static GenericDwarfNode *getImpl(LLVMContext &Context, unsigned Tag,
|
||||||
|
MDString *Header,
|
||||||
|
ArrayRef<Metadata *> DwarfOps,
|
||||||
|
StorageType Storage,
|
||||||
|
bool ShouldCreate = true);
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned getHash() const { return SubclassData32; }
|
||||||
|
|
||||||
|
static GenericDwarfNode *get(LLVMContext &Context,
|
||||||
|
unsigned Tag,
|
||||||
|
MDString *Header,
|
||||||
|
ArrayRef<Metadata *> DwarfOps) {
|
||||||
|
return getImpl(Context, Tag, Header, DwarfOps, Uniqued);
|
||||||
|
}
|
||||||
|
static GenericDwarfNode *getIfExists(LLVMContext &Context, unsigned Tag,
|
||||||
|
MDString *Header,
|
||||||
|
ArrayRef<Metadata *> DwarfOps) {
|
||||||
|
return getImpl(Context, Tag, Header, DwarfOps, Uniqued,
|
||||||
|
/* ShouldCreate */ false);
|
||||||
|
}
|
||||||
|
static GenericDwarfNode *getDistinct(LLVMContext &Context, unsigned Tag,
|
||||||
|
MDString *Header,
|
||||||
|
ArrayRef<Metadata *> DwarfOps) {
|
||||||
|
return getImpl(Context, Tag, Header, DwarfOps, Distinct);
|
||||||
|
}
|
||||||
|
static TempGenericDwarfNode getTemporary(LLVMContext &Context, unsigned Tag,
|
||||||
|
MDString *Header,
|
||||||
|
ArrayRef<Metadata *> DwarfOps) {
|
||||||
|
return TempGenericDwarfNode(
|
||||||
|
getImpl(Context, Tag, Header, DwarfOps, Temporary));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getTag() const { return SubclassData16; }
|
||||||
|
MDString *getHeader() const { return cast_or_null<MDString>(getOperand(0)); }
|
||||||
|
|
||||||
|
op_iterator dwarf_op_begin() const { return op_begin() + 1; }
|
||||||
|
op_iterator dwarf_op_end() const { return op_end(); }
|
||||||
|
op_range dwarf_operands() const {
|
||||||
|
return op_range(dwarf_op_begin(), dwarf_op_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getNumDwarfOperands() const { return getNumOperands() - 1; }
|
||||||
|
const MDOperand &getDwarfOperand(unsigned I) const {
|
||||||
|
return getOperand(I + 1);
|
||||||
|
}
|
||||||
|
void replaceDwarfOperandWith(unsigned I, Metadata *New) {
|
||||||
|
replaceOperandWith(I + 1, New);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool classof(const Metadata *MD) {
|
||||||
|
return MD->getMetadataID() == GenericDwarfNodeKind;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
/// \brief A tuple of MDNodes.
|
/// \brief A tuple of MDNodes.
|
||||||
///
|
///
|
||||||
|
@ -1286,6 +1286,12 @@ raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
|
|||||||
}
|
}
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
|
static void writeGenericDwarfNode(raw_ostream &, const GenericDwarfNode *,
|
||||||
|
TypePrinting *, SlotTracker *,
|
||||||
|
const Module *) {
|
||||||
|
llvm_unreachable("Unimplemented write");
|
||||||
|
}
|
||||||
|
|
||||||
static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
|
static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
|
||||||
TypePrinting *TypePrinter, SlotTracker *Machine,
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
||||||
const Module *Context) {
|
const Module *Context) {
|
||||||
|
@ -180,11 +180,11 @@ namespace llvm {
|
|||||||
static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
|
static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned MDNodeOpsKey::calculateHash(MDNode *N) {
|
unsigned MDNodeOpsKey::calculateHash(MDNode *N, unsigned Offset) {
|
||||||
unsigned Hash = hash_combine_range(N->op_begin(), N->op_end());
|
unsigned Hash = hash_combine_range(N->op_begin() + Offset, N->op_end());
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
{
|
{
|
||||||
SmallVector<Metadata *, 8> MDs(N->op_begin(), N->op_end());
|
SmallVector<Metadata *, 8> MDs(N->op_begin() + Offset, N->op_end());
|
||||||
unsigned RawHash = calculateHash(MDs);
|
unsigned RawHash = calculateHash(MDs);
|
||||||
assert(Hash == RawHash &&
|
assert(Hash == RawHash &&
|
||||||
"Expected hash of MDOperand to equal hash of Metadata*");
|
"Expected hash of MDOperand to equal hash of Metadata*");
|
||||||
|
@ -179,25 +179,27 @@ protected:
|
|||||||
: RawOps(Ops), Hash(calculateHash(Ops)) {}
|
: RawOps(Ops), Hash(calculateHash(Ops)) {}
|
||||||
|
|
||||||
template <class NodeTy>
|
template <class NodeTy>
|
||||||
MDNodeOpsKey(NodeTy *N)
|
MDNodeOpsKey(NodeTy *N, unsigned Offset = 0)
|
||||||
: Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {}
|
: Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {}
|
||||||
|
|
||||||
template <class NodeTy> bool compareOps(const NodeTy *RHS) const {
|
template <class NodeTy>
|
||||||
|
bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const {
|
||||||
if (getHash() != RHS->getHash())
|
if (getHash() != RHS->getHash())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
|
assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
|
||||||
return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS);
|
return RawOps.empty() ? compareOps(Ops, RHS, Offset)
|
||||||
|
: compareOps(RawOps, RHS, Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned calculateHash(MDNode *N);
|
static unsigned calculateHash(MDNode *N, unsigned Offset = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class T>
|
template <class T>
|
||||||
static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS) {
|
static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS, unsigned Offset) {
|
||||||
if (Ops.size() != RHS->getNumOperands())
|
if (Ops.size() != RHS->getNumOperands() - Offset)
|
||||||
return false;
|
return false;
|
||||||
return std::equal(Ops.begin(), Ops.end(), RHS->op_begin());
|
return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned calculateHash(ArrayRef<Metadata *> Ops);
|
static unsigned calculateHash(ArrayRef<Metadata *> Ops);
|
||||||
@ -283,6 +285,48 @@ struct MDLocationInfo {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief DenseMapInfo for GenericDwarfNode.
|
||||||
|
struct GenericDwarfNodeInfo {
|
||||||
|
struct KeyTy : MDNodeOpsKey {
|
||||||
|
unsigned Tag;
|
||||||
|
MDString *Header;
|
||||||
|
KeyTy(unsigned Tag, MDString *Header, ArrayRef<Metadata *> DwarfOps)
|
||||||
|
: MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {}
|
||||||
|
KeyTy(GenericDwarfNode *N)
|
||||||
|
: MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getHeader()) {}
|
||||||
|
|
||||||
|
bool operator==(const GenericDwarfNode *RHS) const {
|
||||||
|
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
||||||
|
return false;
|
||||||
|
return Tag == RHS->getTag() && Header == RHS->getHeader() &&
|
||||||
|
compareOps(RHS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned calculateHash(GenericDwarfNode *N) {
|
||||||
|
return MDNodeOpsKey::calculateHash(N, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static inline GenericDwarfNode *getEmptyKey() {
|
||||||
|
return DenseMapInfo<GenericDwarfNode *>::getEmptyKey();
|
||||||
|
}
|
||||||
|
static inline GenericDwarfNode *getTombstoneKey() {
|
||||||
|
return DenseMapInfo<GenericDwarfNode *>::getTombstoneKey();
|
||||||
|
}
|
||||||
|
static unsigned getHashValue(const KeyTy &Key) {
|
||||||
|
return hash_combine(Key.getHash(), Key.Tag, Key.Header);
|
||||||
|
}
|
||||||
|
static unsigned getHashValue(const GenericDwarfNode *U) {
|
||||||
|
return hash_combine(U->getHash(), U->getTag(), U->getHeader());
|
||||||
|
}
|
||||||
|
static bool isEqual(const KeyTy &LHS, const GenericDwarfNode *RHS) {
|
||||||
|
return LHS == RHS;
|
||||||
|
}
|
||||||
|
static bool isEqual(const GenericDwarfNode *LHS,
|
||||||
|
const GenericDwarfNode *RHS) {
|
||||||
|
return LHS == RHS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LLVMContextImpl {
|
class LLVMContextImpl {
|
||||||
public:
|
public:
|
||||||
/// OwnedModules - The set of modules instantiated in this context, and which
|
/// OwnedModules - The set of modules instantiated in this context, and which
|
||||||
@ -315,6 +359,7 @@ public:
|
|||||||
|
|
||||||
DenseSet<MDTuple *, MDTupleInfo> MDTuples;
|
DenseSet<MDTuple *, MDTupleInfo> MDTuples;
|
||||||
DenseSet<MDLocation *, MDLocationInfo> MDLocations;
|
DenseSet<MDLocation *, MDLocationInfo> MDLocations;
|
||||||
|
DenseSet<GenericDwarfNode *, GenericDwarfNodeInfo> GenericDwarfNodes;
|
||||||
|
|
||||||
// MDNodes may be uniqued or not uniqued. When they're not uniqued, they
|
// MDNodes may be uniqued or not uniqued. When they're not uniqued, they
|
||||||
// aren't in the MDNodeSet, but they're still shared between objects, so no
|
// aren't in the MDNodeSet, but they're still shared between objects, so no
|
||||||
|
@ -397,11 +397,14 @@ void MDNode::operator delete(void *Mem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
|
MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
|
||||||
ArrayRef<Metadata *> MDs)
|
ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2)
|
||||||
: Metadata(ID, Storage), NumOperands(MDs.size()), NumUnresolved(0),
|
: Metadata(ID, Storage), NumOperands(Ops1.size() + Ops2.size()),
|
||||||
Context(Context) {
|
NumUnresolved(0), Context(Context) {
|
||||||
for (unsigned I = 0, E = MDs.size(); I != E; ++I)
|
unsigned Op = 0;
|
||||||
setOperand(I, MDs[I]);
|
for (Metadata *MD : Ops1)
|
||||||
|
setOperand(Op++, MD);
|
||||||
|
for (Metadata *MD : Ops2)
|
||||||
|
setOperand(Op++, MD);
|
||||||
|
|
||||||
if (isDistinct())
|
if (isDistinct())
|
||||||
return;
|
return;
|
||||||
@ -527,6 +530,10 @@ void MDTuple::recalculateHash() {
|
|||||||
setHash(MDTupleInfo::KeyTy::calculateHash(this));
|
setHash(MDTupleInfo::KeyTy::calculateHash(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenericDwarfNode::recalculateHash() {
|
||||||
|
setHash(GenericDwarfNodeInfo::KeyTy::calculateHash(this));
|
||||||
|
}
|
||||||
|
|
||||||
void MDNode::dropAllReferences() {
|
void MDNode::dropAllReferences() {
|
||||||
for (unsigned I = 0, E = NumOperands; I != E; ++I)
|
for (unsigned I = 0, E = NumOperands; I != E; ++I)
|
||||||
setOperand(I, nullptr);
|
setOperand(I, nullptr);
|
||||||
@ -621,6 +628,9 @@ MDNode *MDNode::uniquify() {
|
|||||||
case MDTupleKind:
|
case MDTupleKind:
|
||||||
cast<MDTuple>(this)->recalculateHash();
|
cast<MDTuple>(this)->recalculateHash();
|
||||||
break;
|
break;
|
||||||
|
case GenericDwarfNodeKind:
|
||||||
|
cast<GenericDwarfNode>(this)->recalculateHash();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to insert into uniquing store.
|
// Try to insert into uniquing store.
|
||||||
@ -733,6 +743,29 @@ MDLocation *MDLocation::getImpl(LLVMContext &Context, unsigned Line,
|
|||||||
Storage, Context.pImpl->MDLocations);
|
Storage, Context.pImpl->MDLocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GenericDwarfNode *GenericDwarfNode::getImpl(LLVMContext &Context, unsigned Tag,
|
||||||
|
MDString *Header,
|
||||||
|
ArrayRef<Metadata *> DwarfOps,
|
||||||
|
StorageType Storage,
|
||||||
|
bool ShouldCreate) {
|
||||||
|
unsigned Hash = 0;
|
||||||
|
if (Storage == Uniqued) {
|
||||||
|
GenericDwarfNodeInfo::KeyTy Key(Tag, Header, DwarfOps);
|
||||||
|
if (auto *N = getUniqued(Context.pImpl->GenericDwarfNodes, Key))
|
||||||
|
return N;
|
||||||
|
if (!ShouldCreate)
|
||||||
|
return nullptr;
|
||||||
|
Hash = Key.getHash();
|
||||||
|
} else {
|
||||||
|
assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata *PreOps[] = {Header};
|
||||||
|
return storeImpl(new (DwarfOps.size() + 1) GenericDwarfNode(
|
||||||
|
Context, Storage, Hash, Tag, PreOps, DwarfOps),
|
||||||
|
Storage, Context.pImpl->GenericDwarfNodes);
|
||||||
|
}
|
||||||
|
|
||||||
void MDNode::deleteTemporary(MDNode *N) {
|
void MDNode::deleteTemporary(MDNode *N) {
|
||||||
assert(N->isTemporary() && "Expected temporary node");
|
assert(N->isTemporary() && "Expected temporary node");
|
||||||
N->deleteAsSubclass();
|
N->deleteAsSubclass();
|
||||||
@ -743,6 +776,8 @@ void MDNode::storeDistinctInContext() {
|
|||||||
Storage = Distinct;
|
Storage = Distinct;
|
||||||
if (auto *T = dyn_cast<MDTuple>(this))
|
if (auto *T = dyn_cast<MDTuple>(this))
|
||||||
T->setHash(0);
|
T->setHash(0);
|
||||||
|
else if (auto *G = dyn_cast<GenericDwarfNode>(this))
|
||||||
|
G->setHash(0);
|
||||||
getContext().pImpl->DistinctMDNodes.insert(this);
|
getContext().pImpl->DistinctMDNodes.insert(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +192,14 @@ static TempMDLocation cloneMDLocation(const MDLocation *Node) {
|
|||||||
Node->getInlinedAt());
|
Node->getInlinedAt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TempGenericDwarfNode
|
||||||
|
cloneGenericDwarfNode(const GenericDwarfNode *Node) {
|
||||||
|
SmallVector<Metadata *, 4> DwarfOps;
|
||||||
|
DwarfOps.append(Node->dwarf_op_begin(), Node->dwarf_op_end());
|
||||||
|
return GenericDwarfNode::getTemporary(Node->getContext(), Node->getTag(),
|
||||||
|
Node->getHeader(), DwarfOps);
|
||||||
|
}
|
||||||
|
|
||||||
static TempMDNode cloneMDNode(const MDNode *Node) {
|
static TempMDNode cloneMDNode(const MDNode *Node) {
|
||||||
switch (Node->getMetadataID()) {
|
switch (Node->getMetadataID()) {
|
||||||
default:
|
default:
|
||||||
|
@ -561,6 +561,41 @@ TEST_F(MDLocationTest, getTemporary) {
|
|||||||
EXPECT_FALSE(L->isResolved());
|
EXPECT_FALSE(L->isResolved());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef MetadataTest GenericDwarfNodeTest;
|
||||||
|
|
||||||
|
TEST_F(GenericDwarfNodeTest, get) {
|
||||||
|
auto *Header = MDString::get(Context, "header");
|
||||||
|
auto *Empty = MDNode::get(Context, None);
|
||||||
|
Metadata *Ops1[] = {Empty};
|
||||||
|
auto *N = GenericDwarfNode::get(Context, 15, Header, Ops1);
|
||||||
|
EXPECT_EQ(15u, N->getTag());
|
||||||
|
EXPECT_EQ(2u, N->getNumOperands());
|
||||||
|
EXPECT_EQ(Header, N->getHeader());
|
||||||
|
EXPECT_EQ(Header, N->getOperand(0));
|
||||||
|
EXPECT_EQ(1u, N->getNumDwarfOperands());
|
||||||
|
EXPECT_EQ(Empty, N->getDwarfOperand(0));
|
||||||
|
EXPECT_EQ(Empty, N->getOperand(1));
|
||||||
|
ASSERT_TRUE(N->isUniqued());
|
||||||
|
|
||||||
|
EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops1));
|
||||||
|
|
||||||
|
N->replaceOperandWith(1, nullptr);
|
||||||
|
EXPECT_EQ(15u, N->getTag());
|
||||||
|
EXPECT_EQ(Header, N->getHeader());
|
||||||
|
EXPECT_EQ(nullptr, N->getDwarfOperand(0));
|
||||||
|
ASSERT_TRUE(N->isUniqued());
|
||||||
|
|
||||||
|
Metadata *Ops2[] = {nullptr};
|
||||||
|
EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops2));
|
||||||
|
|
||||||
|
N->replaceDwarfOperandWith(0, Empty);
|
||||||
|
EXPECT_EQ(15u, N->getTag());
|
||||||
|
EXPECT_EQ(Header, N->getHeader());
|
||||||
|
EXPECT_EQ(Empty, N->getDwarfOperand(0));
|
||||||
|
ASSERT_TRUE(N->isUniqued());
|
||||||
|
EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops1));
|
||||||
|
}
|
||||||
|
|
||||||
typedef MetadataTest MetadataAsValueTest;
|
typedef MetadataTest MetadataAsValueTest;
|
||||||
|
|
||||||
TEST_F(MetadataAsValueTest, MDNode) {
|
TEST_F(MetadataAsValueTest, MDNode) {
|
||||||
|
Loading…
Reference in New Issue
Block a user