diff options
| author | Sam Clegg <sbc@chromium.org> | 2017-12-15 00:17:10 +0000 |
|---|---|---|
| committer | Sam Clegg <sbc@chromium.org> | 2017-12-15 00:17:10 +0000 |
| commit | bafe69026d7e78696173bf09e4959996ec750167 (patch) | |
| tree | 5c2396c15d59e9707eb901c1889ea666f7d7faa4 /llvm/lib/MC/WasmObjectWriter.cpp | |
| parent | 476a73924e7a789c5a0844280ba0a9deac155d7b (diff) | |
| download | bcm5719-llvm-bafe69026d7e78696173bf09e4959996ec750167.tar.gz bcm5719-llvm-bafe69026d7e78696173bf09e4959996ec750167.zip | |
[WebAssembly] Implement @llvm.global_ctors and @llvm.global_dtors
Summary:
- lowers @llvm.global_dtors by adding @llvm.global_ctors
functions which register the destructors with `__cxa_atexit`.
- impements @llvm.global_ctors with wasm start functions and linker metadata
See [here](https://github.com/WebAssembly/tool-conventions/issues/25) for more background.
Subscribers: jfb, dschuff, mgorny, jgravelle-google, aheejin, sunfish
Differential Revision: https://reviews.llvm.org/D41211
llvm-svn: 320774
Diffstat (limited to 'llvm/lib/MC/WasmObjectWriter.cpp')
| -rw-r--r-- | llvm/lib/MC/WasmObjectWriter.cpp | 79 |
1 files changed, 75 insertions, 4 deletions
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index b2c5b14bca5..6e76c5fac35 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -284,7 +284,8 @@ private: void writeDataRelocSection(); void writeLinkingMetaDataSection( ArrayRef<WasmDataSegment> Segments, uint32_t DataSize, - SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags); + const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags, + const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs); uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry); void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations, @@ -366,6 +367,10 @@ 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"); @@ -905,7 +910,8 @@ void WasmObjectWriter::writeDataRelocSection() { void WasmObjectWriter::writeLinkingMetaDataSection( ArrayRef<WasmDataSegment> Segments, uint32_t DataSize, - SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags) { + const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags, + const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); SectionBookkeeping SubSection; @@ -937,6 +943,16 @@ void WasmObjectWriter::writeLinkingMetaDataSection( endSection(SubSection); } + if (!InitFuncs.empty()) { + startSection(SubSection, wasm::WASM_INIT_FUNCS); + encodeULEB128(InitFuncs.size(), getStream()); + for (auto &StartFunc : InitFuncs) { + encodeULEB128(StartFunc.first, getStream()); // priority + encodeULEB128(StartFunc.second, getStream()); // function index + } + endSection(SubSection); + } + endSection(Section); } @@ -977,6 +993,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, SmallVector<WasmImport, 4> Imports; SmallVector<WasmExport, 4> Exports; SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags; + SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs; SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken; unsigned NumFuncImports = 0; SmallVector<WasmDataSegment, 4> DataSegments; @@ -1132,6 +1149,10 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, if (!Section.isWasmData()) continue; + // .init_array sections are handled specially elsewhere. + if (cast<MCSectionWasm>(Sec).getSectionName().startswith(".init_array")) + continue; + DataSize = alignTo(DataSize, Section.getAlignment()); DataSegments.emplace_back(); WasmDataSegment &Segment = DataSegments.back(); @@ -1291,6 +1312,56 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, registerFunctionType(*Fixup.Symbol); } + // Translate .init_array section contents into start functions. + for (const MCSection &S : Asm) { + const auto &WS = static_cast<const MCSectionWasm &>(S); + if (WS.getSectionName().startswith(".fini_array")) + report_fatal_error(".fini_array sections are unsupported"); + if (!WS.getSectionName().startswith(".init_array")) + continue; + if (WS.getFragmentList().empty()) + continue; + if (WS.getFragmentList().size() != 2) + report_fatal_error("only one .init_array section fragment supported"); + const MCFragment &AlignFrag = *WS.begin(); + if (AlignFrag.getKind() != MCFragment::FT_Align) + report_fatal_error(".init_array section should be aligned"); + if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4)) + report_fatal_error(".init_array section should be aligned for pointers"); + const MCFragment &Frag = *std::next(WS.begin()); + if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) + report_fatal_error("only data supported in .init_array section"); + uint16_t Priority = UINT16_MAX; + if (WS.getSectionName().size() != 11) { + if (WS.getSectionName()[11] != '.') + report_fatal_error(".init_array section priority should start with '.'"); + if (WS.getSectionName().substr(12).getAsInteger(10, Priority)) + report_fatal_error("invalid .init_array section priority"); + } + const auto &DataFrag = cast<MCDataFragment>(Frag); + const SmallVectorImpl<char> &Contents = DataFrag.getContents(); + for (const uint8_t *p = (const uint8_t *)Contents.data(), + *end = (const uint8_t *)Contents.data() + Contents.size(); + p != end; ++p) { + if (*p != 0) + report_fatal_error("non-symbolic data in .init_array section"); + } + for (const MCFixup &Fixup : DataFrag.getFixups()) { + assert(Fixup.getKind() == MCFixup::getKindForSize(is64Bit() ? 8 : 4, false)); + const MCExpr *Expr = Fixup.getValue(); + auto *Sym = dyn_cast<MCSymbolRefExpr>(Expr); + if (!Sym) + report_fatal_error("fixups in .init_array should be symbol references"); + if (Sym->getKind() != MCSymbolRefExpr::VK_WebAssembly_FUNCTION) + report_fatal_error("symbols in .init_array should be for functions"); + auto I = SymbolIndices.find(cast<MCSymbolWasm>(&Sym->getSymbol())); + if (I == SymbolIndices.end()) + report_fatal_error("symbols in .init_array should be defined"); + uint32_t Index = I->second; + InitFuncs.push_back(std::make_pair(Priority, Index)); + } + } + // Write out the Wasm header. writeHeader(Asm); @@ -1301,14 +1372,14 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, // Skip the "memory" section; we import the memory instead. writeGlobalSection(); writeExportSection(Exports); - // TODO: Start Section writeElemSection(TableElems); writeCodeSection(Asm, Layout, Functions); writeDataSection(DataSegments); writeNameSection(Functions, Imports, NumFuncImports); writeCodeRelocSection(); writeDataRelocSection(); - writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags); + writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags, + InitFuncs); // TODO: Translate the .comment section to the output. // TODO: Translate debug sections to the output. |

