mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-08 18:30:04 +00:00
Add a new "NewDebugLoc" class which will eventually replace DebugLoc,
and will replace the 'DbgInfo' member in Instruction. The benefit of NewDebugLoc is that it is compact (8 bytes vs 12/24 bytes for the DbgInfo member in Instruction on a 32/64 bit system), it means that we will end up not having to allocate MDNodes to represent the "DILocations" in common cases of -O0 -g, and it is much more efficient to get things out of than the MDNode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100072 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1118b5e490
commit
b227925fa3
@ -20,6 +20,61 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class MDNode;
|
class MDNode;
|
||||||
|
class LLVMContext;
|
||||||
|
|
||||||
|
/// DebugLoc - Debug location id. This is carried by Instruction, SDNode,
|
||||||
|
/// and MachineInstr to compactly encode file/line/scope information for an
|
||||||
|
/// operation.
|
||||||
|
class NewDebugLoc {
|
||||||
|
/// LineCol - This 32-bit value encodes the line and column number for the
|
||||||
|
/// location, encoded as 24-bits for line and 8 bits for col. A value of 0
|
||||||
|
/// for either means unknown.
|
||||||
|
unsigned LineCol;
|
||||||
|
|
||||||
|
/// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information,
|
||||||
|
/// decoded by LLVMContext. 0 is unknown.
|
||||||
|
int ScopeIdx;
|
||||||
|
public:
|
||||||
|
NewDebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown.
|
||||||
|
|
||||||
|
static NewDebugLoc get(unsigned Line, unsigned Col,
|
||||||
|
MDNode *Scope, MDNode *InlinedAt);
|
||||||
|
|
||||||
|
/// isUnknown - Return true if this is an unknown location.
|
||||||
|
bool isUnknown() const { return ScopeIdx == 0; }
|
||||||
|
|
||||||
|
unsigned getLine() const {
|
||||||
|
return (LineCol << 8) >> 8; // Mask out column.
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getCol() const {
|
||||||
|
return LineCol >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getScope - This returns the scope pointer for this DebugLoc, or null if
|
||||||
|
/// invalid.
|
||||||
|
MDNode *getScope(const LLVMContext &Ctx) const;
|
||||||
|
|
||||||
|
/// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or
|
||||||
|
/// null if invalid or not present.
|
||||||
|
MDNode *getInlinedAt(const LLVMContext &Ctx) const;
|
||||||
|
|
||||||
|
/// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values.
|
||||||
|
void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
|
||||||
|
const LLVMContext &Ctx) const;
|
||||||
|
|
||||||
|
|
||||||
|
/// getAsMDNode - This method converts the compressed DebugLoc node into a
|
||||||
|
/// DILocation compatible MDNode.
|
||||||
|
MDNode *getAsMDNode(const LLVMContext &Ctx) const;
|
||||||
|
|
||||||
|
bool operator==(const NewDebugLoc &DL) const {
|
||||||
|
return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx;
|
||||||
|
}
|
||||||
|
bool operator!=(const NewDebugLoc &DL) const { return !(*this == DL); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DebugLoc - Debug location id. This is carried by SDNode and MachineInstr
|
/// DebugLoc - Debug location id. This is carried by SDNode and MachineInstr
|
||||||
/// to index into a vector of unique debug location tuples.
|
/// to index into a vector of unique debug location tuples.
|
||||||
|
270
lib/VMCore/DebugLoc.cpp
Normal file
270
lib/VMCore/DebugLoc.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
//===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/Support/DebugLoc.h"
|
||||||
|
#include "LLVMContextImpl.h"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// DebugLoc Implementation
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
MDNode *NewDebugLoc::getScope(const LLVMContext &Ctx) const {
|
||||||
|
if (ScopeIdx == 0) return 0;
|
||||||
|
|
||||||
|
if (ScopeIdx > 0) {
|
||||||
|
// Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
|
||||||
|
// position specified.
|
||||||
|
assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
|
||||||
|
"Invalid ScopeIdx!");
|
||||||
|
return Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, the index is in the ScopeInlinedAtRecords array.
|
||||||
|
assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
|
||||||
|
"Invalid ScopeIdx");
|
||||||
|
return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
MDNode *NewDebugLoc::getInlinedAt(const LLVMContext &Ctx) const {
|
||||||
|
// Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
|
||||||
|
// position specified. Zero is invalid.
|
||||||
|
if (ScopeIdx >= 0) return 0;
|
||||||
|
|
||||||
|
// Otherwise, the index is in the ScopeInlinedAtRecords array.
|
||||||
|
assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
|
||||||
|
"Invalid ScopeIdx");
|
||||||
|
return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return both the Scope and the InlinedAt values.
|
||||||
|
void NewDebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
|
||||||
|
const LLVMContext &Ctx) const {
|
||||||
|
if (ScopeIdx == 0) {
|
||||||
|
Scope = IA = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ScopeIdx > 0) {
|
||||||
|
// Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
|
||||||
|
// position specified.
|
||||||
|
assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
|
||||||
|
"Invalid ScopeIdx!");
|
||||||
|
Scope = Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
|
||||||
|
IA = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, the index is in the ScopeInlinedAtRecords array.
|
||||||
|
assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
|
||||||
|
"Invalid ScopeIdx");
|
||||||
|
Scope = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
|
||||||
|
IA = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NewDebugLoc NewDebugLoc::get(unsigned Line, unsigned Col,
|
||||||
|
MDNode *Scope, MDNode *InlinedAt) {
|
||||||
|
NewDebugLoc Result;
|
||||||
|
|
||||||
|
// If no scope is available, this is an unknown location.
|
||||||
|
if (Scope == 0) return Result;
|
||||||
|
|
||||||
|
// Saturate line and col to "unknown".
|
||||||
|
if (Col > 255) Col = 0;
|
||||||
|
if (Line >= (1 << 24)) Line = 0;
|
||||||
|
Result.LineCol = Line | (Col << 24);
|
||||||
|
|
||||||
|
LLVMContext &Ctx = Scope->getContext();
|
||||||
|
|
||||||
|
// If there is no inlined-at location, use the ScopeRecords array.
|
||||||
|
if (InlinedAt == 0)
|
||||||
|
Result.ScopeIdx = Ctx.pImpl->getOrAddScopeRecordIdxEntry(Scope, 0);
|
||||||
|
else
|
||||||
|
Result.ScopeIdx = Ctx.pImpl->getOrAddScopeInlinedAtIdxEntry(Scope,
|
||||||
|
InlinedAt, 0);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getAsMDNode - This method converts the compressed DebugLoc node into a
|
||||||
|
/// DILocation compatible MDNode.
|
||||||
|
MDNode *NewDebugLoc::getAsMDNode(const LLVMContext &Ctx) const {
|
||||||
|
if (isUnknown()) return 0;
|
||||||
|
|
||||||
|
MDNode *Scope, *IA;
|
||||||
|
getScopeAndInlinedAt(Scope, IA, Ctx);
|
||||||
|
assert(Scope && "If scope is null, this should be isUnknown()");
|
||||||
|
|
||||||
|
LLVMContext &Ctx2 = Scope->getContext();
|
||||||
|
const Type *Int32 = Type::getInt32Ty(Ctx2);
|
||||||
|
Value *Elts[] = {
|
||||||
|
ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()),
|
||||||
|
Scope, IA
|
||||||
|
};
|
||||||
|
return MDNode::get(Ctx2, &Elts[0], 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// LLVMContextImpl Implementation
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
int LLVMContextImpl::getOrAddScopeRecordIdxEntry(MDNode *Scope,
|
||||||
|
int ExistingIdx) {
|
||||||
|
// If we already have an entry for this scope, return it.
|
||||||
|
int &Idx = ScopeRecordIdx[Scope];
|
||||||
|
if (Idx) return Idx;
|
||||||
|
|
||||||
|
// If we don't have an entry, but ExistingIdx is specified, use it.
|
||||||
|
if (ExistingIdx)
|
||||||
|
return Idx = ExistingIdx;
|
||||||
|
|
||||||
|
// Otherwise add a new entry.
|
||||||
|
|
||||||
|
// Start out ScopeRecords with a minimal reasonable size to avoid
|
||||||
|
// excessive reallocation starting out.
|
||||||
|
if (ScopeRecords.empty())
|
||||||
|
ScopeRecords.reserve(128);
|
||||||
|
|
||||||
|
// Index is biased by 1 for index.
|
||||||
|
Idx = ScopeRecords.size()+1;
|
||||||
|
ScopeRecords.push_back(DebugRecVH(Scope, this, Idx));
|
||||||
|
return Idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,
|
||||||
|
int ExistingIdx) {
|
||||||
|
// If we already have an entry, return it.
|
||||||
|
int &Idx = ScopeInlinedAtIdx[std::make_pair(Scope, IA)];
|
||||||
|
if (Idx) return Idx;
|
||||||
|
|
||||||
|
// If we don't have an entry, but ExistingIdx is specified, use it.
|
||||||
|
if (ExistingIdx)
|
||||||
|
return Idx = ExistingIdx;
|
||||||
|
|
||||||
|
// Start out ScopeInlinedAtRecords with a minimal reasonable size to avoid
|
||||||
|
// excessive reallocation starting out.
|
||||||
|
if (ScopeInlinedAtRecords.empty())
|
||||||
|
ScopeInlinedAtRecords.reserve(128);
|
||||||
|
|
||||||
|
// Index is biased by 1 and negated.
|
||||||
|
Idx = -ScopeInlinedAtRecords.size()-1;
|
||||||
|
ScopeInlinedAtRecords.push_back(std::make_pair(DebugRecVH(Scope, this, Idx),
|
||||||
|
DebugRecVH(IA, this, Idx)));
|
||||||
|
return Idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// DebugRecVH Implementation
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// deleted - The MDNode this is pointing to got deleted, so this pointer needs
|
||||||
|
/// to drop to null and we need remove our entry from the DenseMap.
|
||||||
|
void DebugRecVH::deleted() {
|
||||||
|
// If this is a non-canonical reference, just drop the value to null, we know
|
||||||
|
// it doesn't have a map entry.
|
||||||
|
if (Idx == 0) {
|
||||||
|
setValPtr(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MDNode *Cur = get();
|
||||||
|
|
||||||
|
// If the index is positive, it is an entry in ScopeRecords.
|
||||||
|
if (Idx > 0) {
|
||||||
|
assert(Ctx->ScopeRecordIdx[Cur] == Idx && "Mapping out of date!");
|
||||||
|
Ctx->ScopeRecordIdx.erase(Cur);
|
||||||
|
// Reset this VH to null and we're done.
|
||||||
|
setValPtr(0);
|
||||||
|
Idx = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
|
||||||
|
// is the scope or the inlined-at record entry.
|
||||||
|
assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
|
||||||
|
std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
|
||||||
|
assert((this == &Entry.first || this == &Entry.second) &&
|
||||||
|
"Mapping out of date!");
|
||||||
|
|
||||||
|
MDNode *OldScope = Entry.first.get();
|
||||||
|
MDNode *OldInlinedAt = Entry.second.get();
|
||||||
|
assert(OldScope != 0 && OldInlinedAt != 0 &&
|
||||||
|
"Entry should be non-canonical if either val dropped to null");
|
||||||
|
|
||||||
|
// Otherwise, we do have an entry in it, nuke it and we're done.
|
||||||
|
assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
|
||||||
|
"Mapping out of date");
|
||||||
|
Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));
|
||||||
|
|
||||||
|
// Reset this VH to null.
|
||||||
|
setValPtr(0);
|
||||||
|
Idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugRecVH::allUsesReplacedWith(Value *NewVa) {
|
||||||
|
// If being replaced with a non-mdnode value (e.g. undef) handle this as if
|
||||||
|
// the mdnode got deleted.
|
||||||
|
MDNode *NewVal = dyn_cast<MDNode>(NewVa);
|
||||||
|
if (NewVal == 0) return deleted();
|
||||||
|
|
||||||
|
// If this is a non-canonical reference, just change it, we know it already
|
||||||
|
// doesn't have a map entry.
|
||||||
|
if (Idx == 0) {
|
||||||
|
setValPtr(NewVa);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MDNode *OldVal = get();
|
||||||
|
assert(OldVal != NewVa && "Node replaced with self?");
|
||||||
|
|
||||||
|
// If the index is positive, it is an entry in ScopeRecords.
|
||||||
|
if (Idx > 0) {
|
||||||
|
assert(Ctx->ScopeRecordIdx[OldVal] == Idx && "Mapping out of date!");
|
||||||
|
Ctx->ScopeRecordIdx.erase(OldVal);
|
||||||
|
setValPtr(NewVal);
|
||||||
|
|
||||||
|
int NewEntry = Ctx->getOrAddScopeRecordIdxEntry(NewVal, Idx);
|
||||||
|
|
||||||
|
// If NewVal already has an entry, this becomes a non-canonical reference,
|
||||||
|
// just drop Idx to 0 to signify this.
|
||||||
|
if (NewEntry != Idx)
|
||||||
|
Idx = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
|
||||||
|
// is the scope or the inlined-at record entry.
|
||||||
|
assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
|
||||||
|
std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
|
||||||
|
assert((this == &Entry.first || this == &Entry.second) &&
|
||||||
|
"Mapping out of date!");
|
||||||
|
|
||||||
|
MDNode *OldScope = Entry.first.get();
|
||||||
|
MDNode *OldInlinedAt = Entry.second.get();
|
||||||
|
assert(OldScope != 0 && OldInlinedAt != 0 &&
|
||||||
|
"Entry should be non-canonical if either val dropped to null");
|
||||||
|
|
||||||
|
// Otherwise, we do have an entry in it, nuke it and we're done.
|
||||||
|
assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
|
||||||
|
"Mapping out of date");
|
||||||
|
Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));
|
||||||
|
|
||||||
|
// Reset this VH to the new value.
|
||||||
|
setValPtr(NewVal);
|
||||||
|
|
||||||
|
int NewIdx = Ctx->getOrAddScopeInlinedAtIdxEntry(Entry.first.get(),
|
||||||
|
Entry.second.get(), Idx);
|
||||||
|
// If NewVal already has an entry, this becomes a non-canonical reference,
|
||||||
|
// just drop Idx to 0 to signify this.
|
||||||
|
if (NewIdx != Idx)
|
||||||
|
Idx = 0;
|
||||||
|
}
|
@ -90,6 +90,29 @@ struct DenseMapAPFloatKeyInfo {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// DebugRecVH - This is a CallbackVH used to keep the Scope -> index maps
|
||||||
|
/// up to date as MDNodes mutate. This class is implemented in DebugLoc.cpp.
|
||||||
|
class DebugRecVH : public CallbackVH {
|
||||||
|
/// Ctx - This is the LLVM Context being referenced.
|
||||||
|
LLVMContextImpl *Ctx;
|
||||||
|
|
||||||
|
/// Idx - The index into either ScopeRecordIdx or ScopeInlinedAtRecords that
|
||||||
|
/// this reference lives in. If this is zero, then it represents a
|
||||||
|
/// non-canonical entry that has no DenseMap value. This can happen due to
|
||||||
|
/// RAUW.
|
||||||
|
int Idx;
|
||||||
|
public:
|
||||||
|
DebugRecVH(MDNode *n, LLVMContextImpl *ctx, int idx)
|
||||||
|
: CallbackVH(n), Ctx(ctx), Idx(idx) {}
|
||||||
|
|
||||||
|
MDNode *get() const {
|
||||||
|
return cast_or_null<MDNode>(getValPtr());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void deleted();
|
||||||
|
virtual void allUsesReplacedWith(Value *VNew);
|
||||||
|
};
|
||||||
|
|
||||||
class LLVMContextImpl {
|
class LLVMContextImpl {
|
||||||
public:
|
public:
|
||||||
typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*,
|
typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*,
|
||||||
@ -128,7 +151,6 @@ public:
|
|||||||
VectorConstantsTy VectorConstants;
|
VectorConstantsTy VectorConstants;
|
||||||
|
|
||||||
ConstantUniqueMap<char, PointerType, ConstantPointerNull> NullPtrConstants;
|
ConstantUniqueMap<char, PointerType, ConstantPointerNull> NullPtrConstants;
|
||||||
|
|
||||||
ConstantUniqueMap<char, Type, UndefValue> UndefValueConstants;
|
ConstantUniqueMap<char, Type, UndefValue> UndefValueConstants;
|
||||||
|
|
||||||
DenseMap<std::pair<Function*, BasicBlock*> , BlockAddress*> BlockAddresses;
|
DenseMap<std::pair<Function*, BasicBlock*> , BlockAddress*> BlockAddresses;
|
||||||
@ -195,6 +217,27 @@ public:
|
|||||||
/// context.
|
/// context.
|
||||||
DenseMap<const Instruction *, MDMapTy> MetadataStore;
|
DenseMap<const Instruction *, MDMapTy> MetadataStore;
|
||||||
|
|
||||||
|
/// ScopeRecordIdx - This is the index in ScopeRecords for an MDNode scope
|
||||||
|
/// entry with no "inlined at" element.
|
||||||
|
DenseMap<MDNode*, int> ScopeRecordIdx;
|
||||||
|
|
||||||
|
/// ScopeRecords - These are the actual mdnodes (in a value handle) for an
|
||||||
|
/// index. The ValueHandle ensures that ScopeRecordIdx stays up to date if
|
||||||
|
/// the MDNode is RAUW'd.
|
||||||
|
std::vector<DebugRecVH> ScopeRecords;
|
||||||
|
|
||||||
|
/// ScopeInlinedAtIdx - This is the index in ScopeInlinedAtRecords for an
|
||||||
|
/// scope/inlined-at pair.
|
||||||
|
DenseMap<std::pair<MDNode*, MDNode*>, int> ScopeInlinedAtIdx;
|
||||||
|
|
||||||
|
/// ScopeInlinedAtRecords - These are the actual mdnodes (in value handles)
|
||||||
|
/// for an index. The ValueHandle ensures that ScopeINlinedAtIdx stays up
|
||||||
|
/// to date.
|
||||||
|
std::vector<std::pair<DebugRecVH, DebugRecVH> > ScopeInlinedAtRecords;
|
||||||
|
|
||||||
|
int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
|
||||||
|
int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
|
||||||
|
|
||||||
LLVMContextImpl(LLVMContext &C);
|
LLVMContextImpl(LLVMContext &C);
|
||||||
~LLVMContextImpl();
|
~LLVMContextImpl();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user