|
23 | 23 | #include "Pipeline.h" |
24 | 24 | #include "WasmExecutor.h" |
25 | 25 |
|
| 26 | +extern "C" unsigned long __udivdi3(unsigned long a, unsigned long b); |
| 27 | + |
26 | 28 | namespace Halide { |
27 | 29 | namespace Internal { |
28 | 30 |
|
29 | 31 | using std::string; |
30 | 32 |
|
31 | | -#if defined(__GNUC__) && defined(__i386__) |
32 | | -extern "C" unsigned long __udivdi3(unsigned long a, unsigned long b); |
33 | | -#endif |
34 | | - |
35 | 33 | #ifdef _WIN32 |
36 | 34 | void *get_symbol_address(const char *s) { |
37 | 35 | return (void *)GetProcAddress(GetModuleHandle(nullptr), s); |
@@ -135,6 +133,26 @@ void load_webgpu() { |
135 | 133 | << "(Try setting the env var HL_WEBGPU_NATIVE_LIB to an explicit path to fix this.)\n"; |
136 | 134 | } |
137 | 135 |
|
| 136 | +llvm::orc::SymbolMap GetListOfAdditionalSymbols(const llvm::orc::LLJIT &Jit) { |
| 137 | + // Inject a number of symbols that may be in libgcc.a where they are |
| 138 | + // not found automatically. See also the upstream issue: |
| 139 | + // https://github.com/llvm/llvm-project/issues/61289. |
| 140 | + |
| 141 | + static const std::pair<const char *, const void *> NamePtrList[] = { |
| 142 | + // NOTE: at least libgcc does not provide this symbol on 64-bit x86_64, only on 32-bit i386. |
| 143 | + {"__udivdi3", (((CHAR_BIT * sizeof(void *)) == 32) ? ((void *)&__udivdi3) : nullptr)}, |
| 144 | + }; |
| 145 | + |
| 146 | + llvm::orc::SymbolMap AdditionalSymbols; |
| 147 | + for (const auto &NamePtr : NamePtrList) { |
| 148 | + auto Addr = static_cast<llvm::orc::ExecutorAddr>( |
| 149 | + reinterpret_cast<uintptr_t>(NamePtr.second)); |
| 150 | + AdditionalSymbols[Jit.mangleAndIntern(NamePtr.first)] = |
| 151 | + llvm::orc::ExecutorSymbolDef(Addr, llvm::JITSymbolFlags::Exported); |
| 152 | + } |
| 153 | + return AdditionalSymbols; |
| 154 | +} |
| 155 | + |
138 | 156 | } // namespace |
139 | 157 |
|
140 | 158 | using namespace llvm; |
@@ -216,25 +234,6 @@ class HalideJITMemoryManager : public SectionMemoryManager { |
216 | 234 | } |
217 | 235 | } |
218 | 236 | uint64_t result = SectionMemoryManager::getSymbolAddress(name); |
219 | | -#if defined(__GNUC__) && defined(__i386__) |
220 | | - // This is a workaround for an odd corner case (cross-compiling + testing |
221 | | - // Python bindings x86-32 on an x86-64 system): __udivdi3 is a helper function |
222 | | - // that GCC uses to do u64/u64 division on 32-bit systems; it's usually included |
223 | | - // by the linker on these systems as needed. When we JIT, LLVM will include references |
224 | | - // to this call; MCJIT fixes up these references by doing (roughly) dlopen(NULL) |
225 | | - // to look up the symbol. For normal JIT tests, this works fine, as dlopen(NULL) |
226 | | - // finds the test executable, which has the right lookups to locate it inside libHalide.so. |
227 | | - // If, however, we are running a JIT-via-Python test, dlopen(NULL) returns the |
228 | | - // CPython executable... which apparently *doesn't* include this as an exported |
229 | | - // function, so the lookup fails and crashiness ensues. So our workaround here is |
230 | | - // a bit icky, but expedient: check for this name if we can't find it elsewhere, |
231 | | - // and if so, return the one we know should be present. (Obviously, if other runtime |
232 | | - // helper functions of this sort crop up in the future, this should be expanded |
233 | | - // into a "builtins map".) |
234 | | - if (result == 0 && name == "__udivdi3") { |
235 | | - result = (uint64_t)&__udivdi3; |
236 | | - } |
237 | | -#endif |
238 | 237 | internal_assert(result != 0) |
239 | 238 | << "HalideJITMemoryManager: unable to find address for " << name << "\n"; |
240 | 239 | return result; |
@@ -350,6 +349,8 @@ void JITModule::compile_module(std::unique_ptr<llvm::Module> m, const string &fu |
350 | 349 | internal_assert(gen) << llvm::toString(gen.takeError()) << "\n"; |
351 | 350 | JIT->getMainJITDylib().addGenerator(std::move(gen.get())); |
352 | 351 |
|
| 352 | + cantFail(JIT->getMainJITDylib().define(absoluteSymbols(GetListOfAdditionalSymbols(*JIT)))); |
| 353 | + |
353 | 354 | llvm::orc::ThreadSafeModule tsm(std::move(m), std::move(jit_module->context)); |
354 | 355 | auto err = JIT->addIRModule(std::move(tsm)); |
355 | 356 | internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; |
|
0 commit comments