Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/swift/AST/IRGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,13 @@ class IRGenOptions {
/// The DWARF version of debug info.
uint8_t DWARFVersion = 4;

/// Name for the split DWARF file (embedded as DW_AT_dwo_name in skeleton CU).
/// Derived as basename of SplitDwarfOutput.
std::string SplitDwarfFile;

/// Output path for the split DWARF file (.dwo).
std::string SplitDwarfOutput;

/// The command line string that is to be stored in the debug info.
std::string DebugFlags;

Expand Down
4 changes: 4 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,10 @@ def dwarf_version : Joined<["-"], "dwarf-version=">,
HelpText<"DWARF debug info version to produce if requested">,
MetaVarName<"<version>">;

def split_dwarf_output : Separate<["-"], "split-dwarf-output">,
Flags<[FrontendOption]>, MetaVarName<"<path>">,
HelpText<"Emit split DWARF debug info to a .dwo file at the given path">;

def prefix_serialized_debugging_options : Flag<["-"], "prefix-serialized-debugging-options">,
Flags<[FrontendOption]>,
HelpText<"Apply debug prefix mappings to serialized debug info in Swiftmodule files">;
Expand Down
6 changes: 6 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3646,6 +3646,12 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
A->getAsString(Args), A->getValue());
}

if (auto A = Args.getLastArg(OPT_split_dwarf_output)) {
Opts.SplitDwarfOutput = A->getValue();
Opts.SplitDwarfFile =
llvm::sys::path::filename(Opts.SplitDwarfOutput).str();
}

if (auto *A =
Args.getLastArg(OPT_debug_module_path, OPT_debug_module_self_key)) {
if (A->getOption().matches(OPT_debug_module_self_key)) {
Expand Down
23 changes: 22 additions & 1 deletion lib/IRGen/IRGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ swift::getIRTargetOptions(const IRGenOptions &Opts, ASTContext &Ctx,
TargetOpts.EmulatedTLS = Clang->getCodeGenOpts().EmulatedTLS;

TargetOpts.MCOptions.AsmVerbose = Opts.VerboseAsm;
TargetOpts.MCOptions.SplitDwarfFile = Opts.SplitDwarfFile;

// WebAssembly doesn't support atomics yet, see
// https://github.com/apple/swift/issues/54533 for more details.
Expand Down Expand Up @@ -908,15 +909,35 @@ bool swift::compileAndWriteLLVM(
EmitPasses.add(createTargetTransformInfoWrapperPass(
targetMachine->getTargetIRAnalysis()));

// Open a separate output file for split DWARF (.dwo) if requested.
std::unique_ptr<llvm::ToolOutputFile> DwoFile;
if (opts.OutputKind == IRGenOutputKind::ObjectFile &&
!opts.SplitDwarfOutput.empty()) {
std::error_code EC;
DwoFile = std::make_unique<llvm::ToolOutputFile>(
opts.SplitDwarfOutput, EC, llvm::sys::fs::OF_None);
if (EC) {
diagnoseSync(diags, diagMutex, SourceLoc(), diag::error_opening_output,
opts.SplitDwarfOutput, EC.message());
return true;
}
}

bool fail = targetMachine->addPassesToEmitFile(
EmitPasses, out, nullptr, FileType, !opts.Verify, nullptr, casid);
EmitPasses, out, DwoFile ? &DwoFile->os() : nullptr, FileType,
!opts.Verify, nullptr, casid);
if (fail) {
diagnoseSync(diags, diagMutex, SourceLoc(),
diag::error_codegen_init_fail);
return true;
}

EmitPasses.run(*module);

// Keep the DWO file on success (ToolOutputFile deletes on destruction
// unless keep() is called).
if (DwoFile)
DwoFile->keep();
break;
}
}
Expand Down
3 changes: 1 addition & 2 deletions lib/IRGen/IRGenDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2973,8 +2973,7 @@ IRGenDebugInfoImpl::IRGenDebugInfoImpl(const IRGenOptions &Opts,
std::tie(Major, Minor) = version::getSwiftNumericVersion();
unsigned MajorRuntimeVersion = Major;

// No split DWARF on Darwin.
StringRef SplitName = StringRef();
StringRef SplitName = StringRef(Opts.SplitDwarfFile);
// Note that File + Dir need not result in a valid path.
// The directory part of the main file is the current working directory.
std::string RemappedFile = DebugPrefixMap.remapPath(SourcePath);
Expand Down
6 changes: 6 additions & 0 deletions test/DebugInfo/split-dwarf-ir.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g \
// RUN: -split-dwarf-output "test.dwo" -o - | %FileCheck %s

// CHECK: !DICompileUnit({{.*}}splitDebugFilename: "test.dwo"

func hello() -> Int { return 42 }
59 changes: 59 additions & 0 deletions test/DebugInfo/split-dwarf-wasm-multi.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// RUN: %empty-directory(%t)
// RUN: %{python} %utils/split_file.py -o %t %s

// Compile two files with split DWARF via the driver.
// RUN: %empty-directory(%t/out)
// RUN: cd %t/out && %target-swiftc_driver -c %t/main.swift %t/other.swift \
// RUN: -g -enable-split-dwarf -parse-stdlib -module-name TestMod

// Verify each object has only a skeleton CU.
// RUN: %llvm-dwarfdump -v --debug-info %t/out/main.o | %FileCheck --check-prefix=MAIN-OBJ %s
// RUN: %llvm-dwarfdump -v --debug-info %t/out/other.o | %FileCheck --check-prefix=OTHER-OBJ %s

// Verify each .dwo has the full debug info.
// RUN: %llvm-dwarfdump -v --debug-info %t/out/main.dwo | %FileCheck --check-prefix=MAIN-DWO %s
// RUN: %llvm-dwarfdump -v --debug-info %t/out/other.dwo | %FileCheck --check-prefix=OTHER-DWO %s

// Merge into .dwp and verify both CUs are present.
// RUN: llvm-dwp %t/out/main.dwo %t/out/other.dwo -o %t/out/TestMod.dwp
// RUN: %llvm-dwarfdump -v --debug-info %t/out/TestMod.dwp | %FileCheck --check-prefix=MERGED %s

// REQUIRES: CPU=wasm32

// main.o: skeleton only, no subprogram
// MAIN-OBJ: DW_TAG_compile_unit
// MAIN-OBJ: DW_AT_GNU_dwo_name{{.*}}"main.dwo"
// MAIN-OBJ: DW_AT_GNU_dwo_id
// MAIN-OBJ-NOT: DW_TAG_subprogram

// other.o: skeleton only, no subprogram
// OTHER-OBJ: DW_TAG_compile_unit
// OTHER-OBJ: DW_AT_GNU_dwo_name{{.*}}"other.dwo"
// OTHER-OBJ: DW_AT_GNU_dwo_id
// OTHER-OBJ-NOT: DW_TAG_subprogram

// main.dwo: full debug info with foo()
// MAIN-DWO: DW_TAG_compile_unit
// MAIN-DWO: DW_TAG_subprogram
// MAIN-DWO: DW_AT_name{{.*}}"foo"

// other.dwo: full debug info with bar()
// OTHER-DWO: DW_TAG_compile_unit
// OTHER-DWO: DW_TAG_subprogram
// OTHER-DWO: DW_AT_name{{.*}}"bar"

// Merged .dwp: both CUs present (order matches input order to llvm-dwp)
// MERGED: DW_TAG_compile_unit
// MERGED: DW_AT_name{{.*}}main.swift
// MERGED: DW_TAG_subprogram
// MERGED: DW_AT_name{{.*}}"foo"
// MERGED: DW_TAG_compile_unit
// MERGED: DW_AT_name{{.*}}other.swift
// MERGED: DW_TAG_subprogram
// MERGED: DW_AT_name{{.*}}"bar"

// BEGIN main.swift
public func foo() {}

// BEGIN other.swift
public func bar() {}
23 changes: 23 additions & 0 deletions test/DebugInfo/split-dwarf-wasm.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: %empty-directory(%t)
// RUN: cd %t && %target-swiftc_driver -c %s \
// RUN: -g -enable-split-dwarf -parse-stdlib -module-name test
// RUN: %llvm-dwarfdump -v --debug-info %t/split-dwarf-wasm.o | %FileCheck --check-prefix=OBJ %s
// RUN: %llvm-dwarfdump -v %t/split-dwarf-wasm.dwo | %FileCheck --check-prefix=DWO %s
// RUN: llvm-objdump -h %t/split-dwarf-wasm.dwo | %FileCheck --check-prefix=DWO-SECTIONS %s

// REQUIRES: CPU=wasm32

/// The object should contain only a skeleton CU (no full debug info).
// OBJ: DW_TAG_compile_unit
// OBJ: DW_AT_GNU_dwo_name{{.*}}"split-dwarf-wasm.dwo"
// OBJ: DW_AT_GNU_dwo_id
// OBJ-NOT: DW_TAG_subprogram

/// The DWO should contain the full debug info including subprograms.
// DWO: DW_TAG_compile_unit
// DWO: DW_TAG_subprogram

// DWO-SECTIONS: .debug_info.dwo
// DWO-SECTIONS: .debug_abbrev.dwo

public func hello() {}