diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -301,6 +301,7 @@ WASM_SYMBOL_TYPE_GLOBAL = 0x2, WASM_SYMBOL_TYPE_SECTION = 0x3, WASM_SYMBOL_TYPE_EVENT = 0x4, + WASM_SYMBOL_TYPE_TABLE = 0x5, }; // Kinds of event attributes. diff --git a/llvm/include/llvm/BinaryFormat/WasmRelocs.def b/llvm/include/llvm/BinaryFormat/WasmRelocs.def --- a/llvm/include/llvm/BinaryFormat/WasmRelocs.def +++ b/llvm/include/llvm/BinaryFormat/WasmRelocs.def @@ -15,3 +15,4 @@ WASM_RELOC(R_WASM_EVENT_INDEX_LEB, 10) WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB, 11) WASM_RELOC(R_WASM_TABLE_INDEX_REL_SLEB, 12) +WASM_RELOC(R_WASM_TABLE_INDEX_LEB, 13) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -247,7 +247,7 @@ /// Return the in-memory pointer type for the given address space, defaults to /// the pointer type from the data layout. FIXME: The default needs to be /// removed once all the code is updated. - MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const { + virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const { return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); } @@ -1036,7 +1036,7 @@ const bool OptForSize = SI->getParent()->getParent()->hasOptSize(); const unsigned MinDensity = getMinimumJumpTableDensity(OptForSize); const unsigned MaxJumpTableSize = getMaximumJumpTableSize(); - + // Check whether the number of cases is small enough and // the range is dense enough for a jump table. if ((OptForSize || Range <= MaxJumpTableSize) && diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -293,6 +293,7 @@ VK_Hexagon_IE_GOT, VK_WASM_TYPEINDEX, // Reference to a symbol's type (signature) + VK_WASM_TABLEINDEX,// Reference to a table VK_WASM_MBREL, // Memory address relative to memory base VK_WASM_TBREL, // Table index relative to table bare diff --git a/llvm/include/llvm/MC/MCSymbolWasm.h b/llvm/include/llvm/MC/MCSymbolWasm.h --- a/llvm/include/llvm/MC/MCSymbolWasm.h +++ b/llvm/include/llvm/MC/MCSymbolWasm.h @@ -44,6 +44,7 @@ bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; } bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; } bool isEvent() const { return Type == wasm::WASM_SYMBOL_TYPE_EVENT; } + bool isTable() const { return Type == wasm::WASM_SYMBOL_TYPE_TABLE; } wasm::WasmSymbolType getType() const { return Type; } void setType(wasm::WasmSymbolType type) { Type = type; } diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h --- a/llvm/include/llvm/Object/Wasm.h +++ b/llvm/include/llvm/Object/Wasm.h @@ -63,6 +63,8 @@ bool isTypeEvent() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT; } + bool isTypeTable() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE; } + bool isDefined() const { return !isUndefined(); } bool isUndefined() const { @@ -217,9 +219,12 @@ bool isDefinedGlobalIndex(uint32_t Index) const; bool isValidEventIndex(uint32_t Index) const; bool isDefinedEventIndex(uint32_t Index) const; + bool isValidTableIndex(uint32_t Index) const; + bool isDefinedTableIndex(uint32_t Index) const; bool isValidFunctionSymbol(uint32_t Index) const; bool isValidGlobalSymbol(uint32_t Index) const; bool isValidEventSymbol(uint32_t Index) const; + bool isValidTableSymbol(uint32_t Index) const; bool isValidDataSymbol(uint32_t Index) const; bool isValidSectionSymbol(uint32_t Index) const; wasm::WasmFunction &getDefinedFunction(uint32_t Index); @@ -284,6 +289,7 @@ uint32_t NumImportedGlobals = 0; uint32_t NumImportedFunctions = 0; uint32_t NumImportedEvents = 0; + uint32_t NumImportedTables = 0; uint32_t CodeSection = 0; uint32_t DataSection = 0; uint32_t GlobalSection = 0; diff --git a/llvm/lib/BinaryFormat/Wasm.cpp b/llvm/lib/BinaryFormat/Wasm.cpp --- a/llvm/lib/BinaryFormat/Wasm.cpp +++ b/llvm/lib/BinaryFormat/Wasm.cpp @@ -20,6 +20,8 @@ return "WASM_SYMBOL_TYPE_SECTION"; case wasm::WASM_SYMBOL_TYPE_EVENT: return "WASM_SYMBOL_TYPE_EVENT"; + case wasm::WASM_SYMBOL_TYPE_TABLE: + return "WASM_SYMBOL_TYPE_TABLE"; } llvm_unreachable("unknown symbol type"); } diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -1856,7 +1856,7 @@ case Intrinsic::experimental_widenable_condition: { // Give up on future widening oppurtunties so that we can fold away dead // paths and merge blocks before going into block-local instruction - // selection. + // selection. if (II->use_empty()) { II->eraseFromParent(); return true; @@ -5733,6 +5733,9 @@ EVT LoadResultVT = TLI->getValueType(*DL, Load->getType()); unsigned BitWidth = LoadResultVT.getSizeInBits(); + if (!BitWidth) + return false; + APInt DemandBits(BitWidth, 0); APInt WidestAndBits(BitWidth, 0); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -4064,10 +4064,12 @@ Root = Chain; ChainI = 0; } - SDValue A = DAG.getNode(ISD::ADD, dl, - PtrVT, Ptr, - DAG.getConstant(Offsets[i], dl, PtrVT), - Flags); + SDValue A = Ptr; + if (Offsets[i] != 0) + A = DAG.getNode(ISD::ADD, dl, + PtrVT, Ptr, + DAG.getConstant(Offsets[i], dl, PtrVT), + Flags); auto MMOFlags = MachineMemOperand::MONone; if (isVolatile) MMOFlags |= MachineMemOperand::MOVolatile; diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp --- a/llvm/lib/CodeGen/ValueTypes.cpp +++ b/llvm/lib/CodeGen/ValueTypes.cpp @@ -250,7 +250,7 @@ case MVT::Metadata:return "Metadata"; case MVT::Untyped: return "Untyped"; case MVT::exnref : return "exnref"; - case MVT::anyref : return "exnref"; + case MVT::anyref : return "anyref"; } } diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -310,6 +310,7 @@ case VK_Hexagon_IE: return "IE"; case VK_Hexagon_IE_GOT: return "IEGOT"; case VK_WASM_TYPEINDEX: return "TYPEINDEX"; + case VK_WASM_TABLEINDEX: return "TABLEINDEX"; case VK_WASM_MBREL: return "MBREL"; case VK_WASM_TBREL: return "TBREL"; case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; @@ -427,6 +428,7 @@ .Case("hi8", VK_AVR_HI8) .Case("hlo8", VK_AVR_HLO8) .Case("typeindex", VK_WASM_TYPEINDEX) + .Case("tableindex", VK_WASM_TABLEINDEX) .Case("tbrel", VK_WASM_TBREL) .Case("mbrel", VK_WASM_MBREL) .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -254,6 +254,7 @@ unsigned NumFunctionImports = 0; unsigned NumGlobalImports = 0; unsigned NumEventImports = 0; + unsigned NumTableImports = 0; uint32_t SectionCount = 0; // TargetObjectWriter wrappers. @@ -584,6 +585,7 @@ case wasm::R_WASM_FUNCTION_INDEX_LEB: case wasm::R_WASM_GLOBAL_INDEX_LEB: case wasm::R_WASM_EVENT_INDEX_LEB: + case wasm::R_WASM_TABLE_INDEX_LEB: // Provisional value is function/global/event Wasm index assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space"); return WasmIndices[RelEntry.Symbol]; @@ -681,6 +683,7 @@ case wasm::R_WASM_GLOBAL_INDEX_LEB: case wasm::R_WASM_MEMORY_ADDR_LEB: case wasm::R_WASM_EVENT_INDEX_LEB: + case wasm::R_WASM_TABLE_INDEX_LEB: writePatchableLEB(Stream, Value, Offset); break; case wasm::R_WASM_TABLE_INDEX_I32: @@ -974,6 +977,7 @@ case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: + case wasm::WASM_SYMBOL_TYPE_TABLE: encodeULEB128(Sym.ElementIndex, W.OS); if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) @@ -1166,6 +1170,7 @@ TableImport.Kind = wasm::WASM_EXTERNAL_TABLE; TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF; Imports.push_back(TableImport); + NumTableImports++; // Populate SignatureIndices, and Imports and WasmIndices for undefined // symbols. This must be done before populating WasmIndices for defined @@ -1220,6 +1225,15 @@ Imports.push_back(Import); assert(WasmIndices.count(&WS) == 0); WasmIndices[&WS] = NumEventImports++; + } else if (WS.isTable()) { + wasm::WasmImport Import; + Import.Module = WS.getImportModule(); + Import.Field = WS.getImportName(); + Import.Kind = wasm::WASM_EXTERNAL_TABLE; + Import.Table.ElemType = wasm::WASM_TYPE_ANYREF; + Imports.push_back(Import); + assert(WasmIndices.count(&WS) == 0); + WasmIndices[&WS] = NumTableImports++; } } } @@ -1416,7 +1430,16 @@ } LLVM_DEBUG(dbgs() << " -> event index: " << WasmIndices.find(&WS)->second << "\n"); - + } else if (WS.isTable()) { + unsigned Index; + if (WS.isDefined()) { + report_fatal_error("Defined tables are not supported yet"); + } else { + // An import; the index was assigned above. + assert(WasmIndices.count(&WS) > 0); + } + LLVM_DEBUG(dbgs() << " -> table index: " << WasmIndices.find(&WS)->second + << "\n"); } else { assert(WS.isSection()); } diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -470,9 +470,11 @@ std::vector ImportedGlobals; std::vector ImportedFunctions; std::vector ImportedEvents; + std::vector 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); @@ -480,6 +482,8 @@ 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--) { @@ -609,6 +613,27 @@ break; } + case wasm::WASM_SYMBOL_TYPE_TABLE: { + Info.ElementIndex = readVaruint32(Ctx); + if (!isValidTableIndex(Info.ElementIndex) || + IsDefined != isDefinedTableIndex(Info.ElementIndex)) + return make_error("invalid table symbol index", + object_error::parse_failed); + if (IsDefined) { + Info.Name = readString(Ctx); + unsigned TableIndex = Info.ElementIndex - NumImportedTables; + } else { + wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex]; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; + } + break; + } + default: return make_error("Invalid symbol type", object_error::parse_failed); @@ -793,6 +818,11 @@ return make_error("Bad relocation event index", object_error::parse_failed); break; + case wasm::R_WASM_TABLE_INDEX_LEB: + if (!isValidTableSymbol(Reloc.Index)) + return make_error("Bad relocation event index", + object_error::parse_failed); + break; case wasm::R_WASM_MEMORY_ADDR_LEB: case wasm::R_WASM_MEMORY_ADDR_SLEB: case wasm::R_WASM_MEMORY_ADDR_I32: @@ -918,8 +948,10 @@ Im.Memory = readLimits(Ctx); break; case wasm::WASM_EXTERNAL_TABLE: + NumImportedTables++; Im.Table = readTable(Ctx); - if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF) + if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF && + Im.Table.ElemType != wasm::WASM_TYPE_ANYREF) return make_error("Invalid table element type", object_error::parse_failed); break; @@ -1087,6 +1119,14 @@ return Index >= NumImportedEvents && isValidEventIndex(Index); } +bool WasmObjectFile::isValidTableIndex(uint32_t Index) const { + return Index < NumImportedTables + Tables.size(); +} + +bool WasmObjectFile::isDefinedTableIndex(uint32_t Index) const { + return Index >= NumImportedTables && isValidTableIndex(Index); +} + bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { return Index < Symbols.size() && Symbols[Index].isTypeFunction(); } @@ -1099,6 +1139,10 @@ return Index < Symbols.size() && Symbols[Index].isTypeEvent(); } +bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const { + return Index < Symbols.size() && Symbols[Index].isTypeTable(); +} + bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { return Index < Symbols.size() && Symbols[Index].isTypeData(); } diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp --- a/llvm/lib/ObjectYAML/WasmYAML.cpp +++ b/llvm/lib/ObjectYAML/WasmYAML.cpp @@ -493,6 +493,8 @@ IO.mapRequired("Global", Info.ElementIndex); } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT) { IO.mapRequired("Event", Info.ElementIndex); + } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE) { + IO.mapRequired("Table", Info.ElementIndex); } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA) { if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) { IO.mapRequired("Segment", Info.DataRef.Segment); @@ -546,6 +548,7 @@ ECase(GLOBAL); ECase(SECTION); ECase(EVENT); + ECase(TABLE); #undef ECase } diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp --- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp +++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp @@ -196,6 +196,7 @@ case WebAssembly::OPERAND_BASIC_BLOCK: case WebAssembly::OPERAND_LOCAL: case WebAssembly::OPERAND_GLOBAL: + case WebAssembly::OPERAND_TABLE: case WebAssembly::OPERAND_FUNCTION32: case WebAssembly::OPERAND_OFFSET32: case WebAssembly::OPERAND_P2ALIGN: diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp @@ -154,6 +154,7 @@ case WebAssembly::OPERAND_OFFSET32: case WebAssembly::OPERAND_TYPEINDEX: case WebAssembly::OPERAND_GLOBAL: + case WebAssembly::OPERAND_TABLE: case WebAssembly::OPERAND_EVENT: FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i32); break; diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -48,6 +48,8 @@ OPERAND_LOCAL, /// Global index. OPERAND_GLOBAL, + /// Global index. + OPERAND_TABLE, /// 32-bit integer immediates. OPERAND_I32IMM, /// 64-bit integer immediates. @@ -102,6 +104,9 @@ // address relative the __table_base wasm global. // Only applicable to function symbols. MO_TABLE_BASE_REL, + + // On a symbol operand this indicates that this operand is a table index. + MO_TABLE_INDEX, }; } // end namespace WebAssemblyII diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -72,6 +72,8 @@ switch (Modifier) { case MCSymbolRefExpr::VK_GOT: return wasm::R_WASM_GLOBAL_INDEX_LEB; + case MCSymbolRefExpr::VK_WASM_TABLEINDEX: + return wasm::R_WASM_TABLE_INDEX_LEB; case MCSymbolRefExpr::VK_WASM_TBREL: assert(SymA.isFunction()); return wasm::R_WASM_TABLE_INDEX_REL_SLEB; @@ -98,6 +100,8 @@ return wasm::R_WASM_FUNCTION_INDEX_LEB; if (SymA.isEvent()) return wasm::R_WASM_EVENT_INDEX_LEB; + if (SymA.isTable()) + return wasm::R_WASM_TABLE_INDEX_LEB; return wasm::R_WASM_MEMORY_ADDR_LEB; case FK_Data_4: if (SymA.isFunction()) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -48,6 +48,11 @@ MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); } + MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const override { + return AS == 1 ? MVT::anyref : + MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); + } + AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *) const override; FastISel *createFastISel(FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const override; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -67,6 +67,7 @@ } if (Subtarget->hasReferenceTypes()) { addRegisterClass(MVT::anyref, &WebAssembly::ANYREFRegClass); + setOperationAction(ISD::GlobalAddress, MVT::anyref, Custom); } // Compute derived properties from the register classes. computeRegisterProperties(Subtarget->getRegisterInfo()); @@ -1086,8 +1087,8 @@ EVT VT = Op.getValueType(); assert(GA->getTargetFlags() == 0 && "Unexpected target flags on generic GlobalAddressSDNode"); - if (GA->getAddressSpace() != 0) - fail(DL, DAG, "WebAssembly only expects the 0 address space"); + if (GA->getAddressSpace() != 0 && GA->getAddressSpace() != 1) + fail(DL, DAG, "WebAssembly only expects the 0 or 1 address space"); unsigned OperandFlags = 0; if (isPositionIndependent()) { @@ -1119,6 +1120,10 @@ } } + if (GA->getAddressSpace() == 1) { + OperandFlags = WebAssemblyII::MO_TABLE_INDEX; + } + return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT, DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset(), OperandFlags)); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -144,6 +144,9 @@ let OperandType = "OPERAND_GLOBAL" in def global_op : Operand; +let OperandType = "OPERAND_TABLE" in +def table_op : Operand; + let OperandType = "OPERAND_I32IMM" in def i32imm_op : Operand; @@ -353,3 +356,4 @@ include "WebAssemblyInstrSIMD.td" include "WebAssemblyInstrRef.td" include "WebAssemblyInstrBulkMemory.td" +include "WebAssemblyInstrTable.td" diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td @@ -0,0 +1,12 @@ +multiclass WebAssemblyTableGet { + let mayLoad = 1, UseNamedOperandTable = 1 in + defm "": I<(outs rc:$dst), + (ins table_op: $table, I32:$offset), + (outs), (ins table_op: $table), + [], !strconcat(Name, "\t$dst, ${offset}(${table})"), + !strconcat(Name, "\t${table}"), Opcode>; +} + +defm TABLE_GET : WebAssemblyTableGet; + +def : Pat<(anyref (load (WebAssemblywrapper anyref:$addr))), (TABLE_GET anyref:$addr, (CONST_I32 0))>; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -64,6 +64,11 @@ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); } + unsigned TargetFlags = MO.getTargetFlags(); + if (TargetFlags == WebAssemblyII::MO_TABLE_INDEX) { + WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE); + } + return WasmSym; } @@ -90,6 +95,12 @@ return WasmSym; } + unsigned TargetFlags = MO.getTargetFlags(); + if (TargetFlags == WebAssemblyII::MO_TABLE_INDEX) { + WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE); + return WasmSym; + } + SmallVector Returns; SmallVector Params; if (strcmp(Name, "__cpp_exception") == 0) { @@ -130,6 +141,9 @@ switch (TargetFlags) { case WebAssemblyII::MO_NO_FLAG: break; + case WebAssemblyII::MO_TABLE_INDEX: + Kind = MCSymbolRefExpr::VK_WASM_TABLEINDEX; + break; case WebAssemblyII::MO_GOT: Kind = MCSymbolRefExpr::VK_GOT; break; diff --git a/llvm/tools/yaml2obj/yaml2wasm.cpp b/llvm/tools/yaml2obj/yaml2wasm.cpp --- a/llvm/tools/yaml2obj/yaml2wasm.cpp +++ b/llvm/tools/yaml2obj/yaml2wasm.cpp @@ -174,6 +174,7 @@ case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: + case wasm::WASM_SYMBOL_TYPE_TABLE: encodeULEB128(Info.ElementIndex, SubSection.getStream()); if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)