Skip to content

Commit 9be2ebf

Browse files
committed
[cling] Enable JITLink debugging and profiling support
`CLING_PROFILE=1` enables perf profiling using `jitdump` format. Profiling now requires a `perf inject` step (with JITLink): ``` perf record -k 1 <cling> perf inject -j -i perf.data -o perf.jitted.data perf report -i perf.jitted.data ```
1 parent 7c14897 commit 9be2ebf

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

interpreter/cling/lib/Interpreter/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ set(LLVM_LINK_COMPONENTS
4848
object
4949
option
5050
orcjit
51+
orcdebugging
5152
runtimedyld
5253
scalaropts
5354
support

interpreter/cling/lib/Interpreter/IncrementalJIT.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@
1919
#include <clang/Basic/TargetOptions.h>
2020
#include <clang/Frontend/CompilerInstance.h>
2121

22+
#include <llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h>
23+
#include <llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h>
24+
#include <llvm/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.h>
2225
#include <llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h>
2326
#include <llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h>
2427
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
28+
#include <llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h>
2529
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
2630
#include <llvm/IR/LLVMContext.h>
2731
#include <llvm/MC/TargetRegistry.h>
@@ -40,7 +44,57 @@ using namespace llvm;
4044
using namespace llvm::jitlink;
4145
using namespace llvm::orc;
4246

47+
static LLVM_ATTRIBUTE_USED void linkComponents() {
48+
errs() << "Linking in runtime functions\n"
49+
<< (void*)&llvm_orc_registerJITLoaderPerfStart << '\n'
50+
<< (void*)&llvm_orc_registerJITLoaderPerfEnd << '\n'
51+
<< (void*)&llvm_orc_registerJITLoaderPerfImpl << '\n';
52+
}
53+
4354
namespace {
55+
// This could potentially be upstreamed, similar to enableDebuggerSupport()
56+
Error enablePerfSupport(LLJIT& J) {
57+
auto* ObjLinkingLayer =
58+
dyn_cast<ObjectLinkingLayer>(&J.getObjLinkingLayer());
59+
if (!ObjLinkingLayer)
60+
return make_error<StringError>("Cannot enable LLJIT perf support: "
61+
"perf support requires JITLink",
62+
inconvertibleErrorCode());
63+
auto ProcessSymsJD = J.getProcessSymbolsJITDylib();
64+
if (!ProcessSymsJD)
65+
return make_error<StringError>("Cannot enable LLJIT perf support: "
66+
"Process symbols are not available",
67+
inconvertibleErrorCode());
68+
69+
auto& ES = J.getExecutionSession();
70+
const auto& TT = J.getTargetTriple();
71+
72+
switch (TT.getObjectFormat()) {
73+
case Triple::ELF: {
74+
auto debugInfoPreservationPlugin =
75+
DebugInfoPreservationPlugin::Create();
76+
if (!debugInfoPreservationPlugin)
77+
return debugInfoPreservationPlugin.takeError();
78+
79+
auto perfSupportPlugin =
80+
PerfSupportPlugin::Create(ES.getExecutorProcessControl(),
81+
*ProcessSymsJD, true, true);
82+
if (!perfSupportPlugin)
83+
return perfSupportPlugin.takeError();
84+
85+
ObjLinkingLayer->addPlugin(std::move(*debugInfoPreservationPlugin));
86+
ObjLinkingLayer->addPlugin(std::move(*perfSupportPlugin));
87+
88+
return Error::success();
89+
}
90+
default:
91+
return make_error<StringError>("Cannot enable LLJIT perf support: " +
92+
Triple::getObjectFormatTypeName(
93+
TT.getObjectFormat()) +
94+
" is not supported",
95+
inconvertibleErrorCode());
96+
}
97+
}
4498

4599
class ClingMMapper final : public SectionMemoryManager::MemoryMapper {
46100
public:
@@ -491,6 +545,20 @@ IncrementalJIT::IncrementalJIT(
491545
Builder.setDataLayout(m_TM->createDataLayout());
492546
Builder.setExecutorProcessControl(std::move(EPC));
493547

548+
if (m_JITLink) {
549+
Builder.setPrePlatformSetup([](llvm::orc::LLJIT& J) {
550+
// Try to enable debugging of JIT'd code (only works with JITLink for
551+
// ELF and MachO).
552+
if (cling::utils::ConvertEnvValueToBool(std::getenv("CLING_DEBUG")))
553+
consumeError(enableDebuggerSupport(J));
554+
#ifdef __linux__
555+
if (cling::utils::ConvertEnvValueToBool(std::getenv("CLING_PROFILE")))
556+
consumeError(enablePerfSupport(J));
557+
#endif
558+
return llvm::Error::success();
559+
});
560+
}
561+
494562
// Create ObjectLinkingLayer with our own MemoryManager.
495563
Builder.setObjectLinkingLayerCreator([&](ExecutionSession& ES,
496564
const Triple& TT)

0 commit comments

Comments
 (0)