diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h @@ -44,6 +44,7 @@ bool getSymRef(SMLoc ErrorLoc, const MCInst &Inst, const MCSymbolRefExpr *&SymRef); bool getGlobal(SMLoc ErrorLoc, const MCInst &Inst, wasm::ValType &Type); + bool getTable(SMLoc ErrorLoc, const MCInst &Inst, wasm::ValType &Type); public: WebAssemblyAsmTypeCheck(MCAsmParser &Parser, const MCInstrInfo &MII, bool is64); diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp @@ -182,6 +182,20 @@ return false; } +bool WebAssemblyAsmTypeCheck::getTable(SMLoc ErrorLoc, const MCInst &Inst, + wasm::ValType &Type) { + const MCSymbolRefExpr *SymRef; + if (getSymRef(ErrorLoc, Inst, SymRef)) + return true; + auto WasmSym = cast(&SymRef->getSymbol()); + if (WasmSym->getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA) != + wasm::WASM_SYMBOL_TYPE_TABLE) + return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() + + " missing .tabletype"); + Type = static_cast(WasmSym->getTableType().ElemType); + return false; +} + bool WebAssemblyAsmTypeCheck::endOfFunction(SMLoc ErrorLoc) { // Check the return types. for (auto RVT : llvm::reverse(ReturnTypes)) { @@ -225,6 +239,19 @@ return true; if (popType(ErrorLoc, Type)) return true; + } else if (Name == "table.get") { + if (getTable(ErrorLoc, Inst, Type)) + return true; + if (popType(ErrorLoc, wasm::ValType::I32)) + return true; + Stack.push_back(Type); + } else if (Name == "table.set") { + if (getTable(ErrorLoc, Inst, Type)) + return true; + if (popType(ErrorLoc, Type)) + return true; + if (popType(ErrorLoc, wasm::ValType::I32)) + return true; } else if (Name == "drop") { if (popType(ErrorLoc, {})) return true; diff --git a/llvm/test/MC/WebAssembly/funcref-from-table.s b/llvm/test/MC/WebAssembly/funcref-from-table.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/WebAssembly/funcref-from-table.s @@ -0,0 +1,23 @@ +# RUN: llvm-mc -mattr=+reference-types -triple=wasm32-unknown-unknown -filetype=obj -o %t.o %s +# RUN: wasm-ld --no-entry --export obtain_funcref_from_table_index %t.o -o %t.wasm +# RUN: obj2yaml %t.wasm | FileCheck %s + +.globl __indirect_function_table +.tabletype __indirect_function_table, funcref + +.globl obtain_funcref_from_table_index + +obtain_funcref_from_table_index: + .functype obtain_funcref_from_table_index(i32) -> (funcref) + local.get 0 + table.get __indirect_function_table + end_function + +# CHECK: Sections: +# CHECK-NEXT: - Type: TYPE +# CHECK-NEXT: Signatures: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ParamTypes: +# CHECK-NEXT: - I32 +# CHECK-NEXT: ReturnTypes: +# CHECK-NEXT: - FUNCREF