diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -446,6 +446,16 @@ /// inline assembly. void registerInlineAsmLabel(MCSymbol *Sym); + /// getOrCreateWasmFunctionTableSymbol - Gets or creates a symbol denoting a + /// WebAssembly table holding elements of type funcref. + MCSymbol *getOrCreateWasmFunctionTableSymbol(StringRef TableName); + + /// getOrCreateWasmDefaultFunctionTableSymbol - By default, all WebAssembly + /// functions that can be called indirectly are put into a single well-known + /// function table, conventionally called __indirect_function_table. This + /// table's definition is synthesized by the linker. + MCSymbol *getOrCreateWasmDefaultFunctionTableSymbol(); + /// @} /// \name Section Management 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 @@ -96,6 +96,15 @@ 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; } @@ -111,8 +120,9 @@ } 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; } diff --git a/llvm/include/llvm/MC/MCWasmStreamer.h b/llvm/include/llvm/MC/MCWasmStreamer.h --- a/llvm/include/llvm/MC/MCWasmStreamer.h +++ b/llvm/include/llvm/MC/MCWasmStreamer.h @@ -59,8 +59,6 @@ SMLoc Loc = SMLoc()) override; void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0) override; - void emitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc = SMLoc()) override; void emitIdent(StringRef IdentString) override; 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 @@ -299,6 +299,7 @@ uint32_t DataSection = 0; uint32_t EventSection = 0; uint32_t GlobalSection = 0; + uint32_t TableSection = 0; }; class WasmSectionOrderChecker { diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -301,6 +301,24 @@ InlineAsmUsedLabelNames[Sym->getName()] = Sym; } +MCSymbol *MCContext::getOrCreateWasmFunctionTableSymbol(StringRef TableName) { + if (auto Sym = cast_or_null(Symbols.lookup(TableName))) { + if (!Sym->isFunctionTable()) + reportError(SMLoc(), "symbol is not a wasm funcref table"); + return Sym; + } + auto Sym = cast(getOrCreateSymbol(TableName)); + Sym->setFunctionTable(); + return Sym; +} + +MCSymbol *MCContext::getOrCreateWasmDefaultFunctionTableSymbol() { + auto Sym = getOrCreateWasmFunctionTableSymbol("__indirect_function_table"); + // The default function table is synthesized by the linker. + Sym->setUndefined(); + return Sym; +} + MCSymbolXCOFF * MCContext::createXCOFFSymbolImpl(const StringMapEntry *Name, bool IsTemporary) { diff --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp --- a/llvm/lib/MC/MCWasmStreamer.cpp +++ b/llvm/lib/MC/MCWasmStreamer.cpp @@ -148,11 +148,6 @@ llvm_unreachable("Local common symbols are not yet implemented for Wasm"); } -void MCWasmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - MCObjectStreamer::emitValueImpl(Value, Size, Loc); -} - void MCWasmStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value, unsigned ValueSize, unsigned MaxBytesToEmit) { 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 @@ -40,8 +40,8 @@ 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 @@ -218,9 +218,7 @@ SmallVector 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; @@ -270,7 +268,7 @@ SectionFunctions.clear(); NumFunctionImports = 0; NumGlobalImports = 0; - NumTableImports = 1; + NumTableImports = 0; MCObjectWriter::reset(); } @@ -496,6 +494,17 @@ SymA = cast(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 BaseSym = Ctx.getOrCreateWasmDefaultFunctionTableSymbol(); + BaseSym->setUsedInReloc(); + Asm.registerSymbol(*BaseSym); + } + // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be // against a named symbol. if (Type != wasm::R_WASM_TYPE_INDEX_LEB) { @@ -1196,16 +1205,6 @@ : 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. @@ -1264,6 +1263,22 @@ 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; + Import.Table.Index = NumTableImports; + wasm::ValType ElemType = WS.getTableType(); + Import.Table.ElemType = uint8_t(ElemType); + // FIXME: ? + Import.Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0}; + Imports.push_back(Import); + assert(WasmIndices.count(&WS) == 0); + WasmIndices[&WS] = NumTableImports++; } } } 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 @@ -484,9 +484,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); @@ -494,6 +496,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--) { @@ -562,7 +566,6 @@ Info.Name = Import.Field; } GlobalType = &Import.Global; - Info.ImportName = Import.Field; if (!Import.Module.empty()) { Info.ImportModule = Import.Module; } @@ -585,8 +588,18 @@ wasm::WasmTable &Table = Tables[TableIndex]; TableType = Table.ElemType; } else { - return make_error("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; @@ -1038,6 +1051,7 @@ } Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { + TableSection = Sections.size(); uint32_t Count = readVaruint32(Ctx); Tables.reserve(Count); while (Count--) { @@ -1492,6 +1506,8 @@ 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"); } diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -454,6 +454,15 @@ WebAssemblyOperand::IntOp{static_cast(BT)})); } + void addFunctionTableOperand(OperandVector &Operands, StringRef TableName, + SMLoc StartLoc, SMLoc EndLoc) { + auto *Sym = getContext().getOrCreateWasmFunctionTableSymbol(TableName); + auto *Val = MCSymbolRefExpr::create(Sym, getContext()); + Operands.push_back(std::make_unique( + WebAssemblyOperand::Symbol, StartLoc, EndLoc, + WebAssemblyOperand::SymOp{Val})); + } + bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override { // Note: Name does NOT point into the sourcecode, but to a local, so @@ -490,6 +499,7 @@ bool ExpectBlockType = false; bool ExpectFuncType = false; bool ExpectHeapType = false; + bool ExpectFunctionTable = false; if (Name == "block") { push(Block); ExpectBlockType = true; @@ -529,6 +539,7 @@ return true; } else if (Name == "call_indirect" || Name == "return_call_indirect") { ExpectFuncType = true; + ExpectFunctionTable = true; } else if (Name == "ref.null") { ExpectHeapType = true; } @@ -544,7 +555,7 @@ return true; // Got signature as block type, don't need more ExpectBlockType = false; - auto &Ctx = getStreamer().getContext(); + auto &Ctx = getContext(); // The "true" here will cause this to be a nameless symbol. MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true); auto *WasmSym = cast(Sym); @@ -556,6 +567,16 @@ Operands.push_back(std::make_unique( WebAssemblyOperand::Symbol, Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr})); + + // Allow additional operands after the signature, notably for + // call_indirect against a named table. + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (expect(AsmToken::Comma, ",")) + return true; + if (Lexer.is(AsmToken::EndOfStatement)) { + return error("Unexpected trailing comma"); + } + } } while (Lexer.isNot(AsmToken::EndOfStatement)) { @@ -581,8 +602,11 @@ WebAssemblyOperand::Integer, Id.getLoc(), Id.getEndLoc(), WebAssemblyOperand::IntOp{static_cast(HeapType)})); Parser.Lex(); + } else if (ExpectFunctionTable) { + addFunctionTableOperand(Operands, Id.getString(), Id.getLoc(), + Id.getEndLoc()); + Parser.Lex(); } else { - // Assume this identifier is a label. const MCExpr *Val; SMLoc End; if (Parser.parseExpression(Val, End)) @@ -647,6 +671,11 @@ // Support blocks with no operands as default to void. addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void); } + if (ExpectFunctionTable && Operands.size() == 2) { + // If call_indirect doesn't specify a target table, supply one. + addFunctionTableOperand(Operands, "__indirect_function_table", NameLoc, + SMLoc::getFromPointer(Name.end())); + } Parser.Lex(); return false; } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp @@ -68,7 +68,8 @@ for (auto I = Start, E = MI->getNumOperands(); I < E; ++I) { if (MI->getOpcode() == WebAssembly::CALL_INDIRECT && I - Start == NumVariadicDefs) { - // Skip type and flags arguments when printing for tests + // Skip type, table, and flags arguments when printing for tests + ++I; ++I; continue; } 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 @@ -387,6 +387,16 @@ } } +inline bool isRetCallIndirect(unsigned Opc) { + switch (Opc) { + case WebAssembly::RET_CALL_INDIRECT: + case WebAssembly::RET_CALL_INDIRECT_S: + return true; + default: + return false; + } +} + inline bool isBrTable(const MachineInstr &MI) { switch (MI.getOpcode()) { case WebAssembly::BR_TABLE_I32: diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -15,10 +15,12 @@ #include "MCTargetDesc/WebAssemblyTargetStreamer.h" #include "MCTargetDesc/WebAssemblyInstPrinter.h" #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" +#include "WebAssemblyUtilities.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbolWasm.h" +#include "llvm/MC/MCWasmStreamer.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -26,6 +26,7 @@ #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -867,8 +868,12 @@ if (IsDirect) { MIB.addGlobalAddress(Func); } else { - // Add placeholders for the type index and immediate flags + // Placehoder for the type index. MIB.addImm(0); + // The table into which this call_indirect indexes. + auto &Context = MF->getMMI().getContext(); + MIB.addSym(Context.getOrCreateWasmDefaultFunctionTableSymbol()); + // Placeholder for immediate flags. MIB.addImm(0); } 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 @@ -472,9 +472,13 @@ for (auto Def : CallResults.defs()) MIB.add(Def); - // Add placeholders for the type index and immediate flags if (IsIndirect) { + // Placehoder for the type index. MIB.addImm(0); + // The table into which this call_indirect indexes. + auto &Context = MF.getContext(); + MIB.addSym(Context.getOrCreateWasmDefaultFunctionTableSymbol()); + // Placeholder for immediate flags. MIB.addImm(0); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -48,6 +48,9 @@ I<(outs), (ins variable_ops), (outs), (ins), [], "return_call_results", "return_call_results", -1>; +// Note that instructions with variable_ops have custom printers in +// WebAssemblyInstPrinter.cpp. + let variadicOpsAreDefs = 1 in defm CALL : I<(outs), (ins function32_op:$callee, variable_ops), @@ -56,9 +59,12 @@ let variadicOpsAreDefs = 1 in defm CALL_INDIRECT : - I<(outs), (ins TypeIndex:$type, i32imm:$flags, variable_ops), - (outs), (ins TypeIndex:$type, i32imm:$flags), [], - "call_indirect", "call_indirect\t$type", 0x11>; + I<(outs), + (ins TypeIndex:$type, table32_op:$table, i32imm:$flags, variable_ops), + (outs), + (ins TypeIndex:$type, table32_op:$table, i32imm:$flags), + [], + "call_indirect", "call_indirect\t$type, $table", 0x11>; let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in defm RET_CALL : @@ -69,9 +75,9 @@ let isReturn = 1 in defm RET_CALL_INDIRECT : - I<(outs), (ins TypeIndex:$type, i32imm:$flags, variable_ops), - (outs), (ins TypeIndex:$type, i32imm:$flags), [], - "return_call_indirect\t", "return_call_indirect\t$type", + I<(outs), (ins TypeIndex:$type, table32_op:$table, i32imm:$flags, variable_ops), + (outs), (ins TypeIndex:$type, table32_op:$table, i32imm:$flags), [], + "return_call_indirect\t", "return_call_indirect\t$type, $table", 0x13>, Requires<[HasTailCall]>; 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 @@ -158,6 +158,8 @@ report_fatal_error("Global indexes with offsets not supported"); if (WasmSym->isEvent()) report_fatal_error("Event indexes with offsets not supported"); + if (WasmSym->isTable()) + report_fatal_error("Table indexes with offsets not supported"); Expr = MCBinaryExpr::createAdd( Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); @@ -256,7 +258,7 @@ // return_call_indirect instructions have the return type of the // caller - if (MI->getOpcode() == WebAssembly::RET_CALL_INDIRECT) + if (WebAssembly::isRetCallIndirect(MI->getOpcode())) getFunctionReturns(MI, Returns); MCOp = lowerTypeIndexOperand(std::move(Returns), std::move(Params)); diff --git a/llvm/test/CodeGen/WebAssembly/function-pointer64.ll b/llvm/test/CodeGen/WebAssembly/function-pointer64.ll --- a/llvm/test/CodeGen/WebAssembly/function-pointer64.ll +++ b/llvm/test/CodeGen/WebAssembly/function-pointer64.ll @@ -34,7 +34,7 @@ ; CHECK-NEXT: i32.const 1 ; CHECK-NEXT: local.get 0 ; CHECK-NEXT: i32.wrap_i64 -; CHECK-NEXT: call_indirect (i32) -> () +; CHECK-NEXT: call_indirect (i32) -> (), __indirect_function_table ; CHECK: .functype test () -> () ; CHECK-NEXT: i64.const bar @@ -50,7 +50,7 @@ ; YAML: - Type: CODE ; YAML: - Type: R_WASM_TABLE_INDEX_SLEB64 ; YAML-NEXT: Index: 0 -; YAML-NEXT: Offset: 0x00000016 +; YAML-NEXT: Offset: 0x0000001B ; YAML: - Type: DATA ; YAML: - Type: R_WASM_TABLE_INDEX_I64 diff --git a/llvm/test/CodeGen/WebAssembly/multivalue.ll b/llvm/test/CodeGen/WebAssembly/multivalue.ll --- a/llvm/test/CodeGen/WebAssembly/multivalue.ll +++ b/llvm/test/CodeGen/WebAssembly/multivalue.ll @@ -57,7 +57,7 @@ ; CHECK-LABEL: pair_call_indirect: ; CHECK-NEXT: .functype pair_call_indirect (i32) -> (i32, i64) ; CHECK-NEXT: local.get 0{{$}} -; CHECK-NEXT: call_indirect () -> (i32, i64){{$}} +; CHECK-NEXT: call_indirect () -> (i32, i64), __indirect_function_table{{$}} ; CHECK-NEXT: end_function{{$}} ; REGS: call_indirect $push{{[0-9]+}}=, $push{{[0-9]+}}=, $0{{$}} define %pair @pair_call_indirect(%pair()* %f) { diff --git a/llvm/test/MC/WebAssembly/assembler-binary.ll b/llvm/test/MC/WebAssembly/assembler-binary.ll --- a/llvm/test/MC/WebAssembly/assembler-binary.ll +++ b/llvm/test/MC/WebAssembly/assembler-binary.ll @@ -52,14 +52,6 @@ ; CHECK-NEXT: Memory: ; CHECK-NEXT: Initial: 0x00000000 ; 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: 0x00000000 -; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: bar ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 diff --git a/llvm/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s --- a/llvm/test/MC/WebAssembly/basic-assembly.s +++ b/llvm/test/MC/WebAssembly/basic-assembly.s @@ -159,7 +159,7 @@ # CHECK-NEXT: i64.const 1234 # CHECK-NEXT: call something2 # CHECK-NEXT: i32.const 0 -# CHECK-NEXT: call_indirect (i32, f64) -> () +# CHECK-NEXT: call_indirect (i32, f64) -> (), __indirect_function_table # CHECK-NEXT: i32.const 1 # CHECK-NEXT: i32.add # CHECK-NEXT: local.tee 0 diff --git a/llvm/test/MC/WebAssembly/call-indirect-relocs.s b/llvm/test/MC/WebAssembly/call-indirect-relocs.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/WebAssembly/call-indirect-relocs.s @@ -0,0 +1,83 @@ +# RUN: llvm-mc -triple=wasm32-unknown-unknown < %s | FileCheck %s +# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck -check-prefix=BIN %s + +test0: + .functype test0 () -> () + i32.const 42 + f64.const 2.5 + i32.const 0 + call_indirect (i32, f64) -> (), empty_fref_table + end_function + +.tabletype empty_fref_table, funcref +empty_fref_table: + + +# CHECK: .text +# CHECK-LABEL: test0: +# CHECK-NEXT: .functype test0 () -> () +# CHECK-NEXT: i32.const 42 +# CHECK-NEXT: f64.const 0x1.4p1 +# CHECK-NEXT: i32.const 0 +# CHECK-NEXT: call_indirect (i32, f64) -> (), empty_fref_table +# CHECK-NEXT: end_function + +# CHECK: .tabletype empty_fref_table, funcref +# CHECK: empty_fref_table: + +# BIN: --- !WASM +# BIN-NEXT: FileHeader: +# BIN-NEXT: Version: 0x00000001 +# BIN-NEXT: Sections: +# BIN-NEXT: - Type: TYPE +# BIN-NEXT: Signatures: +# BIN-NEXT: - Index: 0 +# BIN-NEXT: ParamTypes: [] +# BIN-NEXT: ReturnTypes: [] +# BIN-NEXT: - Index: 1 +# BIN-NEXT: ParamTypes: +# BIN-NEXT: - I32 +# BIN-NEXT: - F64 +# BIN-NEXT: ReturnTypes: [] +# BIN-NEXT: - Type: IMPORT +# BIN-NEXT: Imports: +# BIN-NEXT: - Module: env +# BIN-NEXT: Field: __linear_memory +# BIN-NEXT: Kind: MEMORY +# BIN-NEXT: Memory: +# BIN-NEXT: Initial: 0x00000000 +# BIN-NEXT: - Type: FUNCTION +# BIN-NEXT: FunctionTypes: [ 0 ] +# BIN-NEXT: - Type: TABLE +# BIN-NEXT: Tables: +# BIN-NEXT: - Index: 0 +# BIN-NEXT: ElemType: FUNCREF +# BIN-NEXT: Limits: +# BIN-NEXT: Initial: 0x00000000 +# BIN-NEXT: - Type: CODE +# BIN-NEXT: Relocations: +# BIN-NEXT: - Type: R_WASM_TYPE_INDEX_LEB +# BIN-NEXT: Index: 1 +# BIN-NEXT: Offset: 0x00000011 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 1 +# BIN-NEXT: Offset: 0x00000016 +# BIN-NEXT: Functions: +# BIN-NEXT: - Index: 0 +# BIN-NEXT: Locals: [] +# BIN-NEXT: Body: 412A44000000000000044041001181808080008080808000000B +# BIN-NEXT: - Type: CUSTOM +# BIN-NEXT: Name: linking +# BIN-NEXT: Version: 2 +# BIN-NEXT: SymbolTable: +# BIN-NEXT: - Index: 0 +# BIN-NEXT: Kind: FUNCTION +# BIN-NEXT: Name: test0 +# BIN-NEXT: Flags: [ BINDING_LOCAL ] +# BIN-NEXT: Function: 0 +# BIN-NEXT: - Index: 1 +# BIN-NEXT: Kind: TABLE +# BIN-NEXT: Name: empty_fref_table +# BIN-NEXT: Flags: [ BINDING_LOCAL ] +# BIN-NEXT: Table: 0 +# BIN-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/comdat.ll b/llvm/test/MC/WebAssembly/comdat.ll --- a/llvm/test/MC/WebAssembly/comdat.ll +++ b/llvm/test/MC/WebAssembly/comdat.ll @@ -39,14 +39,6 @@ ; CHECK-NEXT: Memory: ; CHECK-NEXT: Initial: 0x00000001 ; 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: 0x00000000 -; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: funcImport ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 0 diff --git a/llvm/test/MC/WebAssembly/custom-sections.ll b/llvm/test/MC/WebAssembly/custom-sections.ll --- a/llvm/test/MC/WebAssembly/custom-sections.ll +++ b/llvm/test/MC/WebAssembly/custom-sections.ll @@ -15,18 +15,18 @@ ; CHECK: Section { ; CHECK: Type: CUSTOM (0x0) ; CHECK: Size: 3 -; CHECK: Offset: 72 +; CHECK: Offset: 38 ; CHECK: Name: red ; CHECK: } ; CHECK: Section { ; CHECK: Type: CUSTOM (0x0) ; CHECK: Size: 6 -; CHECK: Offset: 85 +; CHECK: Offset: 51 ; CHECK: Name: green ; CHECK: } ; CHECK: Section { ; CHECK: Type: CUSTOM (0x0) ; CHECK: Size: 25 -; CHECK: Offset: 118 +; CHECK: Offset: 84 ; CHECK: Name: producers ; CHECK: } diff --git a/llvm/test/MC/WebAssembly/data-section.s b/llvm/test/MC/WebAssembly/data-section.s --- a/llvm/test/MC/WebAssembly/data-section.s +++ b/llvm/test/MC/WebAssembly/data-section.s @@ -45,14 +45,6 @@ # BIN-NEXT: Kind: MEMORY # BIN-NEXT: Memory: # BIN-NEXT: Initial: 0x00000001 -# BIN-NEXT: - Module: env -# BIN-NEXT: Field: __indirect_function_table -# BIN-NEXT: Kind: TABLE -# BIN-NEXT: Table: -# BIN-NEXT: Index: 0 -# BIN-NEXT: ElemType: FUNCREF -# BIN-NEXT: Limits: -# BIN-NEXT: Initial: 0x00000000 # BIN-NEXT: - Type: FUNCTION # BIN-NEXT: FunctionTypes: [ 0 ] # BIN-NEXT: - Type: DATACOUNT diff --git a/llvm/test/MC/WebAssembly/debug-info.ll b/llvm/test/MC/WebAssembly/debug-info.ll --- a/llvm/test/MC/WebAssembly/debug-info.ll +++ b/llvm/test/MC/WebAssembly/debug-info.ll @@ -89,44 +89,44 @@ ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) -; CHECK-NEXT: Size: 91 +; CHECK-NEXT: Size: 94 ; CHECK-NEXT: Offset: 731 ; CHECK-NEXT: Name: linking ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 9 -; CHECK-NEXT: Offset: 836 +; CHECK-NEXT: Offset: 839 ; CHECK-NEXT: Name: reloc.DATA ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 61 -; CHECK-NEXT: Offset: 862 +; CHECK-NEXT: Offset: 865 ; CHECK-NEXT: Name: reloc..debug_info ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 6 -; CHECK-NEXT: Offset: 947 +; CHECK-NEXT: Offset: 950 ; CHECK-NEXT: Name: reloc..debug_pubnames ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 6 -; CHECK-NEXT: Offset: 981 +; CHECK-NEXT: Offset: 984 ; CHECK-NEXT: Name: reloc..debug_pubtypes ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 6 -; CHECK-NEXT: Offset: 1015 +; CHECK-NEXT: Offset: 1018 ; CHECK-NEXT: Name: reloc..debug_line ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 77 -; CHECK-NEXT: Offset: 1045 +; CHECK-NEXT: Offset: 1048 ; CHECK-NEXT: Name: producers ; CHECK-NEXT: } ; CHECK-NEXT:] @@ -219,7 +219,6 @@ ; CHECK-NEXT: Flags [ (0x10) ; CHECK-NEXT: UNDEFINED (0x10) ; CHECK-NEXT: ] -; CHECK-NEXT: ImportName: __stack_pointer ; CHECK-NEXT: ImportModule: env ; CHECK-NEXT: ElementIndex: 0x0 ; CHECK-NEXT: } @@ -239,6 +238,15 @@ ; CHECK-NEXT: ] ; CHECK-NEXT: ElementIndex: 0xC ; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Name: __indirect_function_table +; CHECK-NEXT: Type: 0x5 +; CHECK-NEXT: Flags [ (0x10) +; CHECK-NEXT: UNDEFINED (0x10) +; CHECK-NEXT: ] +; CHECK-NEXT: ImportModule: env +; CHECK-NEXT: ElementIndex: 0x0 +; CHECK-NEXT: } ; CHECK-NEXT:] ; generated from the following C code using: clang --target=wasm32 -g -O0 -S -emit-llvm test.c diff --git a/llvm/test/MC/WebAssembly/event-section.ll b/llvm/test/MC/WebAssembly/event-section.ll --- a/llvm/test/MC/WebAssembly/event-section.ll +++ b/llvm/test/MC/WebAssembly/event-section.ll @@ -56,4 +56,4 @@ ; SEC: Type: EVENT (0xD) ; SEC-NEXT: Size: 3 -; SEC-NEXT: Offset: 97 +; SEC-NEXT: Offset: 63 diff --git a/llvm/test/MC/WebAssembly/external-func-address.ll b/llvm/test/MC/WebAssembly/external-func-address.ll --- a/llvm/test/MC/WebAssembly/external-func-address.ll +++ b/llvm/test/MC/WebAssembly/external-func-address.ll @@ -42,8 +42,6 @@ ; CHECK: - Module: env ; CHECK-NEXT: Field: __linear_memory ; CHECK: - Module: env -; CHECK-NEXT: Field: __indirect_function_table -; CHECK: - Module: env ; CHECK-NEXT: Field: varargs ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 @@ -53,6 +51,8 @@ ; CHECK-NEXT: Field: f1 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 0 +; CHECK: - Module: env +; CHECK-NEXT: Field: __indirect_function_table ; CHECK: - Type: ELEM ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: diff --git a/llvm/test/MC/WebAssembly/function-alias.ll b/llvm/test/MC/WebAssembly/function-alias.ll --- a/llvm/test/MC/WebAssembly/function-alias.ll +++ b/llvm/test/MC/WebAssembly/function-alias.ll @@ -41,4 +41,13 @@ ; CHECK-NEXT: ] ; CHECK-NEXT: ElementIndex: 0x0 ; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Name: __indirect_function_table +; CHECK-NEXT: Type: 0x5 +; CHECK-NEXT: Flags [ (0x10) +; CHECK-NEXT: UNDEFINED (0x10) +; CHECK-NEXT: ] +; CHECK-NEXT: ImportModule: env +; CHECK-NEXT: ElementIndex: 0x0 +; CHECK-NEXT: } ; CHECK-NEXT: ] diff --git a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll --- a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll +++ b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll @@ -27,14 +27,6 @@ ; CHECK-NEXT: Memory: ; CHECK-NEXT: Initial: 0x00000001 ; 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: 0x00000002 -; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: func3 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 @@ -54,6 +46,14 @@ ; CHECK-NEXT: Field: func0 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 +; 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: 0x00000002 ; CHECK-NEXT: - Type: FUNCTION ; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 1 ] ; CHECK-NEXT: - Type: ELEM @@ -170,6 +170,11 @@ ; CHECK-NEXT: Name: func0 ; CHECK-NEXT: Flags: [ UNDEFINED ] ; CHECK-NEXT: Function: 4 +; CHECK-NEXT: - Index: 11 +; CHECK-NEXT: Kind: TABLE +; CHECK-NEXT: Name: __indirect_function_table +; CHECK-NEXT: Flags: [ UNDEFINED ] +; CHECK-NEXT: Table: 0 ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .data.global1 diff --git a/llvm/test/MC/WebAssembly/reloc-code.ll b/llvm/test/MC/WebAssembly/reloc-code.ll --- a/llvm/test/MC/WebAssembly/reloc-code.ll +++ b/llvm/test/MC/WebAssembly/reloc-code.ll @@ -43,18 +43,28 @@ ; CHECK-NEXT: Index: 0x1 ; CHECK-NEXT: } ; CHECK-NEXT: Relocation { +; CHECK-NEXT: Type: R_WASM_TABLE_NUMBER_LEB (20) +; CHECK-NEXT: Offset: 0x1F +; CHECK-NEXT: Symbol: __indirect_function_table +; CHECK-NEXT: } +; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WASM_TYPE_INDEX_LEB (6) -; CHECK-NEXT: Offset: 0x24 +; CHECK-NEXT: Offset: 0x29 ; CHECK-NEXT: Index: 0x0 ; CHECK-NEXT: } ; CHECK-NEXT: Relocation { +; CHECK-NEXT: Type: R_WASM_TABLE_NUMBER_LEB (20) +; CHECK-NEXT: Offset: 0x2E +; CHECK-NEXT: Symbol: __indirect_function_table +; CHECK-NEXT: } +; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WASM_FUNCTION_INDEX_LEB (0) -; CHECK-NEXT: Offset: 0x2D +; CHECK-NEXT: Offset: 0x37 ; CHECK-NEXT: Symbol: c ; CHECK-NEXT: } ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WASM_FUNCTION_INDEX_LEB (0) -; CHECK-NEXT: Offset: 0x34 +; CHECK-NEXT: Offset: 0x3E ; CHECK-NEXT: Symbol: d ; CHECK-NEXT: } ; CHECK-NEXT: } diff --git a/llvm/test/MC/WebAssembly/reloc-pic.s b/llvm/test/MC/WebAssembly/reloc-pic.s --- a/llvm/test/MC/WebAssembly/reloc-pic.s +++ b/llvm/test/MC/WebAssembly/reloc-pic.s @@ -63,6 +63,10 @@ # CHECK-NEXT: Memory: # CHECK-NEXT: Initial: 0x00000001 # CHECK-NEXT: - Module: env +# CHECK-NEXT: Field: default_func +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: SigIndex: 0 +# CHECK-NEXT: - Module: env # CHECK-NEXT: Field: __indirect_function_table # CHECK-NEXT: Kind: TABLE # CHECK-NEXT: Table: @@ -70,10 +74,6 @@ # CHECK-NEXT: ElemType: FUNCREF # CHECK-NEXT: Limits: # CHECK-NEXT: Initial: 0x00000001 -# CHECK-NEXT: - Module: env -# CHECK-NEXT: Field: default_func -# CHECK-NEXT: Kind: FUNCTION -# CHECK-NEXT: SigIndex: 0 # CHECK-NEXT: - Module: GOT.mem # CHECK-NEXT: Field: default_data # CHECK-NEXT: Kind: GLOBAL @@ -88,10 +88,10 @@ # CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ] # CHECK-NEXT: - Type: ELEM # CHECK-NEXT: Segments: -# CHECK-NEXT: Offset: -# CHECK-NEXT: Opcode: I32_CONST -# CHECK-NEXT: Value: 1 -# CHECK-NEXT: Functions: [ 5 ] +# CHECK-NEXT: - Offset: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 1 +# CHECK-NEXT: Functions: [ 5 ] # CHECK-NEXT: - Type: DATACOUNT # CHECK-NEXT: Count: 1 # CHECK-NEXT: - Type: CODE @@ -190,6 +190,11 @@ # CHECK-NEXT: Name: hidden_func # CHECK-NEXT: Flags: [ BINDING_LOCAL ] # CHECK-NEXT: Function: 5 +# CHECK-NEXT: - Index: 10 +# CHECK-NEXT: Kind: TABLE +# CHECK-NEXT: Name: __indirect_function_table +# CHECK-NEXT: Flags: [ UNDEFINED ] +# CHECK-NEXT: Table: 0 # CHECK-NEXT: SegmentInfo: # CHECK-NEXT: - Index: 0 # CHECK-NEXT: Name: .rodata.hidden_data diff --git a/llvm/test/MC/WebAssembly/tables.s b/llvm/test/MC/WebAssembly/tables.s --- a/llvm/test/MC/WebAssembly/tables.s +++ b/llvm/test/MC/WebAssembly/tables.s @@ -121,14 +121,22 @@ # BIN: - Type: TABLE # BIN-NEXT: Tables: -# BIN-NEXT: - Index: 1 +# BIN-NEXT: - Index: 0 # BIN-NEXT: ElemType: EXTERNREF # BIN-NEXT: Limits: # BIN-NEXT: Initial: 0x00000000 +# BIN-NEXT: - Index: 1 +# BIN-NEXT: ElemType: FUNCREF +# BIN-NEXT: Limits: +# BIN-NEXT: Initial: 0x00000000 # BIN-NEXT: - Index: 2 # BIN-NEXT: ElemType: FUNCREF # BIN-NEXT: Limits: # BIN-NEXT: Initial: 0x00000000 +# BIN-NEXT: - Index: 3 +# BIN-NEXT: ElemType: FUNCREF +# BIN-NEXT: Limits: +# BIN-NEXT: Initial: 0x00000000 # BIN: - Type: CODE # BIN-NEXT: Relocations: @@ -162,19 +170,19 @@ # BIN-NEXT: Functions: # BIN-NEXT: - Index: 0 # BIN-NEXT: Locals: [] -# BIN-NEXT: Body: 20002001FC108380808000FC0E838080800084808080000B +# BIN-NEXT: Body: 20002001FC108280808000FC0E828080800083808080000B # BIN-NEXT: - Index: 1 # BIN-NEXT: Locals: [] -# BIN-NEXT: Body: 20002581808080000B +# BIN-NEXT: Body: 20002580808080000B # BIN-NEXT: - Index: 2 # BIN-NEXT: Locals: [] -# BIN-NEXT: Body: 200020012681808080000B +# BIN-NEXT: Body: 200020012680808080000B # BIN-NEXT: - Index: 3 # BIN-NEXT: Locals: [] -# BIN-NEXT: Body: 41002581808080002000FC0F818080800020006A0B +# BIN-NEXT: Body: 41002580808080002000FC0F808080800020006A0B # BIN-NEXT: - Index: 4 # BIN-NEXT: Locals: [] -# BIN-NEXT: Body: 200041002583808080002001FC1183808080000B +# BIN-NEXT: Body: 200041002582808080002001FC1182808080000B # BIN: - Type: CUSTOM # BIN-NEXT: Name: linking @@ -184,9 +192,20 @@ # BIN-NEXT: Kind: TABLE # BIN-NEXT: Name: foo # BIN-NEXT: Flags: [ BINDING_LOCAL ] -# BIN-NEXT: Table: 1 +# BIN-NEXT: Table: 0 # BIN-NEXT: - Index: 1 # BIN-NEXT: Kind: TABLE # BIN-NEXT: Name: bar # BIN-NEXT: Flags: [ BINDING_LOCAL ] +# BIN-NEXT: Table: 1 +# BIN-NEXT: - Index: 2 +# BIN-NEXT: Kind: TABLE +# BIN-NEXT: Name: table1 +# BIN-NEXT: Flags: [ BINDING_LOCAL ] # BIN-NEXT: Table: 2 +# BIN-NEXT: - Index: 3 +# BIN-NEXT: Kind: TABLE +# BIN-NEXT: Name: table2 +# BIN-NEXT: Flags: [ BINDING_LOCAL ] +# BIN-NEXT: Table: 3 +# BIN-NEXT: - Index: 4 diff --git a/llvm/test/MC/WebAssembly/tail-call-encodings.s b/llvm/test/MC/WebAssembly/tail-call-encodings.s --- a/llvm/test/MC/WebAssembly/tail-call-encodings.s +++ b/llvm/test/MC/WebAssembly/tail-call-encodings.s @@ -16,7 +16,7 @@ foo2: .functype foo2 () -> () - # CHECK: return_call_indirect (i32) -> (i32) # encoding: [0x13, + # CHECK: return_call_indirect (i32) -> (i32), __indirect_function_table # encoding: [0x13, # CHECK-NEXT: fixup A - offset: 1, value: .Ltypeindex0@TYPEINDEX, kind: fixup_uleb128_i32 return_call_indirect (i32) -> (i32) diff --git a/llvm/test/MC/WebAssembly/type-index.s b/llvm/test/MC/WebAssembly/type-index.s --- a/llvm/test/MC/WebAssembly/type-index.s +++ b/llvm/test/MC/WebAssembly/type-index.s @@ -53,10 +53,13 @@ # BIN-NEXT: - Type: R_WASM_TYPE_INDEX_LEB # BIN-NEXT: Index: 1 # BIN-NEXT: Offset: 0x00000004 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 1 +# BIN-NEXT: Offset: 0x00000009 # BIN-NEXT: Functions: # BIN-NEXT: - Index: 0 # BIN-NEXT: Locals: [] -# BIN-NEXT: Body: 118180808000000B +# BIN-NEXT: Body: 1181808080008080808000000B # BIN-NEXT: - Type: CUSTOM # BIN-NEXT: Name: linking # BIN-NEXT: Version: 2 @@ -66,4 +69,9 @@ # BIN-NEXT: Name: test0 # BIN-NEXT: Flags: [ BINDING_LOCAL ] # BIN-NEXT: Function: 0 +# BIN-NEXT: - Index: 1 +# BIN-NEXT: Kind: TABLE +# BIN-NEXT: Name: __indirect_function_table +# BIN-NEXT: Flags: [ UNDEFINED ] +# BIN-NEXT: Table: 0 # BIN-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/wasm64.s b/llvm/test/MC/WebAssembly/wasm64.s --- a/llvm/test/MC/WebAssembly/wasm64.s +++ b/llvm/test/MC/WebAssembly/wasm64.s @@ -150,14 +150,6 @@ # BIN-NEXT: Flags: [ IS_64 ] # BIN-NEXT: Initial: 0x00000001 # BIN-NEXT: - Module: env -# BIN-NEXT: Field: __indirect_function_table -# BIN-NEXT: Kind: TABLE -# BIN-NEXT: Table: -# BIN-NEXT: Index: 0 -# BIN-NEXT: ElemType: FUNCREF -# BIN-NEXT: Limits: -# BIN-NEXT: Initial: 0x00000000 -# BIN-NEXT: - Module: env # BIN-NEXT: Field: myglob64 # BIN-NEXT: Kind: GLOBAL # BIN-NEXT: GlobalType: I64 diff --git a/llvm/test/MC/WebAssembly/weak-alias.s b/llvm/test/MC/WebAssembly/weak-alias.s --- a/llvm/test/MC/WebAssembly/weak-alias.s +++ b/llvm/test/MC/WebAssembly/weak-alias.s @@ -78,7 +78,7 @@ # CHECK: - Type: TYPE # CHECK-NEXT: Signatures: # CHECK-NEXT: - Index: 0 -# CHECK-NEXT: ParamTypes: +# CHECK-NEXT: ParamTypes: [] # CHECK-NEXT: ReturnTypes: # CHECK-NEXT: - I32 # CHECK-NEXT: - Type: IMPORT @@ -120,28 +120,34 @@ # CHECK-NEXT: - Type: R_WASM_TYPE_INDEX_LEB # CHECK-NEXT: Index: 0 # CHECK-NEXT: Offset: 0x00000024 +# CHECK-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# CHECK-NEXT: Index: 6 +# CHECK-NEXT: Offset: 0x00000029 # CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB -# CHECK-NEXT: Index: 7 -# CHECK-NEXT: Offset: 0x00000031 +# CHECK-NEXT: Index: 8 +# CHECK-NEXT: Offset: 0x00000036 # CHECK-NEXT: - Type: R_WASM_TYPE_INDEX_LEB # CHECK-NEXT: Index: 0 -# CHECK-NEXT: Offset: 0x00000037 +# CHECK-NEXT: Offset: 0x0000003C +# CHECK-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# CHECK-NEXT: Index: 6 +# CHECK-NEXT: Offset: 0x00000041 # CHECK-NEXT: Functions: # CHECK-NEXT: - Index: 0 -# CHECK-NEXT: Locals: +# CHECK-NEXT: Locals: [] # CHECK-NEXT: Body: 41000B # CHECK-NEXT: - Index: 1 -# CHECK-NEXT: Locals: +# CHECK-NEXT: Locals: [] # CHECK-NEXT: Body: 1080808080000B # CHECK-NEXT: - Index: 2 -# CHECK-NEXT: Locals: +# CHECK-NEXT: Locals: [] # CHECK-NEXT: Body: 1080808080000B # CHECK-NEXT: - Index: 3 -# CHECK-NEXT: Locals: -# CHECK-NEXT: Body: 410028028880808000118080808000000B +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 4100280288808080001180808080008080808000000B # CHECK-NEXT: - Index: 4 -# CHECK-NEXT: Locals: -# CHECK-NEXT: Body: 410028029080808000118080808000000B +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 4100280290808080001180808080008080808000000B # CHECK-NEXT: - Type: DATA # CHECK-NEXT: Relocations: # CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_I32 @@ -205,23 +211,28 @@ # CHECK-NEXT: Segment: 1 # CHECK-NEXT: Size: 4 # CHECK-NEXT: - Index: 6 +# CHECK-NEXT: Kind: TABLE +# CHECK-NEXT: Name: __indirect_function_table +# CHECK-NEXT: Flags: [ UNDEFINED ] +# CHECK-NEXT: Table: 0 +# CHECK-NEXT: - Index: 7 # CHECK-NEXT: Kind: FUNCTION # CHECK-NEXT: Name: call_alias_ptr # CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] # CHECK-NEXT: Function: 4 -# CHECK-NEXT: - Index: 7 +# CHECK-NEXT: - Index: 8 # CHECK-NEXT: Kind: DATA # CHECK-NEXT: Name: alias_address # CHECK-NEXT: Flags: [ ] # CHECK-NEXT: Segment: 2 # CHECK-NEXT: Size: 4 -# CHECK-NEXT: - Index: 8 +# CHECK-NEXT: - Index: 9 # CHECK-NEXT: Kind: DATA # CHECK-NEXT: Name: bar # CHECK-NEXT: Flags: [ ] # CHECK-NEXT: Segment: 0 # CHECK-NEXT: Size: 4 -# CHECK-NEXT: - Index: 9 +# CHECK-NEXT: - Index: 10 # CHECK-NEXT: Kind: DATA # CHECK-NEXT: Name: bar_alias # CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN, NO_STRIP ] @@ -231,15 +242,15 @@ # CHECK-NEXT: - Index: 0 # CHECK-NEXT: Name: .data.bar # CHECK-NEXT: Alignment: 3 -# CHECK-NEXT: Flags: [ ] +# CHECK-NEXT: Flags: [ ] # CHECK-NEXT: - Index: 1 # CHECK-NEXT: Name: .data.direct_address # CHECK-NEXT: Alignment: 3 -# CHECK-NEXT: Flags: [ ] +# CHECK-NEXT: Flags: [ ] # CHECK-NEXT: - Index: 2 # CHECK-NEXT: Name: .data.alias_address # CHECK-NEXT: Alignment: 3 -# CHECK-NEXT: Flags: [ ] +# CHECK-NEXT: Flags: [ ] # CHECK-NEXT: ... # CHECK-SYMS: SYMBOL TABLE: