Skip to content

Commit 8d21750

Browse files
committed
Frontend: support dumping the JIT state
Add a debugging mechanism that enables the JIT to dump the LLVM IR and object files to enable debugging the JIT. This makes it easier to debug the JIT mode failures. The idea was from Lang Hames!
1 parent e4f5cc2 commit 8d21750

File tree

5 files changed

+67
-2
lines changed

5 files changed

+67
-2
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ struct PointerAuthOptions : clang::PointerAuthOptions {
139139
PointerAuthSchema ResilientClassStubInitCallbacks;
140140
};
141141

142+
enum class JITDebugArtifact : unsigned {
143+
None, ///< None
144+
LLVMIR, ///< LLVM IR
145+
Object, ///< Object File
146+
};
147+
142148
/// The set of options supported by IR generation.
143149
class IRGenOptions {
144150
public:
@@ -326,6 +332,8 @@ class IRGenOptions {
326332
Optional<llvm::VersionTuple> AutolinkRuntimeCompatibilityLibraryVersion;
327333
Optional<llvm::VersionTuple> AutolinkRuntimeCompatibilityDynamicReplacementLibraryVersion;
328334

335+
JITDebugArtifact DumpJIT = JITDebugArtifact::None;
336+
329337
IRGenOptions()
330338
: DWARFVersion(2), OutputKind(IRGenOutputKind::LLVMAssembly),
331339
Verify(true), OptMode(OptimizationMode::NotSet),

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ def disable_llvm_verify : Flag<["-"], "disable-llvm-verify">,
329329
def disable_llvm_value_names : Flag<["-"], "disable-llvm-value-names">,
330330
HelpText<"Don't add names to local values in LLVM IR">;
331331

332+
def dump_jit : JoinedOrSeparate<["-"], "dump-jit">,
333+
HelpText<"Dump JIT contents">;
334+
332335
def enable_llvm_value_names : Flag<["-"], "enable-llvm-value-names">,
333336
HelpText<"Add names to local values in LLVM IR">;
334337

lib/Frontend/CompilerInvocation.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,9 +1448,23 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
14481448
if (Args.hasArg(OPT_disable_concrete_type_metadata_mangled_name_accessors))
14491449
Opts.DisableConcreteTypeMetadataMangledNameAccessors = true;
14501450

1451-
if (Args.hasArg(OPT_use_jit))
1451+
if (Args.hasArg(OPT_use_jit)) {
14521452
Opts.UseJIT = true;
1453-
1453+
if (const Arg *A = Args.getLastArg(OPT_dump_jit)) {
1454+
llvm::Optional<swift::JITDebugArtifact> artifact =
1455+
llvm::StringSwitch<llvm::Optional<swift::JITDebugArtifact>>(A->getValue())
1456+
.Case("llvm-ir", JITDebugArtifact::LLVMIR)
1457+
.Case("object", JITDebugArtifact::Object)
1458+
.Default(None);
1459+
if (!artifact) {
1460+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
1461+
A->getOption().getName(), A->getValue());
1462+
return true;
1463+
}
1464+
Opts.DumpJIT = *artifact;
1465+
}
1466+
}
1467+
14541468
for (const Arg *A : Args.filtered(OPT_verify_type_layout)) {
14551469
Opts.VerifyTypeLayoutNames.push_back(A->getValue());
14561470
}

lib/Immediate/Immediate.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/SILOptimizer/PassManager/Passes.h"
3131
#include "llvm/ADT/SmallString.h"
3232
#include "llvm/Config/config.h"
33+
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
3334
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
3435
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
3536
#include "llvm/IR/LLVMContext.h"
@@ -75,6 +76,18 @@ static void *loadRuntimeLib(StringRef sharedLibName,
7576
return nullptr;
7677
}
7778

79+
static void DumpLLVMIR(const llvm::Module &M) {
80+
std::string path = (M.getName() + ".ll").str();
81+
for (size_t count = 0; llvm::sys::fs::exists(path); )
82+
path = (M.getName() + llvm::utostr(count++) + ".ll").str();
83+
84+
std::error_code error;
85+
llvm::raw_fd_ostream stream(path, error);
86+
if (error)
87+
return;
88+
M.print(stream, /*AssemblyAnnotationWriter=*/nullptr);
89+
}
90+
7891
void *swift::immediate::loadSwiftRuntime(ArrayRef<std::string>
7992
runtimeLibPaths) {
8093
#if defined(_WIN32)
@@ -290,6 +303,18 @@ int swift::RunImmediately(CompilerInstance &CI,
290303
}
291304

292305
auto Module = GenModule.getModule();
306+
307+
switch (IRGenOpts.DumpJIT) {
308+
case JITDebugArtifact::None:
309+
break;
310+
case JITDebugArtifact::LLVMIR:
311+
DumpLLVMIR(*Module);
312+
break;
313+
case JITDebugArtifact::Object:
314+
JIT->getObjTransformLayer().setTransform(llvm::orc::DumpObjects());
315+
break;
316+
}
317+
293318
{
294319
// Get a generator for the process symbols and attach it to the main
295320
// JITDylib.

test/IRGen/jit-debugging.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// %empty-directory(%t)
2+
// RUN: not %target-swift-frontend -use-jit -dump-jit invalid -interpret %s 2>&1 | %FileCheck -check-prefix CHECK-INVALID %s
3+
// CHECK-INVALID: error: invalid value 'invalid' in 'dump-jit'
4+
5+
// RUN: %empty-directory(%t)
6+
// RUN: cd %t && %target-swift-frontend -use-jit -dump-jit llvm-ir -interpret %s
7+
// RUN: %FileCheck -check-prefix CHECK-LLIR %s < %t/main.ll
8+
// CHECK-LLIR: ; ModuleID = 'main'
9+
10+
// RUN: %empty-directory(%t)
11+
// RUN: cd %t && %target-swift-frontend -use-jit -dump-jit object -interpret %s
12+
// RUN: %llvm-nm --defined-only --extern-only %t/main-jitted-objectbuffer.o | %FileCheck -check-prefix CHECK-OBJ %s
13+
// CHECK-OBJ: T {{_?}}main
14+
15+
let zero = 0

0 commit comments

Comments
 (0)