Loading llvm/include/llvm/MC/MCSymbolWasm.h +12 −2 Original line number Diff line number Diff line Loading @@ -96,6 +96,15 @@ public: StringRef getExportName() const { return ExportName.getValue(); } void setExportName(StringRef Name) { ExportName = Name; } bool isFunctionTable() const { return isTable() && hasTableType() && getTableType() == wasm::ValType::FUNCREF; } void setFunctionTable() { setType(wasm::WASM_SYMBOL_TYPE_TABLE); setTableType(wasm::ValType::FUNCREF); } void setUsedInGOT() const { IsUsedInGOT = true; } bool isUsedInGOT() const { return IsUsedInGOT; } Loading @@ -111,8 +120,9 @@ public: } void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; } const wasm::ValType &getTableType() const { assert(TableType.hasValue()); bool hasTableType() const { return TableType.hasValue(); } wasm::ValType getTableType() const { assert(hasTableType()); return TableType.getValue(); } void setTableType(wasm::ValType TT) { TableType = TT; } Loading llvm/include/llvm/Object/Wasm.h +1 −0 Original line number Diff line number Diff line Loading @@ -299,6 +299,7 @@ private: uint32_t DataSection = 0; uint32_t EventSection = 0; uint32_t GlobalSection = 0; uint32_t TableSection = 0; }; class WasmSectionOrderChecker { Loading llvm/lib/MC/WasmObjectWriter.cpp +48 −16 Original line number Diff line number Diff line Loading @@ -40,8 +40,8 @@ using namespace llvm; namespace { // Went we ceate the indirect function table we start at 1, so that there is // and emtpy slot at 0 and therefore calling a null function pointer will trap. // When we create the indirect function table we start at 1, so that there is // and empty slot at 0 and therefore calling a null function pointer will trap. static const uint32_t InitialTableOffset = 1; // For patching purposes, we need to remember where each section starts, both Loading Loading @@ -218,9 +218,7 @@ class WasmObjectWriter : public MCObjectWriter { SmallVector<WasmDataSegment, 4> DataSegments; unsigned NumFunctionImports = 0; unsigned NumGlobalImports = 0; // NumTableImports is initialized to 1 to account for the hardcoded import of // __indirect_function_table unsigned NumTableImports = 1; unsigned NumTableImports = 0; unsigned NumEventImports = 0; uint32_t SectionCount = 0; Loading Loading @@ -270,7 +268,7 @@ private: SectionFunctions.clear(); NumFunctionImports = 0; NumGlobalImports = 0; NumTableImports = 1; NumTableImports = 0; MCObjectWriter::reset(); } Loading Loading @@ -497,6 +495,29 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, SymA = cast<MCSymbolWasm>(SectionSymbol); } if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB || Type == wasm::R_WASM_TABLE_INDEX_SLEB || Type == wasm::R_WASM_TABLE_INDEX_SLEB64 || Type == wasm::R_WASM_TABLE_INDEX_I32 || Type == wasm::R_WASM_TABLE_INDEX_I64) { // TABLE_INDEX relocs implicitly use the default indirect function table. auto TableName = "__indirect_function_table"; MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(TableName)); if (Sym) { if (!Sym->isFunctionTable()) Ctx.reportError( Fixup.getLoc(), "symbol '__indirect_function_table' is not a function table"); } else { Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(TableName)); Sym->setFunctionTable(); // The default function table is synthesized by the linker. Sym->setUndefined(); } Sym->setUsedInReloc(); Asm.registerSymbol(*Sym); } // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be // against a named symbol. if (Type != wasm::R_WASM_TYPE_INDEX_LEB) { Loading Loading @@ -1201,16 +1222,6 @@ void WasmObjectWriter::prepareImports( : wasm::WASM_LIMITS_FLAG_NONE; 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. wasm::WasmImport TableImport; TableImport.Module = "env"; TableImport.Field = "__indirect_function_table"; TableImport.Kind = wasm::WASM_EXTERNAL_TABLE; TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF; Imports.push_back(TableImport); // Populate SignatureIndices, and Imports and WasmIndices for undefined // symbols. This must be done before populating WasmIndices for defined // symbols. Loading Loading @@ -1269,6 +1280,23 @@ void WasmObjectWriter::prepareImports( Imports.push_back(Import); assert(WasmIndices.count(&WS) == 0); WasmIndices[&WS] = NumEventImports++; } else if (WS.isTable()) { if (WS.isWeak()) report_fatal_error("undefined table symbol cannot be weak"); wasm::WasmImport Import; Import.Module = WS.getImportModule(); Import.Field = WS.getImportName(); Import.Kind = wasm::WASM_EXTERNAL_TABLE; wasm::ValType ElemType = WS.getTableType(); Import.Table.ElemType = uint8_t(ElemType); // FIXME: Extend table type to include limits? For now we don't specify // a min or max which does not place any restrictions on the size of the // imported table. Import.Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0}; Imports.push_back(Import); assert(WasmIndices.count(&WS) == 0); WasmIndices[&WS] = NumTableImports++; } } } Loading Loading @@ -1618,6 +1646,10 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, WS.setIndex(InvalidIndex); continue; } if (WS.isTable() && WS.getName() == "__indirect_function_table") { // For the moment, don't emit table symbols -- wasm-ld can't handle them. continue; } LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n"); uint32_t Flags = 0; Loading llvm/lib/Object/WasmObjectFile.cpp +22 −2 Original line number Diff line number Diff line Loading @@ -498,9 +498,11 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { std::vector<wasm::WasmImport *> ImportedGlobals; std::vector<wasm::WasmImport *> ImportedFunctions; std::vector<wasm::WasmImport *> ImportedEvents; std::vector<wasm::WasmImport *> ImportedTables; ImportedGlobals.reserve(Imports.size()); ImportedFunctions.reserve(Imports.size()); ImportedEvents.reserve(Imports.size()); ImportedTables.reserve(Imports.size()); for (auto &I : Imports) { if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) ImportedFunctions.emplace_back(&I); Loading @@ -508,6 +510,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { ImportedGlobals.emplace_back(&I); else if (I.Kind == wasm::WASM_EXTERNAL_EVENT) ImportedEvents.emplace_back(&I); else if (I.Kind == wasm::WASM_EXTERNAL_TABLE) ImportedTables.emplace_back(&I); } while (Count--) { Loading Loading @@ -600,8 +604,18 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { if (Table.SymbolName.empty()) Table.SymbolName = Info.Name; } else { return make_error<GenericBinaryError>("undefined table symbol", object_error::parse_failed); wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex]; if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { Info.Name = readString(Ctx); Info.ImportName = Import.Field; } else { Info.Name = Import.Field; } TableType = Import.Table.ElemType; // FIXME: Parse limits here too. if (!Import.Module.empty()) { Info.ImportModule = Import.Module; } } break; Loading Loading @@ -1060,6 +1074,7 @@ Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) { } Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { TableSection = Sections.size(); uint32_t Count = readVaruint32(Ctx); Tables.reserve(Count); while (Count--) { Loading Loading @@ -1432,6 +1447,7 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: case wasm::WASM_SYMBOL_TYPE_TABLE: return Sym.Info.ElementIndex; case wasm::WASM_SYMBOL_TYPE_DATA: { // The value of a data symbol is the segment offset, plus the symbol Loading Loading @@ -1481,6 +1497,8 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const { return SymbolRef::ST_Debug; case wasm::WASM_SYMBOL_TYPE_EVENT: return SymbolRef::ST_Other; case wasm::WASM_SYMBOL_TYPE_TABLE: return SymbolRef::ST_Other; } llvm_unreachable("Unknown WasmSymbol::SymbolType"); Loading Loading @@ -1515,6 +1533,8 @@ uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const { return Sym.Info.ElementIndex; case wasm::WASM_SYMBOL_TYPE_EVENT: return EventSection; case wasm::WASM_SYMBOL_TYPE_TABLE: return TableSection; default: llvm_unreachable("Unknown WasmSymbol::SymbolType"); } Loading llvm/test/MC/WebAssembly/assembler-binary.ll +0 −8 Original line number Diff line number Diff line Loading @@ -52,14 +52,6 @@ entry: ; CHECK-NEXT: Memory: ; CHECK-NEXT: Initial: 0x0 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __indirect_function_table ; CHECK-NEXT: Kind: TABLE ; CHECK-NEXT: Table: ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: ElemType: FUNCREF ; CHECK-NEXT: Limits: ; CHECK-NEXT: Initial: 0x0 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: bar ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 Loading Loading
llvm/include/llvm/MC/MCSymbolWasm.h +12 −2 Original line number Diff line number Diff line Loading @@ -96,6 +96,15 @@ public: StringRef getExportName() const { return ExportName.getValue(); } void setExportName(StringRef Name) { ExportName = Name; } bool isFunctionTable() const { return isTable() && hasTableType() && getTableType() == wasm::ValType::FUNCREF; } void setFunctionTable() { setType(wasm::WASM_SYMBOL_TYPE_TABLE); setTableType(wasm::ValType::FUNCREF); } void setUsedInGOT() const { IsUsedInGOT = true; } bool isUsedInGOT() const { return IsUsedInGOT; } Loading @@ -111,8 +120,9 @@ public: } void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; } const wasm::ValType &getTableType() const { assert(TableType.hasValue()); bool hasTableType() const { return TableType.hasValue(); } wasm::ValType getTableType() const { assert(hasTableType()); return TableType.getValue(); } void setTableType(wasm::ValType TT) { TableType = TT; } Loading
llvm/include/llvm/Object/Wasm.h +1 −0 Original line number Diff line number Diff line Loading @@ -299,6 +299,7 @@ private: uint32_t DataSection = 0; uint32_t EventSection = 0; uint32_t GlobalSection = 0; uint32_t TableSection = 0; }; class WasmSectionOrderChecker { Loading
llvm/lib/MC/WasmObjectWriter.cpp +48 −16 Original line number Diff line number Diff line Loading @@ -40,8 +40,8 @@ using namespace llvm; namespace { // Went we ceate the indirect function table we start at 1, so that there is // and emtpy slot at 0 and therefore calling a null function pointer will trap. // When we create the indirect function table we start at 1, so that there is // and empty slot at 0 and therefore calling a null function pointer will trap. static const uint32_t InitialTableOffset = 1; // For patching purposes, we need to remember where each section starts, both Loading Loading @@ -218,9 +218,7 @@ class WasmObjectWriter : public MCObjectWriter { SmallVector<WasmDataSegment, 4> DataSegments; unsigned NumFunctionImports = 0; unsigned NumGlobalImports = 0; // NumTableImports is initialized to 1 to account for the hardcoded import of // __indirect_function_table unsigned NumTableImports = 1; unsigned NumTableImports = 0; unsigned NumEventImports = 0; uint32_t SectionCount = 0; Loading Loading @@ -270,7 +268,7 @@ private: SectionFunctions.clear(); NumFunctionImports = 0; NumGlobalImports = 0; NumTableImports = 1; NumTableImports = 0; MCObjectWriter::reset(); } Loading Loading @@ -497,6 +495,29 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, SymA = cast<MCSymbolWasm>(SectionSymbol); } if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB || Type == wasm::R_WASM_TABLE_INDEX_SLEB || Type == wasm::R_WASM_TABLE_INDEX_SLEB64 || Type == wasm::R_WASM_TABLE_INDEX_I32 || Type == wasm::R_WASM_TABLE_INDEX_I64) { // TABLE_INDEX relocs implicitly use the default indirect function table. auto TableName = "__indirect_function_table"; MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(TableName)); if (Sym) { if (!Sym->isFunctionTable()) Ctx.reportError( Fixup.getLoc(), "symbol '__indirect_function_table' is not a function table"); } else { Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(TableName)); Sym->setFunctionTable(); // The default function table is synthesized by the linker. Sym->setUndefined(); } Sym->setUsedInReloc(); Asm.registerSymbol(*Sym); } // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be // against a named symbol. if (Type != wasm::R_WASM_TYPE_INDEX_LEB) { Loading Loading @@ -1201,16 +1222,6 @@ void WasmObjectWriter::prepareImports( : wasm::WASM_LIMITS_FLAG_NONE; 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. wasm::WasmImport TableImport; TableImport.Module = "env"; TableImport.Field = "__indirect_function_table"; TableImport.Kind = wasm::WASM_EXTERNAL_TABLE; TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF; Imports.push_back(TableImport); // Populate SignatureIndices, and Imports and WasmIndices for undefined // symbols. This must be done before populating WasmIndices for defined // symbols. Loading Loading @@ -1269,6 +1280,23 @@ void WasmObjectWriter::prepareImports( Imports.push_back(Import); assert(WasmIndices.count(&WS) == 0); WasmIndices[&WS] = NumEventImports++; } else if (WS.isTable()) { if (WS.isWeak()) report_fatal_error("undefined table symbol cannot be weak"); wasm::WasmImport Import; Import.Module = WS.getImportModule(); Import.Field = WS.getImportName(); Import.Kind = wasm::WASM_EXTERNAL_TABLE; wasm::ValType ElemType = WS.getTableType(); Import.Table.ElemType = uint8_t(ElemType); // FIXME: Extend table type to include limits? For now we don't specify // a min or max which does not place any restrictions on the size of the // imported table. Import.Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0}; Imports.push_back(Import); assert(WasmIndices.count(&WS) == 0); WasmIndices[&WS] = NumTableImports++; } } } Loading Loading @@ -1618,6 +1646,10 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, WS.setIndex(InvalidIndex); continue; } if (WS.isTable() && WS.getName() == "__indirect_function_table") { // For the moment, don't emit table symbols -- wasm-ld can't handle them. continue; } LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n"); uint32_t Flags = 0; Loading
llvm/lib/Object/WasmObjectFile.cpp +22 −2 Original line number Diff line number Diff line Loading @@ -498,9 +498,11 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { std::vector<wasm::WasmImport *> ImportedGlobals; std::vector<wasm::WasmImport *> ImportedFunctions; std::vector<wasm::WasmImport *> ImportedEvents; std::vector<wasm::WasmImport *> ImportedTables; ImportedGlobals.reserve(Imports.size()); ImportedFunctions.reserve(Imports.size()); ImportedEvents.reserve(Imports.size()); ImportedTables.reserve(Imports.size()); for (auto &I : Imports) { if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) ImportedFunctions.emplace_back(&I); Loading @@ -508,6 +510,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { ImportedGlobals.emplace_back(&I); else if (I.Kind == wasm::WASM_EXTERNAL_EVENT) ImportedEvents.emplace_back(&I); else if (I.Kind == wasm::WASM_EXTERNAL_TABLE) ImportedTables.emplace_back(&I); } while (Count--) { Loading Loading @@ -600,8 +604,18 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { if (Table.SymbolName.empty()) Table.SymbolName = Info.Name; } else { return make_error<GenericBinaryError>("undefined table symbol", object_error::parse_failed); wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex]; if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { Info.Name = readString(Ctx); Info.ImportName = Import.Field; } else { Info.Name = Import.Field; } TableType = Import.Table.ElemType; // FIXME: Parse limits here too. if (!Import.Module.empty()) { Info.ImportModule = Import.Module; } } break; Loading Loading @@ -1060,6 +1074,7 @@ Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) { } Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { TableSection = Sections.size(); uint32_t Count = readVaruint32(Ctx); Tables.reserve(Count); while (Count--) { Loading Loading @@ -1432,6 +1447,7 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: case wasm::WASM_SYMBOL_TYPE_TABLE: return Sym.Info.ElementIndex; case wasm::WASM_SYMBOL_TYPE_DATA: { // The value of a data symbol is the segment offset, plus the symbol Loading Loading @@ -1481,6 +1497,8 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const { return SymbolRef::ST_Debug; case wasm::WASM_SYMBOL_TYPE_EVENT: return SymbolRef::ST_Other; case wasm::WASM_SYMBOL_TYPE_TABLE: return SymbolRef::ST_Other; } llvm_unreachable("Unknown WasmSymbol::SymbolType"); Loading Loading @@ -1515,6 +1533,8 @@ uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const { return Sym.Info.ElementIndex; case wasm::WASM_SYMBOL_TYPE_EVENT: return EventSection; case wasm::WASM_SYMBOL_TYPE_TABLE: return TableSection; default: llvm_unreachable("Unknown WasmSymbol::SymbolType"); } Loading
llvm/test/MC/WebAssembly/assembler-binary.ll +0 −8 Original line number Diff line number Diff line Loading @@ -52,14 +52,6 @@ entry: ; CHECK-NEXT: Memory: ; CHECK-NEXT: Initial: 0x0 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __indirect_function_table ; CHECK-NEXT: Kind: TABLE ; CHECK-NEXT: Table: ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: ElemType: FUNCREF ; CHECK-NEXT: Limits: ; CHECK-NEXT: Initial: 0x0 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: bar ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 Loading