mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-24 08:24:33 +00:00
Debug info: Teach SROA how to update debug info for fragmented variables.
This allows us to generate debug info for extremely advanced code such as typedef struct { long int a; int b;} S; int foo(S s) { return s.b; } which at -O1 on x86_64 is codegen'd into define i32 @foo(i64 %s.coerce0, i32 %s.coerce1) #0 { ret i32 %s.coerce1, !dbg !24 } with this patch we emit the following debug info for this TAG_formal_parameter [3] AT_location( 0x00000000 0x0000000000000000 - 0x0000000000000006: rdi, piece 0x00000008, rsi, piece 0x00000004 0x0000000000000006 - 0x0000000000000008: rdi, piece 0x00000008, rax, piece 0x00000004 ) AT_name( "s" ) AT_decl_file( "/Volumes/Data/llvm/_build.ninja.release/test.c" ) Thanks to chandlerc, dblaikie, and echristo for their feedback on all previous iterations of this patch! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224739 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -953,6 +953,10 @@ class SROA : public FunctionPass {
|
||||
/// currently in the promotable queue.
|
||||
SetVector<SelectInst *, SmallVector<SelectInst *, 2>> SpeculatableSelects;
|
||||
|
||||
/// Debug intrinsics do not show up as regular uses in the
|
||||
/// IR. This side-table holds the missing use edges.
|
||||
DenseMap<AllocaInst *, DbgDeclareInst *> DbgDeclares;
|
||||
|
||||
public:
|
||||
SROA(bool RequiresDomTree = true)
|
||||
: FunctionPass(ID), RequiresDomTree(RequiresDomTree), C(nullptr),
|
||||
@ -3230,6 +3234,27 @@ bool SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS,
|
||||
new AllocaInst(SliceTy, nullptr, Alignment,
|
||||
AI.getName() + ".sroa." + Twine(B - AS.begin()), &AI);
|
||||
++NumNewAllocas;
|
||||
|
||||
// Migrate debug information from the old alloca to the new alloca
|
||||
// and the individial slices.
|
||||
if (DbgDeclareInst *DbgDecl = DbgDeclares.lookup(&AI)) {
|
||||
DIVariable Var(DbgDecl->getVariable());
|
||||
DIExpression Piece;
|
||||
DIBuilder DIB(*AI.getParent()->getParent()->getParent(),
|
||||
/*AllowUnresolved*/ false);
|
||||
// Create a piece expression describing the slice, if the new slize is
|
||||
// smaller than the old alloca or the old alloca already was described
|
||||
// with a piece. It would be even better to just compare against the size
|
||||
// of the type described in the debug info, but then we would need to
|
||||
// build an expensive DIRefMap.
|
||||
if (SliceSize < DL->getTypeAllocSize(AI.getAllocatedType()) ||
|
||||
DIExpression(DbgDecl->getExpression()).isVariablePiece())
|
||||
Piece = DIB.createPieceExpression(BeginOffset, SliceSize);
|
||||
Instruction *NewDDI = DIB.insertDeclare(NewAI, Var, Piece, &AI);
|
||||
NewDDI->setDebugLoc(DbgDecl->getDebugLoc());
|
||||
DbgDeclares.insert(std::make_pair(NewAI, cast<DbgDeclareInst>(NewDDI)));
|
||||
DeadInsts.insert(DbgDecl);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "Rewriting alloca partition "
|
||||
@ -3680,9 +3705,13 @@ bool SROA::runOnFunction(Function &F) {
|
||||
|
||||
BasicBlock &EntryBB = F.getEntryBlock();
|
||||
for (BasicBlock::iterator I = EntryBB.begin(), E = std::prev(EntryBB.end());
|
||||
I != E; ++I)
|
||||
I != E; ++I) {
|
||||
if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
|
||||
Worklist.insert(AI);
|
||||
else if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I))
|
||||
if (auto AI = dyn_cast_or_null<AllocaInst>(DDI->getAddress()))
|
||||
DbgDeclares.insert(std::make_pair(AI, DDI));
|
||||
}
|
||||
|
||||
bool Changed = false;
|
||||
// A set of deleted alloca instruction pointers which should be removed from
|
||||
|
Reference in New Issue
Block a user