From 10e0360f9e8ad88ae2ddbb6c9ba1913b8c16831d Mon Sep 17 00:00:00 2001 From: Derek Gerstmann Date: Thu, 24 Aug 2023 15:22:22 -0700 Subject: [PATCH] [wasm] Enable PIC for WebAssembly on LLVM v18.x (#7803) * Enable PIC code generation for WebAssembly for LLVM >18. Enable +mutable-globals to support dynamic linking * Fix LLVM v18 interface changes for writeArchive() Add RelLookupTableConverterPass for PIC (in LLVM v18) * Resolve conflict for writeArchive interface changes. * Clang format pass --------- Co-authored-by: Derek Gerstmann --- src/CodeGen_LLVM.cpp | 11 +++++++++++ src/CodeGen_WebAssembly.cpp | 19 +++++++++++++++++++ src/LLVM_Headers.h | 3 +++ src/LLVM_Output.cpp | 4 ++++ 4 files changed, 37 insertions(+) diff --git a/src/CodeGen_LLVM.cpp b/src/CodeGen_LLVM.cpp index b3fc5f176495..b4fd79d88a15 100644 --- a/src/CodeGen_LLVM.cpp +++ b/src/CodeGen_LLVM.cpp @@ -1151,6 +1151,17 @@ void CodeGen_LLVM::optimize_module() { using OptimizationLevel = llvm::OptimizationLevel; OptimizationLevel level = OptimizationLevel::O3; +#if LLVM_VERSION >= 180 + if (tm->isPositionIndependent()) { + // Add a pass that converts lookup tables to relative lookup tables to make them PIC-friendly. + // See https://bugs.llvm.org/show_bug.cgi?id=45244 + pb.registerOptimizerLastEPCallback( + [&](ModulePassManager &mpm, OptimizationLevel level) { + mpm.addPass(RelLookupTableConverterPass()); + }); + } +#endif + if (get_target().has_feature(Target::SanitizerCoverage)) { pb.registerOptimizerLastEPCallback( [&](ModulePassManager &mpm, OptimizationLevel level) { diff --git a/src/CodeGen_WebAssembly.cpp b/src/CodeGen_WebAssembly.cpp index 3f82f66bc2a2..69d696ce9f8a 100644 --- a/src/CodeGen_WebAssembly.cpp +++ b/src/CodeGen_WebAssembly.cpp @@ -344,6 +344,14 @@ string CodeGen_WebAssembly::mattrs() const { sep = ","; } + // PIC implies +mutable-globals because the PIC ABI used by the linker + // depends on importing and exporting mutable globals. Also -pthread implies + // mutable-globals too, so quitely enable it if either of these are specified. + if (use_pic() || target.has_feature(Target::WasmThreads)) { + s << sep << "+mutable-globals"; + sep = ","; + } + // Recent Emscripten builds assume that specifying `-pthread` implies bulk-memory too, // so quietly enable it if either of these are specified. if (target.has_feature(Target::WasmBulkMemory) || target.has_feature(Target::WasmThreads)) { @@ -362,7 +370,18 @@ bool CodeGen_WebAssembly::use_soft_float_abi() const { } bool CodeGen_WebAssembly::use_pic() const { +#if LLVM_VERSION >= 180 + // Issues with WASM PIC and dynamic linking only got fixed in LLVM v18.x (June 26th 2023) + // See https://reviews.llvm.org/D153293 + + // Always emitting PIC "does add a little bloat to the object files, due to the extra + // indirection, but when linked into a static binary 100% of this can be removed by + // wasm-opt in release builds." + // See https://github.com/halide/Halide/issues/7796 + return true; +#else return false; +#endif } int CodeGen_WebAssembly::native_vector_bits() const { diff --git a/src/LLVM_Headers.h b/src/LLVM_Headers.h index 6018c4fedff9..ad3f25365577 100644 --- a/src/LLVM_Headers.h +++ b/src/LLVM_Headers.h @@ -102,6 +102,9 @@ #include #include #include +#if LLVM_VERSION >= 180 +#include +#endif // IWYU pragma: end_exports diff --git a/src/LLVM_Output.cpp b/src/LLVM_Output.cpp index f0aadfb9a869..04af5aff3609 100644 --- a/src/LLVM_Output.cpp +++ b/src/LLVM_Output.cpp @@ -397,6 +397,10 @@ void emit_file(const llvm::Module &module_in, Internal::LLVMOStream &out, pass_manager.add(llvm::createRewriteSymbolsPass()); #endif + if (target_machine->isPositionIndependent()) { + Internal::debug(1) << "Target machine is Position Independent!\n"; + } + // Override default to generate verbose assembly. target_machine->Options.MCOptions.AsmVerbose = true;