In LLVM 3.0 JIT on MinGW64 / MSCV64, when handling external symbol addresses outside the 32-bit range (within a 2 GB window before or after the current address) during code-block relocation, the address is cast to 32 bits:

 1// lib\Target\X86\X86JITInfo.cpp:543
 2void X86JITInfo::relocate(void *Function, MachineRelocation *MR,
 3                          unsigned NumRelocs, unsigned char* GOTBase) {
 4  for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
 5    void *RelocPos = (char*)Function + MR->getMachineCodeOffset();
 6    intptr_t ResultPtr = (intptr_t)MR->getResultPointer();
 7    switch ((X86::RelocationType)MR->getRelocationType()) {
 8    case X86::reloc_pcrel_word: {
 9      ResultPtr = ResultPtr -(intptr_t)RelocPos - 4 - MR->getConstantVal();
10      *((unsigned*)RelocPos) += (unsigned)ResultPtr; // This is implicitly cast to 32 bits
11      break;
12    }
13}

This causes the generated instruction to crash at runtime, usually as a segmentation fault.

Fix:

 1From bdc19fc6fa1a87a375e5f77e83bc6e712185676a Mon Sep 17 00:00:00 2001
 2From: zevorn <zevorn@yeah.net>
 3Date: Wed, 22 May 2024 18:31:30 +0800
 4Subject: [PATCH 1/4] <fix>(JIT) Fix a Bug in JIT
 5
 6Fixed a bug in the JIT code-block relocation phase when resolving external symbols
 7---
 8 lib/ExecutionEngine/JIT/JITEmitter.cpp | 6 +++++-
 9 1 file changed, 5 insertions(+), 1 deletion(-)
10
11diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
12index 24020ee..0050b75 100644
13--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
14+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
15@@ -849,7 +849,11 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
16                        << ResultPtr << "]\n");
17 
18           // If the target REALLY wants a stub for this function, emit it now.
19 -          if (MR.mayNeedFarStub()) {
20 +          uintptr_t CurrPtr = getCurrentPCValue();
21 +          const uintptr_t rang = 2ull * 1024 * 1024 * 1024; // 2 GB
22 +          if (MR.mayNeedFarStub()
23 +            || ((CurrPtr + rang) < (uintptr_t)ResultPtr)
24 +            || ((CurrPtr - rang) > (uintptr_t)ResultPtr)) {
25             ResultPtr = Resolver.getExternalFunctionStub(ResultPtr);
26           }
27         } else if (MR.isGlobalValue()) {
28-- 
292.44.0.windows.1

PS: This issue also seems to exist in LLVM 3.1.