https://github.com/aokblast created https://github.com/llvm/llvm-project/pull/201286
In clang-repl, R_*_32 relocations are emitted as direct 32-bit PC-relative references. A normal static linker can resolve distant symbols through PLT or copy relocations, but clang-repl directly mmap shared objects into memory and bypasses static linker. As a result, relocations may become out of range when a symbol is more than 2GB away from the JIT allocation, which can happen on FreeBSD. Use the large code model to avoid generating such relocations. The x86-64 JIT Target Machine already defaults to the large code model, but LLJIT overrides an unset code model with CodeModel::Small. >From f2d55ee986dd1ebe800fd5d905cc52d5ae91c76b Mon Sep 17 00:00:00 2001 From: aokblast <[email protected]> Date: Wed, 3 Jun 2026 01:02:47 +0800 Subject: [PATCH] [Clang][Interpreter] Set default to large code In clang-repl, R_*_32 relocations are emitted as direct 32-bit PC-relative references. A normal static linker can resolve distant symbols through PLT or copy relocations, but clang-repl directly mmap shared objects into memory and bypasses static linker. As a result, relocations may become out of range when a symbol is more than 2GB away from the JIT allocation, which can happen on FreeBSD. Use the large code model to avoid generating such relocations. The x86-64 JIT Target Machine already defaults to the large code model, but LLJIT overrides an unset code model with CodeModel::Small. --- clang/lib/Interpreter/IncrementalExecutor.cpp | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp index 65cb29a2f441a..9ff1bb6bb92b2 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.cpp +++ b/clang/lib/Interpreter/IncrementalExecutor.cpp @@ -65,12 +65,31 @@ IncrementalExecutorBuilder::~IncrementalExecutorBuilder() = default; static llvm::Expected<llvm::orc::JITTargetMachineBuilder> createJITTargetMachineBuilder(const llvm::Triple &TT) { - if (TT.getTriple() == llvm::sys::getProcessTriple()) - // This fails immediately if the target backend is not registered - return llvm::orc::JITTargetMachineBuilder::detectHost(); + auto JTMB = [&]() -> llvm::Expected<llvm::orc::JITTargetMachineBuilder> { + if (TT.getTriple() == llvm::sys::getProcessTriple()) + // This fails immediately if the target backend is not registered + return llvm::orc::JITTargetMachineBuilder::detectHost(); + + // If the target backend is not registered, LLJITBuilder::create() will fail + return llvm::orc::JITTargetMachineBuilder(TT); + }(); + if (!JTMB) + return JTMB.takeError(); - // If the target backend is not registered, LLJITBuilder::create() will fail - return llvm::orc::JITTargetMachineBuilder(TT); + // Use the large code model. Some external symbols used by exception + // handling (e.g. _ZTIPKc) can end up more than 2GB away from the JIT + // allocation on FreeBSD. With the small code model, LLVM may emit + // Delta32/PC32 relocations that cannot reach those symbols. + // + // The x86-64 JIT TargetMachine already defaults to the large code model, + // but LLJIT overrides an unset code model with CodeModel::Small. Set it + // explicitly here to avoid that override. + // + // Unlike -fPIC, this only affects code generation. It does not change + // the __PIC__ preprocessor state, so PCH files remain compatible. + if (!JTMB->getCodeModel()) + JTMB->setCodeModel(llvm::CodeModel::Large); + return JTMB; } static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
