forked from OSchip/llvm-project
This patch adds basic debug info support with basic block sections.
This patch uses ranges for debug information when a function contains basic block sections rather than using [lowpc, highpc]. This is also the first in a series of patches for debug info and does not contain the support for linker relaxation. That will be done as a follow up patch. Differential Revision: https://reviews.llvm.org/D78851
This commit is contained in:
parent
fdbd78333f
commit
e4b3c138de
|
@ -126,6 +126,14 @@ public:
|
|||
/// default, this is equal to CurrentFnSym.
|
||||
MCSymbol *CurrentFnSymForSize = nullptr;
|
||||
|
||||
/// Map a basic block section ID to the begin and end symbols of that section
|
||||
/// which determine the section's range.
|
||||
struct MBBSectionRange {
|
||||
MCSymbol *BeginLabel, *EndLabel;
|
||||
};
|
||||
|
||||
MapVector<unsigned, MBBSectionRange> MBBSectionRanges;
|
||||
|
||||
/// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of
|
||||
/// its number of uses by other globals.
|
||||
using GOTEquivUsePair = std::pair<const GlobalVariable *, unsigned>;
|
||||
|
|
|
@ -67,6 +67,12 @@ public:
|
|||
|
||||
/// Process end of an instruction.
|
||||
virtual void endInstruction() = 0;
|
||||
|
||||
/// Process beginning of a basic block during basic block sections.
|
||||
virtual void beginBasicBlock(const MachineBasicBlock &MBB) {}
|
||||
|
||||
/// Process end of a basic block during basic block sections.
|
||||
virtual void endBasicBlock(const MachineBasicBlock &MBB) {}
|
||||
};
|
||||
} // End of namespace llvm
|
||||
|
||||
|
|
|
@ -118,6 +118,9 @@ public:
|
|||
void beginFunction(const MachineFunction *MF) override;
|
||||
void endFunction(const MachineFunction *MF) override;
|
||||
|
||||
void beginBasicBlock(const MachineBasicBlock &MBB) override;
|
||||
void endBasicBlock(const MachineBasicBlock &MBB) override;
|
||||
|
||||
/// Return Label preceding the instruction.
|
||||
MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
|
||||
|
||||
|
|
|
@ -465,6 +465,12 @@ public:
|
|||
/// Returns the section ID of this basic block.
|
||||
MBBSectionID getSectionID() const { return SectionID; }
|
||||
|
||||
/// Returns the unique section ID number of this basic block.
|
||||
unsigned getSectionIDNum() const {
|
||||
return ((unsigned)MBBSectionID::SectionType::Cold) -
|
||||
((unsigned)SectionID.Type) + SectionID.Number;
|
||||
}
|
||||
|
||||
/// Sets the section ID for this basic block.
|
||||
void setSectionID(MBBSectionID V) { SectionID = V; }
|
||||
|
||||
|
|
|
@ -1207,6 +1207,8 @@ void AsmPrinter::emitFunctionBody() {
|
|||
if (!MBB.sameSection(&MF->front())) {
|
||||
if (MAI->hasDotTypeDotSizeDirective())
|
||||
emitELFSizeDirective(CurrentSectionBeginSym);
|
||||
MBBSectionRanges[MBB.getSectionIDNum()] =
|
||||
MBBSectionRange{CurrentSectionBeginSym, CurrentBBEnd};
|
||||
}
|
||||
}
|
||||
emitBasicBlockEnd(MBB);
|
||||
|
@ -1283,6 +1285,8 @@ void AsmPrinter::emitFunctionBody() {
|
|||
HI.Handler->markFunctionEnd();
|
||||
}
|
||||
|
||||
MBBSectionRanges[MF->front().getSectionIDNum()] =
|
||||
MBBSectionRange{CurrentFnBegin, CurrentFnEnd};
|
||||
|
||||
// Print out jump tables referenced by the function.
|
||||
emitJumpTableInfo();
|
||||
|
@ -1782,6 +1786,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
|
|||
CurrentFnSymForSize = CurrentFnSym;
|
||||
CurrentFnBegin = nullptr;
|
||||
CurrentSectionBeginSym = nullptr;
|
||||
MBBSectionRanges.clear();
|
||||
CurExceptionSym = nullptr;
|
||||
bool NeedsLocalForSize = MAI->needsLocalForSize();
|
||||
if (F.hasFnAttribute("patchable-function-entry") ||
|
||||
|
|
|
@ -327,3 +327,17 @@ void DebugHandlerBase::endFunction(const MachineFunction *MF) {
|
|||
LabelsBeforeInsn.clear();
|
||||
LabelsAfterInsn.clear();
|
||||
}
|
||||
|
||||
void DebugHandlerBase::beginBasicBlock(const MachineBasicBlock &MBB) {
|
||||
if (!MBB.isBeginSection())
|
||||
return;
|
||||
|
||||
PrevLabel = MBB.getSymbol();
|
||||
}
|
||||
|
||||
void DebugHandlerBase::endBasicBlock(const MachineBasicBlock &MBB) {
|
||||
if (!MBB.isEndSection())
|
||||
return;
|
||||
|
||||
PrevLabel = nullptr;
|
||||
}
|
||||
|
|
|
@ -396,7 +396,14 @@ void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin,
|
|||
DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
|
||||
DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes());
|
||||
|
||||
attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd());
|
||||
SmallVector<RangeSpan, 2> BB_List;
|
||||
// If basic block sections are on, ranges for each basic block section has
|
||||
// to be emitted separately.
|
||||
for (const auto &R : Asm->MBBSectionRanges)
|
||||
BB_List.push_back({R.second.BeginLabel, R.second.EndLabel});
|
||||
|
||||
attachRangesOrLowHighPC(*SPDie, BB_List);
|
||||
|
||||
if (DD->useAppleExtensionAttributes() &&
|
||||
!DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim(
|
||||
*DD->getCurrentFunction()))
|
||||
|
@ -570,9 +577,33 @@ void DwarfCompileUnit::attachRangesOrLowHighPC(
|
|||
DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) {
|
||||
SmallVector<RangeSpan, 2> List;
|
||||
List.reserve(Ranges.size());
|
||||
for (const InsnRange &R : Ranges)
|
||||
List.push_back(
|
||||
{DD->getLabelBeforeInsn(R.first), DD->getLabelAfterInsn(R.second)});
|
||||
for (const InsnRange &R : Ranges) {
|
||||
auto *BeginLabel = DD->getLabelBeforeInsn(R.first);
|
||||
auto *EndLabel = DD->getLabelAfterInsn(R.second);
|
||||
|
||||
const auto *BeginMBB = R.first->getParent();
|
||||
const auto *EndMBB = R.second->getParent();
|
||||
|
||||
const auto *MBB = BeginMBB;
|
||||
// Basic block sections allows basic block subsets to be placed in unique
|
||||
// sections. For each section, the begin and end label must be added to the
|
||||
// list. If there is more than one range, debug ranges must be used.
|
||||
// Otherwise, low/high PC can be used.
|
||||
// FIXME: Debug Info Emission depends on block order and this assumes that
|
||||
// the order of blocks will be frozen beyond this point.
|
||||
do {
|
||||
if (MBB->sameSection(EndMBB) || MBB->isEndSection()) {
|
||||
auto MBBSectionRange = Asm->MBBSectionRanges[MBB->getSectionIDNum()];
|
||||
List.push_back(
|
||||
{MBB->sameSection(BeginMBB) ? BeginLabel
|
||||
: MBBSectionRange.BeginLabel,
|
||||
MBB->sameSection(EndMBB) ? EndLabel : MBBSectionRange.EndLabel});
|
||||
}
|
||||
if (MBB->sameSection(EndMBB))
|
||||
break;
|
||||
MBB = MBB->getNextNode();
|
||||
} while (true);
|
||||
}
|
||||
attachRangesOrLowHighPC(Die, std::move(List));
|
||||
}
|
||||
|
||||
|
|
|
@ -1664,7 +1664,8 @@ bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
|
|||
|
||||
const MCSymbol *EndLabel;
|
||||
if (std::next(EI) == Entries.end()) {
|
||||
EndLabel = Asm->getFunctionEnd();
|
||||
const MachineBasicBlock &EndMBB = Asm->MF->back();
|
||||
EndLabel = Asm->MBBSectionRanges[EndMBB.getSectionIDNum()].EndLabel;
|
||||
if (EI->isClobber())
|
||||
EndMI = EI->getInstr();
|
||||
}
|
||||
|
@ -2115,7 +2116,9 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
|
|||
collectEntityInfo(TheCU, SP, Processed);
|
||||
|
||||
// Add the range of this function to the list of ranges for the CU.
|
||||
TheCU.addRange({Asm->getFunctionBegin(), Asm->getFunctionEnd()});
|
||||
// With basic block sections, add ranges for all basic block sections.
|
||||
for (const auto &R : Asm->MBBSectionRanges)
|
||||
TheCU.addRange({R.second.BeginLabel, R.second.EndLabel});
|
||||
|
||||
// Under -gmlt, skip building the subprogram if there are no inlined
|
||||
// subroutines inside it. But with -fdebug-info-for-profiling, the subprogram
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
; RUN: llc -O0 %s -mtriple=x86_64-* -filetype=obj -o %t && llvm-dwarfdump -debug-info -v %t | FileCheck --check-prefix=NO-SECTIONS %s
|
||||
; RUN: llc -O0 %s --basicblock-sections=all --unique-bb-section-names -mtriple=x86_64-* -filetype=obj -o %t && llvm-dwarfdump -debug-info -v %t | FileCheck --check-prefix=BB-SECTIONS %s
|
||||
; RUN: llc -O0 %s --basicblock-sections=all --unique-bb-section-names -mtriple=x86_64-* -filetype=obj -split-dwarf-file=%t.dwo -o %t && llvm-dwarfdump -debug-info -v %t | FileCheck --check-prefix=BB-SECTIONS %s
|
||||
; RUN: llc -O0 %s --basicblock-sections=all -mtriple=x86_64-* -filetype=asm -o - | FileCheck --check-prefix=BB-SECTIONS-ASM %s
|
||||
|
||||
; From:
|
||||
; int foo(int a) {
|
||||
; if (a > 20)
|
||||
; return 2;
|
||||
; else
|
||||
; return 0;
|
||||
; }
|
||||
|
||||
; NO-SECTIONS: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000 ".text")
|
||||
; NO-SECTIONS: DW_AT_high_pc [DW_FORM_data4] ({{.*}})
|
||||
; BB-SECTIONS: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
; BB-SECTIONS-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
; BB-SECTIONS-NEXT: [{{.*}}) ".text._Z3fooi.1"
|
||||
; BB-SECTIONS-NEXT: [{{.*}}) ".text._Z3fooi.2"
|
||||
; BB-SECTIONS-NEXT: [{{.*}}) ".text._Z3fooi.3"
|
||||
; BB-SECTIONS-NEXT: [{{.*}}) ".text"
|
||||
; BB-SECTIONS-ASM: _Z3fooi:
|
||||
; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
|
||||
; BB-SECTIONS-ASM-NEXT: .loc 1 2 9 prologue_end
|
||||
; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
|
||||
; BB-SECTIONS-ASM-NEXT: .loc 1 2 7 is_stmt
|
||||
; BB-SECTIONS-ASM: _Z3fooi.1:
|
||||
; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
|
||||
; BB-SECTIONS-ASM: .size _Z3fooi.1, .Ltmp{{[0-9]+}}-_Z3fooi.1
|
||||
; BB-SECTIONS-ASM: _Z3fooi.2:
|
||||
; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
|
||||
; BB-SECTIONS-ASM-NEXT: .Ltmp{{[0-9]+}}:
|
||||
; BB-SECTIONS-ASM: .size _Z3fooi.2, .Ltmp{{[0-9]+}}-_Z3fooi.2
|
||||
; BB-SECTIONS-ASM: _Z3fooi.3:
|
||||
; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
|
||||
; BB-SECTIONS-ASM-NEXT: .Ltmp{{[0-9]+}}:
|
||||
; BB-SECTIONS-ASM: .size _Z3fooi.3, .Ltmp{{[0-9]+}}-_Z3fooi.3
|
||||
; BB-SECTIONS-ASM: .Lfunc_end0:
|
||||
; BB-SECTIONS-ASM: .Ldebug_ranges0:
|
||||
; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.1
|
||||
; BB-SECTIONS-ASM-NEXT: .quad .Ltmp{{[0-9]+}}
|
||||
; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.2
|
||||
; BB-SECTIONS-ASM-NEXT: .quad .Ltmp{{[0-9]+}}
|
||||
; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.3
|
||||
; BB-SECTIONS-ASM-NEXT: .quad .Ltmp{{[0-9]+}}
|
||||
; BB-SECTIONS-ASM-NEXT: .quad .Lfunc_begin0
|
||||
; BB-SECTIONS-ASM-NEXT: .quad .Lfunc_end0
|
||||
; BB-SECTIONS-ASM-NEXT: .quad 0
|
||||
; BB-SECTIONS-ASM-NEXT: .quad 0
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local i32 @_Z3fooi(i32 %0) !dbg !7 {
|
||||
%2 = alloca i32, align 4
|
||||
%3 = alloca i32, align 4
|
||||
store i32 %0, i32* %3, align 4
|
||||
call void @llvm.dbg.declare(metadata i32* %3, metadata !11, metadata !DIExpression()), !dbg !12
|
||||
%4 = load i32, i32* %3, align 4, !dbg !13
|
||||
%5 = icmp sgt i32 %4, 20, !dbg !15
|
||||
br i1 %5, label %6, label %7, !dbg !16
|
||||
|
||||
6: ; preds = %1
|
||||
store i32 2, i32* %2, align 4, !dbg !17
|
||||
br label %8, !dbg !17
|
||||
|
||||
7: ; preds = %1
|
||||
store i32 0, i32* %2, align 4, !dbg !18
|
||||
br label %8, !dbg !18
|
||||
|
||||
8: ; preds = %7, %6
|
||||
%9 = load i32, i32* %2, align 4, !dbg !19
|
||||
ret i32 %9, !dbg !19
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone speculatable willreturn
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata)
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 10.0.0 (git@github.com:google/llvm-propeller.git f9421ebf4b3d8b64678bf6c49d1607fdce3f50c5)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "debuginfo.cc", directory: "/")
|
||||
!2 = !{}
|
||||
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!8 = !DISubroutineType(types: !9)
|
||||
!9 = !{!10, !10}
|
||||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!11 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 1, type: !10)
|
||||
!12 = !DILocation(line: 1, column: 13, scope: !7)
|
||||
!13 = !DILocation(line: 2, column: 7, scope: !14)
|
||||
!14 = distinct !DILexicalBlock(scope: !7, file: !1, line: 2, column: 7)
|
||||
!15 = !DILocation(line: 2, column: 9, scope: !14)
|
||||
!16 = !DILocation(line: 2, column: 7, scope: !7)
|
||||
!17 = !DILocation(line: 3, column: 5, scope: !14)
|
||||
!18 = !DILocation(line: 5, column: 5, scope: !14)
|
||||
!19 = !DILocation(line: 6, column: 1, scope: !7)
|
Loading…
Reference in New Issue