mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-26 07:24:25 +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:
@ -50,6 +50,7 @@ HANDLE_METADATA_BRANCH(MDNode)
|
|||||||
HANDLE_METADATA_LEAF(MDNodeFwdDecl)
|
HANDLE_METADATA_LEAF(MDNodeFwdDecl)
|
||||||
HANDLE_UNIQUABLE_BRANCH(UniquableMDNode)
|
HANDLE_UNIQUABLE_BRANCH(UniquableMDNode)
|
||||||
HANDLE_UNIQUABLE_LEAF(MDTuple)
|
HANDLE_UNIQUABLE_LEAF(MDTuple)
|
||||||
|
HANDLE_UNIQUABLE_LEAF(MDLocation)
|
||||||
|
|
||||||
#undef HANDLE_METADATA
|
#undef HANDLE_METADATA
|
||||||
#undef HANDLE_METADATA_LEAF
|
#undef HANDLE_METADATA_LEAF
|
||||||
|
@ -57,6 +57,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
enum MetadataKind {
|
enum MetadataKind {
|
||||||
MDTupleKind,
|
MDTupleKind,
|
||||||
|
MDLocationKind,
|
||||||
MDNodeFwdDeclKind,
|
MDNodeFwdDeclKind,
|
||||||
ConstantAsMetadataKind,
|
ConstantAsMetadataKind,
|
||||||
LocalAsMetadataKind,
|
LocalAsMetadataKind,
|
||||||
@ -670,6 +671,7 @@ 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() == MDNodeFwdDeclKind;
|
MD->getMetadataID() == MDNodeFwdDeclKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,7 +728,8 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static bool classof(const Metadata *MD) {
|
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.
|
/// \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);
|
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.
|
/// \brief Forward declaration of metadata.
|
||||||
///
|
///
|
||||||
/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a
|
/// 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 << "}";
|
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,
|
static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
|
||||||
TypePrinting *TypePrinter,
|
TypePrinting *TypePrinter,
|
||||||
SlotTracker *Machine,
|
SlotTracker *Machine,
|
||||||
|
@ -140,11 +140,15 @@ LLVMContextImpl::~LLVMContextImpl() {
|
|||||||
I->dropAllReferences();
|
I->dropAllReferences();
|
||||||
for (auto *I : MDTuples)
|
for (auto *I : MDTuples)
|
||||||
I->dropAllReferences();
|
I->dropAllReferences();
|
||||||
|
for (auto *I : MDLocations)
|
||||||
|
I->dropAllReferences();
|
||||||
|
|
||||||
for (UniquableMDNode *I : DistinctMDNodes)
|
for (UniquableMDNode *I : DistinctMDNodes)
|
||||||
I->deleteAsSubclass();
|
I->deleteAsSubclass();
|
||||||
for (MDTuple *I : MDTuples)
|
for (MDTuple *I : MDTuples)
|
||||||
delete I;
|
delete I;
|
||||||
|
for (MDLocation *I : MDLocations)
|
||||||
|
delete I;
|
||||||
|
|
||||||
// Destroy MDStrings.
|
// Destroy MDStrings.
|
||||||
MDStringCache.clear();
|
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 {
|
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
|
||||||
@ -246,6 +288,7 @@ public:
|
|||||||
DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
|
DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
|
||||||
|
|
||||||
DenseSet<MDTuple *, MDTupleInfo> MDTuples;
|
DenseSet<MDTuple *, MDTupleInfo> MDTuples;
|
||||||
|
DenseSet<MDLocation *, MDLocationInfo> MDLocations;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -640,6 +640,93 @@ MDTuple *MDTuple::uniquifyImpl() {
|
|||||||
|
|
||||||
void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); }
|
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,
|
MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
|
||||||
ArrayRef<Metadata *> MDs) {
|
ArrayRef<Metadata *> MDs) {
|
||||||
return MDNodeFwdDecl::get(Context, MDs);
|
return MDNodeFwdDecl::get(Context, MDs);
|
||||||
@ -650,9 +737,9 @@ void MDNode::deleteTemporary(MDNode *N) { delete cast<MDNodeFwdDecl>(N); }
|
|||||||
void UniquableMDNode::storeDistinctInContext() {
|
void UniquableMDNode::storeDistinctInContext() {
|
||||||
assert(!IsDistinctInContext && "Expected newly distinct metadata");
|
assert(!IsDistinctInContext && "Expected newly distinct metadata");
|
||||||
IsDistinctInContext = true;
|
IsDistinctInContext = true;
|
||||||
auto *T = cast<MDTuple>(this);
|
if (auto *T = dyn_cast<MDTuple>(this))
|
||||||
T->setHash(0);
|
T->setHash(0);
|
||||||
getContext().pImpl->DistinctMDNodes.insert(T);
|
getContext().pImpl->DistinctMDNodes.insert(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
|
void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
|
||||||
|
@ -387,6 +387,43 @@ TEST_F(MDNodeTest, replaceResolvedOperand) {
|
|||||||
Temp->replaceAllUsesWith(nullptr);
|
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;
|
typedef MetadataTest MetadataAsValueTest;
|
||||||
|
|
||||||
TEST_F(MetadataAsValueTest, MDNode) {
|
TEST_F(MetadataAsValueTest, MDNode) {
|
||||||
|
Reference in New Issue
Block a user