diff options
Diffstat (limited to 'llvm/lib/MC/WasmObjectWriter.cpp')
-rw-r--r-- | llvm/lib/MC/WasmObjectWriter.cpp | 146 |
1 files changed, 123 insertions, 23 deletions
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 0b703f4387b..548d99fe4b9 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -50,16 +50,6 @@ struct SectionBookkeeping { uint64_t ContentsOffset; }; -// This record records information about a call_indirect which needs its -// type index fixed up once we've computed type indices. -struct TypeIndexFixup { - uint64_t Offset; - const MCSymbolWasm *Symbol; - const MCSectionWasm *FixupSection; - TypeIndexFixup(uint64_t O, const MCSymbolWasm *S, MCSectionWasm *F) - : Offset(O), Symbol(S), FixupSection(F) {} -}; - class WasmObjectWriter : public MCObjectWriter { /// Helper struct for containing some precomputed information on symbols. struct WasmSymbolData { @@ -80,7 +70,7 @@ class WasmObjectWriter : public MCObjectWriter { std::vector<WasmRelocationEntry> DataRelocations; // Fixups for call_indirect type indices. - std::vector<TypeIndexFixup> TypeIndexFixups; + std::vector<WasmRelocationEntry> TypeIndexFixups; // Index values to use for fixing up call_indirect type indices. std::vector<uint32_t> TypeIndexFixupTypes; @@ -269,8 +259,11 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, if (RefA) { if (RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX) { - TypeIndexFixups.push_back(TypeIndexFixup(FixupOffset, SymA, - &FixupSection)); + assert(C == 0); + WasmRelocationEntry Rec(FixupOffset, SymA, C, + wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB, + &FixupSection); + TypeIndexFixups.push_back(Rec); return; } } @@ -358,7 +351,9 @@ struct WasmExport { struct WasmGlobal { wasm::ValType Type; bool IsMutable; - uint32_t InitialValue; + bool HasImport; + uint64_t InitialValue; + uint32_t ImportIndex; }; } // end anonymous namespace @@ -507,6 +502,29 @@ static void WriteRelocations( } } +// Write out the the type relocation records that the linker will +// need to handle. +static void WriteTypeRelocations( + ArrayRef<WasmRelocationEntry> TypeIndexFixups, + ArrayRef<uint32_t> TypeIndexFixupTypes, + raw_pwrite_stream &Stream) +{ + for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) { + const WasmRelocationEntry &Fixup = TypeIndexFixups[i]; + uint32_t Type = TypeIndexFixupTypes[i]; + + assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); + assert(Fixup.Addend == 0); + + uint64_t Offset = Fixup.Offset + + Fixup.FixupSection->getSectionOffset(); + + encodeULEB128(Fixup.Type, Stream); + encodeULEB128(Offset, Stream); + encodeULEB128(Type, Stream); + } +} + void WasmObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { MCContext &Ctx = Asm.getContext(); @@ -526,6 +544,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, unsigned NumFuncImports = 0; unsigned NumGlobalImports = 0; SmallVector<char, 0> DataBytes; + uint32_t StackPointerGlobal = 0; + bool HasStackPointer = false; // Populate the IsAddressTaken set. for (WasmRelocationEntry RelEntry : CodeRelocations) { @@ -605,15 +625,68 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, if (!DataFrag.getFixups().empty()) report_fatal_error("fixups not supported in .global_variables"); const SmallVectorImpl<char> &Contents = DataFrag.getContents(); - for (char p : Contents) { + for (const uint8_t *p = (const uint8_t *)Contents.data(), + *end = (const uint8_t *)Contents.data() + Contents.size(); + p != end; ) { WasmGlobal G; - G.Type = wasm::ValType(p); - G.IsMutable = true; - G.InitialValue = 0; + if (end - p < 3) + report_fatal_error("truncated global variable encoding"); + G.Type = wasm::ValType(int8_t(*p++)); + G.IsMutable = bool(*p++); + G.HasImport = bool(*p++); + if (G.HasImport) { + G.InitialValue = 0; + + WasmImport Import; + Import.ModuleName = (const char *)p; + const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p); + if (!nul) + report_fatal_error("global module name must be nul-terminated"); + p = nul + 1; + nul = (const uint8_t *)memchr(p, '\0', end - p); + if (!nul) + report_fatal_error("global base name must be nul-terminated"); + Import.FieldName = (const char *)p; + p = nul + 1; + + Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; + Import.Type = int32_t(G.Type); + + G.ImportIndex = NumGlobalImports; + ++NumGlobalImports; + + Imports.push_back(Import); + } else { + unsigned n; + G.InitialValue = decodeSLEB128(p, &n); + G.ImportIndex = 0; + if (n > end - p) + report_fatal_error("global initial value must be valid SLEB128"); + p += n; + } Globals.push_back(G); } } + // 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 MCDataFragment &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(); + } + // Handle defined symbols. for (const MCSymbol &S : Asm.symbols()) { // Ignore unnamed temporary symbols, which aren't ever exported, imported, @@ -712,7 +785,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, 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); } @@ -736,7 +811,10 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, } // Add types for indirect function calls. - for (const TypeIndexFixup &Fixup : TypeIndexFixups) { + for (const WasmRelocationEntry &Fixup : TypeIndexFixups) { + assert(Fixup.Addend == 0); + assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); + WasmFunctionType F; F.Returns = Fixup.Symbol->getReturns(); F.Params = Fixup.Symbol->getParams(); @@ -793,7 +871,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, encodeULEB128(Import.Type, getStream()); break; case wasm::WASM_EXTERNAL_GLOBAL: - encodeSLEB128(Import.Type, getStream()); + encodeSLEB128(int32_t(Import.Type), getStream()); encodeULEB128(0, getStream()); // mutability break; default: @@ -853,8 +931,15 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, writeValueType(Global.Type); write8(Global.IsMutable); - write8(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(Global.InitialValue, getStream()); // offset + if (Global.HasImport) { + assert(Global.InitialValue == 0); + write8(wasm::WASM_OPCODE_GET_GLOBAL); + encodeULEB128(Global.ImportIndex, getStream()); + } else { + assert(Global.ImportIndex == 0); + write8(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(Global.InitialValue, getStream()); // offset + } write8(wasm::WASM_OPCODE_END); } @@ -944,7 +1029,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, uint32_t Type = TypeIndexFixupTypes[i]; unsigned Padding = PaddingFor5ByteULEB128(Type); - const TypeIndexFixup &Fixup = TypeIndexFixups[i]; + const WasmRelocationEntry &Fixup = TypeIndexFixups[i]; + assert(Fixup.Addend == 0); + assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); uint64_t Offset = Fixup.Offset + Fixup.FixupSection->getSectionOffset(); @@ -1021,6 +1108,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, encodeULEB128(CodeRelocations.size(), getStream()); WriteRelocations(CodeRelocations, getStream(), SymbolIndices); + WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream()); endSection(Section); } @@ -1038,6 +1126,18 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, endSection(Section); } + // === Linking Metadata Section ============================================== + if (HasStackPointer) { + startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); + + encodeULEB128(1, getStream()); // count + + encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type + encodeULEB128(StackPointerGlobal, getStream()); // id + + endSection(Section); + } + // TODO: Translate the .comment section to the output. // TODO: Translate debug sections to the output. |