summaryrefslogtreecommitdiff
path: root/lib/MC/WasmObjectWriter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-26 20:32:52 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-26 20:32:52 +0000
commit08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch)
tree80108f0f128657f8623f8f66ad9735b4d88e7b47 /lib/MC/WasmObjectWriter.cpp
parent7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff)
Notes
Diffstat (limited to 'lib/MC/WasmObjectWriter.cpp')
-rw-r--r--lib/MC/WasmObjectWriter.cpp318
1 files changed, 196 insertions, 122 deletions
diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp
index db304c027f991..45534ba182123 100644
--- a/lib/MC/WasmObjectWriter.cpp
+++ b/lib/MC/WasmObjectWriter.cpp
@@ -129,15 +129,15 @@ struct WasmGlobal {
// Information about a single relocation.
struct WasmRelocationEntry {
- uint64_t Offset; // Where is the relocation.
- const MCSymbolWasm *Symbol; // The symbol to relocate with.
- int64_t Addend; // A value to add to the symbol.
- unsigned Type; // The type of the relocation.
- MCSectionWasm *FixupSection;// The section the relocation is targeting.
+ uint64_t Offset; // Where is the relocation.
+ const MCSymbolWasm *Symbol; // The symbol to relocate with.
+ int64_t Addend; // A value to add to the symbol.
+ unsigned Type; // The type of the relocation.
+ const MCSectionWasm *FixupSection;// The section the relocation is targeting.
WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
int64_t Addend, unsigned Type,
- MCSectionWasm *FixupSection)
+ const MCSectionWasm *FixupSection)
: Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
FixupSection(FixupSection) {}
@@ -156,9 +156,19 @@ struct WasmRelocationEntry {
Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend
<< ", Type=" << Type << ", FixupSection=" << FixupSection;
}
- void dump() const { print(errs()); }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
+#endif
};
+#if !defined(NDEBUG)
+raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
+ Rel.print(OS);
+ return OS;
+}
+#endif
+
class WasmObjectWriter : public MCObjectWriter {
/// Helper struct for containing some precomputed information on symbols.
struct WasmSymbolData {
@@ -229,6 +239,11 @@ private:
void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+ void writeString(const StringRef Str) {
+ encodeULEB128(Str.size(), getStream());
+ writeBytes(Str);
+ }
+
void writeValueType(wasm::ValType Ty) {
encodeSLEB128(int32_t(Ty), getStream());
}
@@ -250,7 +265,8 @@ private:
uint32_t NumFuncImports);
void writeCodeRelocSection();
void writeDataRelocSection(uint64_t DataSectionHeaderSize);
- void writeLinkingMetaDataSection(bool HasStackPointer,
+ void writeLinkingMetaDataSection(ArrayRef<StringRef> WeakSymbols,
+ bool HasStackPointer,
uint32_t StackPointerGlobal);
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
@@ -282,6 +298,7 @@ void WasmObjectWriter::startSection(SectionBookkeeping &Section,
assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
"Only custom sections can have names");
+ DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
encodeULEB128(SectionId, getStream());
Section.SizeOffset = getStream().tell();
@@ -295,8 +312,8 @@ void WasmObjectWriter::startSection(SectionBookkeeping &Section,
// Custom sections in wasm also have a string identifier.
if (SectionId == wasm::WASM_SEC_CUSTOM) {
- encodeULEB128(strlen(Name), getStream());
- writeBytes(Name);
+ assert(Name);
+ writeString(StringRef(Name));
}
}
@@ -307,6 +324,7 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
if (uint32_t(Size) != Size)
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
@@ -332,7 +350,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
bool &IsPCRel, uint64_t &FixedValue) {
- MCSectionWasm &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
+ const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
uint64_t C = Target.getConstant();
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
MCContext &Ctx = Asm.getContext();
@@ -406,9 +424,12 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
}
assert(!IsPCRel);
+ assert(SymA);
+
unsigned Type = getRelocType(Target, Fixup);
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
+ DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
if (FixupSection.hasInstructions())
CodeRelocations.push_back(Rec);
@@ -453,11 +474,10 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
const MCSymbolWasm *Sym = RelEntry.Symbol;
// For undefined symbols, use a hopefully invalid value.
- if (!Sym->isDefined(false))
+ if (!Sym->isDefined(/*SetUsed=*/false))
return UINT32_MAX;
- MCSectionWasm &Section =
- cast<MCSectionWasm>(RelEntry.Symbol->getSection(false));
+ const auto &Section = cast<MCSectionWasm>(RelEntry.Symbol->getSection(false));
uint64_t Address = Section.getSectionOffset() + RelEntry.Addend;
// Ignore overflow. LLVM allows address arithmetic to silently wrap.
@@ -471,16 +491,23 @@ uint32_t WasmObjectWriter::getRelocationIndexValue(
switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
- assert(IndirectSymbolIndices.count(RelEntry.Symbol));
+ if (!IndirectSymbolIndices.count(RelEntry.Symbol))
+ report_fatal_error("symbol not found table index space:" +
+ RelEntry.Symbol->getName());
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:
- assert(SymbolIndices.count(RelEntry.Symbol));
+ if (!SymbolIndices.count(RelEntry.Symbol))
+ report_fatal_error("symbol not found function/global index space:" +
+ RelEntry.Symbol->getName());
return SymbolIndices[RelEntry.Symbol];
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
- assert(TypeIndices.count(RelEntry.Symbol));
+ if (!TypeIndices.count(RelEntry.Symbol))
+ report_fatal_error("symbol not found in type index space:" +
+ RelEntry.Symbol->getName());
return TypeIndices[RelEntry.Symbol];
default:
llvm_unreachable("invalid relocation type");
@@ -497,10 +524,12 @@ void WasmObjectWriter::applyRelocations(
RelEntry.FixupSection->getSectionOffset() +
RelEntry.Offset;
+ DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: {
+ case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
uint32_t Index = getRelocationIndexValue(RelEntry);
WritePatchableSLEB(Stream, Index, Offset);
break;
@@ -526,7 +555,7 @@ void WasmObjectWriter::applyRelocations(
break;
}
default:
- llvm_unreachable("unsupported relocation type");
+ llvm_unreachable("invalid relocation type");
}
}
}
@@ -573,6 +602,7 @@ void WasmObjectWriter::writeTypeSection(
endSection(Section);
}
+
void WasmObjectWriter::writeImportSection(
const SmallVector<WasmImport, 4> &Imports) {
if (Imports.empty())
@@ -583,13 +613,8 @@ void WasmObjectWriter::writeImportSection(
encodeULEB128(Imports.size(), getStream());
for (const WasmImport &Import : Imports) {
- StringRef ModuleName = Import.ModuleName;
- encodeULEB128(ModuleName.size(), getStream());
- writeBytes(ModuleName);
-
- StringRef FieldName = Import.FieldName;
- encodeULEB128(FieldName.size(), getStream());
- writeBytes(FieldName);
+ writeString(Import.ModuleName);
+ writeString(Import.FieldName);
encodeULEB128(Import.Kind, getStream());
@@ -697,11 +722,8 @@ void WasmObjectWriter::writeExportSection(
encodeULEB128(Exports.size(), getStream());
for (const WasmExport &Export : Exports) {
- encodeULEB128(Export.FieldName.size(), getStream());
- writeBytes(Export.FieldName);
-
+ writeString(Export.FieldName);
encodeSLEB128(Export.Kind, getStream());
-
encodeULEB128(Export.Index, getStream());
}
@@ -743,17 +765,7 @@ void WasmObjectWriter::writeCodeSection(
encodeULEB128(Functions.size(), getStream());
for (const WasmFunction &Func : Functions) {
- MCSectionWasm &FuncSection =
- static_cast<MCSectionWasm &>(Func.Sym->getSection());
-
- if (Func.Sym->isVariable())
- report_fatal_error("weak symbols not supported yet");
-
- if (Func.Sym->getOffset() != 0)
- report_fatal_error("function sections must contain one function each");
-
- if (!Func.Sym->getSize())
- report_fatal_error("function symbols must have a size set with .size");
+ auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
int64_t Size = 0;
if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
@@ -761,8 +773,7 @@ void WasmObjectWriter::writeCodeSection(
encodeULEB128(Size, getStream());
- FuncSection.setSectionOffset(getStream().tell() -
- Section.ContentsOffset);
+ FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
Asm.writeSectionData(&FuncSection, Layout);
}
@@ -815,15 +826,13 @@ void WasmObjectWriter::writeNameSection(
for (const WasmImport &Import : Imports) {
if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
encodeULEB128(Index, getStream());
- encodeULEB128(Import.FieldName.size(), getStream());
- writeBytes(Import.FieldName);
+ writeString(Import.FieldName);
++Index;
}
}
for (const WasmFunction &Func : Functions) {
encodeULEB128(Index, getStream());
- encodeULEB128(Func.Sym->getName().size(), getStream());
- writeBytes(Func.Sym->getName());
+ writeString(Func.Sym->getName());
++Index;
}
@@ -868,22 +877,37 @@ void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
}
void WasmObjectWriter::writeLinkingMetaDataSection(
- bool HasStackPointer, uint32_t StackPointerGlobal) {
- if (!HasStackPointer)
+ ArrayRef<StringRef> WeakSymbols, bool HasStackPointer,
+ uint32_t StackPointerGlobal) {
+ if (!HasStackPointer && WeakSymbols.empty())
return;
+
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
+ SectionBookkeeping SubSection;
- encodeULEB128(1, getStream()); // count
+ if (HasStackPointer) {
+ startSection(SubSection, wasm::WASM_STACK_POINTER);
+ encodeULEB128(StackPointerGlobal, getStream()); // id
+ endSection(SubSection);
+ }
- encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type
- encodeULEB128(StackPointerGlobal, getStream()); // id
+ if (WeakSymbols.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());
+ }
+ endSection(SubSection);
+ }
endSection(Section);
}
void WasmObjectWriter::writeObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
+ DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
MCContext &Ctx = Asm.getContext();
wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
@@ -894,6 +918,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
SmallVector<WasmGlobal, 4> Globals;
SmallVector<WasmImport, 4> Imports;
SmallVector<WasmExport, 4> Exports;
+ SmallVector<StringRef, 4> WeakSymbols;
SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
unsigned NumFuncImports = 0;
unsigned NumGlobalImports = 0;
@@ -902,7 +927,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
bool HasStackPointer = false;
// Populate the IsAddressTaken set.
- for (WasmRelocationEntry RelEntry : CodeRelocations) {
+ for (const WasmRelocationEntry &RelEntry : CodeRelocations) {
switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
@@ -912,7 +937,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
break;
}
}
- for (WasmRelocationEntry RelEntry : DataRelocations) {
+ for (const WasmRelocationEntry &RelEntry : DataRelocations) {
switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
@@ -975,7 +1000,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
const MCFragment &Frag = *GlobalVars->begin();
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
report_fatal_error("only data supported in .global_variables");
- const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
+ const auto &DataFrag = cast<MCDataFragment>(Frag);
if (!DataFrag.getFixups().empty())
report_fatal_error("fixups not supported in .global_variables");
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
@@ -1031,7 +1056,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
const MCFragment &Frag = *StackPtr->begin();
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
report_fatal_error("only data supported in .stack_pointer");
- const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
+ 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();
@@ -1041,14 +1066,30 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
}
- // Handle defined symbols.
+ // Handle regular defined and undefined symbols.
for (const MCSymbol &S : Asm.symbols()) {
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
// or used in relocations.
if (S.isTemporary() && S.getName().empty())
continue;
+
+ // Variable references (weak references) are handled in a second pass
+ if (S.isVariable())
+ continue;
+
const auto &WS = static_cast<const MCSymbolWasm &>(S);
+ DEBUG(dbgs() << "MCSymbol: '" << S << "'"
+ << " isDefined=" << S.isDefined() << " isExternal="
+ << S.isExternal() << " isTemporary=" << S.isTemporary()
+ << " isFunction=" << WS.isFunction()
+ << " isWeak=" << WS.isWeak()
+ << " isVariable=" << WS.isVariable() << "\n");
+
+ if (WS.isWeak())
+ WeakSymbols.push_back(WS.getName());
+
unsigned Index;
+
if (WS.isFunction()) {
// Prepare the function's type, if we haven't seen it yet.
WasmFunctionType F;
@@ -1062,6 +1103,14 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
int32_t Type = Pair.first->second;
if (WS.isDefined(/*SetUsed=*/false)) {
+ if (WS.getOffset() != 0)
+ report_fatal_error(
+ "function sections must contain one function each");
+
+ if (WS.getSize() == 0)
+ report_fatal_error(
+ "function symbols must have a size set with .size");
+
// A definition. Take the next available index.
Index = NumFuncImports + Functions.size();
@@ -1072,6 +1121,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
SymbolIndices[&WS] = Index;
Functions.push_back(Func);
} else {
+ // Should be no such thing as weak undefined symbol
+ assert(!WS.isVariable());
+
// An import; the index was assigned above.
Index = SymbolIndices.find(&WS)->second;
}
@@ -1085,86 +1137,108 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
if (WS.isTemporary() && !WS.getSize())
continue;
- if (WS.isDefined(false)) {
- 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());
-
- int64_t Size = 0;
- if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
- report_fatal_error(".size expression must be evaluatable");
-
- MCSectionWasm &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()));
-
- DataSection.setSectionOffset(DataBytes.size());
-
- for (MCSection::iterator I = DataSection.begin(), E = DataSection.end();
- I != E; ++I) {
- const MCFragment &Frag = *I;
- if (Frag.hasInstructions())
- report_fatal_error("only data supported in data sections");
-
- if (const MCAlignFragment *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 (const MCFillFragment *Fill =
- dyn_cast<MCFillFragment>(&Frag)) {
- DataBytes.insert(DataBytes.end(), Size, Fill->getValue());
- } else {
- const MCDataFragment &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();
+ if (!WS.isDefined(/*SetUsed=*/false))
+ continue;
- WasmGlobal Global;
- Global.Type = PtrType;
- Global.IsMutable = false;
- Global.HasImport = false;
- Global.InitialValue = DataSection.getSectionOffset();
- Global.ImportIndex = 0;
- SymbolIndices[&WS] = Index;
- Globals.push_back(Global);
+ 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());
+
+ int64_t Size = 0;
+ 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()));
+
+ 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(), Size, 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();
+
+ WasmGlobal Global;
+ Global.Type = PtrType;
+ Global.IsMutable = false;
+ Global.HasImport = false;
+ Global.InitialValue = DataSection.getSectionOffset();
+ Global.ImportIndex = 0;
+ SymbolIndices[&WS] = Index;
+ Globals.push_back(Global);
}
// If the symbol is visible outside this translation unit, export it.
- if (WS.isExternal()) {
- assert(WS.isDefined(false));
+ if (WS.isExternal() && WS.isDefined(/*SetUsed=*/false)) {
WasmExport Export;
Export.FieldName = WS.getName();
Export.Index = Index;
-
if (WS.isFunction())
Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
else
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
-
Exports.push_back(Export);
}
}
+ // Handle weak aliases
+ for (const MCSymbol &S : Asm.symbols()) {
+ if (!S.isVariable())
+ continue;
+ assert(S.isExternal());
+ assert(S.isDefined(/*SetUsed=*/false));
+
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+
+ // Find the target symbol of this weak alias
+ const MCExpr *Expr = WS.getVariableValue();
+ auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
+ const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
+ uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
+ DEBUG(dbgs() << "Weak alias: '" << WS << "' -> '" << ResolvedSym << "' = " << Index << "\n");
+ SymbolIndices[&WS] = Index;
+
+ WasmExport Export;
+ Export.FieldName = WS.getName();
+ Export.Index = Index;
+ if (WS.isFunction())
+ Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
+ else
+ Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ WeakSymbols.push_back(Export.FieldName);
+ Exports.push_back(Export);
+ }
+
// Add types for indirect function calls.
for (const WasmRelocationEntry &Fixup : CodeRelocations) {
if (Fixup.Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
@@ -1198,7 +1272,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
writeNameSection(Functions, Imports, NumFuncImports);
writeCodeRelocSection();
writeDataRelocSection(DataSectionHeaderSize);
- writeLinkingMetaDataSection(HasStackPointer, StackPointerGlobal);
+ writeLinkingMetaDataSection(WeakSymbols, HasStackPointer, StackPointerGlobal);
// TODO: Translate the .comment section to the output.
// TODO: Translate debug sections to the output.