forked from OSchip/llvm-project
Support stripping indirectly referenced DILocations from !llvm.loop metadata
in stripDebugInfo(). This patch fixes an oversight in https://reviews.llvm.org/D96181 and also takes into account loop metadata pointing to other MDNodes that point into the debug info. rdar://78487175 Differential Revision: https://reviews.llvm.org/D103220
This commit is contained in:
parent
50f17e9d31
commit
f3869a5c32
|
@ -70,11 +70,11 @@ bool stripDebugInfo(Function &F);
|
|||
bool stripNonLineTableDebugInfo(Module &M);
|
||||
|
||||
/// Update the debug locations contained within the MD_loop metadata attached
|
||||
/// to the instruction \p I, if one exists. \p Updater is applied to each debug
|
||||
/// location in the MD_loop metadata: the returned value is included in the
|
||||
/// to the instruction \p I, if one exists. \p Updater is applied to Metadata
|
||||
/// operand in the MD_loop metadata: the returned value is included in the
|
||||
/// updated loop metadata node if it is non-null.
|
||||
void updateLoopMetadataDebugLocations(
|
||||
Instruction &I, function_ref<DILocation *(const DILocation &)> Updater);
|
||||
Instruction &I, function_ref<Metadata *(Metadata *)> Updater);
|
||||
|
||||
/// Return Debug Info Metadata Version by checking module flags.
|
||||
unsigned getDebugMetadataVersionFromModule(const Module &M);
|
||||
|
|
|
@ -348,8 +348,7 @@ bool DebugInfoFinder::addScope(DIScope *Scope) {
|
|||
}
|
||||
|
||||
static MDNode *updateLoopMetadataDebugLocationsImpl(
|
||||
MDNode *OrigLoopID,
|
||||
function_ref<DILocation *(const DILocation &)> Updater) {
|
||||
MDNode *OrigLoopID, function_ref<Metadata *(Metadata *)> Updater) {
|
||||
assert(OrigLoopID && OrigLoopID->getNumOperands() > 0 &&
|
||||
"Loop ID needs at least one operand");
|
||||
assert(OrigLoopID && OrigLoopID->getOperand(0).get() == OrigLoopID &&
|
||||
|
@ -360,11 +359,10 @@ static MDNode *updateLoopMetadataDebugLocationsImpl(
|
|||
|
||||
for (unsigned i = 1; i < OrigLoopID->getNumOperands(); ++i) {
|
||||
Metadata *MD = OrigLoopID->getOperand(i);
|
||||
if (DILocation *DL = dyn_cast<DILocation>(MD)) {
|
||||
if (DILocation *NewDL = Updater(*DL))
|
||||
MDs.push_back(NewDL);
|
||||
} else
|
||||
MDs.push_back(MD);
|
||||
if (!MD)
|
||||
MDs.push_back(nullptr);
|
||||
else if (Metadata *NewMD = Updater(MD))
|
||||
MDs.push_back(NewMD);
|
||||
}
|
||||
|
||||
MDNode *NewLoopID = MDNode::getDistinct(OrigLoopID->getContext(), MDs);
|
||||
|
@ -374,7 +372,7 @@ static MDNode *updateLoopMetadataDebugLocationsImpl(
|
|||
}
|
||||
|
||||
void llvm::updateLoopMetadataDebugLocations(
|
||||
Instruction &I, function_ref<DILocation *(const DILocation &)> Updater) {
|
||||
Instruction &I, function_ref<Metadata *(Metadata *)> Updater) {
|
||||
MDNode *OrigLoopID = I.getMetadata(LLVMContext::MD_loop);
|
||||
if (!OrigLoopID)
|
||||
return;
|
||||
|
@ -382,26 +380,64 @@ void llvm::updateLoopMetadataDebugLocations(
|
|||
I.setMetadata(LLVMContext::MD_loop, NewLoopID);
|
||||
}
|
||||
|
||||
/// Return true if a node is a DILocation or if a DILocation is
|
||||
/// indirectly referenced by one of the node's children.
|
||||
static bool isDILocationReachable(SmallPtrSetImpl<Metadata *> &Visited,
|
||||
SmallPtrSetImpl<Metadata *> &Reachable,
|
||||
Metadata *MD) {
|
||||
MDNode *N = dyn_cast_or_null<MDNode>(MD);
|
||||
if (!N)
|
||||
return false;
|
||||
if (Reachable.count(N) || isa<DILocation>(N))
|
||||
return true;
|
||||
if (!Visited.insert(N).second)
|
||||
return false;
|
||||
for (auto &OpIt : N->operands()) {
|
||||
Metadata *Op = OpIt.get();
|
||||
if (isDILocationReachable(Visited, Reachable, Op)) {
|
||||
Reachable.insert(N);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static MDNode *stripDebugLocFromLoopID(MDNode *N) {
|
||||
assert(!N->operands().empty() && "Missing self reference?");
|
||||
SmallPtrSet<Metadata *, 8> Visited, DILocationReachable;
|
||||
// If we already visited N, there is nothing to do.
|
||||
if (!Visited.insert(N).second)
|
||||
return N;
|
||||
|
||||
// if there is no debug location, we do not have to rewrite this MDNode.
|
||||
if (std::none_of(N->op_begin() + 1, N->op_end(), [](const MDOperand &Op) {
|
||||
return isa<DILocation>(Op.get());
|
||||
}))
|
||||
// If there is no debug location, we do not have to rewrite this
|
||||
// MDNode. This loop also initializes DILocationReachable, later
|
||||
// needed by updateLoopMetadataDebugLocationsImpl; the use of
|
||||
// count_if avoids an early exit.
|
||||
if (!std::count_if(N->op_begin() + 1, N->op_end(),
|
||||
[&Visited, &DILocationReachable](const MDOperand &Op) {
|
||||
return isa<DILocation>(Op.get()) ||
|
||||
isDILocationReachable(
|
||||
Visited, DILocationReachable, Op.get());
|
||||
}))
|
||||
return N;
|
||||
|
||||
// If there is only the debug location without any actual loop metadata, we
|
||||
// can remove the metadata.
|
||||
if (std::none_of(N->op_begin() + 1, N->op_end(), [](const MDOperand &Op) {
|
||||
return !isa<DILocation>(Op.get());
|
||||
}))
|
||||
if (std::all_of(
|
||||
N->op_begin() + 1, N->op_end(),
|
||||
[&Visited, &DILocationReachable](const MDOperand &Op) {
|
||||
return isa<DILocation>(Op.get()) ||
|
||||
isDILocationReachable(Visited, DILocationReachable,
|
||||
Op.get());
|
||||
}))
|
||||
return nullptr;
|
||||
|
||||
auto dropDebugLoc = [](const DILocation &) -> DILocation * {
|
||||
return nullptr;
|
||||
};
|
||||
return updateLoopMetadataDebugLocationsImpl(N, dropDebugLoc);
|
||||
return updateLoopMetadataDebugLocationsImpl(
|
||||
N, [&DILocationReachable](Metadata *MD) -> Metadata * {
|
||||
if (isa<DILocation>(MD) || DILocationReachable.count(MD))
|
||||
return nullptr;
|
||||
return MD;
|
||||
});
|
||||
}
|
||||
|
||||
bool llvm::stripDebugInfo(Function &F) {
|
||||
|
@ -411,7 +447,7 @@ bool llvm::stripDebugInfo(Function &F) {
|
|||
F.setSubprogram(nullptr);
|
||||
}
|
||||
|
||||
DenseMap<MDNode*, MDNode*> LoopIDsMap;
|
||||
DenseMap<MDNode *, MDNode *> LoopIDsMap;
|
||||
for (BasicBlock &BB : F) {
|
||||
for (auto II = BB.begin(), End = BB.end(); II != End;) {
|
||||
Instruction &I = *II++; // We may delete the instruction, increment now.
|
||||
|
@ -740,8 +776,10 @@ bool llvm::stripNonLineTableDebugInfo(Module &M) {
|
|||
I.setDebugLoc(remapDebugLoc(I.getDebugLoc()));
|
||||
|
||||
// Remap DILocations in llvm.loop attachments.
|
||||
updateLoopMetadataDebugLocations(I, [&](const DILocation &Loc) {
|
||||
return remapDebugLoc(&Loc).get();
|
||||
updateLoopMetadataDebugLocations(I, [&](Metadata *MD) -> Metadata * {
|
||||
if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
|
||||
return remapDebugLoc(Loc).get();
|
||||
return MD;
|
||||
});
|
||||
|
||||
// Strip heapallocsite attachments, they point into the DIType system.
|
||||
|
|
|
@ -1552,10 +1552,11 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
|
|||
I.setDebugLoc(DILocation::get(Ctx, DL.getLine(), DL.getCol(), NewSP));
|
||||
|
||||
// Loop info metadata may contain line locations. Fix them up.
|
||||
auto updateLoopInfoLoc = [&Ctx,
|
||||
NewSP](const DILocation &Loc) -> DILocation * {
|
||||
return DILocation::get(Ctx, Loc.getLine(), Loc.getColumn(), NewSP,
|
||||
nullptr);
|
||||
auto updateLoopInfoLoc = [&Ctx, NewSP](Metadata *MD) -> Metadata * {
|
||||
if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
|
||||
return DILocation::get(Ctx, Loc->getLine(), Loc->getColumn(), NewSP,
|
||||
nullptr);
|
||||
return MD;
|
||||
};
|
||||
updateLoopMetadataDebugLocations(I, updateLoopInfoLoc);
|
||||
}
|
||||
|
|
|
@ -1519,9 +1519,11 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
|
|||
BI != BE; ++BI) {
|
||||
// Loop metadata needs to be updated so that the start and end locs
|
||||
// reference inlined-at locations.
|
||||
auto updateLoopInfoLoc = [&Ctx, &InlinedAtNode, &IANodes](
|
||||
const DILocation &Loc) -> DILocation * {
|
||||
return inlineDebugLoc(&Loc, InlinedAtNode, Ctx, IANodes).get();
|
||||
auto updateLoopInfoLoc = [&Ctx, &InlinedAtNode,
|
||||
&IANodes](Metadata *MD) -> Metadata * {
|
||||
if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
|
||||
return inlineDebugLoc(Loc, InlinedAtNode, Ctx, IANodes).get();
|
||||
return MD;
|
||||
};
|
||||
updateLoopMetadataDebugLocations(*BI, updateLoopInfoLoc);
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
; RUN: llvm-as -disable-output < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
; RUN: llvm-as < %s -o - | llvm-dis - | FileCheck %s --check-prefix=CHECK-STRIP
|
||||
; CHECK: DICompileUnit not listed in llvm.dbg.cu
|
||||
; CHECK: ignoring invalid debug info in
|
||||
; CHECK-NOT: DICompileUnit not listed in llvm.dbg.cu
|
||||
declare hidden void @g() local_unnamed_addr #1 align 2
|
||||
define hidden void @f() {
|
||||
tail call void @g() #2, !llvm.loop !5
|
||||
ret void
|
||||
}
|
||||
!llvm.module.flags = !{!0, !1}
|
||||
!0 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!1 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = distinct !{!5, !14, !15, !"fake loop metadata"}
|
||||
; CHECK-STRIP: ![[MD:.*]] = distinct !{![[MD]], !{{[0-9]+}}, !"fake loop metadata"}
|
||||
!7 = distinct !DISubprogram(name: "f", scope: !8, file: !8, line: 1324, type: !9, scopeLine: 1324, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11)
|
||||
!8 = !DIFile(filename: "/", directory: "f.cpp")
|
||||
!9 = !DISubroutineType(types: !10)
|
||||
!10 = !{}
|
||||
!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !8)
|
||||
!14 = !{!"metadata 1", i1 true}
|
||||
!15 = !{!"metadata 1", !16}
|
||||
!16 = distinct !{!16, !17}
|
||||
!17 = !DILocation(line: 105, column: 3, scope: !18)
|
||||
!18 = distinct !DILexicalBlock(scope: !7, file: !8, line: 105, column: 3)
|
Loading…
Reference in New Issue