From 4e40544465324b47d0fc30b41a6de886ce36d125 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 30 Mar 2020 17:37:01 -0700 Subject: [PATCH 1/2] [WebAssembly] Emit .llvmcmd and .llvmbc as custom sections Fixes: https://bugs.llvm.org/show_bug.cgi?id=45362 Differential Revision: https://reviews.llvm.org/D77115 --- clang/test/Driver/embed-bitcode-wasm.c | 6 ++++++ clang/test/Driver/fembed-bitcode.c | 9 +++++++++ lld/wasm/Writer.cpp | 12 ++++++++++-- llvm/include/llvm/MC/MCSymbolWasm.h | 4 ++++ .../CodeGen/TargetLoweringObjectFileImpl.cpp | 8 ++++++++ llvm/lib/MC/WasmObjectWriter.cpp | 19 +++++++++---------- 6 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 clang/test/Driver/embed-bitcode-wasm.c diff --git a/clang/test/Driver/embed-bitcode-wasm.c b/clang/test/Driver/embed-bitcode-wasm.c new file mode 100644 index 00000000000000..3705a4d24875d7 --- /dev/null +++ b/clang/test/Driver/embed-bitcode-wasm.c @@ -0,0 +1,6 @@ +// REQUIRES: webassembly-registered-target + +// RUN: %clang -c -target wasm32-unknown-unknown %s -fembed-bitcode -o %t.o +// RUN: llvm-readobj -S %t.o | FileCheck --check-prefix=CHECK %s +// CHECK: Name: .llvmbc +// CHECK: Name: .llvmcmd diff --git a/clang/test/Driver/fembed-bitcode.c b/clang/test/Driver/fembed-bitcode.c index c1f020b38ad2be..f6b56ef171205b 100644 --- a/clang/test/Driver/fembed-bitcode.c +++ b/clang/test/Driver/fembed-bitcode.c @@ -34,3 +34,12 @@ // RUN: | FileCheck --check-prefix=CHECK-HEXAGON %s // CHECK-HEXAGON: "-target-feature" // CHECK-HEXAGON: "+reserved-r19" +// +// RUN: %clang -target wasm32-unknown-unknown -fembed-bitcode=all -pthread -c %s -o /dev/null -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-WASM %s + +// CHECK-WASM: "-cc1" +// CHECK-WASM: "-target-feature" "+atomics" + +// CHECK-WASM: "-cc1" +// CHECK-WASM: "-target-feature" "+atomics" diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 6338b6e5fa2ad1..2aeea5c6f3fb13 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -111,13 +111,21 @@ void Writer::calculateCustomSections() { for (InputSection *section : file->customSections) { StringRef name = section->getName(); // These custom sections are known the linker and synthesized rather than - // blindly copied + // blindly copied. if (name == "linking" || name == "name" || name == "producers" || name == "target_features" || name.startswith("reloc.")) continue; - // .. or it is a debug section + // These custom sections are generated by `clang -fembed-bitcode`. + // These are used by the rust toolchain to ship LTO data along with + // compiled object code, but they don't want this included in the linker + // output. + if (name == ".llvmbc" || name == ".llvmcmd") + continue; + // Strip debug section in that option was specified. if (stripDebug && name.startswith(".debug_")) continue; + // Otherwise include custom sections by default and concatenate their + // contents. customSectionMapping[name].push_back(section); } } diff --git a/llvm/include/llvm/MC/MCSymbolWasm.h b/llvm/include/llvm/MC/MCSymbolWasm.h index c50cd0ee470901..23c41301806ea4 100644 --- a/llvm/include/llvm/MC/MCSymbolWasm.h +++ b/llvm/include/llvm/MC/MCSymbolWasm.h @@ -18,6 +18,7 @@ class MCSymbolWasm : public MCSymbol { bool IsWeak = false; bool IsHidden = false; bool IsComdat = false; + mutable bool IsUsedInInitArray = false; mutable bool IsUsedInGOT = false; Optional ImportModule; Optional ImportName; @@ -82,6 +83,9 @@ class MCSymbolWasm : public MCSymbol { void setUsedInGOT() const { IsUsedInGOT = true; } bool isUsedInGOT() const { return IsUsedInGOT; } + void setUsedInInitArray() const { IsUsedInInitArray = true; } + bool isUsedInInitArray() const { return IsUsedInInitArray; } + const wasm::WasmSignature *getSignature() const { return Signature; } void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 4c8f75b237aa8e..1c23e8cb4e0dc4 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1688,6 +1688,14 @@ static const Comdat *getWasmComdat(const GlobalValue *GV) { } static SectionKind getWasmKindForNamedSection(StringRef Name, SectionKind K) { + // Certain data sections we treat as named custom sections rather than + // segments within the data section. + // This could be avoided if all data segements (the wasm sense) were + // represented as thier own sections (in the llvm sense). + // TODO(sbc): https://github.com/WebAssembly/tool-conventions/issues/138 + if (Name == ".llvmcmd" || Name == ".llvmbc") + return SectionKind::getMetadata(); + // If we're told we have function data, then use that. if (K.isText()) return SectionKind::getText(); diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 098343cd0107b3..f59f0c7dc3b2e6 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -434,10 +434,6 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); MCContext &Ctx = Asm.getContext(); - // The .init_array isn't translated as data, so don't do relocations in it. - if (FixupSection.getSectionName().startswith(".init_array")) - return; - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { assert(RefB->getKind() == MCSymbolRefExpr::VK_None && "Should not have constructed this"); @@ -483,6 +479,12 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, const MCSymbolRefExpr *RefA = Target.getSymA(); const auto *SymA = RefA ? cast(&RefA->getSymbol()) : nullptr; + // The .init_array isn't translated as data, so don't do relocations in it. + if (FixupSection.getSectionName().startswith(".init_array")) { + SymA->setUsedInInitArray(); + return; + } + if (SymA && SymA->isVariable()) { const MCExpr *Expr = SymA->getVariableValue(); const auto *Inner = cast(Expr); @@ -1113,16 +1115,13 @@ void WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) { } static bool isInSymtab(const MCSymbolWasm &Sym) { - if (Sym.isUsedInReloc()) + if (Sym.isUsedInReloc() || Sym.isUsedInInitArray()) return true; if (Sym.isComdat() && !Sym.isDefined()) return false; - if (Sym.isTemporary() && Sym.getName().empty()) - return false; - - if (Sym.isTemporary() && Sym.isData() && !Sym.getSize()) + if (Sym.isTemporary()) return false; if (Sym.isSection()) @@ -1578,7 +1577,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, report_fatal_error("fixups in .init_array should be symbol references"); const auto &TargetSym = cast(SymRef->getSymbol()); if (TargetSym.getIndex() == InvalidIndex) - report_fatal_error("symbols in .init_array should exist in symbtab"); + report_fatal_error("symbols in .init_array should exist in symtab"); if (!TargetSym.isFunction()) report_fatal_error("symbols in .init_array should be for functions"); InitFuncs.push_back( From e319edacac6aa5626c5ba167e8f02c5a9be424c6 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 15 Apr 2020 11:35:35 -0700 Subject: [PATCH 2/2] Enable finding bitcode in wasm objects This commit fixes using functions in `IRObjectFile` to load bitcode from wasm objects by recognizing the file magic for wasm and also inheriting the default implementation of classifying sections as bitcode. Patch By: alexcrichton Differential Revision: https://reviews.llvm.org/D78199 --- llvm/include/llvm/Object/Wasm.h | 1 - llvm/lib/Object/IRObjectFile.cpp | 1 + llvm/lib/Object/WasmObjectFile.cpp | 2 -- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h index e130ea32ed21bd..dc2775c59c2067 100644 --- a/llvm/include/llvm/Object/Wasm.h +++ b/llvm/include/llvm/Object/Wasm.h @@ -183,7 +183,6 @@ class WasmObjectFile : public ObjectFile { bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool isSectionBitcode(DataRefImpl Sec) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; diff --git a/llvm/lib/Object/IRObjectFile.cpp b/llvm/lib/Object/IRObjectFile.cpp index 636f1521262fde..931e842edb4480 100644 --- a/llvm/lib/Object/IRObjectFile.cpp +++ b/llvm/lib/Object/IRObjectFile.cpp @@ -94,6 +94,7 @@ IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { return Object; case file_magic::elf_relocatable: case file_magic::macho_object: + case file_magic::wasm_object: case file_magic::coff_object: { Expected> ObjFile = ObjectFile::createObjectFile(Object, Type); diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index 82aa1830dcedbf..e1ea4cc7e608bf 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -1455,8 +1455,6 @@ bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } -bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } - relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { DataRefImpl RelocRef; RelocRef.d.a = Ref.d.a;