Skip to content

Commit 44a6c49

Browse files
committed
doc: add three-platform init/fini strategy documentation
1 parent f3aa823 commit 44a6c49

2 files changed

Lines changed: 33 additions & 10 deletions

File tree

addons/tvm-ffi-orcjit/src/ffi/orcjit_dylib.cc

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,11 @@ ORCJITDynamicLibraryObj::ORCJITDynamicLibraryObj(ORCJITExecutionSession session,
6262
}
6363

6464
ORCJITDynamicLibraryObj::~ORCJITDynamicLibraryObj() {
65+
// See InitFiniPlugin class doc in orcjit_session.cc for the three-platform
66+
// init/fini strategy (macOS native vs. Linux/Windows plugin).
6567
#if defined(__linux__) || defined(_WIN32)
66-
// Linux/Windows: run section-based deinitializers (.fini_array, .dtors, .CRT$XT*)
67-
// collected by our custom InitFiniPlugin.
6868
session_->RunPendingDeinitializers(GetJITDylib());
6969
#else
70-
// macOS: native platform's deinitialize drains __cxa_atexit handlers
71-
// (registered during initialization) via the ORC runtime.
7270
if (auto err = jit_->deinitialize(*dylib_)) {
7371
llvm::consumeError(std::move(err));
7472
}
@@ -115,12 +113,12 @@ void* ORCJITDynamicLibraryObj::GetSymbol(const String& name) {
115113
auto symbol_or_err =
116114
jit_->getExecutionSession().lookup(search_order, jit_->mangleAndIntern(name.c_str()));
117115

116+
// Run pending initializers. Both paths are idempotent: RunPendingInitializers
117+
// drains and erases the entry; jit_->initialize() uses dlopen-like refcounting.
118+
// See InitFiniPlugin class doc in orcjit_session.cc for three-platform strategy.
118119
#if defined(__linux__) || defined(_WIN32)
119-
// Linux/Windows: run initializers collected by our custom InitFiniPlugin.
120120
session_->RunPendingInitializers(GetJITDylib());
121121
#else
122-
// macOS: use native platform's init mechanism (handles __mod_init_func
123-
// and __cxa_atexit registration).
124122
if (auto err = jit_->initialize(*dylib_)) {
125123
llvm::consumeError(std::move(err));
126124
}

addons/tvm-ffi-orcjit/src/ffi/orcjit_session.cc

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,31 @@ struct LLVMInitializer {
7373

7474
static LLVMInitializer llvm_initializer;
7575

76+
/*!
77+
* \brief Custom ObjectLinkingLayer plugin for init/fini section handling.
78+
*
79+
* Collects function pointers from init/fini sections (.init_array, .fini_array,
80+
* .ctors, .dtors, .CRT$XC*, .CRT$XT*) and runs them in priority order.
81+
*
82+
* Three-platform init/fini strategy:
83+
*
84+
* - **macOS**: MachOPlatform (via orc_rt) handles __mod_init_func/__mod_term_func
85+
* and __cxa_atexit natively. We delegate to jit_->initialize()/deinitialize().
86+
* No InitFiniPlugin needed.
87+
*
88+
* - **Windows**: COFFPlatform is unusable — it requires MSVC CRT symbols
89+
* (_CxxThrowException, RTTI vtables, etc.) that LLVM's COFF ORC runtime
90+
* cannot provide (stalled for 2+ years). Our plugin handles .CRT$XC*/.CRT$XT*
91+
* sections instead.
92+
*
93+
* - **Linux**: ELFNixPlatform does not handle .init_array/.fini_array correctly
94+
* prior to https://github.com/llvm/llvm-project/pull/175981. Once a new LLVM
95+
* release includes that patch, we can switch Linux to ELFNixPlatform and
96+
* remove the plugin for that platform.
97+
*
98+
* The plugin is gated behind `#if defined(__linux__) || defined(_WIN32)` so it
99+
* can be removed per-platform as LLVM's native platform support matures.
100+
*/
76101
class InitFiniPlugin : public llvm::orc::ObjectLinkingLayer::Plugin {
77102
// Store a raw pointer to avoid a reference cycle:
78103
// Session → LLJIT → ObjectLinkingLayer → Plugin → Session
@@ -565,9 +590,9 @@ ORCJITExecutionSessionObj::ORCJITExecutionSessionObj(const std::string& orc_rt_p
565590
});
566591
#endif
567592
#if defined(__linux__) || defined(_WIN32)
568-
// Linux/Windows: use our custom InitFiniPlugin for init/fini section collection
569-
// and priority-ordered execution.
570-
// macOS: MachOPlatform handles init/fini natively via jit_->initialize()/deinitialize().
593+
// Linux/Windows: use our custom InitFiniPlugin for init/fini section
594+
// collection and priority-ordered execution. See InitFiniPlugin class
595+
// documentation for the three-platform init/fini strategy.
571596
auto& objlayer = jit_->getObjLinkingLayer();
572597
static_cast<llvm::orc::ObjectLinkingLayer&>(objlayer).addPlugin(
573598
std::make_unique<InitFiniPlugin>(this));

0 commit comments

Comments
 (0)