Skip to content

Commit e6401b0

Browse files
jcelerierclaude
andcommitted
jit: use the large code model on COFF so vtable/type_info pointers aren't truncated
After the slab + double-run fixes the real add-on compiles, links and runs its constructors, but crashes in score::registerPlugin -> __dynamic_cast jumping to a half-truncated pointer (0xffffff16_25ffffff). The small (default) code model emits 32-bit absolute relocations for data pointers (vtables, type_info); at the high slab load address those truncate and corrupt RTTI. Set CodeModel::Large on COFF (score plugin + jitmin) for 64-bit references throughout -- expected to fix cross-module dynamic_cast and the c05 exception-typeinfo crash too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJk9KBVYSsZdLhNv2q3mfi
1 parent 458947d commit e6401b0

2 files changed

Lines changed: 21 additions & 0 deletions

File tree

src/plugins/score-plugin-jit/JitCpp/Compiler/Compiler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@ static std::unique_ptr<llvm::orc::LLJIT> jitBuilder(JitCompiler& self)
145145

146146
JTMB->setCodeGenOptLevel(llvm::CodeGenOptLevel::Aggressive);
147147

148+
// On Windows/COFF the add-on is JIT-mapped at a high address (the reserved
149+
// slab) and must reference host symbols far away -- libc++abi RTTI vtables and
150+
// the EH personality among them. The small (default) code model emits 32-bit
151+
// absolute relocations for those data pointers, which truncate at the high load
152+
// address and corrupt vtables / type_info, crashing __dynamic_cast during
153+
// plugin registration (and exception typeinfo lookups). The large code model
154+
// uses 64-bit references throughout, so cross-module RTTI and EH resolve.
155+
if(JTMB->getTargetTriple().isOSBinFormatCOFF())
156+
JTMB->setCodeModel(llvm::CodeModel::Large);
157+
148158
// When the SDK ships LLVM's ORC runtime, drive the executor through an Orc
149159
// Platform (native TLS, real static-init/atexit and -- on COFF -- exception
150160
// registration). Otherwise keep the legacy path (emulated TLS + atexit

tests/jit-min/main.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h>
1717
#include <llvm/ExecutionEngine/Orc/ExecutionUtils.h>
18+
#include <llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h>
1819
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
1920
#include <llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h>
2021
#include <llvm/ExecutionEngine/Orc/MemoryMapper.h>
@@ -76,6 +77,16 @@ int main(int argc, char** argv)
7677
fail("MapperJITLinkMemoryManager::CreateWithMapper", M.takeError());
7778

7879
LLJITBuilder builder;
80+
// Large code model: 64-bit references so vtable/type_info data pointers and far
81+
// host references don't get truncated by 32-bit absolute relocations at the
82+
// high JIT load address (mirrors the score JIT plugin).
83+
if(auto JTMB = JITTargetMachineBuilder::detectHost())
84+
{
85+
JTMB->setCodeModel(CodeModel::Large);
86+
builder.setJITTargetMachineBuilder(std::move(*JTMB));
87+
}
88+
else
89+
fail("JITTargetMachineBuilder::detectHost", JTMB.takeError());
7990
builder.setObjectLinkingLayerCreator(
8091
[](ExecutionSession& ES) -> Expected<std::unique_ptr<ObjectLayer>> {
8192
auto oll = std::make_unique<ObjectLinkingLayer>(ES, *g_memmgr);

0 commit comments

Comments
 (0)