summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/WasmObjectWriter.cpp
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2017-12-15 00:17:10 +0000
committerSam Clegg <sbc@chromium.org>2017-12-15 00:17:10 +0000
commitbafe69026d7e78696173bf09e4959996ec750167 (patch)
tree5c2396c15d59e9707eb901c1889ea666f7d7faa4 /llvm/lib/MC/WasmObjectWriter.cpp
parent476a73924e7a789c5a0844280ba0a9deac155d7b (diff)
downloadbcm5719-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.cpp79
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.
OpenPOWER on IntegriCloud