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:
Duncan P. N. Exon Smith 2015-01-13 20:44:56 +00:00
parent 9e495c518c
commit d640962656
7 changed files with 266 additions and 4 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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();

View File

@ -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

View File

@ -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) {

View File

@ -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) {