diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -174,6 +174,15 @@ MCSection *getSectionForJumpTable(const Function &F, const TargetMachine &TM) const override; + MCSection * + getSectionForMachineBasicBlock(const Function &F, + const MachineBasicBlock &MBB, + const TargetMachine &TM) const override; + + MCSection * + getUniqueSectionForFunction(const Function &F, + const TargetMachine &TM) const override; + /// Emit Obj-C garbage collection and linker options. void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override; diff --git a/llvm/lib/CodeGen/BasicBlockSections.cpp b/llvm/lib/CodeGen/BasicBlockSections.cpp --- a/llvm/lib/CodeGen/BasicBlockSections.cpp +++ b/llvm/lib/CodeGen/BasicBlockSections.cpp @@ -411,7 +411,8 @@ }; sortBasicBlocksAndUpdateBranches(MF, Comparator); - avoidZeroOffsetLandingPad(MF); + if (MF.getTarget().getTargetTriple().isOSBinFormatELF()) + avoidZeroOffsetLandingPad(MF); return true; } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1695,6 +1695,59 @@ COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); } +/// Returns a unique section for the given machine basic block. +MCSection *TargetLoweringObjectFileCOFF::getSectionForMachineBasicBlock( + const Function &F, const MachineBasicBlock &MBB, + const TargetMachine &TM) const { + assert(MBB.isBeginSection() && "Basic block does not start a section!"); + SectionKind Kind = SectionKind::getText(); + unsigned Characteristics = getCOFFSectionFlags(Kind, TM); + // If we have -ffunction-sections then we should emit the global value to a + // uniqued section specifically for it. + if (TM.getFunctionSections() || F.hasComdat()) + Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; + unsigned UniqueID = MCContext::GenericSectionID; + StringRef COMDATSymName; + if (TM.getUniqueBasicBlockSectionNames()) + COMDATSymName = MBB.getSymbol()->getName(); + else { + UniqueID = NextUniqueID++; + COMDATSymName = MBB.getParent()->getName(); + } + + // TODO: construct exception section in the case of section ID of MBB is + // MBBSectionID::ExceptionSectionID and cold section in the case of section + // ID of MBB is MBBSectionID::ColdSectionID + SmallString<128> Name; + Name += getCOFFSectionNameForUniqueGlobal(SectionKind::getText()); + + // Append "$symbol" to the section name *before* IR-level mangling is + // applied when targetting mingw. This is what GCC does, and the ld.bfd + // COFF linker will not properly handle comdats otherwise. + if (getTargetTriple().isWindowsGNUEnvironment()) { + Name += '$'; + Name += COMDATSymName; + } + + return getContext().getCOFFSection( + Name, Characteristics, SectionKind::getText(), COMDATSymName, + COFF::IMAGE_COMDAT_SELECT_NODUPLICATES, UniqueID); +} + +MCSection *TargetLoweringObjectFileCOFF::getUniqueSectionForFunction( + const Function &F, const TargetMachine &TM) const { + SectionKind Kind = SectionKind::getText(); + unsigned Characteristics = getCOFFSectionFlags(Kind, TM); + // If we have -ffunction-sections then we should emit the global value to a + // uniqued section specifically for it. + if (TM.getFunctionSections() || F.hasComdat()) + Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; + return getContext().getCOFFSection( + getCOFFSectionNameForUniqueGlobal(Kind), Characteristics, Kind, + TM.getSymbol(&F)->getName(), COFF::IMAGE_COMDAT_SELECT_NODUPLICATES, + NextUniqueID++); +} + void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer, Module &M) const { emitLinkerDirectives(Streamer, M); diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -325,12 +325,6 @@ // Track the section if (FI->Section == nullptr) FI->Section = getCurrentSectionOnly(); - else if (FI->Section != getCurrentSectionOnly()) { - getContext().reportError( - Loc, - "all .cv_loc directives for a function must be in the same section"); - return false; - } return true; } diff --git a/llvm/test/DebugInfo/COFF/basic-block-sections.ll b/llvm/test/DebugInfo/COFF/basic-block-sections.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/basic-block-sections.ll @@ -0,0 +1,225 @@ +; RUN: llc -O0 %s -function-sections -basic-block-sections=all -unique-basic-block-section-names -mtriple=i686-pc-win32 -filetype=asm -frame-pointer=all -o - | FileCheck --check-prefix=X86 %s +; RUN: llc -O0 %s -basic-block-sections=all -unique-basic-block-section-names -mtriple=i686-pc-win32 -frame-pointer=all -o - | llvm-mc -triple=i686-pc-win32 -filetype=obj | llvm-readobj -S --sr --codeview - | FileCheck --check-prefix=OBJ32 %s +; RUN: llc -O0 %s -function-sections -basic-block-sections=all -unique-basic-block-section-names -mtriple=x86_64-pc-win32 -filetype=asm -frame-pointer=all -o - | FileCheck --check-prefix=X64 %s +; RUN: llc -O0 %s -basic-block-sections=all -unique-basic-block-section-names -mtriple=x86_64-pc-win32 -frame-pointer=all -o - | llvm-mc -triple=x86_64-pc-win32 -filetype=obj | llvm-readobj -S --sr --codeview - | FileCheck --check-prefix=OBJ64 %s + +;; Generated with below C++ source: +;; void f1(); +;; void f3(bool b) { +;; if (b) +;; f1(); +;; } + +; X86: .text,"xr",one_only,"?f3@@YAX_N@Z" +; X86-LABEL: "?f3@@YAX_N@Z": +; X86: .cv_file 1 "c:\\work\\basic-block-sections.cpp" +; X86: .cv_loc 0 1 2 0 +; X86-LABEL: Ltmp0: +; X86: .cv_loc 0 1 3 0 +; X86: .section .text,"xr",one_only,"?f3@@YAX_N@Z.__part.1" +; X86-LABEL: "?f3@@YAX_N@Z.__part.1": +; X86: .cv_loc 0 1 4 0 +; X86: .section .text,"xr",one_only,"?f3@@YAX_N@Z.__part.2" +; X86-LABEL: "?f3@@YAX_N@Z.__part.2": +; X86: .cv_loc 0 1 5 0 +; X86: retl +; X86: .section .text,"xr",one_only,"?f3@@YAX_N@Z" +; X86: [[END_OF_F3:.?Lfunc_end.*]]: + +; Line table +; X86: .cv_linetable 0, "?f3@@YAX_N@Z", [[END_OF_F3]] +; X86-NEXT: .section .debug$S,"dr" +; File index to string table offset subsection +; X86-NEXT: .cv_filechecksums +; String table +; X86-NEXT: .cv_stringtable + +; OBJ32: Section { +; OBJ32: Name: .debug$S +; OBJ32: Characteristics [ (0x42300040) +; OBJ32: ] +; OBJ32: Section { +; OBJ32: Name: .debug$S +; OBJ32: Characteristics [ (0x42301040) +; OBJ32: ] +; OBJ32: Relocations [ +; OBJ32: 0xC IMAGE_REL_I386_DIR32NB ?f3@@YAX_N@Z (13) +; OBJ32: 0x78 IMAGE_REL_I386_SECREL ?f3@@YAX_N@Z (13) +; OBJ32: 0x7C IMAGE_REL_I386_SECTION ?f3@@YAX_N@Z (13) +; OBJ32: 0xB8 IMAGE_REL_I386_SECREL .text (0) +; OBJ32: 0xBC IMAGE_REL_I386_SECTION .text (0) +; OBJ32: 0xCC IMAGE_REL_I386_SECREL ?f3@@YAX_N@Z (13) +; OBJ32: 0xD0 IMAGE_REL_I386_SECTION ?f3@@YAX_N@Z (13) +; OBJ32: ] +; OBJ32: CodeViewDebugInfo [ +; OBJ32: Subsection [ +; OBJ32-NEXT: SubSectionType: Symbols (0xF1) +; OBJ32: {{.*}}Proc{{.*}}Sym { +; OBJ32: CodeSize: 0x1D +; OBJ32: DisplayName: f3 +; OBJ32: LinkageName: ?f3@@YAX_N@Z +; OBJ32: } +; OBJ32: ProcEnd { +; OBJ32: } +; OBJ32-NEXT: ] +; OBJ32: FunctionLineTable [ +; OBJ32-NEXT: LinkageName: ?f3@@YAX_N@Z +; OBJ32-NEXT: Flags: 0x0 +; OBJ32-NEXT: CodeSize: 0x1D +; OBJ32-NEXT: FilenameSegment [ +; OBJ32-NEXT: Filename: c:\work\basic-block-sections.cpp +; OBJ32-NEXT: +0x0 [ +; OBJ32-NEXT: LineNumberStart: 2 +; OBJ32-NEXT: LineNumberEndDelta: 0 +; OBJ32-NEXT: IsStatement: No +; OBJ32-NEXT: ] +; OBJ32-NEXT: +0xB [ +; OBJ32-NEXT: LineNumberStart: 3 +; OBJ32-NEXT: LineNumberEndDelta: 0 +; OBJ32-NEXT: IsStatement: No +; OBJ32-NEXT: ] +; OBJ32-NEXT: +0x14 [ +; OBJ32-NEXT: LineNumberStart: 4 +; OBJ32-NEXT: LineNumberEndDelta: 0 +; OBJ32-NEXT: IsStatement: No +; OBJ32-NEXT: ] +; OBJ32-NEXT: +0x1B [ +; OBJ32-NEXT: LineNumberStart: 5 +; OBJ32-NEXT: LineNumberEndDelta: 0 +; OBJ32-NEXT: IsStatement: No +; OBJ32-NEXT: ] +; OBJ32-NEXT: ] +; X64: .text,"xr",one_only,"?f3@@YAX_N@Z" +; X64-LABEL: "?f3@@YAX_N@Z": +; X64: .cv_file 1 "c:\\work\\basic-block-sections.cpp" +; X64: .cv_loc 0 1 2 0 +; X64-LABEL: .Ltmp0: +; X64: .cv_loc 0 1 3 0 +; X64: .section .text,"xr",one_only,"?f3@@YAX_N@Z.__part.1" +; X64-LABEL: "?f3@@YAX_N@Z.__part.1": +; X64: .cv_loc 0 1 4 0 +; X64: .section .text,"xr",one_only,"?f3@@YAX_N@Z.__part.2" +; X64-LABEL: "?f3@@YAX_N@Z.__part.2": +; X64: .cv_loc 0 1 5 0 +; X64: addq $40, %rsp +; X64-NEXT: retq +; X64: .section .text,"xr",one_only,"?f3@@YAX_N@Z" +; X64: [[END_OF_F3:.?Lfunc_end.*]]: + +; Line table +; X64: .cv_linetable 0, "?f3@@YAX_N@Z", [[END_OF_F3]] +; X64-NEXT: .section .debug$S,"dr" +; File index to string table offset subsection +; X64-NEXT: .cv_filechecksums +; String table +; X64-NEXT: .cv_stringtable + +; OBJ64: Section { +; OBJ64: Name: .debug$S +; OBJ64: Characteristics [ (0x42300040) +; OBJ64: ] +; OBJ64: Section { +; OBJ64: Name: .debug$S +; OBJ64: Characteristics [ (0x42301040) +; OBJ64: ] +; OBJ64: Relocations [ +; OBJ64: 0x2C IMAGE_REL_AMD64_SECREL ?f3@@YAX_N@Z (17) +; OBJ64: 0x30 IMAGE_REL_AMD64_SECTION ?f3@@YAX_N@Z (17) +; OBJ64: 0x6C IMAGE_REL_AMD64_SECREL .text (0) +; OBJ64: 0x70 IMAGE_REL_AMD64_SECTION .text (0) +; OBJ64: 0x80 IMAGE_REL_AMD64_SECREL ?f3@@YAX_N@Z (17) +; OBJ64: 0x84 IMAGE_REL_AMD64_SECTION ?f3@@YAX_N@Z (17) +; OBJ64: ] +; OBJ64: CodeViewDebugInfo [ +; OBJ64: Subsection [ +; OBJ64-NEXT: SubSectionType: Symbols (0xF1) +; OBJ64: {{.*}}Proc{{.*}}Sym { +; OBJ64: CodeSize: 0x20 +; OBJ64: DisplayName: f3 +; OBJ64: LinkageName: ?f3@@YAX_N@Z +; OBJ64: } +; OBJ64: ProcEnd { +; OBJ64: } +; OBJ64-NEXT: ] +; OBJ64: FunctionLineTable [ +; OBJ64-NEXT: LinkageName: ?f3@@YAX_N@Z +; OBJ64-NEXT: Flags: 0x0 +; OBJ64-NEXT: CodeSize: 0x20 +; OBJ64-NEXT: FilenameSegment [ +; OBJ64-NEXT: Filename: c:\work\basic-block-sections.cpp +; OBJ64-NEXT: +0x0 [ +; OBJ64-NEXT: LineNumberStart: 2 +; OBJ64-NEXT: LineNumberEndDelta: 0 +; OBJ64-NEXT: IsStatement: No +; OBJ64-NEXT: ] +; OBJ64-NEXT: +0xB [ +; OBJ64-NEXT: LineNumberStart: 3 +; OBJ64-NEXT: LineNumberEndDelta: 0 +; OBJ64-NEXT: IsStatement: No +; OBJ64-NEXT: ] +; OBJ64-NEXT: +0x14 [ +; OBJ64-NEXT: LineNumberStart: 4 +; OBJ64-NEXT: LineNumberEndDelta: 0 +; OBJ64-NEXT: IsStatement: No +; OBJ64-NEXT: ] +; OBJ64-NEXT: +0x1B [ +; OBJ64-NEXT: LineNumberStart: 5 +; OBJ64-NEXT: LineNumberEndDelta: 0 +; OBJ64-NEXT: IsStatement: No +; OBJ64-NEXT: ] +; OBJ64-NEXT: ] + +; ModuleID = 'basic-block-sections.cpp' +source_filename = "basic-block-sections.cpp" +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.24245" + +; Function Attrs: noinline optnone uwtable mustprogress +define dso_local void @"?f3@@YAX_N@Z"(i1 zeroext %0) #0 !dbg !8 { + %2 = alloca i8, align 1 + %3 = zext i1 %0 to i8 + store i8 %3, i8* %2, align 1 + call void @llvm.dbg.declare(metadata i8* %2, metadata !12, metadata !DIExpression()), !dbg !13 + %4 = load i8, i8* %2, align 1, !dbg !14 + %5 = trunc i8 %4 to i1, !dbg !14 + br i1 %5, label %6, label %7, !dbg !14 + +6: ; preds = %1 + call void @"?f1@@YAXXZ"(), !dbg !15 + br label %7, !dbg !15 + +7: ; preds = %6, %1 + ret void, !dbg !17 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +declare dso_local void @"?f1@@YAXXZ"() #2 + +attributes #0 = { noinline optnone uwtable mustprogress "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } +attributes #2 = { "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0 (https://github.com/llvm/llvm-project.git 5207f19d103dc3e0ec974fa64d2c031d84d497a8)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "basic-block-sections.cpp", directory: "c:\\work", checksumkind: CSK_MD5, checksum: "38d417097a2d2dd73e59660521597146") +!2 = !{} +!3 = !{i32 2, !"CodeView", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 2} +!6 = !{i32 7, !"PIC Level", i32 2} +!7 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git 5207f19d103dc3e0ec974fa64d2c031d84d497a8)"} +!8 = distinct !DISubprogram(name: "f3", linkageName: "?f3@@YAX_N@Z", scope: !1, file: !1, line: 2, type: !9, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!9 = !DISubroutineType(types: !10) +!10 = !{null, !11} +!11 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) +!12 = !DILocalVariable(name: "b", arg: 1, scope: !8, file: !1, line: 2, type: !11) +!13 = !DILocation(line: 2, scope: !8) +!14 = !DILocation(line: 3, scope: !8) +!15 = !DILocation(line: 4, scope: !16) +!16 = distinct !DILexicalBlock(scope: !8, file: !1, line: 3) +!17 = !DILocation(line: 5, scope: !8) diff --git a/llvm/test/MC/COFF/cv-loc-cross-section.s b/llvm/test/MC/COFF/cv-loc-cross-section.s deleted file mode 100644 --- a/llvm/test/MC/COFF/cv-loc-cross-section.s +++ /dev/null @@ -1,26 +0,0 @@ -# RUN: not llvm-mc -triple=x86_64-pc-win32 < %s -o /dev/null 2>&1 | FileCheck %s - - .text - .global baz -baz: -.Lfunc_begin0: - .cv_file 1 "t.cpp" - .cv_func_id 0 - .cv_loc 0 1 1 1 - pushq %rbp - movq %rsp, %rbp - .cv_loc 0 1 2 1 - - .data # Switching sections raises an error. - - incl x(%rip) - .cv_loc 0 1 3 1 -# CHECK: error: all .cv_loc directives for a function must be in the same section - popq %rbp - retq -.Lfunc_end0: - - .section .debug$S,"dr" - .cv_linetable 0 .Lfunc_begin0 .Lfunc_end0 - .short 2 # Record length - .short 2 # Record kind: S_INLINESITE_END