diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3434,11 +3434,13 @@ CodeGenOpts<"DebugColumnInfo">, DefaultTrue, NegFlag, PosFlag, BothFlags<[CoreOption]>>, Group; -def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group; +def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group, + Flags<[CoreOption]>; def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group, - HelpText<"Set DWARF fission mode">, + Flags<[CoreOption]>, HelpText<"Set DWARF fission mode">, Values<"split,single">; -def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group; +def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group, + Flags<[CoreOption]>; def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group; def gsimple_template_names_EQ : Joined<["-"], "gsimple-template-names=">, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3925,12 +3925,13 @@ // `-dumpdir x-` to cc1. If -o is unspecified, use // stem(getDefaultImageName()) (usually stem("a.out") = "a"). if (!Args.hasArg(options::OPT_dumpdir)) { + Arg *FinalOutput = Args.getLastArg(options::OPT_o, options::OPT__SLASH_o); Arg *Arg = Args.MakeSeparateArg( nullptr, getOpts().getOption(options::OPT_dumpdir), - Args.MakeArgString(Args.getLastArgValue( - options::OPT_o, - llvm::sys::path::stem(getDefaultImageName())) + - "-")); + Args.MakeArgString( + (FinalOutput ? FinalOutput->getValue() + : llvm::sys::path::stem(getDefaultImageName())) + + "-")); Arg->claim(); Args.append(Arg); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5647,7 +5647,8 @@ // can propagate it to the backend. bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) && (TC.getTriple().isOSBinFormatELF() || - TC.getTriple().isOSBinFormatWasm()) && + TC.getTriple().isOSBinFormatWasm() || + TC.getTriple().isOSBinFormatCOFF()) && (isa(JA) || isa(JA) || isa(JA)); if (SplitDWARF) { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1278,7 +1278,7 @@ if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) { T = A->getValue(); } else { - Arg *FinalOutput = Args.getLastArg(options::OPT_o); + Arg *FinalOutput = Args.getLastArg(options::OPT_o, options::OPT__SLASH_o); if (FinalOutput && Args.hasArg(options::OPT_c)) { T = FinalOutput->getValue(); llvm::sys::path::remove_filename(T); diff --git a/clang/test/Driver/split-debug.c b/clang/test/Driver/split-debug.c --- a/clang/test/Driver/split-debug.c +++ b/clang/test/Driver/split-debug.c @@ -16,6 +16,7 @@ // RUN: %clang -### -c -target wasm32 -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=SPLIT // RUN: %clang -### -c -target amdgcn-amd-amdhsa -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=SPLIT +// RUN: %clang_cl -### -c --target=x86_64-unknown-windows-msvc -gno-split-dwarf -gsplit-dwarf -g -- %s 2>&1 | FileCheck %s --check-prefix=SPLIT /// -gsplit-dwarf is a no-op on a non-ELF platform. // RUN: %clang -### -c -target x86_64-apple-darwin -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=DARWIN @@ -51,12 +52,14 @@ // SINGLE-NOT: "-split-dwarf-output" // RUN: %clang -### -c -target x86_64 -gsplit-dwarf=single -g -o %tfoo.o %s 2>&1 | FileCheck %s --check-prefix=SINGLE_WITH_FILENAME +// RUN: %clang_cl -### -c --target=x86_64-unknown-windows-msvc -gsplit-dwarf=single -g -o %tfoo.o -- %s 2>&1 | FileCheck %s --check-prefix=SINGLE_WITH_FILENAME // SINGLE_WITH_FILENAME: "-split-dwarf-file" "{{.*}}foo.o" // SINGLE_WITH_FILENAME-NOT: "-split-dwarf-output" /// If linking is the final phase, the .dwo filename is derived from -o (if specified) or "a". // RUN: %clang -### --target=x86_64-unknown-linux-gnu -gsplit-dwarf -g %s -o obj/out 2>&1 | FileCheck %s --check-prefix=SPLIT_LINK +// RUN: %clang_cl -### --target=x86_64-unknown-windows-msvc -gsplit-dwarf -g -o obj/out -- %s 2>&1 | FileCheck %s --check-prefix=SPLIT_LINK // RUN: %clang -### --target=x86_64-unknown-linux-gnu -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=SPLIT_LINK_A // SPLIT_LINK: "-dumpdir" "obj/out-" diff --git a/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h b/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h --- a/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -51,6 +51,10 @@ std::unique_ptr createWinCOFFObjectWriter(std::unique_ptr MOTW, raw_pwrite_stream &OS); + +std::unique_ptr +createWinCOFFDwoObjectWriter(std::unique_ptr MOTW, + raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS); } // end namespace llvm #endif // LLVM_MC_MCWINCOFFOBJECTWRITER_H diff --git a/llvm/lib/MC/MCAsmBackend.cpp b/llvm/lib/MC/MCAsmBackend.cpp --- a/llvm/lib/MC/MCAsmBackend.cpp +++ b/llvm/lib/MC/MCAsmBackend.cpp @@ -61,6 +61,9 @@ raw_pwrite_stream &DwoOS) const { auto TW = createObjectTargetWriter(); switch (TW->getFormat()) { + case Triple::COFF: + return createWinCOFFDwoObjectWriter( + cast(std::move(TW)), OS, DwoOS); case Triple::ELF: return createELFDwoObjectWriter( cast(std::move(TW)), OS, DwoOS, @@ -69,7 +72,7 @@ return createWasmDwoObjectWriter( cast(std::move(TW)), OS, DwoOS); default: - report_fatal_error("dwo only supported with ELF and Wasm"); + report_fatal_error("dwo only supported with COFF, ELF, and Wasm"); } } diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -154,7 +154,14 @@ MCSectionCOFF *AddrsigSection = nullptr; MCSectionCOFF *CGProfileSection = nullptr; - WinCOFFWriter(WinCOFFObjectWriter &OWriter, raw_pwrite_stream &OS); + enum DwoMode { + AllSections, + NonDwoOnly, + DwoOnly, + } Mode; + + WinCOFFWriter(WinCOFFObjectWriter &OWriter, raw_pwrite_stream &OS, + DwoMode Mode); void reset(); void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); @@ -200,13 +207,22 @@ friend class WinCOFFWriter; std::unique_ptr TargetObjectWriter; - std::unique_ptr ObjWriter; + std::unique_ptr ObjWriter, DwoWriter; public: WinCOFFObjectWriter(std::unique_ptr MOTW, raw_pwrite_stream &OS) : TargetObjectWriter(std::move(MOTW)), - ObjWriter(std::make_unique(*this, OS)) {} + ObjWriter(std::make_unique(*this, OS, + WinCOFFWriter::AllSections)) { + } + WinCOFFObjectWriter(std::unique_ptr MOTW, + raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS) + : TargetObjectWriter(std::move(MOTW)), + ObjWriter(std::make_unique(*this, OS, + WinCOFFWriter::NonDwoOnly)), + DwoWriter(std::make_unique(*this, DwoOS, + WinCOFFWriter::DwoOnly)) {} // MCObjectWriter interface implementation. void reset() override; @@ -224,6 +240,10 @@ } // end anonymous namespace +static bool isDwoSection(const MCSection &Sec) { + return Sec.getName().endswith(".dwo"); +} + //------------------------------------------------------------------------------ // Symbol class implementation @@ -239,8 +259,8 @@ // WinCOFFWriter class implementation WinCOFFWriter::WinCOFFWriter(WinCOFFObjectWriter &OWriter, - raw_pwrite_stream &OS) - : OWriter(OWriter), W(OS, support::little) { + raw_pwrite_stream &OS, DwoMode Mode) + : OWriter(OWriter), W(OS, support::little), Mode(Mode) { Header.Machine = OWriter.TargetObjectWriter->getMachine(); // Some relocations on ARM64 (the 21 bit ADRP relocations) have a slightly // limited range for the immediate offset (+/- 1 MB); create extra offset @@ -818,12 +838,17 @@ const MCAsmLayout &Layout) { // "Define" each section & symbol. This creates section & symbol // entries in the staging area. - for (const auto &Section : Asm) + for (const auto &Section : Asm) { + if ((Mode == NonDwoOnly && isDwoSection(Section)) || + (Mode == DwoOnly && !isDwoSection(Section))) + continue; defineSection(static_cast(Section), Layout); + } - for (const MCSymbol &Symbol : Asm.symbols()) - if (!Symbol.isTemporary()) - DefineSymbol(Symbol, Asm, Layout); + if (Mode != DwoOnly) + for (const MCSymbol &Symbol : Asm.symbols()) + if (!Symbol.isTemporary()) + DefineSymbol(Symbol, Asm, Layout); } void WinCOFFWriter::recordRelocation(MCAssembler &Asm, @@ -998,7 +1023,8 @@ setWeakDefaultNames(); assignSectionNumbers(); - createFileSymbols(Asm); + if (Mode != DwoOnly) + createFileSymbols(Asm); for (auto &Symbol : Symbols) { // Update section number & offset for symbols that have them. @@ -1068,7 +1094,7 @@ } // Create the contents of the .llvm_addrsig section. - if (OWriter.EmitAddrsigSection) { + if (Mode != DwoOnly && OWriter.EmitAddrsigSection) { auto Frag = new MCDataFragment(AddrsigSection); Frag->setLayoutOrder(0); raw_svector_ostream OS(Frag->getContents()); @@ -1089,7 +1115,7 @@ } // Create the contents of the .llvm.call-graph-profile section. - if (CGProfileSection) { + if (Mode != DwoOnly && CGProfileSection) { auto *Frag = new MCDataFragment(CGProfileSection); Frag->setLayoutOrder(0); raw_svector_ostream OS(Frag->getContents()); @@ -1122,8 +1148,12 @@ sections::iterator IE = Sections.end(); MCAssembler::iterator J = Asm.begin(); MCAssembler::iterator JE = Asm.end(); - for (; I != IE && J != JE; ++I, ++J) - assert((**I).MCSection == &*J && "Wrong bound MCSection"); + for (; I != IE && J != JE; ++I, ++J) { + while (J != JE && ((Mode == NonDwoOnly && isDwoSection(*J)) || + (Mode == DwoOnly && !isDwoSection(*J)))) + ++J; + assert(J != JE && (**I).MCSection == &*J && "Wrong bound MCSection"); + } #endif // Write section contents. @@ -1152,6 +1182,8 @@ void WinCOFFObjectWriter::reset() { ObjWriter->reset(); + if (DwoWriter) + DwoWriter->reset(); MCObjectWriter::reset(); } @@ -1188,6 +1220,8 @@ } ObjWriter->executePostLayoutBinding(Asm, Layout); + if (DwoWriter) + DwoWriter->executePostLayoutBinding(Asm, Layout); } void WinCOFFObjectWriter::recordRelocation(MCAssembler &Asm, @@ -1195,13 +1229,19 @@ const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) { + assert(!isDwoSection(*Fragment->getParent()) && + "No relocation in Dwo sections"); ObjWriter->recordRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); } uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { - return ObjWriter->writeObject(Asm, Layout); + uint64_t TotalSize = ObjWriter->writeObject(Asm, Layout); + if (DwoWriter) + TotalSize += DwoWriter->writeObject(Asm, Layout); + return TotalSize; } + MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) : Machine(Machine_) {} @@ -1215,3 +1255,9 @@ std::unique_ptr MOTW, raw_pwrite_stream &OS) { return std::make_unique(std::move(MOTW), OS); } + +std::unique_ptr llvm::createWinCOFFDwoObjectWriter( + std::unique_ptr MOTW, raw_pwrite_stream &OS, + raw_pwrite_stream &DwoOS) { + return std::make_unique(std::move(MOTW), OS, DwoOS); +} diff --git a/llvm/test/DebugInfo/COFF/dwarf-headers.ll b/llvm/test/DebugInfo/COFF/dwarf-headers.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/dwarf-headers.ll @@ -0,0 +1,75 @@ +; RUN: llc -dwarf-version=4 \ +; RUN: -filetype=obj -O0 -mtriple=x86_64-unknown-windows-msvc < %s \ +; RUN: | llvm-dwarfdump -v - | FileCheck %s --check-prefix=SINGLE-4 + +; RUN: llc -split-dwarf-file=foo.dwo -split-dwarf-output=%t.dwo \ +; RUN: -dwarf-version=4 \ +; RUN: -filetype=obj -O0 -mtriple=x86_64-unknown-windows-msvc < %s \ +; RUN: | llvm-dwarfdump -v - | FileCheck %s --check-prefix=O-4 +; RUN: llvm-dwarfdump -v %t.dwo | FileCheck %s --check-prefix=DWO-4 + +; This test is derived from test/CodeGen/X86/dwarf-headers.ll + +; Looking for DWARF headers to be generated correctly. +; There are 8 variants with 5 formats: v4 CU, v4 TU, v5 normal/partial CU, +; v5 skeleton/split CU, v5 normal/split TU. Some v5 variants differ only +; in the unit_type code, and the skeleton/split CU differs from normal/partial +; by having one extra field (dwo_id). +; (v2 thru v4 CUs are all the same, and TUs were invented in v4, +; so we don't bother checking older versions.) + +; Test case built from: +;struct S { +; int s1; +;}; +; +;S s; + +; Verify the v4 non-split headers. +; Note that we check the exact offset of the DIEs because that tells us +; the length of the header. +; +; SINGLE-4: .debug_info contents: +; SINGLE-4: 0x00000000: Compile Unit: {{.*}} version = 0x0004, abbr_offset +; SINGLE-4: 0x0000000b: DW_TAG_compile_unit + +; Verify the v4 split headers. +; +; O-4: .debug_info contents: +; O-4: 0x00000000: Compile Unit: {{.*}} version = 0x0004, abbr_offset +; O-4: 0x0000000b: DW_TAG_compile_unit +; +; DWO-4: .debug_info.dwo contents: +; DWO-4: 0x00000000: Compile Unit: {{.*}} version = 0x0004, abbr_offset +; DWO-4: 0x0000000b: DW_TAG_compile_unit + + +; ModuleID = 't.cpp' +source_filename = "t.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-unknown-windows-msvc" + +%struct.S = type { i32 } + +@"?s@@3US@@A" = dso_local global %struct.S zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!9, !10, !11, !12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "s", linkageName: "?s@@3US@@A", scope: !2, file: !3, line: 5, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git f1106ef6c9d14d5b516ec352279aeee8f9d12818)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "t.cpp", directory: "e:\\llvm-project\\foo") +!4 = !{!0} +!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !3, line: 1, size: 32, flags: DIFlagTypePassByValue, elements: !6, identifier: ".?AUS@@") +!6 = !{!7} +!7 = !DIDerivedType(tag: DW_TAG_member, name: "s1", scope: !5, file: !3, line: 2, baseType: !8, size: 32) +!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!9 = !{i32 7, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 2} +!12 = !{i32 8, !"PIC Level", i32 2} +!13 = !{i32 7, !"uwtable", i32 2} +!14 = !{i32 1, !"MaxTLSAlign", i32 65536} +!15 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git f1106ef6c9d14d5b516ec352279aeee8f9d12818)"} diff --git a/llvm/test/DebugInfo/COFF/fission-cu.ll b/llvm/test/DebugInfo/COFF/fission-cu.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/fission-cu.ll @@ -0,0 +1,120 @@ +; RUN: llc -split-dwarf-file=baz.dwo -O0 %s -mtriple=x86_64-unknown-windows-msvc -filetype=obj -o %t +; RUN: llvm-dwarfdump -v -all %t | FileCheck %s +; RUN: llvm-readobj --relocations %t | FileCheck --check-prefix=OBJ %s +; RUN: llvm-objdump -h %t | FileCheck --check-prefix=HDR %s + +; This test is derived from test/DebugInfo/X86/fission-cu.ll + +source_filename = "test/DebugInfo/X86/fission-cu.ll" + +@a = common global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!4} +!llvm.module.flags = !{!7} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 1, type: !3, isLocal: false, isDefinition: true) +!2 = !DIFile(filename: "baz.c", directory: "e:\\llvm-project\\tmp") +!3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "baz.dwo", emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) +!5 = !{} +; Check that the skeleton compile unit contains the proper attributes: +; This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, +; DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, +; DW_AT_ranges_base, DW_AT_addr_base. + +; CHECK: .debug_abbrev contents: +; CHECK: Abbrev table for offset: 0x00000000 +; CHECK: [1] DW_TAG_compile_unit DW_CHILDREN_no +; CHECK: DW_AT_stmt_list DW_FORM_sec_offset +; CHECK: DW_AT_comp_dir DW_FORM_strp +; CHECK: DW_AT_GNU_dwo_name DW_FORM_strp +; CHECK: DW_AT_GNU_dwo_id DW_FORM_data8 + +; Check that we're using the right forms. +; CHECK: .debug_abbrev.dwo contents: +; CHECK: Abbrev table for offset: 0x00000000 +; CHECK: [1] DW_TAG_compile_unit DW_CHILDREN_yes +; CHECK: DW_AT_producer DW_FORM_GNU_str_index +; CHECK: DW_AT_language DW_FORM_data2 +; CHECK: DW_AT_name DW_FORM_GNU_str_index +; CHECK: DW_AT_GNU_dwo_name DW_FORM_GNU_str_index +; CHECK-NOT: DW_AT_low_pc +; CHECK-NOT: DW_AT_stmt_list +; CHECK-NOT: DW_AT_comp_dir +; CHECK: DW_AT_GNU_dwo_id DW_FORM_data8 + +; CHECK: [2] DW_TAG_variable DW_CHILDREN_no +; CHECK: DW_AT_name DW_FORM_GNU_str_index +; CHECK: DW_AT_type DW_FORM_ref4 +; CHECK: DW_AT_external DW_FORM_flag_present +; CHECK: DW_AT_decl_file DW_FORM_data1 +; CHECK: DW_AT_decl_line DW_FORM_data1 +; CHECK: DW_AT_location DW_FORM_exprloc + +; CHECK: [3] DW_TAG_base_type DW_CHILDREN_no +; CHECK: DW_AT_name DW_FORM_GNU_str_index +; CHECK: DW_AT_encoding DW_FORM_data1 +; CHECK: DW_AT_byte_size DW_FORM_data1 + +; CHECK: .debug_info contents: +; CHECK: DW_TAG_compile_unit +; CHECK-NEXT: DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000) +; CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000000] = "e:\\llvm-project\\tmp") +; CHECK-NEXT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000014] = "baz.dwo") +; CHECK-NEXT: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x1f1f859683d49324) + +; Check that the rest of the compile units have information. +; CHECK: .debug_info.dwo contents: +; CHECK: DW_TAG_compile_unit +; CHECK: DW_AT_producer [DW_FORM_GNU_str_index] (indexed (00000002) string = "clang version 3.3 (trunk 169021) (llvm/trunk 169020)") +; CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99) +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000003) string = "baz.c") +; CHECK: DW_AT_GNU_dwo_name [DW_FORM_GNU_str_index] (indexed (00000004) string = "baz.dwo") +; CHECK-NOT: DW_AT_low_pc +; CHECK-NOT: DW_AT_stmt_list +; CHECK-NOT: DW_AT_comp_dir +; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x1f1f859683d49324) +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000000) string = "a") +; CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[0-9a-f]*}} => {[[TYPE:0x[0-9a-f]*]]} +; CHECK: DW_AT_external [DW_FORM_flag_present] (true) +; CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01) +; CHECK: DW_AT_decl_line [DW_FORM_data1] (1) +; CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x0) +; CHECK: [[TYPE]]: DW_TAG_base_type +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000001) string = "int") + +; CHECK: .debug_str contents: +; CHECK: 0x00000000: "e:\\llvm-project\\tmp" +; CHECK: 0x00000014: "baz.dwo" + +; CHECK: .debug_str.dwo contents: +; CHECK: 0x00000000: "a" +; CHECK: 0x00000002: "int" +; CHECK: 0x00000006: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)" +; CHECK: 0x0000003b: "baz.c" +; CHECK: 0x00000041: "baz.dwo" + +; CHECK: .debug_str_offsets.dwo contents: +; CHECK: 0x00000000: 00000000 +; CHECK: 0x00000004: 00000002 +; CHECK: 0x00000008: 00000006 +; CHECK: 0x0000000c: 0000003b +; CHECK: 0x00000010: 00000041 + +; Object file checks +; For COFF we should have this set of relocations for the debug info section +; +; OBJ: .debug_info +; OBJ-NEXT: IMAGE_REL_AMD64_SECREL .debug_abbrev (6) +; OBJ-NEXT: IMAGE_REL_AMD64_SECREL .debug_line (26) +; OBJ-NEXT: IMAGE_REL_AMD64_SECREL .debug_str (10) +; OBJ-NEXT: IMAGE_REL_AMD64_SECREL .debug_str (10) +; OBJ-NEXT: IMAGE_REL_AMD64_SECREL .debug_addr (20) +; OBJ-NEXT: } + +; HDR-NOT: .debug_aranges + +!6 = !{!0} +!7 = !{i32 1, !"Debug Info Version", i32 3} diff --git a/llvm/test/DebugInfo/COFF/fission-sections.ll b/llvm/test/DebugInfo/COFF/fission-sections.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/fission-sections.ll @@ -0,0 +1,42 @@ +; RUN: llc -split-dwarf-file=baz.dwo -split-dwarf-output=%t.dwo -O0 %s -mtriple=x86_64-unknown-windows-msvc -filetype=obj -o %t +; RUN: llvm-objdump -h %t | FileCheck --check-prefix=OBJ %s +; RUN: llvm-objdump -h %t.dwo | FileCheck --check-prefix=DWO %s + +; This test is derived from test/DebugInfo/X86/fission-cu.ll +; But it checks that the output objects have the expected sections + +source_filename = "test/DebugInfo/X86/fission-cu.ll" + +@a = common global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!4} +!llvm.module.flags = !{!7} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 1, type: !3, isLocal: false, isDefinition: true) +!2 = !DIFile(filename: "baz.c", directory: "e:\\llvm-project\\tmp") +!3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "baz.dwo", emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) +!5 = !{} +!6 = !{!0} +!7 = !{i32 1, !"Debug Info Version", i32 3} + +; CHECK-LABEL: Sections: + +; OBJ: Idx Name +; OBJ-NEXT: 0 .text +; OBJ-NEXT: 1 .data +; OBJ-NEXT: 2 .bss +; OBJ-NEXT: 3 .debug_abbrev +; OBJ-NEXT: 4 .debug_info +; OBJ-NEXT: 5 .debug_str +; OBJ-NEXT: 6 .debug_addr +; OBJ-NEXT: 7 .debug_pubnames +; OBJ-NEXT: 8 .debug_pubtypes +; OBJ-NEXT: 9 .debug_line + +; DWO: Idx Name +; DWO-NEXT: 0 .debug_str.dwo +; DWO-NEXT: 1 .debug_str_offsets.dwo +; DWO-NEXT: 2 .debug_info.dwo +; DWO-NEXT: 3 .debug_abbrev.dwo