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

Reply via email to