diff --git a/clang/test/Driver/embed-bitcode-wasm.c b/clang/test/Driver/embed-bitcode-wasm.c new file mode 100644 --- /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 --- a/clang/test/Driver/fembed-bitcode.c +++ b/clang/test/Driver/fembed-bitcode.c @@ -30,3 +30,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 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -110,13 +110,21 @@ 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 --- a/llvm/include/llvm/MC/MCSymbolWasm.h +++ b/llvm/include/llvm/MC/MCSymbolWasm.h @@ -18,6 +18,7 @@ bool IsWeak = false; bool IsHidden = false; bool IsComdat = false; + mutable bool IsUsedInInitArray = false; mutable bool IsUsedInGOT = false; Optional ImportModule; Optional ImportName; @@ -104,6 +105,9 @@ 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 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1765,6 +1765,14 @@ StringRef Name = GO->getSection(); + // 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") + Kind = SectionKind::getMetadata(); + StringRef Group = ""; if (const Comdat *C = getWasmComdat(GO)) { Group = C->getName(); diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -436,10 +436,6 @@ 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()) { // To get here the A - B expression must have failed evaluateAsRelocatable. // This means either A or B must be undefined and in WebAssembly we can't @@ -456,6 +452,12 @@ const MCSymbolRefExpr *RefA = Target.getSymA(); const auto *SymA = cast(&RefA->getSymbol()); + // 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->isVariable()) { const MCExpr *Expr = SymA->getVariableValue(); const auto *Inner = cast(Expr); @@ -1084,16 +1086,13 @@ } 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()) @@ -1565,7 +1564,7 @@ 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(