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 @@ -14,6 +14,7 @@ #include "WebAssemblyISelLowering.h" #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "Utils/WebAssemblyUtilities.h" +#include "Utils/WebAssemblyTypeUtilities.h" #include "WebAssemblyMachineFunctionInfo.h" #include "WebAssemblySubtarget.h" #include "WebAssemblyTargetMachine.h" @@ -559,15 +560,21 @@ // slot with ref.null upon call_indirect return. if (IsIndirect && IsFuncrefCall) { MCSymbolWasm *Table = WebAssembly::getOrCreateFuncrefCallTableSymbol(MF.getContext(), Subtarget); + Register RegZero = + MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass); + MachineInstr *Const0 = BuildMI(MF, DL, TII.get(WebAssembly::CONST_I32), RegZero) + .addImm(0); + BB->insertAfter(MIB.getInstr()->getIterator(), Const0); + Register RegFuncref = MF.getRegInfo().createVirtualRegister(&WebAssembly::FUNCREFRegClass); - MachineInstrBuilder RefNull(MF, MF.CreateMachineInstr(TII.get(WebAssembly::REF_NULL_FUNCREF), DL)); - RefNull.addReg(RegFuncref); - BB->insert(MIB.getInstr()->getIterator(), RefNull); + MachineInstr *RefNull = BuildMI(MF, DL, TII.get(WebAssembly::REF_NULL_FUNCREF), RegFuncref) + .addImm(static_cast(WebAssembly::HeapType::Funcref)); + BB->insertAfter(Const0->getIterator(), RefNull); - MachineInstrBuilder TableSet(MF, MF.CreateMachineInstr(TII.get(WebAssembly::TABLE_SET_FUNCREF), DL)); - TableSet.addSym(Table).addReg(RegFuncref).addImm(0); - BB->insert(RefNull.getInstr()->getIterator(), TableSet); + MachineInstr *TableSet = BuildMI(MF, DL, TII.get(WebAssembly::TABLE_SET_FUNCREF)) + .addSym(Table).addReg(RegZero).addReg(RegFuncref); + BB->insertAfter(RefNull->getIterator(), TableSet); } return BB; @@ -1113,7 +1120,7 @@ MF.getContext(), Subtarget); SDValue Sym = DAG.getMCSymbol(Table, PtrVT); SDValue TableSlot = DAG.getConstant(0, DL, MVT::i32); - SDValue TableSetOps[] = {Chain, Sym, Callee, TableSlot}; + SDValue TableSetOps[] = {Chain, Sym, TableSlot, Callee}; SDValue TableSet = DAG.getMemIntrinsicNode( WebAssemblyISD::TABLE_SET, DL, DAG.getVTList(MVT::Other), TableSetOps, MVT::funcref, diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td @@ -51,11 +51,11 @@ def wasm_table_set : SDNode<"WebAssemblyISD::TABLE_SET", wasm_table_set_t, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def : Pat<(wasm_table_set i32:$table, funcref:$r, i32:$idx), - (TABLE_SET_FUNCREF i32:$table, funcref:$r, i32:$idx)>, +def : Pat<(wasm_table_set i32:$table, i32:$idx, funcref:$r), + (TABLE_SET_FUNCREF i32:$table, i32:$idx, funcref:$r)>, Requires<[HasReferenceTypes]>; -def : Pat<(wasm_table_set i32:$table, externref:$r, i32:$idx), - (TABLE_SET_EXTERNREF i32:$table, externref:$r, i32:$idx)>, +def : Pat<(wasm_table_set i32:$table, i32:$idx, externref:$r), + (TABLE_SET_EXTERNREF i32:$table, i32:$idx, externref:$r)>, Requires<[HasReferenceTypes]>; defm TABLE_SIZE : I<(outs I32:$sz), (ins table32_op:$table), diff --git a/llvm/test/CodeGen/WebAssembly/funcref-call.ll b/llvm/test/CodeGen/WebAssembly/funcref-call.ll --- a/llvm/test/CodeGen/WebAssembly/funcref-call.ll +++ b/llvm/test/CodeGen/WebAssembly/funcref-call.ll @@ -10,11 +10,14 @@ ; CHECK-LABEL: call_funcref: ; CHECK-NEXT: functype call_funcref (funcref) -> () -; CHECK-NEXT: local.get 0 ; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.get 0 ; CHECK-NEXT: table.set __funcref_call_table ; CHECK-NEXT: local.get 0 ; CHECK-NEXT: call_indirect __funcref_call_table, () -> () +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: ref.null func +; CHECK-NEXT: table.set __funcref_call_table ; CHECK-NEXT: end_function ; CHECK: .tabletype __funcref_call_table, funcref