https://github.com/aokblast updated https://github.com/llvm/llvm-project/pull/201286
>From e8b89d39d83b6bcb2894bc2a090b22f7addae659 Mon Sep 17 00:00:00 2001 From: aokblast <[email protected]> Date: Wed, 3 Jun 2026 21:48:20 +0800 Subject: [PATCH 1/4] [Clang][Interpreter] Force GOT access for external data references In clang-repl, R_*_32 relocations are emitted as direct 32-bit PC-relative references. A normal static linker can resolve references to distinct symbol through the GOT or Copy relocation, but clang-repl directly mmaps shared objects into memory and bypasses the static linker. As a result, relocations may become out of range when a symbol is located more than 2GB away from the JIT allocation, which can happen on FreeBSD. Disable DirectAccessExtraData to force external data accesses through the GOT, avoiding the generation of direct 32-bit relocations that are subject to the 2GB addressing limit. --- clang/lib/Interpreter/Interpreter.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 7586c26235449..70cea2819fb5f 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -133,6 +133,17 @@ CreateCI(const llvm::opt::ArgStringList &Argv) { // times, reusing the same AST. Clang->getCodeGenOpts().ClearASTBeforeBackend = false; + // Clang emits direct PC-relative accesses for external data (e.g. C++ + // type-info used by exception handling). As clang-repl directly mmap()s + // shared objects into memory, the target symbol may be more than 2GB away + // from the generated code, resulting in an out-of-range Delta32/PC32 + // relocation. Force GOT-based access instead so the relocation remains + // within range. + // + // Unlike -fPIC, this does not define __PIC__ and remains compatible with + // precompiled headers. + Clang->getCodeGenOpts().DirectAccessExternalData = false; + Clang->getFrontendOpts().DisableFree = false; Clang->getCodeGenOpts().DisableFree = false; return std::move(Clang); >From 53616b351dbdd4c83603f633edad4f4c9344e4bf Mon Sep 17 00:00:00 2001 From: aokblast <[email protected]> Date: Tue, 9 Jun 2026 21:38:20 +0800 Subject: [PATCH 2/4] fixup! [Clang][Interpreter] Force GOT access for external data references --- clang/lib/Interpreter/Interpreter.cpp | 22 +++++++++++----------- clang/test/Interpreter/execute-pch.cpp | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 70cea2819fb5f..34da251b033da 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -133,17 +133,6 @@ CreateCI(const llvm::opt::ArgStringList &Argv) { // times, reusing the same AST. Clang->getCodeGenOpts().ClearASTBeforeBackend = false; - // Clang emits direct PC-relative accesses for external data (e.g. C++ - // type-info used by exception handling). As clang-repl directly mmap()s - // shared objects into memory, the target symbol may be more than 2GB away - // from the generated code, resulting in an out-of-range Delta32/PC32 - // relocation. Force GOT-based access instead so the relocation remains - // within range. - // - // Unlike -fPIC, this does not define __PIC__ and remains compatible with - // precompiled headers. - Clang->getCodeGenOpts().DirectAccessExternalData = false; - Clang->getFrontendOpts().DisableFree = false; Clang->getCodeGenOpts().DisableFree = false; return std::move(Clang); @@ -164,6 +153,17 @@ IncrementalCompilerBuilder::create(std::string TT, ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str()); + // Compile as position-independent code. This prevents the frontend from + // marking external symbols (e.g. C++ type-info such as _ZTIPKc used for + // exception handling) as dso_local and emitting direct PC-relative + // references. JITLink can place the GOT entry near the JIT'd code, keeping + // the relocation in range. Without -fPIC, a direct Delta32 relocation to a + // host symbol may be out of range when the JIT memory is mapped more than + // 2GB away (as on FreeBSD), breaking tests such as + // Interpreter/simple-exception.cpp. Insert before user arguments so it can + // still be overridden. + ClangArgv.insert(ClangArgv.begin() + 1, "-fPIC"); + // Prepending -c to force the driver to do something if no action was // specified. By prepending we allow users to override the default // action and use other actions in incremental mode. diff --git a/clang/test/Interpreter/execute-pch.cpp b/clang/test/Interpreter/execute-pch.cpp index 8041ee6ac966d..2247cf5583095 100644 --- a/clang/test/Interpreter/execute-pch.cpp +++ b/clang/test/Interpreter/execute-pch.cpp @@ -5,7 +5,7 @@ // RUN: mkdir -p %t // RUN: split-file %s %t // -// RUN: %clang -fmax-type-align=16 -Xclang -fdeprecated-macro -fno-stack-protector -Xclang -fwrapv -Xclang -fblocks -Xclang -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -target %host-jit-triple -Xclang -fblocks -Xclang -fmax-type-align=8 -Xclang -fincremental-extensions -Xclang -emit-pch -x c++-header -o %t/include.pch %t/include.hpp +// RUN: %clang -fPIC -fmax-type-align=16 -Xclang -fdeprecated-macro -fno-stack-protector -Xclang -fwrapv -Xclang -fblocks -Xclang -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -target %host-jit-triple -Xclang -fblocks -Xclang -fmax-type-align=8 -Xclang -fincremental-extensions -Xclang -emit-pch -x c++-header -o %t/include.pch %t/include.hpp // // RUN: cat %t/main.cpp \ // RUN: | clang-repl -Xcc -fgnuc-version=0 -Xcc -fno-stack-protector -Xcc -fwrapv -Xcc -fblocks -Xcc -fskip-odr-check-in-gmf -Xcc -fmax-type-align=8 -Xcc -include-pch -Xcc %t/include.pch \ >From 0422591ba27ab25b2634ccc28571f5ed28e24b2e Mon Sep 17 00:00:00 2001 From: aokblast <[email protected]> Date: Wed, 10 Jun 2026 01:37:19 +0800 Subject: [PATCH 3/4] fixup! [Clang][Interpreter] Force GOT access for external data references --- clang/test/Interpreter/execute-pch.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/test/Interpreter/execute-pch.cpp b/clang/test/Interpreter/execute-pch.cpp index 2247cf5583095..d7b69989fc2bc 100644 --- a/clang/test/Interpreter/execute-pch.cpp +++ b/clang/test/Interpreter/execute-pch.cpp @@ -5,7 +5,12 @@ // RUN: mkdir -p %t // RUN: split-file %s %t // -// RUN: %clang -fPIC -fmax-type-align=16 -Xclang -fdeprecated-macro -fno-stack-protector -Xclang -fwrapv -Xclang -fblocks -Xclang -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -target %host-jit-triple -Xclang -fblocks -Xclang -fmax-type-align=8 -Xclang -fincremental-extensions -Xclang -emit-pch -x c++-header -o %t/include.pch %t/include.hpp +// RUN: %if system-windows %{ \ +// RUN: %clang -fmax-type-align=16 -Xclang -fdeprecated-macro -fno-stack-protector -Xclang -fwrapv -Xclang -fblocks -Xclang -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -target %host-jit-triple -Xclang -fblocks -Xclang -fmax-type-align=8 -Xclang -fincremental-extensions -Xclang -emit-pch -x c++-header -o %t/include.pch %t/include.hpp \ +// RUN: %} \ +// RUN: %else %{ \ +// RUN: %clang -fPIC -fmax-type-align=16 -Xclang -fdeprecated-macro -fno-stack-protector -Xclang -fwrapv -Xclang -fblocks -Xclang -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -target %host-jit-triple -Xclang -fblocks -Xclang -fmax-type-align=8 -Xclang -fincremental-extensions -Xclang -emit-pch -x c++-header -o %t/include.pch %t/include.hpp \ +// RUN: %} // // RUN: cat %t/main.cpp \ // RUN: | clang-repl -Xcc -fgnuc-version=0 -Xcc -fno-stack-protector -Xcc -fwrapv -Xcc -fblocks -Xcc -fskip-odr-check-in-gmf -Xcc -fmax-type-align=8 -Xcc -include-pch -Xcc %t/include.pch \ >From 8ede2399e8454fc0e8c05a5a0f4f9a9d6f27943e Mon Sep 17 00:00:00 2001 From: ShengYi Hung <[email protected]> Date: Fri, 19 Jun 2026 21:23:23 +0800 Subject: [PATCH 4/4] fixup! [Clang][Interpreter] Force GOT access for external data references --- clang/lib/Interpreter/Interpreter.cpp | 46 +++++++++++++++++++++ clang/test/Interpreter/pch-pic-mismatch.cpp | 28 +++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 clang/test/Interpreter/pch-pic-mismatch.cpp diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 34da251b033da..4199b11aee00a 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Mangle.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/FileManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CodeGenAction.h" #include "clang/CodeGen/ObjectFilePCHContainerWriter.h" @@ -40,6 +41,8 @@ #include "clang/Options/OptionUtils.h" #include "clang/Options/Options.h" #include "clang/Sema/Lookup.h" +#include "clang/Serialization/ASTReader.h" +#include "clang/Serialization/ModuleCache.h" #include "clang/Serialization/ObjectFilePCHContainerReader.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" @@ -80,6 +83,22 @@ GetCC1Arguments(DiagnosticsEngine *Diagnostics, return &Cmd->getArguments(); } +// ASTReaderListener that captures the PIC level stored in a PCH file so the +// interpreter can compare it against its own PIC level. +class PICLevelReader : public ASTReaderListener { + unsigned &PICLevel; + +public: + PICLevelReader(unsigned &PICLevel) : PICLevel(PICLevel) {} + + bool ReadLanguageOptions(const LangOptions &LangOpts, + StringRef ModuleFilename, bool Complain, + bool AllowCompatibleDifferences) override { + PICLevel = LangOpts.PICLevel; + return false; + } +}; + static llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCI(const llvm::opt::ArgStringList &Argv) { std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); @@ -135,6 +154,32 @@ CreateCI(const llvm::opt::ArgStringList &Argv) { Clang->getFrontendOpts().DisableFree = false; Clang->getCodeGenOpts().DisableFree = false; + + // clang-repl always compiles position-independent code (it injects -fPIC), + // so a PCH that was built with a different PIC level is incompatible: mixing + // the two leads to relocations that may be out of range once the JIT maps + // code more than 2GB away. PICLevel is a "compatible" language option, so the + // ASTReader would otherwise accept the mismatch silently. Reject it up front + // here, before any Interpreter/FrontendAction is constructed. + StringRef PCHInclude = Clang->getPreprocessorOpts().ImplicitPCHInclude; + if (!PCHInclude.empty()) { + llvm::IntrusiveRefCntPtr<FileManager> FileMgr(new FileManager( + Clang->getFileSystemOpts(), Clang->getVirtualFileSystemPtr())); + std::shared_ptr<ModuleCache> ModCache = createCrossProcessModuleCache(); + unsigned PCHPICLevel = 0; + PICLevelReader Reader(PCHPICLevel); + if (!ASTReader::readASTFileControlBlock( + PCHInclude, *FileMgr, *ModCache, Clang->getPCHContainerReader(), + /*FindModuleFileExtensions=*/false, Reader, + /*ValidateDiagnosticOptions=*/false) && + PCHPICLevel != Clang->getLangOpts().PICLevel) + return llvm::createStringError( + llvm::errc::not_supported, + "PCH file '%s' was built with PIC level %u, which is incompatible " + "with clang-repl's PIC level %u", + PCHInclude.str().c_str(), PCHPICLevel, Clang->getLangOpts().PICLevel); + } + return std::move(Clang); } @@ -275,6 +320,7 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance, if (ErrOut) return; + CI->ExecuteAction(*Act); IncrParser = diff --git a/clang/test/Interpreter/pch-pic-mismatch.cpp b/clang/test/Interpreter/pch-pic-mismatch.cpp new file mode 100644 index 0000000000000..0a0a79fbee079 --- /dev/null +++ b/clang/test/Interpreter/pch-pic-mismatch.cpp @@ -0,0 +1,28 @@ +// REQUIRES: host-supports-jit +// UNSUPPORTED: system-aix, system-windows +// +// clang-repl compiles position-independent code (it injects -fPIC), so a PCH +// built with a different PIC level is incompatible and must be rejected instead +// of silently accepted as a "compatible" language-option difference. +// +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang -fno-pic -Xclang -fincremental-extensions -target %host-jit-triple \ +// RUN: -Xclang -emit-pch -x c++-header -o %t/include.pch %t/include.hpp +// +// RUN: cat %t/main.cpp \ +// RUN: | not clang-repl -Xcc -include-pch -Xcc %t/include.pch 2>&1 \ +// RUN: | FileCheck %s + +//--- include.hpp + +int f_pch() { return 5; } + +//--- main.cpp + +extern "C" int printf(const char *, ...); +printf("f_pch = %d\n", f_pch()); + +// CHECK: incompatible with clang-repl's PIC level _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
