about summary refs log tree commit diff
path: root/src/rustllvm
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2018-07-18 12:12:53 -0700
committerAlex Crichton <alex@alexcrichton.com>2018-07-18 12:12:53 -0700
commite08fcbbd8d241ab68d72dc8b288ca55b8c1114fe (patch)
treeeddeeb70161b48a90aa6b3e2e79d9395830df24d /src/rustllvm
parent12ed235adc62e63b16bb4f715b143c37a5efa00d (diff)
downloadrust-e08fcbbd8d241ab68d72dc8b288ca55b8c1114fe.tar.gz
rust-e08fcbbd8d241ab68d72dc8b288ca55b8c1114fe.zip
rustc: Work around an upstream wasm ThinLTO bug
This commit implements a workaround for an [upstream LLVM bug][1] where custom
sections were accidentally duplicated amongst codegen units when ThinLTO passes
were performed. This is due to the fact that custom sections for wasm are stored
as metadata nodes which are automatically imported into modules when ThinLTO
happens. The fix here is to forcibly delete the metadata node from imported
modules before LLVM has a chance to try to copy it over.

[1]: https://bugs.llvm.org/show_bug.cgi?id=38184
Diffstat (limited to 'src/rustllvm')
-rw-r--r--src/rustllvm/PassWrapper.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index a00ff3b345d..637f2e0beaa 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -1084,11 +1084,40 @@ LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef
 extern "C" bool
 LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
   Module &Mod = *unwrap(M);
+
   const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
   auto Loader = [&](StringRef Identifier) {
     const auto &Memory = Data->ModuleMap.lookup(Identifier);
     auto &Context = Mod.getContext();
-    return getLazyBitcodeModule(Memory, Context, true, true);
+    auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
+
+    if (!MOrErr)
+      return std::move(MOrErr);
+
+    // The rest of this closure is a workaround for
+    // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
+    // we accidentally import wasm custom sections into different modules,
+    // duplicating them by in the final output artifact.
+    //
+    // The issue is worked around here by manually removing the
+    // `wasm.custom_sections` named metadata node from any imported module. This
+    // we know isn't used by any optimization pass so there's no need for it to
+    // be imported.
+    //
+    // Note that the metadata is currently lazily loaded, so we materialize it
+    // here before looking up if there's metadata inside. The `FunctionImporter`
+    // will immediately materialize metadata anyway after an import, so this
+    // shouldn't be a perf hit.
+    if (Error Err = (*MOrErr)->materializeMetadata()) {
+      Expected<std::unique_ptr<Module>> Ret(std::move(Err));
+      return std::move(Ret);
+    }
+
+    auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
+    if (WasmCustomSections)
+      WasmCustomSections->eraseFromParent();
+
+    return std::move(MOrErr);
   };
   FunctionImporter Importer(Data->Index, Loader);
   Expected<bool> Result = Importer.importFunctions(Mod, ImportList);