mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 06:30:39 +00:00
IR: Add MDLocation class
Add a new subclass of `UniquableMDNode`, `MDLocation`. This will be the IR version of `DebugLoc` and `DILocation`. The goal is to rename this to `DILocation` once the IR classes supersede the `DI`-prefixed wrappers. This isn't used anywhere yet. Part of PR21433. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225824 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9e495c518c
commit
d640962656
@ -50,6 +50,7 @@ HANDLE_METADATA_BRANCH(MDNode)
|
||||
HANDLE_METADATA_LEAF(MDNodeFwdDecl)
|
||||
HANDLE_UNIQUABLE_BRANCH(UniquableMDNode)
|
||||
HANDLE_UNIQUABLE_LEAF(MDTuple)
|
||||
HANDLE_UNIQUABLE_LEAF(MDLocation)
|
||||
|
||||
#undef HANDLE_METADATA
|
||||
#undef HANDLE_METADATA_LEAF
|
||||
|
@ -57,6 +57,7 @@ protected:
|
||||
public:
|
||||
enum MetadataKind {
|
||||
MDTupleKind,
|
||||
MDLocationKind,
|
||||
MDNodeFwdDeclKind,
|
||||
ConstantAsMetadataKind,
|
||||
LocalAsMetadataKind,
|
||||
@ -670,6 +671,7 @@ public:
|
||||
/// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static bool classof(const Metadata *MD) {
|
||||
return MD->getMetadataID() == MDTupleKind ||
|
||||
MD->getMetadataID() == MDLocationKind ||
|
||||
MD->getMetadataID() == MDNodeFwdDeclKind;
|
||||
}
|
||||
|
||||
@ -726,7 +728,8 @@ protected:
|
||||
|
||||
public:
|
||||
static bool classof(const Metadata *MD) {
|
||||
return MD->getMetadataID() == MDTupleKind;
|
||||
return MD->getMetadataID() == MDTupleKind ||
|
||||
MD->getMetadataID() == MDLocationKind;
|
||||
}
|
||||
|
||||
/// \brief Check whether any operands are forward declarations.
|
||||
@ -812,6 +815,60 @@ MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
|
||||
return MDTuple::getDistinct(Context, MDs);
|
||||
}
|
||||
|
||||
/// \brief Debug location.
|
||||
///
|
||||
/// A debug location in source code, used for debug info and otherwise.
|
||||
class MDLocation : public UniquableMDNode {
|
||||
friend class LLVMContextImpl;
|
||||
friend class UniquableMDNode;
|
||||
|
||||
MDLocation(LLVMContext &C, unsigned Line, unsigned Column,
|
||||
ArrayRef<Metadata *> MDs, bool AllowRAUW);
|
||||
~MDLocation() { dropAllReferences(); }
|
||||
|
||||
static MDLocation *constructHelper(LLVMContext &Context, unsigned Line,
|
||||
unsigned Column, Metadata *Scope,
|
||||
Metadata *InlinedAt, bool AllowRAUW);
|
||||
|
||||
static MDLocation *getImpl(LLVMContext &Context, unsigned Line,
|
||||
unsigned Column, Metadata *Scope,
|
||||
Metadata *InlinedAt, bool ShouldCreate);
|
||||
|
||||
// Disallow replacing operands.
|
||||
void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION;
|
||||
|
||||
public:
|
||||
static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column,
|
||||
Metadata *Scope, Metadata *InlinedAt = nullptr) {
|
||||
return getImpl(Context, Line, Column, Scope, InlinedAt,
|
||||
/* ShouldCreate */ true);
|
||||
}
|
||||
static MDLocation *getIfExists(LLVMContext &Context, unsigned Line,
|
||||
unsigned Column, Metadata *Scope,
|
||||
Metadata *InlinedAt = nullptr) {
|
||||
return getImpl(Context, Line, Column, Scope, InlinedAt,
|
||||
/* ShouldCreate */ false);
|
||||
}
|
||||
static MDLocation *getDistinct(LLVMContext &Context, unsigned Line,
|
||||
unsigned Column, Metadata *Scope,
|
||||
Metadata *InlinedAt = nullptr);
|
||||
|
||||
unsigned getLine() const { return MDNodeSubclassData; }
|
||||
unsigned getColumn() const { return SubclassData16; }
|
||||
Metadata *getScope() const { return getOperand(0); }
|
||||
Metadata *getInlinedAt() const {
|
||||
return getNumOperands() == 2 ? getOperand(1) : nullptr;
|
||||
}
|
||||
|
||||
static bool classof(const Metadata *MD) {
|
||||
return MD->getMetadataID() == MDLocationKind;
|
||||
}
|
||||
|
||||
private:
|
||||
MDLocation *uniquifyImpl();
|
||||
void eraseFromStoreImpl();
|
||||
};
|
||||
|
||||
/// \brief Forward declaration of metadata.
|
||||
///
|
||||
/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a
|
||||
|
@ -1272,6 +1272,39 @@ static void writeMDTuple(raw_ostream &Out, const MDTuple *Node,
|
||||
Out << "}";
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct FieldSeparator {
|
||||
bool Skip;
|
||||
FieldSeparator() : Skip(true) {}
|
||||
};
|
||||
raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
|
||||
if (FS.Skip) {
|
||||
FS.Skip = false;
|
||||
return OS;
|
||||
}
|
||||
return OS << ", ";
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
|
||||
TypePrinting *TypePrinter, SlotTracker *Machine,
|
||||
const Module *Context) {
|
||||
Out << "!MDLocation(";
|
||||
FieldSeparator FS;
|
||||
if (DL->getLine())
|
||||
Out << FS << "line: " << DL->getLine();
|
||||
if (DL->getColumn())
|
||||
Out << FS << "column: " << DL->getColumn();
|
||||
Out << FS << "scope: ";
|
||||
WriteAsOperandInternal(Out, DL->getScope(), TypePrinter, Machine, Context);
|
||||
if (DL->getInlinedAt()) {
|
||||
Out << FS << "inlinedAt: ";
|
||||
WriteAsOperandInternal(Out, DL->getInlinedAt(), TypePrinter, Machine,
|
||||
Context);
|
||||
}
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
|
||||
TypePrinting *TypePrinter,
|
||||
SlotTracker *Machine,
|
||||
|
@ -140,11 +140,15 @@ LLVMContextImpl::~LLVMContextImpl() {
|
||||
I->dropAllReferences();
|
||||
for (auto *I : MDTuples)
|
||||
I->dropAllReferences();
|
||||
for (auto *I : MDLocations)
|
||||
I->dropAllReferences();
|
||||
|
||||
for (UniquableMDNode *I : DistinctMDNodes)
|
||||
I->deleteAsSubclass();
|
||||
for (MDTuple *I : MDTuples)
|
||||
delete I;
|
||||
for (MDLocation *I : MDLocations)
|
||||
delete I;
|
||||
|
||||
// Destroy MDStrings.
|
||||
MDStringCache.clear();
|
||||
|
@ -215,6 +215,48 @@ struct MDTupleInfo {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief DenseMapInfo for MDLocation.
|
||||
struct MDLocationInfo {
|
||||
struct KeyTy {
|
||||
unsigned Line;
|
||||
unsigned Column;
|
||||
Metadata *Scope;
|
||||
Metadata *InlinedAt;
|
||||
|
||||
KeyTy(unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt)
|
||||
: Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt) {}
|
||||
|
||||
KeyTy(const MDLocation *L)
|
||||
: Line(L->getLine()), Column(L->getColumn()), Scope(L->getScope()),
|
||||
InlinedAt(L->getInlinedAt()) {}
|
||||
|
||||
bool operator==(const MDLocation *RHS) const {
|
||||
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
||||
return false;
|
||||
return Line == RHS->getLine() && Column == RHS->getColumn() &&
|
||||
Scope == RHS->getScope() && InlinedAt == RHS->getInlinedAt();
|
||||
}
|
||||
};
|
||||
static inline MDLocation *getEmptyKey() {
|
||||
return DenseMapInfo<MDLocation *>::getEmptyKey();
|
||||
}
|
||||
static inline MDLocation *getTombstoneKey() {
|
||||
return DenseMapInfo<MDLocation *>::getTombstoneKey();
|
||||
}
|
||||
static unsigned getHashValue(const KeyTy &Key) {
|
||||
return hash_combine(Key.Line, Key.Column, Key.Scope, Key.InlinedAt);
|
||||
}
|
||||
static unsigned getHashValue(const MDLocation *U) {
|
||||
return getHashValue(KeyTy(U));
|
||||
}
|
||||
static bool isEqual(const KeyTy &LHS, const MDLocation *RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
static bool isEqual(const MDLocation *LHS, const MDLocation *RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
class LLVMContextImpl {
|
||||
public:
|
||||
/// OwnedModules - The set of modules instantiated in this context, and which
|
||||
@ -246,6 +288,7 @@ public:
|
||||
DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
|
||||
|
||||
DenseSet<MDTuple *, MDTupleInfo> MDTuples;
|
||||
DenseSet<MDLocation *, MDLocationInfo> MDLocations;
|
||||
|
||||
// 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
|
||||
|
@ -640,6 +640,93 @@ MDTuple *MDTuple::uniquifyImpl() {
|
||||
|
||||
void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); }
|
||||
|
||||
MDLocation::MDLocation(LLVMContext &C, unsigned Line, unsigned Column,
|
||||
ArrayRef<Metadata *> MDs, bool AllowRAUW)
|
||||
: UniquableMDNode(C, MDLocationKind, MDs, AllowRAUW) {
|
||||
assert((MDs.size() == 1 || MDs.size() == 2) &&
|
||||
"Expected a scope and optional inlined-at");
|
||||
|
||||
// Set line and column.
|
||||
assert(Line < (1u << 24) && "Expected 24-bit line");
|
||||
assert(Column < (1u << 8) && "Expected 8-bit column");
|
||||
|
||||
MDNodeSubclassData = Line;
|
||||
SubclassData16 = Column;
|
||||
}
|
||||
|
||||
MDLocation *MDLocation::constructHelper(LLVMContext &Context, unsigned Line,
|
||||
unsigned Column, Metadata *Scope,
|
||||
Metadata *InlinedAt, bool AllowRAUW) {
|
||||
SmallVector<Metadata *, 2> Ops;
|
||||
Ops.push_back(Scope);
|
||||
if (InlinedAt)
|
||||
Ops.push_back(InlinedAt);
|
||||
return new (Ops.size()) MDLocation(Context, Line, Column, Ops, AllowRAUW);
|
||||
}
|
||||
|
||||
static void adjustLine(unsigned &Line) {
|
||||
// Set to unknown on overflow. Still use 24 bits for now.
|
||||
if (Line >= (1u << 24))
|
||||
Line = 0;
|
||||
}
|
||||
|
||||
static void adjustColumn(unsigned &Column) {
|
||||
// Set to unknown on overflow. Still use 8 bits for now.
|
||||
if (Column >= (1u << 8))
|
||||
Column = 0;
|
||||
}
|
||||
|
||||
MDLocation *MDLocation::getImpl(LLVMContext &Context, unsigned Line,
|
||||
unsigned Column, Metadata *Scope,
|
||||
Metadata *InlinedAt, bool ShouldCreate) {
|
||||
// Fixup line/column.
|
||||
adjustLine(Line);
|
||||
adjustColumn(Column);
|
||||
|
||||
MDLocationInfo::KeyTy Key(Line, Column, Scope, InlinedAt);
|
||||
|
||||
auto &Store = Context.pImpl->MDLocations;
|
||||
auto I = Store.find_as(Key);
|
||||
if (I != Store.end())
|
||||
return *I;
|
||||
if (!ShouldCreate)
|
||||
return nullptr;
|
||||
|
||||
auto *N = constructHelper(Context, Line, Column, Scope, InlinedAt,
|
||||
/* AllowRAUW */ true);
|
||||
Store.insert(N);
|
||||
return N;
|
||||
}
|
||||
|
||||
MDLocation *MDLocation::getDistinct(LLVMContext &Context, unsigned Line,
|
||||
unsigned Column, Metadata *Scope,
|
||||
Metadata *InlinedAt) {
|
||||
// Fixup line/column.
|
||||
adjustLine(Line);
|
||||
adjustColumn(Column);
|
||||
|
||||
auto *N = constructHelper(Context, Line, Column, Scope, InlinedAt,
|
||||
/* AllowRAUW */ false);
|
||||
N->storeDistinctInContext();
|
||||
return N;
|
||||
}
|
||||
|
||||
MDLocation *MDLocation::uniquifyImpl() {
|
||||
MDLocationInfo::KeyTy Key(this);
|
||||
|
||||
auto &Store = getContext().pImpl->MDLocations;
|
||||
auto I = Store.find_as(Key);
|
||||
if (I == Store.end()) {
|
||||
Store.insert(this);
|
||||
return this;
|
||||
}
|
||||
return *I;
|
||||
}
|
||||
|
||||
void MDLocation::eraseFromStoreImpl() {
|
||||
getContext().pImpl->MDLocations.erase(this);
|
||||
}
|
||||
|
||||
MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
|
||||
ArrayRef<Metadata *> MDs) {
|
||||
return MDNodeFwdDecl::get(Context, MDs);
|
||||
@ -650,9 +737,9 @@ void MDNode::deleteTemporary(MDNode *N) { delete cast<MDNodeFwdDecl>(N); }
|
||||
void UniquableMDNode::storeDistinctInContext() {
|
||||
assert(!IsDistinctInContext && "Expected newly distinct metadata");
|
||||
IsDistinctInContext = true;
|
||||
auto *T = cast<MDTuple>(this);
|
||||
T->setHash(0);
|
||||
getContext().pImpl->DistinctMDNodes.insert(T);
|
||||
if (auto *T = dyn_cast<MDTuple>(this))
|
||||
T->setHash(0);
|
||||
getContext().pImpl->DistinctMDNodes.insert(this);
|
||||
}
|
||||
|
||||
void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
|
||||
|
@ -387,6 +387,43 @@ TEST_F(MDNodeTest, replaceResolvedOperand) {
|
||||
Temp->replaceAllUsesWith(nullptr);
|
||||
}
|
||||
|
||||
typedef MetadataTest MDLocationTest;
|
||||
|
||||
TEST_F(MDLocationTest, Overflow) {
|
||||
MDNode *N = MDNode::get(Context, None);
|
||||
{
|
||||
MDLocation *L = MDLocation::get(Context, 2, 7, N);
|
||||
EXPECT_EQ(2u, L->getLine());
|
||||
EXPECT_EQ(7u, L->getColumn());
|
||||
}
|
||||
unsigned U24 = 1u << 24;
|
||||
unsigned U8 = 1u << 8;
|
||||
{
|
||||
MDLocation *L = MDLocation::get(Context, U24 - 1, U8 - 1, N);
|
||||
EXPECT_EQ(U24 - 1, L->getLine());
|
||||
EXPECT_EQ(U8 - 1, L->getColumn());
|
||||
}
|
||||
{
|
||||
MDLocation *L = MDLocation::get(Context, U24, U8, N);
|
||||
EXPECT_EQ(0u, L->getLine());
|
||||
EXPECT_EQ(0u, L->getColumn());
|
||||
}
|
||||
{
|
||||
MDLocation *L = MDLocation::get(Context, U24 + 1, U8 + 1, N);
|
||||
EXPECT_EQ(0u, L->getLine());
|
||||
EXPECT_EQ(0u, L->getColumn());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MDLocationTest, getDistinct) {
|
||||
MDNode *N = MDNode::get(Context, None);
|
||||
MDLocation *L0 = MDLocation::getDistinct(Context, 2, 7, N);
|
||||
EXPECT_TRUE(L0->isDistinct());
|
||||
MDLocation *L1 = MDLocation::get(Context, 2, 7, N);
|
||||
EXPECT_FALSE(L1->isDistinct());
|
||||
EXPECT_EQ(L1, MDLocation::get(Context, 2, 7, N));
|
||||
}
|
||||
|
||||
typedef MetadataTest MetadataAsValueTest;
|
||||
|
||||
TEST_F(MetadataAsValueTest, MDNode) {
|
||||
|
Loading…
Reference in New Issue
Block a user