|
| 1 | +diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp |
| 2 | +index bd25fd1a8933..b906bff5d5c7 100644 |
| 3 | +--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp |
| 4 | ++++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp |
| 5 | +@@ -6,6 +6,8 @@ |
| 6 | + // |
| 7 | + //===----------------------------------------------------------------------===// |
| 8 | + |
| 9 | ++#include <sstream> |
| 10 | ++ |
| 11 | + #include "WebAssembly.h" |
| 12 | + #include "CommonArgs.h" |
| 13 | + #include "Gnu.h" |
| 14 | +@@ -19,6 +21,7 @@ |
| 15 | + #include "llvm/Option/ArgList.h" |
| 16 | + #include "llvm/Support/FileSystem.h" |
| 17 | + #include "llvm/Support/Path.h" |
| 18 | ++#include "llvm/Support/Process.h" |
| 19 | + #include "llvm/Support/VirtualFileSystem.h" |
| 20 | + |
| 21 | + using namespace clang::driver; |
| 22 | +@@ -168,21 +171,12 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
| 23 | + CmdArgs.push_back("-o"); |
| 24 | + CmdArgs.push_back(Output.getFilename()); |
| 25 | + |
| 26 | +- // Don't use wasm-opt by default on `wasip2` as it doesn't have support for |
| 27 | +- // components at this time. Retain the historical default otherwise, though, |
| 28 | +- // of running `wasm-opt` by default. |
| 29 | +- bool WasmOptDefault = !TargetBuildsComponents(ToolChain.getTriple()); |
| 30 | +- bool RunWasmOpt = Args.hasFlag(options::OPT_wasm_opt, |
| 31 | +- options::OPT_no_wasm_opt, WasmOptDefault); |
| 32 | +- |
| 33 | + // If wasm-opt is enabled and optimizations are happening look for the |
| 34 | + // `wasm-opt` program. If it's not found auto-disable it. |
| 35 | + std::string WasmOptPath; |
| 36 | +- if (RunWasmOpt && Args.getLastArg(options::OPT_O_Group)) { |
| 37 | +- WasmOptPath = ToolChain.GetProgramPath("wasm-opt"); |
| 38 | +- if (WasmOptPath == "wasm-opt") { |
| 39 | +- WasmOptPath = {}; |
| 40 | +- } |
| 41 | ++ WasmOptPath = ToolChain.GetProgramPath("wasm-opt"); |
| 42 | ++ if (WasmOptPath == "wasm-opt") { |
| 43 | ++ WasmOptPath = {}; |
| 44 | + } |
| 45 | + |
| 46 | + if (!WasmOptPath.empty()) { |
| 47 | +@@ -193,29 +187,27 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
| 48 | + ResponseFileSupport::AtFileCurCP(), |
| 49 | + Linker, CmdArgs, Inputs, Output)); |
| 50 | + |
| 51 | +- if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { |
| 52 | +- if (!WasmOptPath.empty()) { |
| 53 | +- StringRef OOpt = "s"; |
| 54 | +- if (A->getOption().matches(options::OPT_O4) || |
| 55 | +- A->getOption().matches(options::OPT_Ofast)) |
| 56 | +- OOpt = "4"; |
| 57 | +- else if (A->getOption().matches(options::OPT_O0)) |
| 58 | +- OOpt = "0"; |
| 59 | +- else if (A->getOption().matches(options::OPT_O)) |
| 60 | +- OOpt = A->getValue(); |
| 61 | +- |
| 62 | +- if (OOpt != "0") { |
| 63 | +- const char *WasmOpt = Args.MakeArgString(WasmOptPath); |
| 64 | +- ArgStringList OptArgs; |
| 65 | +- OptArgs.push_back(Output.getFilename()); |
| 66 | +- OptArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt)); |
| 67 | +- OptArgs.push_back("-o"); |
| 68 | +- OptArgs.push_back(Output.getFilename()); |
| 69 | +- C.addCommand(std::make_unique<Command>( |
| 70 | +- JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, OptArgs, |
| 71 | +- Inputs, Output)); |
| 72 | +- } |
| 73 | ++ if (!WasmOptPath.empty() && Args.hasArg(options::OPT_shared) && |
| 74 | ++ llvm::sys::Process::GetEnv("WASM_SO_OPT")) { |
| 75 | ++ const char *WasmOpt = Args.MakeArgString(WasmOptPath); |
| 76 | ++ ArgStringList OptArgs; |
| 77 | ++ OptArgs.push_back(Output.getFilename()); |
| 78 | ++ OptArgs.push_back("-o"); |
| 79 | ++ OptArgs.push_back(Output.getFilename()); |
| 80 | ++ |
| 81 | ++ std::istringstream iss(llvm::sys::Process::GetEnv("WASM_SO_OPT").value()); |
| 82 | ++ std::string arg; |
| 83 | ++ |
| 84 | ++ while (iss >> arg) { |
| 85 | ++ auto *arg_heap = new char[arg.size() + 1]; |
| 86 | ++ std::copy(arg.begin(), arg.end(), arg_heap); |
| 87 | ++ arg_heap[arg.size()] = '\0'; |
| 88 | ++ OptArgs.push_back(arg_heap); |
| 89 | + } |
| 90 | ++ |
| 91 | ++ C.addCommand(std::make_unique<Command>(JA, *this, |
| 92 | ++ ResponseFileSupport::AtFileCurCP(), |
| 93 | ++ WasmOpt, OptArgs, Inputs, Output)); |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | +diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake |
| 98 | +index c3e734f72392..282a321fd70b 100644 |
| 99 | +--- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake |
| 100 | ++++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake |
| 101 | +@@ -382,8 +382,8 @@ function(add_compiler_rt_runtime name type) |
| 102 | + target_link_libraries(${libname} PRIVATE ${builtins_${libname}}) |
| 103 | + endif() |
| 104 | + if(${type} STREQUAL "SHARED") |
| 105 | +- if(APPLE OR WIN32) |
| 106 | +- set_property(TARGET ${libname} PROPERTY BUILD_WITH_INSTALL_RPATH ON) |
| 107 | ++ if(COMMAND llvm_setup_rpath) |
| 108 | ++ llvm_setup_rpath(${libname}) |
| 109 | + endif() |
| 110 | + if(WIN32 AND NOT CYGWIN AND NOT MINGW) |
| 111 | + set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "") |
| 112 | +diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp |
| 113 | +index 0e6c4e691be1..bfa438505d98 100644 |
| 114 | +--- a/lld/wasm/InputChunks.cpp |
| 115 | ++++ b/lld/wasm/InputChunks.cpp |
| 116 | +@@ -361,12 +361,11 @@ uint64_t InputChunk::getVA(uint64_t offset) const { |
| 117 | + // Generate code to apply relocations to the data section at runtime. |
| 118 | + // This is only called when generating shared libraries (PIC) where address are |
| 119 | + // not known at static link time. |
| 120 | +-bool InputChunk::generateRelocationCode(raw_ostream &os) const { |
| 121 | ++void InputChunk::generateRelocationCode(std::vector<std::string> &funcs) const { |
| 122 | + LLVM_DEBUG(dbgs() << "generating runtime relocations: " << name |
| 123 | + << " count=" << relocations.size() << "\n"); |
| 124 | + |
| 125 | + bool is64 = ctx.arg.is64.value_or(false); |
| 126 | +- bool generated = false; |
| 127 | + unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST |
| 128 | + : WASM_OPCODE_I32_CONST; |
| 129 | + unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD |
| 130 | +@@ -385,6 +384,14 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const { |
| 131 | + if (!requiresRuntimeReloc) |
| 132 | + continue; |
| 133 | + |
| 134 | ++ if (funcs.empty() || funcs.back().size() >= 7654300) { |
| 135 | ++ funcs.emplace_back(std::string()); |
| 136 | ++ raw_string_ostream os(funcs.back()); |
| 137 | ++ writeUleb128(os, 0, "num locals"); |
| 138 | ++ } |
| 139 | ++ |
| 140 | ++ raw_string_ostream os(funcs.back()); |
| 141 | ++ |
| 142 | + LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type) |
| 143 | + << " addend=" << rel.Addend << " index=" << rel.Index |
| 144 | + << " output offset=" << offset << "\n"); |
| 145 | +@@ -439,9 +446,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const { |
| 146 | + writeU8(os, opcode_reloc_store, "I32_STORE"); |
| 147 | + writeUleb128(os, 2, "align"); |
| 148 | + writeUleb128(os, 0, "offset"); |
| 149 | +- generated = true; |
| 150 | + } |
| 151 | +- return generated; |
| 152 | + } |
| 153 | + |
| 154 | + // Split WASM_SEG_FLAG_STRINGS section. Such a section is a sequence of |
| 155 | +diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h |
| 156 | +index f545449e1246..d231382a5f5e 100644 |
| 157 | +--- a/lld/wasm/InputChunks.h |
| 158 | ++++ b/lld/wasm/InputChunks.h |
| 159 | +@@ -78,7 +78,7 @@ public: |
| 160 | + |
| 161 | + size_t getNumRelocations() const { return relocations.size(); } |
| 162 | + void writeRelocations(llvm::raw_ostream &os) const; |
| 163 | +- bool generateRelocationCode(raw_ostream &os) const; |
| 164 | ++ void generateRelocationCode(std::vector<std::string> &funcs) const; |
| 165 | + |
| 166 | + bool isTLS() const { return flags & llvm::wasm::WASM_SEG_FLAG_TLS; } |
| 167 | + bool isRetained() const { return flags & llvm::wasm::WASM_SEG_FLAG_RETAIN; } |
| 168 | +diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp |
| 169 | +index 0e2aa57e9048..e5df7d8c0be0 100644 |
| 170 | +--- a/lld/wasm/SyntheticSections.cpp |
| 171 | ++++ b/lld/wasm/SyntheticSections.cpp |
| 172 | +@@ -299,6 +299,8 @@ void FunctionSection::writeBody() { |
| 173 | + void FunctionSection::addFunction(InputFunction *func) { |
| 174 | + if (!func->live) |
| 175 | + return; |
| 176 | ++ if (func->hasFunctionIndex()) |
| 177 | ++ return; |
| 178 | + uint32_t functionIndex = |
| 179 | + out.importSec->getNumImportedFunctions() + inputFunctions.size(); |
| 180 | + inputFunctions.emplace_back(func); |
| 181 | +diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp |
| 182 | +index 2bf4b370a7db..19fca2616c7a 100644 |
| 183 | +--- a/lld/wasm/Writer.cpp |
| 184 | ++++ b/lld/wasm/Writer.cpp |
| 185 | +@@ -1452,20 +1452,21 @@ void Writer::createStartFunction() { |
| 186 | + void Writer::createApplyDataRelocationsFunction() { |
| 187 | + LLVM_DEBUG(dbgs() << "createApplyDataRelocationsFunction\n"); |
| 188 | + // First write the body's contents to a string. |
| 189 | +- std::string bodyContent; |
| 190 | ++ std::vector<std::string> funcs; |
| 191 | + { |
| 192 | +- raw_string_ostream os(bodyContent); |
| 193 | +- writeUleb128(os, 0, "num locals"); |
| 194 | +- bool generated = false; |
| 195 | + for (const OutputSegment *seg : segments) |
| 196 | + if (!ctx.arg.sharedMemory || !seg->isTLS()) |
| 197 | + for (const InputChunk *inSeg : seg->inputSegments) |
| 198 | +- generated |= inSeg->generateRelocationCode(os); |
| 199 | ++ inSeg->generateRelocationCode(funcs); |
| 200 | ++ } |
| 201 | + |
| 202 | +- if (!generated) { |
| 203 | +- LLVM_DEBUG(dbgs() << "skipping empty __wasm_apply_data_relocs\n"); |
| 204 | +- return; |
| 205 | +- } |
| 206 | ++ if (funcs.empty()) { |
| 207 | ++ LLVM_DEBUG(dbgs() << "skipping empty __wasm_apply_data_relocs\n"); |
| 208 | ++ return; |
| 209 | ++ } |
| 210 | ++ |
| 211 | ++ for (auto &func : funcs) { |
| 212 | ++ raw_string_ostream os(func); |
| 213 | + writeU8(os, WASM_OPCODE_END, "END"); |
| 214 | + } |
| 215 | + |
| 216 | +@@ -1478,24 +1479,67 @@ void Writer::createApplyDataRelocationsFunction() { |
| 217 | + make<SyntheticFunction>(nullSignature, "__wasm_apply_data_relocs")); |
| 218 | + def->markLive(); |
| 219 | + |
| 220 | +- createFunction(def, bodyContent); |
| 221 | ++ if (funcs.size() == 1) { |
| 222 | ++ createFunction(def, funcs.back()); |
| 223 | ++ return; |
| 224 | ++ } |
| 225 | ++ |
| 226 | ++ std::string body; |
| 227 | ++ { |
| 228 | ++ raw_string_ostream os(body); |
| 229 | ++ writeUleb128(os, 0, "num locals"); |
| 230 | ++ |
| 231 | ++ for (std::size_t i = 0; i < funcs.size(); ++i) { |
| 232 | ++ auto &name = |
| 233 | ++ *make<std::string>("__wasm_apply_data_relocs_" + std::to_string(i)); |
| 234 | ++ auto *func = make<SyntheticFunction>(nullSignature, name); |
| 235 | ++ auto *def = symtab->addSyntheticFunction( |
| 236 | ++ name, WASM_SYMBOL_VISIBILITY_HIDDEN, func); |
| 237 | ++ def->markLive(); |
| 238 | ++ // Normally this shouldn't be called manually for a synthetic |
| 239 | ++ // function, since the function indices in |
| 240 | ++ // ctx.syntheticFunctions will be calculated later (check |
| 241 | ++ // functionSec->addFunction call hierarchy for details). |
| 242 | ++ // However, at this point we already need the correct index. The |
| 243 | ++ // solution is to place the new synthetic function eagerly, and |
| 244 | ++ // also making addFunction idempotent by skipping when there's |
| 245 | ++ // already a function index. |
| 246 | ++ out.functionSec->addFunction(func); |
| 247 | ++ createFunction(def, funcs[i]); |
| 248 | ++ |
| 249 | ++ writeU8(os, WASM_OPCODE_CALL, "CALL"); |
| 250 | ++ writeUleb128(os, def->getFunctionIndex(), "function index"); |
| 251 | ++ } |
| 252 | ++ |
| 253 | ++ writeU8(os, WASM_OPCODE_END, "END"); |
| 254 | ++ } |
| 255 | ++ createFunction(def, body); |
| 256 | + } |
| 257 | + |
| 258 | + void Writer::createApplyTLSRelocationsFunction() { |
| 259 | + LLVM_DEBUG(dbgs() << "createApplyTLSRelocationsFunction\n"); |
| 260 | +- std::string bodyContent; |
| 261 | ++ std::vector<std::string> funcs; |
| 262 | + { |
| 263 | +- raw_string_ostream os(bodyContent); |
| 264 | +- writeUleb128(os, 0, "num locals"); |
| 265 | + for (const OutputSegment *seg : segments) |
| 266 | + if (seg->isTLS()) |
| 267 | + for (const InputChunk *inSeg : seg->inputSegments) |
| 268 | +- inSeg->generateRelocationCode(os); |
| 269 | ++ inSeg->generateRelocationCode(funcs); |
| 270 | ++ } |
| 271 | + |
| 272 | ++ if (funcs.empty()) { |
| 273 | ++ funcs.emplace_back(std::string()); |
| 274 | ++ raw_string_ostream os(funcs.back()); |
| 275 | ++ writeUleb128(os, 0, "num locals"); |
| 276 | ++ } |
| 277 | ++ |
| 278 | ++ for (auto &func : funcs) { |
| 279 | ++ raw_string_ostream os(func); |
| 280 | + writeU8(os, WASM_OPCODE_END, "END"); |
| 281 | + } |
| 282 | + |
| 283 | +- createFunction(ctx.sym.applyTLSRelocs, bodyContent); |
| 284 | ++ assert(funcs.size() == 1); |
| 285 | ++ |
| 286 | ++ createFunction(ctx.sym.applyTLSRelocs, funcs.back()); |
| 287 | + } |
| 288 | + |
| 289 | + // Similar to createApplyDataRelocationsFunction but generates relocation code |
| 290 | +diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake |
| 291 | +index d3e9377c8d2f..50a34184919a 100644 |
| 292 | +--- a/llvm/cmake/modules/AddLLVM.cmake |
| 293 | ++++ b/llvm/cmake/modules/AddLLVM.cmake |
| 294 | +@@ -2524,8 +2524,7 @@ function(llvm_setup_rpath name) |
| 295 | + # FIXME: update this when there is better solution. |
| 296 | + set(_install_rpath "${LLVM_LIBRARY_OUTPUT_INTDIR}" "${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) |
| 297 | + elseif(UNIX) |
| 298 | +- set(_build_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) |
| 299 | +- set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}") |
| 300 | ++ set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) |
| 301 | + if(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)") |
| 302 | + set_property(TARGET ${name} APPEND_STRING PROPERTY |
| 303 | + LINK_FLAGS " -Wl,-z,origin ") |
| 304 | +@@ -2539,16 +2538,9 @@ function(llvm_setup_rpath name) |
| 305 | + return() |
| 306 | + endif() |
| 307 | + |
| 308 | +- # Enable BUILD_WITH_INSTALL_RPATH unless CMAKE_BUILD_RPATH is set and not |
| 309 | +- # building for macOS or AIX, as those platforms seemingly require it. |
| 310 | +- # On AIX, the tool chain doesn't support modifying rpaths/libpaths for XCOFF |
| 311 | +- # on install at the moment, so BUILD_WITH_INSTALL_RPATH is required. |
| 312 | ++ # Enable BUILD_WITH_INSTALL_RPATH unless CMAKE_BUILD_RPATH is set. |
| 313 | + if("${CMAKE_BUILD_RPATH}" STREQUAL "") |
| 314 | +- if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin|AIX") |
| 315 | +- set_property(TARGET ${name} PROPERTY BUILD_WITH_INSTALL_RPATH ON) |
| 316 | +- else() |
| 317 | +- set_property(TARGET ${name} APPEND PROPERTY BUILD_RPATH "${_build_rpath}") |
| 318 | +- endif() |
| 319 | ++ set_property(TARGET ${name} PROPERTY BUILD_WITH_INSTALL_RPATH ON) |
| 320 | + endif() |
| 321 | + |
| 322 | + set_target_properties(${name} PROPERTIES |
0 commit comments