From 41b3fe41d2499afc86d421d105b584dd30c5ac38 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Tue, 8 Nov 2022 10:34:25 +0300 Subject: [PATCH 01/14] Migrate from MCJIT to ORC JIT --- dependencies/llvm/CMakeLists.txt | 2 +- src/JITModule.cpp | 192 ++++++++++++++++--------------- src/LLVM_Headers.h | 4 +- 3 files changed, 102 insertions(+), 96 deletions(-) diff --git a/dependencies/llvm/CMakeLists.txt b/dependencies/llvm/CMakeLists.txt index ef357ecd5baf..41be363b5744 100644 --- a/dependencies/llvm/CMakeLists.txt +++ b/dependencies/llvm/CMakeLists.txt @@ -53,7 +53,7 @@ endif () # Create options for including or excluding LLVM backends. ## -set(active_components mcjit bitwriter linker passes) +set(active_components orcjit bitwriter linker passes) set(known_components AArch64 AMDGPU ARM Hexagon Mips NVPTX PowerPC RISCV WebAssembly X86) foreach (comp IN LISTS known_components) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index e595613ffb5e..a58127f7955f 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -127,15 +127,16 @@ class JITModuleContents { JITModuleContents() = default; ~JITModuleContents() { - if (execution_engine != nullptr) { - execution_engine->runStaticConstructorsDestructors(true); - delete execution_engine; + if (JIT != nullptr) { + llvm::cantFail(dtorRunner->run()); + delete dtorRunner; } } std::map exports; - llvm::LLVMContext context; - ExecutionEngine *execution_engine = nullptr; + std::unique_ptr context = std::make_unique(); + std::unique_ptr JIT = nullptr; + llvm::orc::CtorDtorRunner* dtorRunner = nullptr; std::vector dependencies; JITModule::Symbol entrypoint; JITModule::Symbol argv_entrypoint; @@ -156,11 +157,15 @@ void destroy(const JITModuleContents *f) { namespace { // Retrieve a function pointer from an llvm module, possibly by compiling it. -JITModule::Symbol compile_and_get_function(ExecutionEngine &ee, const string &name) { +JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT& JIT, const string &name) { debug(2) << "JIT Compiling " << name << "\n"; - llvm::Function *fn = ee.FindFunctionNamed(name); - internal_assert(fn->getName() == name); - void *f = (void *)ee.getFunctionAddress(name); + + auto addr = JIT.lookup(name); + if (auto E = addr.takeError()) { + throw E; + } + + void *f = (void *)addr->getValue(); if (!f) { internal_error << "Compiling " << name << " returned nullptr\n"; } @@ -172,56 +177,38 @@ JITModule::Symbol compile_and_get_function(ExecutionEngine &ee, const string &na return symbol; } -// Expand LLVM's search for symbols to include code contained in a set of JITModule. -class HalideJITMemoryManager : public SectionMemoryManager { - std::vector modules; - std::vector> code_pages; - +class HalideJITGenerator : public llvm::orc::DefinitionGenerator { public: - HalideJITMemoryManager(const std::vector &modules) - : modules(modules) { - } - - uint64_t getSymbolAddress(const std::string &name) override { - for (const auto &module : modules) { - std::map::const_iterator iter = module.exports().find(name); - if (iter == module.exports().end() && starts_with(name, "_")) { - iter = module.exports().find(name.substr(1)); - } - if (iter != module.exports().end()) { - return (uint64_t)iter->second.address; + HalideJITGenerator(const std::vector &modules) + : modules(modules) {} + + llvm::Error tryToGenerate(llvm::orc::LookupState &LS, llvm::orc::LookupKind K, llvm::orc::JITDylib &JD, + llvm::orc::JITDylibLookupFlags JDLookupFlags, + const llvm::orc::SymbolLookupSet &LookupSet) override { + llvm::orc::SymbolMap NewSymbols; + + llvm::orc::SymbolLookupSet LookupSetCopy; + for (auto& symbol : LookupSet) { + std::string name = (*symbol.first).str(); + + for (const auto &module : modules) { + std::map::const_iterator iter = module.exports().find(name); + if (iter == module.exports().end() && starts_with(name, "_")) { + iter = module.exports().find(name.substr(1)); + } + if (iter != module.exports().end()) { + NewSymbols.insert({symbol.first, llvm::JITEvaluatedSymbol::fromPointer(iter->second.address)}); + } } } - uint64_t result = SectionMemoryManager::getSymbolAddress(name); -#if defined(__GNUC__) && defined(__i386__) - // This is a workaround for an odd corner case (cross-compiling + testing - // Python bindings x86-32 on an x86-64 system): __udivdi3 is a helper function - // that GCC uses to do u64/u64 division on 32-bit systems; it's usually included - // by the linker on these systems as needed. When we JIT, LLVM will include references - // to this call; MCJIT fixes up these references by doing (roughly) dlopen(NULL) - // to look up the symbol. For normal JIT tests, this works fine, as dlopen(NULL) - // finds the test executable, which has the right lookups to locate it inside libHalide.so. - // If, however, we are running a JIT-via-Python test, dlopen(NULL) returns the - // CPython executable... which apparently *doesn't* include this as an exported - // function, so the lookup fails and crashiness ensues. So our workaround here is - // a bit icky, but expedient: check for this name if we can't find it elsewhere, - // and if so, return the one we know should be present. (Obviously, if other runtime - // helper functions of this sort crop up in the future, this should be expanded - // into a "builtins map".) - if (result == 0 && name == "__udivdi3") { - result = (uint64_t)&__udivdi3; - } -#endif - internal_assert(result != 0) - << "HalideJITMemoryManager: unable to find address for " << name << "\n"; - return result; - } + if (NewSymbols.empty()) + return llvm::Error::success(); - uint8_t *allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, StringRef section_name) override { - uint8_t *result = SectionMemoryManager::allocateCodeSection(size, alignment, section_id, section_name); - code_pages.emplace_back(result, size); - return result; + return JD.define(llvm::orc::absoluteSymbols(std::move(NewSymbols))); } + +private: + std::vector modules; }; } // namespace @@ -233,7 +220,7 @@ JITModule::JITModule() { JITModule::JITModule(const Module &m, const LoweredFunc &fn, const std::vector &dependencies) { jit_module = new JITModuleContents(); - std::unique_ptr llvm_module(compile_module_to_llvm_module(m, jit_module->context)); + std::unique_ptr llvm_module(compile_module_to_llvm_module(m, *jit_module->context)); std::vector deps_with_runtime = dependencies; std::vector shared_runtime = JITSharedRuntime::get(llvm_module.get(), m.target()); deps_with_runtime.insert(deps_with_runtime.end(), shared_runtime.begin(), shared_runtime.end()); @@ -262,30 +249,23 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu DataLayout initial_module_data_layout = m->getDataLayout(); string module_name = m->getModuleIdentifier(); - llvm::EngineBuilder engine_builder((std::move(m))); - engine_builder.setTargetOptions(options); - engine_builder.setErrorStr(&error_string); - engine_builder.setEngineKind(llvm::EngineKind::JIT); - HalideJITMemoryManager *memory_manager = new HalideJITMemoryManager(dependencies); - engine_builder.setMCJITMemoryManager(std::unique_ptr(memory_manager)); + // Build TargetMachine + llvm::orc::JITTargetMachineBuilder tm_builder(llvm::Triple("x86_64-unknown-linux-gnu")); + tm_builder.setOptions(options); + tm_builder.setCodeGenOptLevel(CodeGenOpt::Aggressive); - engine_builder.setOptLevel(CodeGenOpt::Aggressive); + auto tm = tm_builder.createTargetMachine(); + if (auto E = tm.takeError()) { + throw E; + } - TargetMachine *tm = engine_builder.selectTarget(); - internal_assert(tm) << error_string << "\n"; - DataLayout target_data_layout(tm->createDataLayout()); + DataLayout target_data_layout(tm.get()->createDataLayout()); if (initial_module_data_layout != target_data_layout) { internal_error << "Warning: data layout mismatch between module (" << initial_module_data_layout.getStringRepresentation() << ") and what the execution engine expects (" << target_data_layout.getStringRepresentation() << ")\n"; } - ExecutionEngine *ee = engine_builder.create(tm); - - if (!ee) { - std::cerr << error_string << "\n"; - } - internal_assert(ee) << "Couldn't create execution engine\n"; // Do any target-specific initialization std::vector listeners; @@ -296,8 +276,39 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu // TODO: If this ever works in LLVM, this would allow profiling of JIT code with symbols with oprofile. // listeners.push_back(llvm::createOProfileJITEventListener()); - for (auto &listener : listeners) { - ee->RegisterJITEventListener(listener); + // Create LLJIT + const auto compilerBuilder = [&](llvm::orc::JITTargetMachineBuilder /*jtmb*/) + -> llvm::Expected> { + return std::make_unique(std::move(*tm)); + }; + + const auto linkerBuilder = [&](llvm::orc::ExecutionSession& session, const llvm::Triple&) { + return std::make_unique(session); + }; + + auto JIT = llvm::cantFail(llvm::orc::LLJITBuilder() + .setDataLayout(target_data_layout) + .setCompileFunctionCreator(compilerBuilder) + .setObjectLinkingLayerCreator(linkerBuilder) + .create()); + + auto ctors = llvm::orc::getConstructors(*m.get()); + llvm::orc::CtorDtorRunner ctorRunner(JIT->getMainJITDylib()); + ctorRunner.add(ctors); + + auto dtors = llvm::orc::getDestructors(*m.get()); + llvm::orc::CtorDtorRunner* dtorRunner = new llvm::orc::CtorDtorRunner(JIT->getMainJITDylib()); + dtorRunner->add(dtors); + + // Resolve system symbols (like pthread, dl and others) + JIT->getMainJITDylib().addGenerator(llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(target_data_layout.getGlobalPrefix()))); + // Resolve internal symbol dependencies + JIT->getMainJITDylib().addGenerator(std::make_unique(dependencies)); + + llvm::orc::ThreadSafeModule tsm(std::move(m), std::move(jit_module->context)); + auto err = JIT->addIRModule(std::move(tsm)); + if (err) { + throw err; } // Retrieve function pointers from the compiled module (which also @@ -310,31 +321,26 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu Symbol entrypoint; Symbol argv_entrypoint; if (!function_name.empty()) { - entrypoint = compile_and_get_function(*ee, function_name); + entrypoint = compile_and_get_function(*JIT, function_name); exports[function_name] = entrypoint; - argv_entrypoint = compile_and_get_function(*ee, function_name + "_argv"); + argv_entrypoint = compile_and_get_function(*JIT, function_name + "_argv"); exports[function_name + "_argv"] = argv_entrypoint; } for (const auto &requested_export : requested_exports) { - exports[requested_export] = compile_and_get_function(*ee, requested_export); - } - - debug(2) << "Finalizing object\n"; - ee->finalizeObject(); - // Do any target-specific post-compilation module meddling - for (auto &listener : listeners) { - ee->UnregisterJITEventListener(listener); - delete listener; + exports[requested_export] = compile_and_get_function(*JIT, requested_export); } - listeners.clear(); // TODO: I don't think this is necessary, we shouldn't have any static constructors - ee->runStaticConstructorsDestructors(false); + err = ctorRunner.run(); + if (err) { + throw err; + } // Stash the various objects that need to stay alive behind a reference-counted pointer. jit_module->exports = exports; - jit_module->execution_engine = ee; + jit_module->JIT = std::move(JIT); + jit_module->dtorRunner = dtorRunner; jit_module->dependencies = dependencies; jit_module->entrypoint = entrypoint; jit_module->argv_entrypoint = argv_entrypoint; @@ -362,7 +368,7 @@ JITModule JITModule::make_trampolines_module(const Target &target_arg, } std::unique_ptr llvm_module = CodeGen_LLVM::compile_trampolines( - target, result.jit_module->context, suffix, extern_signatures); + target, *result.jit_module->context, suffix, extern_signatures); result.compile_module(std::move(llvm_module), /*function_name*/ "", target, deps, requested_exports); @@ -461,7 +467,7 @@ void JITModule::reuse_device_allocations(bool b) const { } bool JITModule::compiled() const { - return jit_module->execution_engine != nullptr; + return jit_module->JIT != nullptr; } namespace { @@ -760,7 +766,7 @@ JITModule &make_module(llvm::Module *for_module, Target target, // This function is protected by a mutex so this is thread safe. auto module = get_initial_module_for_target(one_gpu, - &runtime.jit_module->context, + runtime.jit_module->context.get(), true, runtime_kind != MainShared); if (for_module) { @@ -860,13 +866,11 @@ JITModule &make_module(llvm::Module *for_module, Target target, } } - uint64_t arg_addr = - runtime.jit_module->execution_engine->getGlobalValueAddress("halide_jit_module_argument"); - + uint64_t arg_addr = llvm::cantFail(runtime.jit_module->JIT->lookup("halide_jit_module_argument")).getValue(); internal_assert(arg_addr != 0); *((void **)arg_addr) = runtime.jit_module.get(); - uint64_t fun_addr = runtime.jit_module->execution_engine->getGlobalValueAddress("halide_jit_module_adjust_ref_count"); + uint64_t fun_addr = llvm::cantFail(runtime.jit_module->JIT->lookup("halide_jit_module_adjust_ref_count")).getValue(); internal_assert(fun_addr != 0); *(void (**)(void *arg, int32_t count))fun_addr = &adjust_module_ref_count; } diff --git a/src/LLVM_Headers.h b/src/LLVM_Headers.h index b3986a4d5ddb..990ad3fe75a2 100644 --- a/src/LLVM_Headers.h +++ b/src/LLVM_Headers.h @@ -37,7 +37,9 @@ #include #include #include -#include +#include +#include +#include #include #include #include From e6f25a164c7b5834d2ba375df0f79670500c97d6 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Sat, 12 Nov 2022 11:17:31 +0300 Subject: [PATCH 02/14] Fix LLVM 14 compilation. Use getTargetTriple --- src/JITModule.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index a58127f7955f..c547b43ebea1 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -165,7 +165,11 @@ JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT& JIT, const string & throw E; } +#if LLVM_VERSION >= 150 void *f = (void *)addr->getValue(); +#else + void *f = (void *)addr->getAddress(); +#endif if (!f) { internal_error << "Compiling " << name << " returned nullptr\n"; } @@ -250,7 +254,7 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu string module_name = m->getModuleIdentifier(); // Build TargetMachine - llvm::orc::JITTargetMachineBuilder tm_builder(llvm::Triple("x86_64-unknown-linux-gnu")); + llvm::orc::JITTargetMachineBuilder tm_builder(llvm::Triple(m->getTargetTriple())); tm_builder.setOptions(options); tm_builder.setCodeGenOptLevel(CodeGenOpt::Aggressive); @@ -866,11 +870,21 @@ JITModule &make_module(llvm::Module *for_module, Target target, } } - uint64_t arg_addr = llvm::cantFail(runtime.jit_module->JIT->lookup("halide_jit_module_argument")).getValue(); + uint64_t arg_addr = llvm::cantFail(runtime.jit_module->JIT->lookup("halide_jit_module_argument")) +#if LLVM_VERSION >= 150 + .getValue(); +#else + .getAddress(); +#endif internal_assert(arg_addr != 0); *((void **)arg_addr) = runtime.jit_module.get(); - uint64_t fun_addr = llvm::cantFail(runtime.jit_module->JIT->lookup("halide_jit_module_adjust_ref_count")).getValue(); + uint64_t fun_addr = llvm::cantFail(runtime.jit_module->JIT->lookup("halide_jit_module_adjust_ref_count")) +#if LLVM_VERSION >= 150 + .getValue(); +#else + .getAddress(); +#endif internal_assert(fun_addr != 0); *(void (**)(void *arg, int32_t count))fun_addr = &adjust_module_ref_count; } From 2a92b0b2279ffb2d328565dac6de7981361d99a7 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Sat, 12 Nov 2022 11:20:49 +0300 Subject: [PATCH 03/14] Fix code style --- src/JITModule.cpp | 33 +++++++++++++++++---------------- src/LLVM_Headers.h | 2 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index c547b43ebea1..02bb69cd0e28 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -136,7 +136,7 @@ class JITModuleContents { std::map exports; std::unique_ptr context = std::make_unique(); std::unique_ptr JIT = nullptr; - llvm::orc::CtorDtorRunner* dtorRunner = nullptr; + llvm::orc::CtorDtorRunner *dtorRunner = nullptr; std::vector dependencies; JITModule::Symbol entrypoint; JITModule::Symbol argv_entrypoint; @@ -157,7 +157,7 @@ void destroy(const JITModuleContents *f) { namespace { // Retrieve a function pointer from an llvm module, possibly by compiling it. -JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT& JIT, const string &name) { +JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT &JIT, const string &name) { debug(2) << "JIT Compiling " << name << "\n"; auto addr = JIT.lookup(name); @@ -184,7 +184,8 @@ JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT& JIT, const string & class HalideJITGenerator : public llvm::orc::DefinitionGenerator { public: HalideJITGenerator(const std::vector &modules) - : modules(modules) {} + : modules(modules) { + } llvm::Error tryToGenerate(llvm::orc::LookupState &LS, llvm::orc::LookupKind K, llvm::orc::JITDylib &JD, llvm::orc::JITDylibLookupFlags JDLookupFlags, @@ -192,7 +193,7 @@ class HalideJITGenerator : public llvm::orc::DefinitionGenerator { llvm::orc::SymbolMap NewSymbols; llvm::orc::SymbolLookupSet LookupSetCopy; - for (auto& symbol : LookupSet) { + for (auto &symbol : LookupSet) { std::string name = (*symbol.first).str(); for (const auto &module : modules) { @@ -282,26 +283,26 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu // Create LLJIT const auto compilerBuilder = [&](llvm::orc::JITTargetMachineBuilder /*jtmb*/) - -> llvm::Expected> { + -> llvm::Expected> { return std::make_unique(std::move(*tm)); }; - const auto linkerBuilder = [&](llvm::orc::ExecutionSession& session, const llvm::Triple&) { + const auto linkerBuilder = [&](llvm::orc::ExecutionSession &session, const llvm::Triple &) { return std::make_unique(session); }; - + auto JIT = llvm::cantFail(llvm::orc::LLJITBuilder() - .setDataLayout(target_data_layout) - .setCompileFunctionCreator(compilerBuilder) - .setObjectLinkingLayerCreator(linkerBuilder) - .create()); + .setDataLayout(target_data_layout) + .setCompileFunctionCreator(compilerBuilder) + .setObjectLinkingLayerCreator(linkerBuilder) + .create()); auto ctors = llvm::orc::getConstructors(*m.get()); llvm::orc::CtorDtorRunner ctorRunner(JIT->getMainJITDylib()); ctorRunner.add(ctors); auto dtors = llvm::orc::getDestructors(*m.get()); - llvm::orc::CtorDtorRunner* dtorRunner = new llvm::orc::CtorDtorRunner(JIT->getMainJITDylib()); + llvm::orc::CtorDtorRunner *dtorRunner = new llvm::orc::CtorDtorRunner(JIT->getMainJITDylib()); dtorRunner->add(dtors); // Resolve system symbols (like pthread, dl and others) @@ -872,18 +873,18 @@ JITModule &make_module(llvm::Module *for_module, Target target, uint64_t arg_addr = llvm::cantFail(runtime.jit_module->JIT->lookup("halide_jit_module_argument")) #if LLVM_VERSION >= 150 - .getValue(); + .getValue(); #else - .getAddress(); + .getAddress(); #endif internal_assert(arg_addr != 0); *((void **)arg_addr) = runtime.jit_module.get(); uint64_t fun_addr = llvm::cantFail(runtime.jit_module->JIT->lookup("halide_jit_module_adjust_ref_count")) #if LLVM_VERSION >= 150 - .getValue(); + .getValue(); #else - .getAddress(); + .getAddress(); #endif internal_assert(fun_addr != 0); *(void (**)(void *arg, int32_t count))fun_addr = &adjust_module_ref_count; diff --git a/src/LLVM_Headers.h b/src/LLVM_Headers.h index 990ad3fe75a2..ccd166519aa1 100644 --- a/src/LLVM_Headers.h +++ b/src/LLVM_Headers.h @@ -37,8 +37,8 @@ #include #include #include -#include #include +#include #include #include #include From 8581a0ee009197ca771fdf849709287b57ede12b Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Sat, 12 Nov 2022 16:36:00 +0300 Subject: [PATCH 04/14] Fix clang-tidy errors --- src/JITModule.cpp | 26 +++++++++++--------------- test/correctness/c_function.cpp | 2 +- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index 02bb69cd0e28..ba965b6b5db2 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -161,8 +161,8 @@ JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT &JIT, const string & debug(2) << "JIT Compiling " << name << "\n"; auto addr = JIT.lookup(name); - if (auto E = addr.takeError()) { - throw E; + if (!addr) { + internal_error << llvm::toString(addr.takeError()) << "\n"; } #if LLVM_VERSION >= 150 @@ -193,7 +193,7 @@ class HalideJITGenerator : public llvm::orc::DefinitionGenerator { llvm::orc::SymbolMap NewSymbols; llvm::orc::SymbolLookupSet LookupSetCopy; - for (auto &symbol : LookupSet) { + for (const auto &symbol : LookupSet) { std::string name = (*symbol.first).str(); for (const auto &module : modules) { @@ -260,8 +260,8 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu tm_builder.setCodeGenOptLevel(CodeGenOpt::Aggressive); auto tm = tm_builder.createTargetMachine(); - if (auto E = tm.takeError()) { - throw E; + if (!tm) { + internal_error << llvm::toString(tm.takeError()) << "\n"; } DataLayout target_data_layout(tm.get()->createDataLayout()); @@ -297,11 +297,11 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu .setObjectLinkingLayerCreator(linkerBuilder) .create()); - auto ctors = llvm::orc::getConstructors(*m.get()); + auto ctors = llvm::orc::getConstructors(*m); llvm::orc::CtorDtorRunner ctorRunner(JIT->getMainJITDylib()); ctorRunner.add(ctors); - auto dtors = llvm::orc::getDestructors(*m.get()); + auto dtors = llvm::orc::getDestructors(*m); llvm::orc::CtorDtorRunner *dtorRunner = new llvm::orc::CtorDtorRunner(JIT->getMainJITDylib()); dtorRunner->add(dtors); @@ -311,10 +311,7 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu JIT->getMainJITDylib().addGenerator(std::make_unique(dependencies)); llvm::orc::ThreadSafeModule tsm(std::move(m), std::move(jit_module->context)); - auto err = JIT->addIRModule(std::move(tsm)); - if (err) { - throw err; - } + llvm::cantFail(JIT->addIRModule(std::move(tsm))); // Retrieve function pointers from the compiled module (which also // triggers compilation) @@ -336,11 +333,10 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu exports[requested_export] = compile_and_get_function(*JIT, requested_export); } + listeners.clear(); + // TODO: I don't think this is necessary, we shouldn't have any static constructors - err = ctorRunner.run(); - if (err) { - throw err; - } + llvm::cantFail(ctorRunner.run()); // Stash the various objects that need to stay alive behind a reference-counted pointer. jit_module->exports = exports; diff --git a/test/correctness/c_function.cpp b/test/correctness/c_function.cpp index cadab3386f7f..846c977b6613 100644 --- a/test/correctness/c_function.cpp +++ b/test/correctness/c_function.cpp @@ -71,7 +71,7 @@ int main(int argc, char **argv) { } if (call_counter2 != 32 * 32) { - printf("C function my_func2 was called %d times instead of %d\n", call_counter, 32 * 32); + printf("C function my_func2 was called %d times instead of %d\n", call_counter2, 32 * 32); return -1; } From bff867ef22e98fb7675837ce262094a436190b88 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Sun, 13 Nov 2022 11:41:09 +0300 Subject: [PATCH 05/14] Redefine dependency symbols by force --- src/JITModule.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index ba965b6b5db2..f6e5cf02ad1a 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -192,7 +192,6 @@ class HalideJITGenerator : public llvm::orc::DefinitionGenerator { const llvm::orc::SymbolLookupSet &LookupSet) override { llvm::orc::SymbolMap NewSymbols; - llvm::orc::SymbolLookupSet LookupSetCopy; for (const auto &symbol : LookupSet) { std::string name = (*symbol.first).str(); @@ -206,8 +205,9 @@ class HalideJITGenerator : public llvm::orc::DefinitionGenerator { } } } - if (NewSymbols.empty()) + if (NewSymbols.empty()) { return llvm::Error::success(); + } return JD.define(llvm::orc::absoluteSymbols(std::move(NewSymbols))); } @@ -282,7 +282,7 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu // listeners.push_back(llvm::createOProfileJITEventListener()); // Create LLJIT - const auto compilerBuilder = [&](llvm::orc::JITTargetMachineBuilder /*jtmb*/) + const auto compilerBuilder = [&tm](llvm::orc::JITTargetMachineBuilder /*jtmb*/) -> llvm::Expected> { return std::make_unique(std::move(*tm)); }; @@ -307,8 +307,17 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu // Resolve system symbols (like pthread, dl and others) JIT->getMainJITDylib().addGenerator(llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(target_data_layout.getGlobalPrefix()))); - // Resolve internal symbol dependencies - JIT->getMainJITDylib().addGenerator(std::make_unique(dependencies)); + + // Resolve symbol dependencies. + llvm::orc::SymbolMap NewSymbols; + auto symbolStringPool = JIT->getExecutionSession().getExecutorProcessControl().getSymbolStringPool(); + for (const auto &module : dependencies) { + for (auto const &iter : module.exports()) { + orc::SymbolStringPtr name = symbolStringPool->intern(iter.first); + NewSymbols.insert({name, llvm::JITEvaluatedSymbol::fromPointer(iter.second.address)}); + } + } + llvm::cantFail(JIT->getMainJITDylib().define(llvm::orc::absoluteSymbols(std::move(NewSymbols)))); llvm::orc::ThreadSafeModule tsm(std::move(m), std::move(jit_module->context)); llvm::cantFail(JIT->addIRModule(std::move(tsm))); From 7f685fae7afaa96e5beeb3270d29aa53dec73166 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 14 Nov 2022 08:30:46 +0300 Subject: [PATCH 06/14] Fix Makefile. Define dependencies only once --- Makefile | 2 +- src/JITModule.cpp | 43 +++++-------------------------------------- 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index a3de1df1a820..4697746cdb27 100644 --- a/Makefile +++ b/Makefile @@ -231,7 +231,7 @@ LLVM_STATIC_LIBFILES = \ linker \ ipo \ passes \ - mcjit \ + orcjit \ $(X86_LLVM_CONFIG_LIB) \ $(ARM_LLVM_CONFIG_LIB) \ $(OPENCL_LLVM_CONFIG_LIB) \ diff --git a/src/JITModule.cpp b/src/JITModule.cpp index f6e5cf02ad1a..9782a8b9aaba 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -181,41 +181,6 @@ JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT &JIT, const string & return symbol; } -class HalideJITGenerator : public llvm::orc::DefinitionGenerator { -public: - HalideJITGenerator(const std::vector &modules) - : modules(modules) { - } - - llvm::Error tryToGenerate(llvm::orc::LookupState &LS, llvm::orc::LookupKind K, llvm::orc::JITDylib &JD, - llvm::orc::JITDylibLookupFlags JDLookupFlags, - const llvm::orc::SymbolLookupSet &LookupSet) override { - llvm::orc::SymbolMap NewSymbols; - - for (const auto &symbol : LookupSet) { - std::string name = (*symbol.first).str(); - - for (const auto &module : modules) { - std::map::const_iterator iter = module.exports().find(name); - if (iter == module.exports().end() && starts_with(name, "_")) { - iter = module.exports().find(name.substr(1)); - } - if (iter != module.exports().end()) { - NewSymbols.insert({symbol.first, llvm::JITEvaluatedSymbol::fromPointer(iter->second.address)}); - } - } - } - if (NewSymbols.empty()) { - return llvm::Error::success(); - } - - return JD.define(llvm::orc::absoluteSymbols(std::move(NewSymbols))); - } - -private: - std::vector modules; -}; - } // namespace JITModule::JITModule() { @@ -282,12 +247,12 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu // listeners.push_back(llvm::createOProfileJITEventListener()); // Create LLJIT - const auto compilerBuilder = [&tm](llvm::orc::JITTargetMachineBuilder /*jtmb*/) + const auto compilerBuilder = [&](const llvm::orc::JITTargetMachineBuilder & /*jtmb*/) -> llvm::Expected> { return std::make_unique(std::move(*tm)); }; - const auto linkerBuilder = [&](llvm::orc::ExecutionSession &session, const llvm::Triple &) { + const auto linkerBuilder = [](llvm::orc::ExecutionSession &session, const llvm::Triple &) { return std::make_unique(session); }; @@ -314,7 +279,9 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu for (const auto &module : dependencies) { for (auto const &iter : module.exports()) { orc::SymbolStringPtr name = symbolStringPool->intern(iter.first); - NewSymbols.insert({name, llvm::JITEvaluatedSymbol::fromPointer(iter.second.address)}); + if (!NewSymbols.count(name)) { + NewSymbols.insert({name, llvm::JITEvaluatedSymbol::fromPointer(iter.second.address)}); + } } } llvm::cantFail(JIT->getMainJITDylib().define(llvm::orc::absoluteSymbols(std::move(NewSymbols)))); From 4a8f190fa4b9327c272ca7aac5039be27e2860bb Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 14 Nov 2022 09:24:40 +0300 Subject: [PATCH 07/14] Bring HalideJITGenerator back for the undefined _halide_* methods --- src/JITModule.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index 9782a8b9aaba..02c1281c31ea 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -181,6 +181,42 @@ JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT &JIT, const string & return symbol; } +class HalideJITGenerator : public llvm::orc::DefinitionGenerator { +public: + HalideJITGenerator(const std::vector &modules) + : modules(modules) { + } + + llvm::Error tryToGenerate(llvm::orc::LookupState &LS, llvm::orc::LookupKind K, llvm::orc::JITDylib &JD, + llvm::orc::JITDylibLookupFlags JDLookupFlags, + const llvm::orc::SymbolLookupSet &LookupSet) override { + llvm::orc::SymbolMap NewSymbols; + + for (const auto &symbol : LookupSet) { + std::string name = (*symbol.first).str(); + + for (const auto &module : modules) { + std::map::const_iterator iter = module.exports().find(name); + if (iter == module.exports().end() && starts_with(name, "_")) { + iter = module.exports().find(name.substr(1)); + } + if (iter != module.exports().end()) { + NewSymbols.insert({symbol.first, llvm::JITEvaluatedSymbol::fromPointer(iter->second.address)}); + break; + } + } + } + if (NewSymbols.empty()) { + return llvm::Error::success(); + } + + return JD.define(llvm::orc::absoluteSymbols(std::move(NewSymbols))); + } + +private: + std::vector modules; +}; + } // namespace JITModule::JITModule() { @@ -273,6 +309,9 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu // Resolve system symbols (like pthread, dl and others) JIT->getMainJITDylib().addGenerator(llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(target_data_layout.getGlobalPrefix()))); + // For undefined symbols resolving + JIT->getMainJITDylib().addGenerator(std::make_unique(dependencies)); + // Resolve symbol dependencies. llvm::orc::SymbolMap NewSymbols; auto symbolStringPool = JIT->getExecutionSession().getExecutorProcessControl().getSymbolStringPool(); From 4029aa7efc7dd21c7c9aeaeb8a200df996abddc9 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 14 Nov 2022 11:38:36 +0300 Subject: [PATCH 08/14] Try to set relocation model to static for i386 --- src/JITModule.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index 02c1281c31ea..a80cd02b13a2 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -161,9 +161,7 @@ JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT &JIT, const string & debug(2) << "JIT Compiling " << name << "\n"; auto addr = JIT.lookup(name); - if (!addr) { - internal_error << llvm::toString(addr.takeError()) << "\n"; - } + internal_assert(addr) << llvm::toString(addr.takeError()) << "\n"; #if LLVM_VERSION >= 150 void *f = (void *)addr->getValue(); @@ -259,11 +257,13 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu llvm::orc::JITTargetMachineBuilder tm_builder(llvm::Triple(m->getTargetTriple())); tm_builder.setOptions(options); tm_builder.setCodeGenOptLevel(CodeGenOpt::Aggressive); + // Workaround for "JIT session error: Unsupported i386 relocation:4" (R_386_PLT32) + if (target.arch == Target::Arch::X86 && target.bits == 32) { + tm_builder.setRelocationModel(llvm::Reloc::Static); + } auto tm = tm_builder.createTargetMachine(); - if (!tm) { - internal_error << llvm::toString(tm.takeError()) << "\n"; - } + internal_assert(tm) << llvm::toString(tm.takeError()) << "\n"; DataLayout target_data_layout(tm.get()->createDataLayout()); if (initial_module_data_layout != target_data_layout) { From 6a4818779147f8b3eab1b886a0f4adf25b79d73f Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 14 Nov 2022 14:37:34 +0300 Subject: [PATCH 09/14] Use CodeModel::Medium in TargetMachine --- src/JITModule.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index a80cd02b13a2..7ee117a61373 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -257,10 +257,7 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu llvm::orc::JITTargetMachineBuilder tm_builder(llvm::Triple(m->getTargetTriple())); tm_builder.setOptions(options); tm_builder.setCodeGenOptLevel(CodeGenOpt::Aggressive); - // Workaround for "JIT session error: Unsupported i386 relocation:4" (R_386_PLT32) - if (target.arch == Target::Arch::X86 && target.bits == 32) { - tm_builder.setRelocationModel(llvm::Reloc::Static); - } + tm_builder.setCodeModel(llvm::CodeModel::Medium); auto tm = tm_builder.createTargetMachine(); internal_assert(tm) << llvm::toString(tm.takeError()) << "\n"; From f573775031deabe254987a83ef042ebd11c8a9f7 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 14 Nov 2022 17:06:56 +0300 Subject: [PATCH 10/14] Fallback to RTDyldObjectLinkingLayer for i386 --- src/JITModule.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++--- src/LLVM_Headers.h | 1 + 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index 7ee117a61373..1e69a2b543e6 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -179,6 +179,58 @@ JITModule::Symbol compile_and_get_function(llvm::orc::LLJIT &JIT, const string & return symbol; } +// Expand LLVM's search for symbols to include code contained in a set of JITModule. +class HalideJITMemoryManager : public SectionMemoryManager { + std::vector modules; + std::vector> code_pages; + +public: + HalideJITMemoryManager(const std::vector &modules) + : modules(modules) { + } + + uint64_t getSymbolAddress(const std::string &name) override { + for (const auto &module : modules) { + std::map::const_iterator iter = module.exports().find(name); + if (iter == module.exports().end() && starts_with(name, "_")) { + iter = module.exports().find(name.substr(1)); + } + if (iter != module.exports().end()) { + return (uint64_t)iter->second.address; + } + } + uint64_t result = SectionMemoryManager::getSymbolAddress(name); +#if defined(__GNUC__) && defined(__i386__) + // This is a workaround for an odd corner case (cross-compiling + testing + // Python bindings x86-32 on an x86-64 system): __udivdi3 is a helper function + // that GCC uses to do u64/u64 division on 32-bit systems; it's usually included + // by the linker on these systems as needed. When we JIT, LLVM will include references + // to this call; MCJIT fixes up these references by doing (roughly) dlopen(NULL) + // to look up the symbol. For normal JIT tests, this works fine, as dlopen(NULL) + // finds the test executable, which has the right lookups to locate it inside libHalide.so. + // If, however, we are running a JIT-via-Python test, dlopen(NULL) returns the + // CPython executable... which apparently *doesn't* include this as an exported + // function, so the lookup fails and crashiness ensues. So our workaround here is + // a bit icky, but expedient: check for this name if we can't find it elsewhere, + // and if so, return the one we know should be present. (Obviously, if other runtime + // helper functions of this sort crop up in the future, this should be expanded + // into a "builtins map".) + if (result == 0 && name == "__udivdi3") { + result = (uint64_t)&__udivdi3; + } +#endif + internal_assert(result != 0) + << "HalideJITMemoryManager: unable to find address for " << name << "\n"; + return result; + } + + uint8_t *allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, StringRef section_name) override { + uint8_t *result = SectionMemoryManager::allocateCodeSection(size, alignment, section_id, section_name); + code_pages.emplace_back(result, size); + return result; + } +}; + class HalideJITGenerator : public llvm::orc::DefinitionGenerator { public: HalideJITGenerator(const std::vector &modules) @@ -257,7 +309,9 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu llvm::orc::JITTargetMachineBuilder tm_builder(llvm::Triple(m->getTargetTriple())); tm_builder.setOptions(options); tm_builder.setCodeGenOptLevel(CodeGenOpt::Aggressive); - tm_builder.setCodeModel(llvm::CodeModel::Medium); + if (target.arch == Target::Arch::RISCV) { + tm_builder.setCodeModel(llvm::CodeModel::Medium); + } auto tm = tm_builder.createTargetMachine(); internal_assert(tm) << llvm::toString(tm.takeError()) << "\n"; @@ -285,9 +339,19 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu return std::make_unique(std::move(*tm)); }; - const auto linkerBuilder = [](llvm::orc::ExecutionSession &session, const llvm::Triple &) { - return std::make_unique(session); - }; + llvm::orc::LLJITBuilderState::ObjectLinkingLayerCreator linkerBuilder; + if (target.arch == Target::Arch::X86 && target.bits == 32) { + // Fallback to RTDyld-based linking to workaround "JIT session error: Unsupported i386 relocation:4" (R_386_PLT32). + linkerBuilder = [&](llvm::orc::ExecutionSession &session, const llvm::Triple &) { + return std::make_unique(session, [&]() { + return std::make_unique(dependencies); + }); + }; + } else { + linkerBuilder = [](llvm::orc::ExecutionSession &session, const llvm::Triple &) { + return std::make_unique(session); + }; + } auto JIT = llvm::cantFail(llvm::orc::LLJITBuilder() .setDataLayout(target_data_layout) diff --git a/src/LLVM_Headers.h b/src/LLVM_Headers.h index ccd166519aa1..15d4f751a83f 100644 --- a/src/LLVM_Headers.h +++ b/src/LLVM_Headers.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include From 7ff4c127d9630ee64274863ac378ef2271aed142 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Wed, 16 Nov 2022 18:41:01 +0300 Subject: [PATCH 11/14] Change order of addIRModule and dependency symbols definition. Add errors check --- src/JITModule.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index 1e69a2b543e6..d3877db10211 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -128,7 +128,8 @@ class JITModuleContents { ~JITModuleContents() { if (JIT != nullptr) { - llvm::cantFail(dtorRunner->run()); + auto err = dtorRunner->run(); + internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; delete dtorRunner; } } @@ -373,7 +374,11 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu // For undefined symbols resolving JIT->getMainJITDylib().addGenerator(std::make_unique(dependencies)); - // Resolve symbol dependencies. + llvm::orc::ThreadSafeModule tsm(std::move(m), std::move(jit_module->context)); + auto err = JIT->addIRModule(std::move(tsm)); + internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; + + // Resolve symbol dependencies. Required for correctness_c_function test llvm::orc::SymbolMap NewSymbols; auto symbolStringPool = JIT->getExecutionSession().getExecutorProcessControl().getSymbolStringPool(); for (const auto &module : dependencies) { @@ -384,10 +389,8 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu } } } - llvm::cantFail(JIT->getMainJITDylib().define(llvm::orc::absoluteSymbols(std::move(NewSymbols)))); - - llvm::orc::ThreadSafeModule tsm(std::move(m), std::move(jit_module->context)); - llvm::cantFail(JIT->addIRModule(std::move(tsm))); + err = JIT->getMainJITDylib().define(llvm::orc::absoluteSymbols(std::move(NewSymbols))); + internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; // Retrieve function pointers from the compiled module (which also // triggers compilation) @@ -412,7 +415,8 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu listeners.clear(); // TODO: I don't think this is necessary, we shouldn't have any static constructors - llvm::cantFail(ctorRunner.run()); + err = ctorRunner.run(); + internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; // Stash the various objects that need to stay alive behind a reference-counted pointer. jit_module->exports = exports; From e6441e6ae2fc8807ba66ea532b55841de81bb75e Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Thu, 17 Nov 2022 12:45:01 +0300 Subject: [PATCH 12/14] Try without DefinitionGenerator --- src/JITModule.cpp | 50 ++++++++--------------------------------------- 1 file changed, 8 insertions(+), 42 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index d3877db10211..3c49cf8f81a0 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -232,42 +232,6 @@ class HalideJITMemoryManager : public SectionMemoryManager { } }; -class HalideJITGenerator : public llvm::orc::DefinitionGenerator { -public: - HalideJITGenerator(const std::vector &modules) - : modules(modules) { - } - - llvm::Error tryToGenerate(llvm::orc::LookupState &LS, llvm::orc::LookupKind K, llvm::orc::JITDylib &JD, - llvm::orc::JITDylibLookupFlags JDLookupFlags, - const llvm::orc::SymbolLookupSet &LookupSet) override { - llvm::orc::SymbolMap NewSymbols; - - for (const auto &symbol : LookupSet) { - std::string name = (*symbol.first).str(); - - for (const auto &module : modules) { - std::map::const_iterator iter = module.exports().find(name); - if (iter == module.exports().end() && starts_with(name, "_")) { - iter = module.exports().find(name.substr(1)); - } - if (iter != module.exports().end()) { - NewSymbols.insert({symbol.first, llvm::JITEvaluatedSymbol::fromPointer(iter->second.address)}); - break; - } - } - } - if (NewSymbols.empty()) { - return llvm::Error::success(); - } - - return JD.define(llvm::orc::absoluteSymbols(std::move(NewSymbols))); - } - -private: - std::vector modules; -}; - } // namespace JITModule::JITModule() { @@ -371,25 +335,27 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu // Resolve system symbols (like pthread, dl and others) JIT->getMainJITDylib().addGenerator(llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(target_data_layout.getGlobalPrefix()))); - // For undefined symbols resolving - JIT->getMainJITDylib().addGenerator(std::make_unique(dependencies)); - llvm::orc::ThreadSafeModule tsm(std::move(m), std::move(jit_module->context)); auto err = JIT->addIRModule(std::move(tsm)); internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; - // Resolve symbol dependencies. Required for correctness_c_function test + // Resolve symbol dependencies llvm::orc::SymbolMap NewSymbols; auto symbolStringPool = JIT->getExecutionSession().getExecutorProcessControl().getSymbolStringPool(); for (const auto &module : dependencies) { for (auto const &iter : module.exports()) { orc::SymbolStringPtr name = symbolStringPool->intern(iter.first); + orc::SymbolStringPtr _name = symbolStringPool->intern("_" + iter.first); + auto symbol = llvm::JITEvaluatedSymbol::fromPointer(iter.second.address); if (!NewSymbols.count(name)) { - NewSymbols.insert({name, llvm::JITEvaluatedSymbol::fromPointer(iter.second.address)}); + NewSymbols.insert({name, symbol}); + } + if (!NewSymbols.count(_name)) { + NewSymbols.insert({_name, symbol}); } } } - err = JIT->getMainJITDylib().define(llvm::orc::absoluteSymbols(std::move(NewSymbols))); + err = JIT->getMainJITDylib().define(orc::absoluteSymbols(std::move(NewSymbols))); internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; // Retrieve function pointers from the compiled module (which also From 3a0c4f95be2eb5a564e519160720674f959c737c Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Thu, 17 Nov 2022 14:40:09 +0300 Subject: [PATCH 13/14] Remove unused LLVM headers --- src/JITModule.cpp | 11 ----------- src/LLVM_Headers.h | 2 -- 2 files changed, 13 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index 3c49cf8f81a0..0ccff90b5fd8 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -289,15 +289,6 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu << target_data_layout.getStringRepresentation() << ")\n"; } - // Do any target-specific initialization - std::vector listeners; - - if (target.arch == Target::X86) { - listeners.push_back(llvm::JITEventListener::createIntelJITEventListener()); - } - // TODO: If this ever works in LLVM, this would allow profiling of JIT code with symbols with oprofile. - // listeners.push_back(llvm::createOProfileJITEventListener()); - // Create LLJIT const auto compilerBuilder = [&](const llvm::orc::JITTargetMachineBuilder & /*jtmb*/) -> llvm::Expected> { @@ -378,8 +369,6 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu exports[requested_export] = compile_and_get_function(*JIT, requested_export); } - listeners.clear(); - // TODO: I don't think this is necessary, we shouldn't have any static constructors err = ctorRunner.run(); internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; diff --git a/src/LLVM_Headers.h b/src/LLVM_Headers.h index 15d4f751a83f..da0f301e11fb 100644 --- a/src/LLVM_Headers.h +++ b/src/LLVM_Headers.h @@ -35,9 +35,7 @@ #include #include #include -#include #include -#include #include #include #include From ae3d8b28c56e0fd44c850f75b22b0e218faec975 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Fri, 18 Nov 2022 09:52:08 +0300 Subject: [PATCH 14/14] Fix review comments --- src/JITModule.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/JITModule.cpp b/src/JITModule.cpp index 0ccff90b5fd8..0ebdfde3126d 100644 --- a/src/JITModule.cpp +++ b/src/JITModule.cpp @@ -130,14 +130,13 @@ class JITModuleContents { if (JIT != nullptr) { auto err = dtorRunner->run(); internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; - delete dtorRunner; } } std::map exports; std::unique_ptr context = std::make_unique(); std::unique_ptr JIT = nullptr; - llvm::orc::CtorDtorRunner *dtorRunner = nullptr; + std::unique_ptr dtorRunner = nullptr; std::vector dependencies; JITModule::Symbol entrypoint; JITModule::Symbol argv_entrypoint; @@ -296,8 +295,11 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu }; llvm::orc::LLJITBuilderState::ObjectLinkingLayerCreator linkerBuilder; - if (target.arch == Target::Arch::X86 && target.bits == 32) { - // Fallback to RTDyld-based linking to workaround "JIT session error: Unsupported i386 relocation:4" (R_386_PLT32). + if ((target.arch == Target::Arch::X86 && target.bits == 32) || + (target.arch == Target::Arch::ARM && target.bits == 32)) { + // Fallback to RTDyld-based linking to workaround errors: + // i386: "JIT session error: Unsupported i386 relocation:4" (R_386_PLT32) + // ARM 32bit: Unsupported target machine architecture in ELF object shared runtime-jitted-objectbuffer linkerBuilder = [&](llvm::orc::ExecutionSession &session, const llvm::Triple &) { return std::make_unique(session, [&]() { return std::make_unique(dependencies); @@ -320,33 +322,35 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu ctorRunner.add(ctors); auto dtors = llvm::orc::getDestructors(*m); - llvm::orc::CtorDtorRunner *dtorRunner = new llvm::orc::CtorDtorRunner(JIT->getMainJITDylib()); + auto dtorRunner = std::make_unique(JIT->getMainJITDylib()); dtorRunner->add(dtors); // Resolve system symbols (like pthread, dl and others) - JIT->getMainJITDylib().addGenerator(llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(target_data_layout.getGlobalPrefix()))); + auto gen = llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(target_data_layout.getGlobalPrefix()); + internal_assert(gen) << llvm::toString(gen.takeError()) << "\n"; + JIT->getMainJITDylib().addGenerator(std::move(gen.get())); llvm::orc::ThreadSafeModule tsm(std::move(m), std::move(jit_module->context)); auto err = JIT->addIRModule(std::move(tsm)); internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; // Resolve symbol dependencies - llvm::orc::SymbolMap NewSymbols; + llvm::orc::SymbolMap newSymbols; auto symbolStringPool = JIT->getExecutionSession().getExecutorProcessControl().getSymbolStringPool(); for (const auto &module : dependencies) { for (auto const &iter : module.exports()) { orc::SymbolStringPtr name = symbolStringPool->intern(iter.first); orc::SymbolStringPtr _name = symbolStringPool->intern("_" + iter.first); auto symbol = llvm::JITEvaluatedSymbol::fromPointer(iter.second.address); - if (!NewSymbols.count(name)) { - NewSymbols.insert({name, symbol}); + if (!newSymbols.count(name)) { + newSymbols.insert({name, symbol}); } - if (!NewSymbols.count(_name)) { - NewSymbols.insert({_name, symbol}); + if (!newSymbols.count(_name)) { + newSymbols.insert({_name, symbol}); } } } - err = JIT->getMainJITDylib().define(orc::absoluteSymbols(std::move(NewSymbols))); + err = JIT->getMainJITDylib().define(orc::absoluteSymbols(std::move(newSymbols))); internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; // Retrieve function pointers from the compiled module (which also @@ -369,14 +373,13 @@ void JITModule::compile_module(std::unique_ptr m, const string &fu exports[requested_export] = compile_and_get_function(*JIT, requested_export); } - // TODO: I don't think this is necessary, we shouldn't have any static constructors err = ctorRunner.run(); internal_assert(!err) << llvm::toString(std::move(err)) << "\n"; // Stash the various objects that need to stay alive behind a reference-counted pointer. jit_module->exports = exports; jit_module->JIT = std::move(JIT); - jit_module->dtorRunner = dtorRunner; + jit_module->dtorRunner = std::move(dtorRunner); jit_module->dependencies = dependencies; jit_module->entrypoint = entrypoint; jit_module->argv_entrypoint = argv_entrypoint;