diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -126,6 +126,14 @@ /// 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 MBBSectionRanges; + /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of /// its number of uses by other globals. using GOTEquivUsePair = std::pair; diff --git a/llvm/include/llvm/CodeGen/AsmPrinterHandler.h b/llvm/include/llvm/CodeGen/AsmPrinterHandler.h --- a/llvm/include/llvm/CodeGen/AsmPrinterHandler.h +++ b/llvm/include/llvm/CodeGen/AsmPrinterHandler.h @@ -67,6 +67,12 @@ /// 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 diff --git a/llvm/include/llvm/CodeGen/DebugHandlerBase.h b/llvm/include/llvm/CodeGen/DebugHandlerBase.h --- a/llvm/include/llvm/CodeGen/DebugHandlerBase.h +++ b/llvm/include/llvm/CodeGen/DebugHandlerBase.h @@ -118,6 +118,9 @@ 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); diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h --- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -465,6 +465,12 @@ /// 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; } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1207,6 +1207,8 @@ if (!MBB.sameSection(&MF->front())) { if (MAI->hasDotTypeDotSizeDirective()) emitELFSizeDirective(CurrentSectionBeginSym); + MBBSectionRanges[MBB.getSectionIDNum()] = + MBBSectionRange{CurrentSectionBeginSym, CurrentBBEnd}; } } emitBasicBlockEnd(MBB); @@ -1283,6 +1285,8 @@ HI.Handler->markFunctionEnd(); } + MBBSectionRanges[MF->front().getSectionIDNum()] = + MBBSectionRange{CurrentFnBegin, CurrentFnEnd}; // Print out jump tables referenced by the function. emitJumpTableInfo(); @@ -1782,6 +1786,7 @@ CurrentFnSymForSize = CurrentFnSym; CurrentFnBegin = nullptr; CurrentSectionBeginSym = nullptr; + MBBSectionRanges.clear(); CurExceptionSym = nullptr; bool NeedsLocalForSize = MAI->needsLocalForSize(); if (F.hasFnAttribute("patchable-function-entry") || diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -327,3 +327,17 @@ 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; +} diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -396,7 +396,14 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); - attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd()); + SmallVector 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 @@ DIE &Die, const SmallVectorImpl &Ranges) { SmallVector 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)); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1664,7 +1664,8 @@ 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 @@ 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 diff --git a/llvm/test/DebugInfo/X86/basicblock-sections_1.ll b/llvm/test/DebugInfo/X86/basicblock-sections_1.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/basicblock-sections_1.ll @@ -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)