Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -15,6 +15,7 @@ #ifndef LLVM_CODEGEN_ASMPRINTER_H #define LLVM_CODEGEN_ASMPRINTER_H +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -126,6 +127,13 @@ /// 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; + }; + IndexedMap MBBSectionRanges; + /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of /// its number of uses by other globals. using GOTEquivUsePair = std::pair; Index: llvm/include/llvm/CodeGen/AsmPrinterHandler.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinterHandler.h +++ 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 Index: llvm/include/llvm/CodeGen/DebugHandlerBase.h =================================================================== --- llvm/include/llvm/CodeGen/DebugHandlerBase.h +++ 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); Index: llvm/include/llvm/CodeGen/MachineBasicBlock.h =================================================================== --- llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -69,6 +69,16 @@ bool operator!=(const MBBSectionID &Other) const { return !(*this == Other); } + // This returns a unique index for the section in the range [0, max(Number)+3] + struct ToIndexFunctor { + using argument_type = MBBSectionID; + unsigned operator()(MBBSectionID SectionID) const { + return ((unsigned)MBBSectionID::SectionType::Cold) - + ((unsigned)SectionID.Type) + SectionID.Number; + } + static unsigned indexSize(unsigned NumBlockIDs) { return NumBlockIDs + 3; } + }; + private: // This is only used to construct the special cold and exception sections. MBBSectionID(SectionType T) : Type(T), Number(0) {} Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1227,6 +1227,8 @@ if (!MBB.sameSection(&MF->front())) { if (MAI->hasDotTypeDotSizeDirective()) emitELFSizeDirective(CurrentSectionBeginSym); + MBBSectionRanges[MBB.getSectionID()] = + MBBSectionRange{CurrentSectionBeginSym, CurrentBBEnd}; } } emitBasicBlockEnd(MBB); @@ -1303,6 +1305,8 @@ HI.Handler->markFunctionEnd(); } + MBBSectionRanges[MF->front().getSectionID()] = + MBBSectionRange{CurrentFnBegin, CurrentFnEnd}; // Print out jump tables referenced by the function. emitJumpTableInfo(); @@ -1796,6 +1800,9 @@ CurrentFnSymForSize = CurrentFnSym; CurrentFnBegin = nullptr; CurrentSectionBeginSym = nullptr; + MBBSectionRanges.clear(); + MBBSectionRanges.resize( + MBBSectionID::ToIndexFunctor::indexSize(MF.getNumBlockIDs())); CurExceptionSym = nullptr; bool NeedsLocalForSize = MAI->needsLocalForSize(); if (F.hasFnAttribute("patchable-function-entry") || Index: llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -212,10 +212,15 @@ // doing that violates the ranges that are calculated in the history map. // However, we currently do not emit debug values for constant arguments // directly at the start of the function, so this code is still useful. + // + // If the first mention of an argument is in a unique-section basic block, + // we cannot assign the CurrentFnBegin label, as it lies in a different + // section. For simplicity, we simply ignore such mentions in this code. const DILocalVariable *DIVar = Entries.front().getInstr()->getDebugVariable(); if (DIVar->isParameter() && - getDISubprogram(DIVar->getScope())->describes(&MF->getFunction())) { + getDISubprogram(DIVar->getScope())->describes(&MF->getFunction()) && + Entries.front().getInstr()->getParent()->sameSection(&MF->front())) { if (!IsDescribedByReg(Entries.front().getInstr())) LabelsBeforeInsn[Entries.front().getInstr()] = Asm->getFunctionBegin(); if (Entries.front().getInstr()->getDebugExpression()->isFragment()) { @@ -327,3 +332,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; +} Index: llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -396,7 +396,23 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); - attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd()); + if (!Asm->MF->hasBBSections()) + attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd()); + else { + SmallVector BB_List; + BB_List.push_back({Asm->getFunctionBegin(), Asm->getFunctionEnd()}); + // If basic block sections are on, the [getFunctionBegin(), + // getFunctionEnd()] range will include all BBs which are in the same + // section as the entry block. Ranges for the other BBs have to be emitted + // separately. + for (auto &MBB : *Asm->MF) { + if (&MBB != &Asm->MF->front() && MBB.isBeginSection()) + BB_List.push_back({MBB.getSymbol(), + Asm->MBBSectionRanges[MBB.getSectionID()].EndLabel}); + } + + attachRangesOrLowHighPC(*SPDie, BB_List); + } if (DD->useAppleExtensionAttributes() && !DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim( *DD->getCurrentFunction())) @@ -567,9 +583,31 @@ 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, High PC can be used. + do { + if (MBB->sameSection(EndMBB) || MBB->isEndSection()) { + auto MBBSectionRange = Asm->MBBSectionRanges[MBB->getSectionID()]; + 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)); } Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ 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.getSectionID()].EndLabel; if (EI->isClobber()) EndMI = EI->getInstr(); } @@ -2115,7 +2116,12 @@ 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 (auto &MBB : *MF) { + if (&MBB == &MF->front() || MBB.isBeginSection()) + TheCU.addRange({Asm->MBBSectionRanges[MBB.getSectionID()].BeginLabel, + Asm->MBBSectionRanges[MBB.getSectionID()].EndLabel}); + } // Under -gmlt, skip building the subprogram if there are no inlined // subroutines inside it. But with -fdebug-info-for-profiling, the subprogram Index: llvm/test/DebugInfo/X86/basicblock-sections_1.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/basicblock-sections_1.ll @@ -0,0 +1,93 @@ +; RUN: llc -O0 %s -mtriple=x86_64-* -filetype=obj -o %t && llvm-dwarfdump -debug-abbrev %t | FileCheck --check-prefix=NO-SECTIONS %s +; RUN: llc -O0 %s --basicblock-sections=all -mtriple=x86_64-* -filetype=asm -o - | FileCheck --check-prefix=BB-SECTIONS-ASM %s +; RUN: llc -O0 %s --basicblock-sections=all -mtriple=x86_64-* -filetype=obj -o %t && llvm-dwarfdump -debug-abbrev %t | FileCheck --check-prefix=BB-SECTIONS %s +; RUN: llc -O0 %s --basicblock-sections=all -mtriple=x86_64-* -filetype=obj -split-dwarf-file=%t.dwo -o %t && llvm-dwarfdump -debug-abbrev %t | FileCheck --check-prefix=BB-SECTIONS %s + +; From: +; int foo(int a) { +; if (a > 20) +; return 2; +; else +; return 0; +; } + +; NO-SECTIONS: DW_AT_low_pc DW_FORM_addr +; NO-SECTIONS: DW_AT_high_pc DW_FORM_data4 +; BB-SECTIONS-ASM: _Z3fooi: +; BB-SECTIONS-ASM: .Ltmp0: +; BB-SECTIONS-ASM-NEXT: .loc 1 2 9 prologue_end +; BB-SECTIONS-ASM: .Ltmp1: +; BB-SECTIONS-ASM-NEXT: .loc 1 2 7 is_stmt +; BB-SECTIONS-ASM: _Z3fooi.1: +; BB-SECTIONS-ASM: .Ltmp2: +; BB-SECTIONS-ASM-NEXT: .size _Z3fooi.1, .Ltmp2-_Z3fooi.1 +; BB-SECTIONS-ASM: _Z3fooi.2: +; BB-SECTIONS-ASM: .Ltmp3: +; BB-SECTIONS-ASM-NEXT: .Ltmp4: +; BB-SECTIONS-ASM-NEXT: .size _Z3fooi.2, .Ltmp4-_Z3fooi.2 +; BB-SECTIONS-ASM: _Z3fooi.3: +; BB-SECTIONS-ASM: .Ltmp5: +; BB-SECTIONS-ASM-NEXT: .Ltmp6: +; BB-SECTIONS-ASM-NEXT: .size _Z3fooi.3, .Ltmp6-_Z3fooi.3 +; BB-SECTIONS-ASM: .Lfunc_end0: +; BB-SECTIONS-ASM: .Ldebug_ranges0: +; BB-SECTIONS-ASM-NEXT: .quad .Lfunc_begin0 +; BB-SECTIONS-ASM-NEXT: .quad .Lfunc_end0 +; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.1 +; BB-SECTIONS-ASM-NEXT: .quad .Ltmp2 +; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.2 +; BB-SECTIONS-ASM-NEXT: .quad .Ltmp4 +; BB-SECTIONS-ASM-NEXT: .quad _Z3fooi.3 +; BB-SECTIONS-ASM-NEXT: .quad .Ltmp6 +; BB-SECTIONS-ASM-NEXT: .quad 0 +; BB-SECTIONS-ASM-NEXT: .quad 0 +; BB-SECTIONS: DW_AT_low_pc DW_FORM_addr +; BB-SECTIONS: DW_AT_ranges DW_FORM_sec_offset + +; 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)