summaryrefslogtreecommitdiff
path: root/lib/MC/WasmObjectWriter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/MC/WasmObjectWriter.cpp
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'lib/MC/WasmObjectWriter.cpp')
-rw-r--r--lib/MC/WasmObjectWriter.cpp648
1 files changed, 374 insertions, 274 deletions
diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp
index 0d31f65c49d9f..6e76c5fac35f3 100644
--- a/lib/MC/WasmObjectWriter.cpp
+++ b/lib/MC/WasmObjectWriter.cpp
@@ -15,13 +15,11 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionWasm.h"
#include "llvm/MC/MCSymbolWasm.h"
@@ -96,12 +94,26 @@ struct WasmFunctionTypeDenseMapInfo {
}
};
+// A wasm data segment. A wasm binary contains only a single data section
+// but that can contain many segments, each with their own virtual location
+// in memory. Each MCSection data created by llvm is modeled as its own
+// wasm data segment.
+struct WasmDataSegment {
+ MCSectionWasm *Section;
+ StringRef Name;
+ uint32_t Offset;
+ uint32_t Alignment;
+ uint32_t Flags;
+ SmallVector<char, 4> Data;
+};
+
// A wasm import to be written into the import section.
struct WasmImport {
StringRef ModuleName;
StringRef FieldName;
unsigned Kind;
int32_t Type;
+ bool IsMutable;
};
// A wasm function to be written into the function section.
@@ -142,9 +154,9 @@ struct WasmRelocationEntry {
bool hasAddend() const {
switch (Type) {
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
return true;
default:
return false;
@@ -153,7 +165,8 @@ struct WasmRelocationEntry {
void print(raw_ostream &Out) const {
Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
- << ", Type=" << Type << ", FixupSection=" << FixupSection;
+ << ", Type=" << Type
+ << ", FixupSection=" << FixupSection->getSectionName();
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -199,6 +212,8 @@ class WasmObjectWriter : public MCObjectWriter {
DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
FunctionTypeIndices;
SmallVector<WasmFunctionType, 4> FunctionTypes;
+ SmallVector<WasmGlobal, 4> Globals;
+ unsigned NumGlobalImports = 0;
// TargetObjectWriter wrappers.
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
@@ -211,8 +226,10 @@ class WasmObjectWriter : public MCObjectWriter {
void endSection(SectionBookkeeping &Section);
public:
- WasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS)
- : MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {}
+ WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS)
+ : MCObjectWriter(OS, /*IsLittleEndian=*/true),
+ TargetObjectWriter(std::move(MOTW)) {}
private:
~WasmObjectWriter() override;
@@ -225,7 +242,9 @@ private:
IndirectSymbolIndices.clear();
FunctionTypeIndices.clear();
FunctionTypes.clear();
+ Globals.clear();
MCObjectWriter::reset();
+ NumGlobalImports = 0;
}
void writeHeader(const MCAssembler &Asm);
@@ -248,33 +267,31 @@ private:
encodeSLEB128(int32_t(Ty), getStream());
}
- void writeTypeSection(const SmallVector<WasmFunctionType, 4> &FunctionTypes);
- void writeImportSection(const SmallVector<WasmImport, 4> &Imports);
- void writeFunctionSection(const SmallVector<WasmFunction, 4> &Functions);
- void writeTableSection(uint32_t NumElements);
- void writeMemorySection(const SmallVector<char, 0> &DataBytes);
- void writeGlobalSection(const SmallVector<WasmGlobal, 4> &Globals);
- void writeExportSection(const SmallVector<WasmExport, 4> &Exports);
- void writeElemSection(const SmallVector<uint32_t, 4> &TableElems);
+ void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
+ void writeImportSection(ArrayRef<WasmImport> Imports, uint32_t DataSize,
+ uint32_t NumElements);
+ void writeFunctionSection(ArrayRef<WasmFunction> Functions);
+ void writeGlobalSection();
+ void writeExportSection(ArrayRef<WasmExport> Exports);
+ void writeElemSection(ArrayRef<uint32_t> TableElems);
void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
- const SmallVector<WasmFunction, 4> &Functions);
- uint64_t
- writeDataSection(const SmallVector<char, 0> &DataBytes);
- void writeNameSection(const SmallVector<WasmFunction, 4> &Functions,
- const SmallVector<WasmImport, 4> &Imports,
+ ArrayRef<WasmFunction> Functions);
+ void writeDataSection(ArrayRef<WasmDataSegment> Segments);
+ void writeNameSection(ArrayRef<WasmFunction> Functions,
+ ArrayRef<WasmImport> Imports,
uint32_t NumFuncImports);
void writeCodeRelocSection();
- void writeDataRelocSection(uint64_t DataSectionHeaderSize);
- void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment,
- ArrayRef<StringRef> WeakSymbols,
- bool HasStackPointer,
- uint32_t StackPointerGlobal);
+ void writeDataRelocSection();
+ void writeLinkingMetaDataSection(
+ ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
+ 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,
uint64_t ContentsOffset);
- void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations,
- uint64_t HeaderSize);
+ void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations);
uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
uint32_t getFunctionType(const MCSymbolWasm& Symbol);
uint32_t registerFunctionType(const MCSymbolWasm& Symbol);
@@ -284,16 +301,6 @@ private:
WasmObjectWriter::~WasmObjectWriter() {}
-// Return the padding size to write a 32-bit value into a 5-byte ULEB128.
-static unsigned PaddingFor5ByteULEB128(uint32_t X) {
- return X == 0 ? 4 : (4u - (31u - countLeadingZeros(X)) / 7u);
-}
-
-// Return the padding size to write a 32-bit value into a 5-byte SLEB128.
-static unsigned PaddingFor5ByteSLEB128(int32_t X) {
- return 5 - getSLEB128Size(X);
-}
-
// Write out a section header and a patchable section size field.
void WasmObjectWriter::startSection(SectionBookkeeping &Section,
unsigned SectionId,
@@ -328,12 +335,11 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
report_fatal_error("section size does not fit in a uint32_t");
DEBUG(dbgs() << "endSection size=" << Size << "\n");
- unsigned Padding = PaddingFor5ByteULEB128(Size);
// Write the final section size to the payload_len field, which follows
// the section id byte.
uint8_t Buffer[16];
- unsigned SizeLen = encodeULEB128(Size, Buffer, Padding);
+ unsigned SizeLen = encodeULEB128(Size, Buffer, 5);
assert(SizeLen == 5);
getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
}
@@ -361,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");
@@ -429,10 +439,13 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
- if (FixupSection.hasInstructions())
- CodeRelocations.push_back(Rec);
- else
+ if (FixupSection.isWasmData())
DataRelocations.push_back(Rec);
+ else if (FixupSection.getKind().isText())
+ CodeRelocations.push_back(Rec);
+ else if (!FixupSection.getKind().isMetadata())
+ // TODO(sbc): Add support for debug sections.
+ llvm_unreachable("unexpected section type");
}
// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
@@ -440,8 +453,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
static void
WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
uint8_t Buffer[5];
- unsigned Padding = PaddingFor5ByteULEB128(X);
- unsigned SizeLen = encodeULEB128(X, Buffer, Padding);
+ unsigned SizeLen = encodeULEB128(X, Buffer, 5);
assert(SizeLen == 5);
Stream.pwrite((char *)Buffer, SizeLen, Offset);
}
@@ -451,8 +463,7 @@ WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
static void
WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
uint8_t Buffer[5];
- unsigned Padding = PaddingFor5ByteSLEB128(X);
- unsigned SizeLen = encodeSLEB128(X, Buffer, Padding);
+ unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
assert(SizeLen == 5);
Stream.pwrite((char *)Buffer, SizeLen, Offset);
}
@@ -464,19 +475,30 @@ static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
}
+static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) {
+ if (Symbol.isVariable()) {
+ const MCExpr *Expr = Symbol.getVariableValue();
+ auto *Inner = cast<MCSymbolRefExpr>(Expr);
+ return cast<MCSymbolWasm>(&Inner->getSymbol());
+ }
+ return &Symbol;
+}
+
// Compute a value to write into the code at the location covered
// by RelEntry. This value isn't used by the static linker, since
// we have addends; it just serves to make the code more readable
// and to make standalone wasm modules directly usable.
-static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
- const MCSymbolWasm *Sym = RelEntry.Symbol;
+uint32_t
+WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
+ const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
// For undefined symbols, use a hopefully invalid value.
if (!Sym->isDefined(/*SetUsed=*/false))
return UINT32_MAX;
- const auto &Section = cast<MCSectionWasm>(RelEntry.Symbol->getSection(false));
- uint64_t Address = Section.getSectionOffset() + RelEntry.Addend;
+ uint32_t GlobalIndex = SymbolIndices[Sym];
+ const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports];
+ uint64_t Address = Global.InitialValue + RelEntry.Addend;
// Ignore overflow. LLVM allows address arithmetic to silently wrap.
uint32_t Value = Address;
@@ -484,6 +506,47 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
return Value;
}
+static void addData(SmallVectorImpl<char> &DataBytes,
+ MCSectionWasm &DataSection) {
+ DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
+
+ DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
+
+ size_t LastFragmentSize = 0;
+ for (const MCFragment &Frag : DataSection) {
+ if (Frag.hasInstructions())
+ report_fatal_error("only data supported in data sections");
+
+ if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
+ if (Align->getValueSize() != 1)
+ report_fatal_error("only byte values supported for alignment");
+ // If nops are requested, use zeros, as this is the data section.
+ uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
+ uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
+ Align->getAlignment()),
+ DataBytes.size() +
+ Align->getMaxBytesToEmit());
+ DataBytes.resize(Size, Value);
+ } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
+ DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue());
+ } else {
+ const auto &DataFrag = cast<MCDataFragment>(Frag);
+ const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+
+ DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
+ LastFragmentSize = Contents.size();
+ }
+ }
+
+ // Don't allow empty segments, or segments that end with zero-sized
+ // fragment, otherwise the linker cannot map symbols to a unique
+ // data segment. This can be triggered by zero-sized structs
+ // See: test/MC/WebAssembly/bss.ll
+ if (LastFragmentSize == 0)
+ DataBytes.resize(DataBytes.size() + 1);
+ DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
+}
+
uint32_t WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
switch (RelEntry.Type) {
@@ -495,9 +558,9 @@ uint32_t WasmObjectWriter::getRelocationIndexValue(
return IndirectSymbolIndices[RelEntry.Symbol];
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
if (!SymbolIndices.count(RelEntry.Symbol))
report_fatal_error("symbol not found function/global index space: " +
RelEntry.Symbol->getName());
@@ -537,18 +600,18 @@ void WasmObjectWriter::applyRelocations(
WriteI32(Stream, Index, Offset);
break;
}
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: {
- uint32_t Value = ProvisionalValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
+ uint32_t Value = getProvisionalValue(RelEntry);
WritePatchableSLEB(Stream, Value, Offset);
break;
}
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: {
- uint32_t Value = ProvisionalValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
+ uint32_t Value = getProvisionalValue(RelEntry);
WritePatchableLEB(Stream, Value, Offset);
break;
}
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: {
- uint32_t Value = ProvisionalValue(RelEntry);
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: {
+ uint32_t Value = getProvisionalValue(RelEntry);
WriteI32(Stream, Value, Offset);
break;
}
@@ -561,12 +624,12 @@ void WasmObjectWriter::applyRelocations(
// Write out the portions of the relocation records that the linker will
// need to handle.
void WasmObjectWriter::writeRelocations(
- ArrayRef<WasmRelocationEntry> Relocations, uint64_t HeaderSize) {
+ ArrayRef<WasmRelocationEntry> Relocations) {
raw_pwrite_stream &Stream = getStream();
for (const WasmRelocationEntry& RelEntry : Relocations) {
uint64_t Offset = RelEntry.Offset +
- RelEntry.FixupSection->getSectionOffset() + HeaderSize;
+ RelEntry.FixupSection->getSectionOffset();
uint32_t Index = getRelocationIndexValue(RelEntry);
encodeULEB128(RelEntry.Type, Stream);
@@ -578,7 +641,7 @@ void WasmObjectWriter::writeRelocations(
}
void WasmObjectWriter::writeTypeSection(
- const SmallVector<WasmFunctionType, 4> &FunctionTypes) {
+ ArrayRef<WasmFunctionType> FunctionTypes) {
if (FunctionTypes.empty())
return;
@@ -600,12 +663,14 @@ void WasmObjectWriter::writeTypeSection(
endSection(Section);
}
-
-void WasmObjectWriter::writeImportSection(
- const SmallVector<WasmImport, 4> &Imports) {
+void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports,
+ uint32_t DataSize,
+ uint32_t NumElements) {
if (Imports.empty())
return;
+ uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
+
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_IMPORT);
@@ -622,7 +687,16 @@ void WasmObjectWriter::writeImportSection(
break;
case wasm::WASM_EXTERNAL_GLOBAL:
encodeSLEB128(int32_t(Import.Type), getStream());
- encodeULEB128(0, getStream()); // mutability
+ encodeULEB128(int32_t(Import.IsMutable), getStream());
+ break;
+ case wasm::WASM_EXTERNAL_MEMORY:
+ encodeULEB128(0, getStream()); // flags
+ encodeULEB128(NumPages, getStream()); // initial
+ break;
+ case wasm::WASM_EXTERNAL_TABLE:
+ encodeSLEB128(int32_t(Import.Type), getStream());
+ encodeULEB128(0, getStream()); // flags
+ encodeULEB128(NumElements, getStream()); // initial
break;
default:
llvm_unreachable("unsupported import kind");
@@ -632,8 +706,7 @@ void WasmObjectWriter::writeImportSection(
endSection(Section);
}
-void WasmObjectWriter::writeFunctionSection(
- const SmallVector<WasmFunction, 4> &Functions) {
+void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
if (Functions.empty())
return;
@@ -647,43 +720,7 @@ void WasmObjectWriter::writeFunctionSection(
endSection(Section);
}
-void WasmObjectWriter::writeTableSection(uint32_t NumElements) {
- // For now, always emit the table section, since indirect calls are not
- // valid without it. In the future, we could perhaps be more clever and omit
- // it if there are no indirect calls.
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_TABLE);
-
- encodeULEB128(1, getStream()); // The number of tables.
- // Fixed to 1 for now.
- encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table
- encodeULEB128(0, getStream()); // flags
- encodeULEB128(NumElements, getStream()); // initial
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeMemorySection(
- const SmallVector<char, 0> &DataBytes) {
- // For now, always emit the memory section, since loads and stores are not
- // valid without it. In the future, we could perhaps be more clever and omit
- // it if there are no loads or stores.
- SectionBookkeeping Section;
- uint32_t NumPages =
- (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
-
- startSection(Section, wasm::WASM_SEC_MEMORY);
- encodeULEB128(1, getStream()); // number of memory spaces
-
- encodeULEB128(0, getStream()); // flags
- encodeULEB128(NumPages, getStream()); // initial
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeGlobalSection(
- const SmallVector<WasmGlobal, 4> &Globals) {
+void WasmObjectWriter::writeGlobalSection() {
if (Globals.empty())
return;
@@ -710,8 +747,7 @@ void WasmObjectWriter::writeGlobalSection(
endSection(Section);
}
-void WasmObjectWriter::writeExportSection(
- const SmallVector<WasmExport, 4> &Exports) {
+void WasmObjectWriter::writeExportSection(ArrayRef<WasmExport> Exports) {
if (Exports.empty())
return;
@@ -728,8 +764,7 @@ void WasmObjectWriter::writeExportSection(
endSection(Section);
}
-void WasmObjectWriter::writeElemSection(
- const SmallVector<uint32_t, 4> &TableElems) {
+void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
if (TableElems.empty())
return;
@@ -751,9 +786,9 @@ void WasmObjectWriter::writeElemSection(
endSection(Section);
}
-void WasmObjectWriter::writeCodeSection(
- const MCAssembler &Asm, const MCAsmLayout &Layout,
- const SmallVector<WasmFunction, 4> &Functions) {
+void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ ArrayRef<WasmFunction> Functions) {
if (Functions.empty())
return;
@@ -770,9 +805,7 @@ void WasmObjectWriter::writeCodeSection(
report_fatal_error(".size expression must be evaluatable");
encodeULEB128(Size, getStream());
-
FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
-
Asm.writeSectionData(&FuncSection, Layout);
}
@@ -782,33 +815,34 @@ void WasmObjectWriter::writeCodeSection(
endSection(Section);
}
-uint64_t WasmObjectWriter::writeDataSection(
- const SmallVector<char, 0> &DataBytes) {
- if (DataBytes.empty())
- return 0;
+void WasmObjectWriter::writeDataSection(ArrayRef<WasmDataSegment> Segments) {
+ if (Segments.empty())
+ return;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_DATA);
- encodeULEB128(1, getStream()); // count
- encodeULEB128(0, getStream()); // memory index
- write8(wasm::WASM_OPCODE_I32_CONST);
- encodeSLEB128(0, getStream()); // offset
- write8(wasm::WASM_OPCODE_END);
- encodeULEB128(DataBytes.size(), getStream()); // size
- uint32_t HeaderSize = getStream().tell() - Section.ContentsOffset;
- writeBytes(DataBytes); // data
+ encodeULEB128(Segments.size(), getStream()); // count
+
+ for (const WasmDataSegment & Segment : Segments) {
+ encodeULEB128(0, getStream()); // memory index
+ write8(wasm::WASM_OPCODE_I32_CONST);
+ encodeSLEB128(Segment.Offset, getStream()); // offset
+ write8(wasm::WASM_OPCODE_END);
+ encodeULEB128(Segment.Data.size(), getStream()); // size
+ Segment.Section->setSectionOffset(getStream().tell() - Section.ContentsOffset);
+ writeBytes(Segment.Data); // data
+ }
// Apply fixups.
- applyRelocations(DataRelocations, Section.ContentsOffset + HeaderSize);
+ applyRelocations(DataRelocations, Section.ContentsOffset);
endSection(Section);
- return HeaderSize;
}
void WasmObjectWriter::writeNameSection(
- const SmallVector<WasmFunction, 4> &Functions,
- const SmallVector<WasmImport, 4> &Imports,
+ ArrayRef<WasmFunction> Functions,
+ ArrayRef<WasmImport> Imports,
unsigned NumFuncImports) {
uint32_t TotalFunctions = NumFuncImports + Functions.size();
if (TotalFunctions == 0)
@@ -851,12 +885,12 @@ void WasmObjectWriter::writeCodeRelocSection() {
encodeULEB128(wasm::WASM_SEC_CODE, getStream());
encodeULEB128(CodeRelocations.size(), getStream());
- writeRelocations(CodeRelocations, 0);
+ writeRelocations(CodeRelocations);
endSection(Section);
}
-void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
+void WasmObjectWriter::writeDataRelocSection() {
// See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
// for descriptions of the reloc sections.
@@ -869,30 +903,25 @@ void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
encodeULEB128(wasm::WASM_SEC_DATA, getStream());
encodeULEB128(DataRelocations.size(), getStream());
- writeRelocations(DataRelocations, DataSectionHeaderSize);
+ writeRelocations(DataRelocations);
endSection(Section);
}
void WasmObjectWriter::writeLinkingMetaDataSection(
- uint32_t DataSize, uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
- bool HasStackPointer, uint32_t StackPointerGlobal) {
+ ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
+ 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;
- if (HasStackPointer) {
- startSection(SubSection, wasm::WASM_STACK_POINTER);
- encodeULEB128(StackPointerGlobal, getStream()); // id
- endSection(SubSection);
- }
-
- if (WeakSymbols.size() != 0) {
+ if (SymbolFlags.size() != 0) {
startSection(SubSection, wasm::WASM_SYMBOL_INFO);
- encodeULEB128(WeakSymbols.size(), getStream());
- for (const StringRef Export: WeakSymbols) {
- writeString(Export);
- encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
+ encodeULEB128(SymbolFlags.size(), getStream());
+ for (auto Pair: SymbolFlags) {
+ writeString(Pair.first);
+ encodeULEB128(Pair.second, getStream());
}
endSection(SubSection);
}
@@ -901,9 +930,26 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
startSection(SubSection, wasm::WASM_DATA_SIZE);
encodeULEB128(DataSize, getStream());
endSection(SubSection);
+ }
- startSection(SubSection, wasm::WASM_DATA_ALIGNMENT);
- encodeULEB128(DataAlignment, getStream());
+ if (Segments.size()) {
+ startSection(SubSection, wasm::WASM_SEGMENT_INFO);
+ encodeULEB128(Segments.size(), getStream());
+ for (const WasmDataSegment &Segment : Segments) {
+ writeString(Segment.Name);
+ encodeULEB128(Segment.Alignment, getStream());
+ encodeULEB128(Segment.Flags, getStream());
+ }
+ 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);
}
@@ -920,16 +966,9 @@ uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) {
assert(Symbol.isFunction());
WasmFunctionType F;
- if (Symbol.isVariable()) {
- const MCExpr *Expr = Symbol.getVariableValue();
- auto *Inner = cast<MCSymbolRefExpr>(Expr);
- const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
- F.Returns = ResolvedSym->getReturns();
- F.Params = ResolvedSym->getParams();
- } else {
- F.Returns = Symbol.getReturns();
- F.Params = Symbol.getParams();
- }
+ const MCSymbolWasm* ResolvedSym = ResolveSymbol(Symbol);
+ F.Returns = ResolvedSym->getReturns();
+ F.Params = ResolvedSym->getParams();
auto Pair =
FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
@@ -951,23 +990,20 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
// Collect information from the available symbols.
SmallVector<WasmFunction, 4> Functions;
SmallVector<uint32_t, 4> TableElems;
- SmallVector<WasmGlobal, 4> Globals;
SmallVector<WasmImport, 4> Imports;
SmallVector<WasmExport, 4> Exports;
- SmallVector<StringRef, 4> WeakSymbols;
+ 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;
- unsigned NumGlobalImports = 0;
- SmallVector<char, 0> DataBytes;
- uint32_t DataAlignment = 1;
- uint32_t StackPointerGlobal = 0;
- bool HasStackPointer = false;
+ SmallVector<WasmDataSegment, 4> DataSegments;
+ uint32_t DataSize = 0;
// Populate the IsAddressTaken set.
for (const WasmRelocationEntry &RelEntry : CodeRelocations) {
switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
IsAddressTaken.insert(RelEntry.Symbol);
break;
default:
@@ -977,7 +1013,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
for (const WasmRelocationEntry &RelEntry : DataRelocations) {
switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
IsAddressTaken.insert(RelEntry.Symbol);
break;
default:
@@ -985,42 +1021,11 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}
}
- // Populate the Imports set.
- for (const MCSymbol &S : Asm.symbols()) {
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
-
- if (WS.isTemporary())
- continue;
-
- if (WS.isFunction())
- registerFunctionType(WS);
-
- // If the symbol is not defined in this translation unit, import it.
- if (!WS.isDefined(/*SetUsed=*/false) || WS.isVariable()) {
- WasmImport Import;
- Import.ModuleName = WS.getModuleName();
- Import.FieldName = WS.getName();
-
- if (WS.isFunction()) {
- Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
- Import.Type = getFunctionType(WS);
- SymbolIndices[&WS] = NumFuncImports;
- ++NumFuncImports;
- } else {
- Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
- Import.Type = int32_t(PtrType);
- SymbolIndices[&WS] = NumGlobalImports;
- ++NumGlobalImports;
- }
-
- Imports.push_back(Import);
- }
- }
-
// In the special .global_variables section, we've encoded global
// variables used by the function. Translate them into the Globals
// list.
- MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
+ MCSectionWasm *GlobalVars =
+ Ctx.getWasmSection(".global_variables", SectionKind::getMetadata());
if (!GlobalVars->getFragmentList().empty()) {
if (GlobalVars->getFragmentList().size() != 1)
report_fatal_error("only one .global_variables fragment supported");
@@ -1074,23 +1079,91 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}
}
- // In the special .stack_pointer section, we've encoded the stack pointer
- // index.
- MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
- if (!StackPtr->getFragmentList().empty()) {
- if (StackPtr->getFragmentList().size() != 1)
- report_fatal_error("only one .stack_pointer fragment supported");
- const MCFragment &Frag = *StackPtr->begin();
- if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
- report_fatal_error("only data supported in .stack_pointer");
- const auto &DataFrag = cast<MCDataFragment>(Frag);
- if (!DataFrag.getFixups().empty())
- report_fatal_error("fixups not supported in .stack_pointer");
- const SmallVectorImpl<char> &Contents = DataFrag.getContents();
- if (Contents.size() != 4)
- report_fatal_error("only one entry supported in .stack_pointer");
- HasStackPointer = true;
- StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
+ // For now, always emit the memory import, since loads and stores are not
+ // valid without it. In the future, we could perhaps be more clever and omit
+ // it if there are no loads or stores.
+ MCSymbolWasm *MemorySym =
+ cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory"));
+ WasmImport MemImport;
+ MemImport.ModuleName = MemorySym->getModuleName();
+ MemImport.FieldName = MemorySym->getName();
+ MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
+ Imports.push_back(MemImport);
+
+ // For now, always emit the table section, since indirect calls are not
+ // valid without it. In the future, we could perhaps be more clever and omit
+ // it if there are no indirect calls.
+ MCSymbolWasm *TableSym =
+ cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table"));
+ WasmImport TableImport;
+ TableImport.ModuleName = TableSym->getModuleName();
+ TableImport.FieldName = TableSym->getName();
+ TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
+ TableImport.Type = wasm::WASM_TYPE_ANYFUNC;
+ Imports.push_back(TableImport);
+
+ // Populate FunctionTypeIndices and Imports.
+ for (const MCSymbol &S : Asm.symbols()) {
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+
+ // Register types for all functions, including those with private linkage
+ // (making them
+ // because wasm always needs a type signature.
+ if (WS.isFunction())
+ registerFunctionType(WS);
+
+ if (WS.isTemporary())
+ continue;
+
+ // If the symbol is not defined in this translation unit, import it.
+ if (!WS.isDefined(/*SetUsed=*/false)) {
+ WasmImport Import;
+ Import.ModuleName = WS.getModuleName();
+ Import.FieldName = WS.getName();
+
+ if (WS.isFunction()) {
+ Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
+ Import.Type = getFunctionType(WS);
+ SymbolIndices[&WS] = NumFuncImports;
+ ++NumFuncImports;
+ } else {
+ Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ Import.Type = int32_t(PtrType);
+ Import.IsMutable = false;
+ SymbolIndices[&WS] = NumGlobalImports;
+
+ // If this global is the stack pointer, make it mutable and remember it
+ // so that we can emit metadata for it.
+ if (WS.getName() == "__stack_pointer")
+ Import.IsMutable = true;
+
+ ++NumGlobalImports;
+ }
+
+ Imports.push_back(Import);
+ }
+ }
+
+ for (MCSection &Sec : Asm) {
+ auto &Section = static_cast<MCSectionWasm &>(Sec);
+ 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();
+ Segment.Name = Section.getSectionName();
+ Segment.Offset = DataSize;
+ Segment.Section = &Section;
+ addData(Segment.Data, Section);
+ Segment.Alignment = Section.getAlignment();
+ Segment.Flags = 0;
+ DataSize += Segment.Data.size();
+ Section.setMemoryOffset(Segment.Offset);
}
// Handle regular defined and undefined symbols.
@@ -1106,10 +1179,14 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
<< S.isExternal() << " isTemporary=" << S.isTemporary()
<< " isFunction=" << WS.isFunction()
<< " isWeak=" << WS.isWeak()
+ << " isHidden=" << WS.isHidden()
<< " isVariable=" << WS.isVariable() << "\n");
- if (WS.isWeak())
- WeakSymbols.push_back(WS.getName());
+ if (WS.isWeak() || WS.isHidden()) {
+ uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) |
+ (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0);
+ SymbolFlags.emplace_back(WS.getName(), Flags);
+ }
if (WS.isVariable())
continue;
@@ -1155,9 +1232,6 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
if (!WS.isDefined(/*SetUsed=*/false))
continue;
- if (WS.getOffset() != 0)
- report_fatal_error("data sections must contain one variable each: " +
- WS.getName());
if (!WS.getSize())
report_fatal_error("data symbols must have a size set with .size: " +
WS.getName());
@@ -1166,49 +1240,16 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
report_fatal_error(".size expression must be evaluatable");
- auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
-
- if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection))
- report_fatal_error("data sections must contain at most one variable");
-
- DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
- DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
-
- DataSection.setSectionOffset(DataBytes.size());
-
- for (const MCFragment &Frag : DataSection) {
- if (Frag.hasInstructions())
- report_fatal_error("only data supported in data sections");
-
- if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
- if (Align->getValueSize() != 1)
- report_fatal_error("only byte values supported for alignment");
- // If nops are requested, use zeros, as this is the data section.
- uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
- uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
- Align->getAlignment()),
- DataBytes.size() +
- Align->getMaxBytesToEmit());
- DataBytes.resize(Size, Value);
- } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
- DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue());
- } else {
- const auto &DataFrag = cast<MCDataFragment>(Frag);
- const SmallVectorImpl<char> &Contents = DataFrag.getContents();
-
- DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
- }
- }
-
// For each global, prepare a corresponding wasm global holding its
// address. For externals these will also be named exports.
Index = NumGlobalImports + Globals.size();
+ auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
WasmGlobal Global;
Global.Type = PtrType;
Global.IsMutable = false;
Global.HasImport = false;
- Global.InitialValue = DataSection.getSectionOffset();
+ Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS);
Global.ImportIndex = 0;
SymbolIndices[&WS] = Index;
DEBUG(dbgs() << " -> global index: " << Index << "\n");
@@ -1216,7 +1257,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}
// If the symbol is visible outside this translation unit, export it.
- if ((WS.isExternal() && WS.isDefined(/*SetUsed=*/false))) {
+ if (WS.isDefined(/*SetUsed=*/false)) {
WasmExport Export;
Export.FieldName = WS.getName();
Export.Index = Index;
@@ -1226,6 +1267,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
Exports.push_back(Export);
+ if (!WS.isExternal())
+ SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
}
}
@@ -1235,18 +1278,18 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
for (const MCSymbol &S : Asm.symbols()) {
if (!S.isVariable())
continue;
+
assert(S.isDefined(/*SetUsed=*/false));
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
// Find the target symbol of this weak alias and export that index
- const MCExpr *Expr = WS.getVariableValue();
- auto *Inner = cast<MCSymbolRefExpr>(Expr);
- const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+ const MCSymbolWasm *ResolvedSym = ResolveSymbol(WS);
DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym << "'\n");
assert(SymbolIndices.count(ResolvedSym) > 0);
uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
DEBUG(dbgs() << " -> index:" << Index << "\n");
+ SymbolIndices[&WS] = Index;
WasmExport Export;
Export.FieldName = WS.getName();
Export.Index = Index;
@@ -1256,6 +1299,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
Exports.push_back(Export);
+
+ if (!WS.isExternal())
+ SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
}
// Add types for indirect function calls.
@@ -1266,30 +1312,84 @@ 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);
writeTypeSection(FunctionTypes);
- writeImportSection(Imports);
+ writeImportSection(Imports, DataSize, TableElems.size());
writeFunctionSection(Functions);
- writeTableSection(TableElems.size());
- writeMemorySection(DataBytes);
- writeGlobalSection(Globals);
+ // Skip the "table" section; we import the table instead.
+ // Skip the "memory" section; we import the memory instead.
+ writeGlobalSection();
writeExportSection(Exports);
- // TODO: Start Section
writeElemSection(TableElems);
writeCodeSection(Asm, Layout, Functions);
- uint64_t DataSectionHeaderSize = writeDataSection(DataBytes);
+ writeDataSection(DataSegments);
writeNameSection(Functions, Imports, NumFuncImports);
writeCodeRelocSection();
- writeDataRelocSection(DataSectionHeaderSize);
- writeLinkingMetaDataSection(DataBytes.size(), DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal);
+ writeDataRelocSection();
+ writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags,
+ InitFuncs);
// TODO: Translate the .comment section to the output.
// TODO: Translate debug sections to the output.
}
-MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
- raw_pwrite_stream &OS) {
- return new WasmObjectWriter(MOTW, OS);
+std::unique_ptr<MCObjectWriter>
+llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS) {
+ // FIXME: Can't use make_unique<WasmObjectWriter>(...) as WasmObjectWriter's
+ // destructor is private. Is that necessary?
+ return std::unique_ptr<MCObjectWriter>(
+ new WasmObjectWriter(std::move(MOTW), OS));
}