[clang] 3eee5aa - [COFF] Support -gsplit-dwarf for COFF on Windows

via cfe-commits cfe-commits at lists.llvm.org
Sat Jun 24 20:56:19 PDT 2023


Author: Haohai Wen
Date: 2023-06-25T11:54:39+08:00
New Revision: 3eee5aa528abd67bb6d057e25ce1980d0d38c445

URL: https://github.com/llvm/llvm-project/commit/3eee5aa528abd67bb6d057e25ce1980d0d38c445
DIFF: https://github.com/llvm/llvm-project/commit/3eee5aa528abd67bb6d057e25ce1980d0d38c445.diff

LOG: [COFF] Support -gsplit-dwarf for COFF on Windows

D152340 has split WinCOFFObjectWriter to WinCOFFWriter. This patch adds
another WinCOFFWriter as DwoWriter to write Dwo sections to dwo file.
Driver options are also updated accordingly to support -gsplit-dwarf in
CL mode.

e.g. $ clang-cl  -c -gdwarf -gsplit-dwarf foo.c

Like what -gsplit-dwarf did in ELF, using this option will create DWARF object
(.dwo) file. DWARF debug info is split between COFF object and DWARF object
file. It can reduce the executable file size especially for large project.

Reviewed By: skan, MaskRay

Differential Revision: https://reviews.llvm.org/D152785

Added: 
    llvm/test/DebugInfo/COFF/dwarf-headers.ll
    llvm/test/DebugInfo/COFF/fission-cu.ll
    llvm/test/DebugInfo/COFF/fission-sections.ll

Modified: 
    clang/include/clang/Driver/Options.td
    clang/lib/Driver/Driver.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Driver/ToolChains/CommonArgs.cpp
    clang/test/Driver/split-debug.c
    llvm/include/llvm/MC/MCWinCOFFObjectWriter.h
    llvm/lib/MC/MCAsmBackend.cpp
    llvm/lib/MC/WinCOFFObjectWriter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index bb3d487886eb7..77dcef9c73b9e 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3434,11 +3434,13 @@ defm column_info : BoolOption<"g", "column-info",
   CodeGenOpts<"DebugColumnInfo">, DefaultTrue,
   NegFlag<SetFalse, [CC1Option]>, PosFlag<SetTrue>, BothFlags<[CoreOption]>>,
   Group<g_flags_Group>;
-def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
+def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>,
+  Flags<[CoreOption]>;
 def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_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<g_flags_Group>;
+def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group<g_flags_Group>,
+  Flags<[CoreOption]>;
 def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group<g_flags_Group>;
 def gsimple_template_names_EQ
     : Joined<["-"], "gsimple-template-names=">,

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 696db21d97c51..1580f092bcde0 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -3925,12 +3925,13 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
     // `-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
index de22ea4455fa7..82e135012d6c9 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5647,7 +5647,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   // can propagate it to the backend.
   bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) &&
                     (TC.getTriple().isOSBinFormatELF() ||
-                     TC.getTriple().isOSBinFormatWasm()) &&
+                     TC.getTriple().isOSBinFormatWasm() ||
+                     TC.getTriple().isOSBinFormatCOFF()) &&
                     (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
                      isa<BackendJobAction>(JA));
   if (SplitDWARF) {

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 4afe3cc1f7a6e..61b26cf1d3d19 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1278,7 +1278,7 @@ const char *tools::SplitDebugName(const JobAction &JA, const ArgList &Args,
   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
index e45d2e19bb81e..a19f4e1fc3b51 100644
--- 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 %s -o obj/out 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
index e471be6b549e5..307800e73c687 100644
--- a/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h
+++ b/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h
@@ -51,6 +51,10 @@ class MCWinCOFFObjectTargetWriter : public MCObjectTargetWriter {
 std::unique_ptr<MCObjectWriter>
 createWinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
                           raw_pwrite_stream &OS);
+
+std::unique_ptr<MCObjectWriter>
+createWinCOFFDwoObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> 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
index 75db32e797f41..4fe61d5f265fb 100644
--- a/llvm/lib/MC/MCAsmBackend.cpp
+++ b/llvm/lib/MC/MCAsmBackend.cpp
@@ -61,6 +61,9 @@ MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
                                     raw_pwrite_stream &DwoOS) const {
   auto TW = createObjectTargetWriter();
   switch (TW->getFormat()) {
+  case Triple::COFF:
+    return createWinCOFFDwoObjectWriter(
+        cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS, DwoOS);
   case Triple::ELF:
     return createELFDwoObjectWriter(
         cast<MCELFObjectTargetWriter>(std::move(TW)), OS, DwoOS,
@@ -69,7 +72,7 @@ MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
     return createWasmDwoObjectWriter(
         cast<MCWasmObjectTargetWriter>(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
index f48046753e20f..c203280d2c107 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -154,7 +154,14 @@ class WinCOFFWriter {
   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 @@ class WinCOFFObjectWriter : public MCObjectWriter {
   friend class WinCOFFWriter;
 
   std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
-  std::unique_ptr<WinCOFFWriter> ObjWriter;
+  std::unique_ptr<WinCOFFWriter> ObjWriter, DwoWriter;
 
 public:
   WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
                       raw_pwrite_stream &OS)
       : TargetObjectWriter(std::move(MOTW)),
-        ObjWriter(std::make_unique<WinCOFFWriter>(*this, OS)) {}
+        ObjWriter(std::make_unique<WinCOFFWriter>(*this, OS,
+                                                  WinCOFFWriter::AllSections)) {
+  }
+  WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
+                      raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS)
+      : TargetObjectWriter(std::move(MOTW)),
+        ObjWriter(std::make_unique<WinCOFFWriter>(*this, OS,
+                                                  WinCOFFWriter::NonDwoOnly)),
+        DwoWriter(std::make_unique<WinCOFFWriter>(*this, DwoOS,
+                                                  WinCOFFWriter::DwoOnly)) {}
 
   // MCObjectWriter interface implementation.
   void reset() override;
@@ -224,6 +240,10 @@ class WinCOFFObjectWriter : public MCObjectWriter {
 
 } // end anonymous namespace
 
+static bool isDwoSection(const MCSection &Sec) {
+  return Sec.getName().endswith(".dwo");
+}
+
 //------------------------------------------------------------------------------
 // Symbol class implementation
 
@@ -239,8 +259,8 @@ void COFFSymbol::set_name_offset(uint32_t Offset) {
 // 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 @@ void WinCOFFWriter::executePostLayoutBinding(MCAssembler &Asm,
                                              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<const MCSectionCOFF &>(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 @@ uint64_t WinCOFFWriter::writeObject(MCAssembler &Asm,
 
   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 @@ uint64_t WinCOFFWriter::writeObject(MCAssembler &Asm,
   }
 
   // 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 @@ uint64_t WinCOFFWriter::writeObject(MCAssembler &Asm,
   }
 
   // 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 @@ uint64_t WinCOFFWriter::writeObject(MCAssembler &Asm,
   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 @@ uint64_t WinCOFFWriter::writeObject(MCAssembler &Asm,
 
 void WinCOFFObjectWriter::reset() {
   ObjWriter->reset();
+  if (DwoWriter)
+    DwoWriter->reset();
   MCObjectWriter::reset();
 }
 
@@ -1188,6 +1220,8 @@ void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
   }
 
   ObjWriter->executePostLayoutBinding(Asm, Layout);
+  if (DwoWriter)
+    DwoWriter->executePostLayoutBinding(Asm, Layout);
 }
 
 void WinCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
@@ -1195,13 +1229,19 @@ void WinCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
                                            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<MCObjectWriter> llvm::createWinCOFFObjectWriter(
     std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) {
   return std::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS);
 }
+
+std::unique_ptr<MCObjectWriter> llvm::createWinCOFFDwoObjectWriter(
+    std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS,
+    raw_pwrite_stream &DwoOS) {
+  return std::make_unique<WinCOFFObjectWriter>(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
index 0000000000000..9d515f6cec640
--- /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 
diff er only
+; in the unit_type code, and the skeleton/split CU 
diff ers 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
index 0000000000000..944d886c3e834
--- /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"
+
+ at 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
index 0000000000000..da1418d937bb6
--- /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"
+
+ at 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


        


More information about the cfe-commits mailing list