[WebAssembly] Fix Fast ISEL not lowering 64-bit function pointers
authorWouter van Oortmerssen <aardappel@gmail.com>
Tue, 26 Jan 2021 00:49:09 +0000 (16:49 -0800)
committerWouter van Oortmerssen <aardappel@gmail.com>
Thu, 28 Jan 2021 18:05:29 +0000 (10:05 -0800)
Differential Revision: https://reviews.llvm.org/D95410

llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
llvm/test/CodeGen/WebAssembly/fast-isel-call-indirect64.ll [new file with mode: 0644]

index 82b0322..509f2be 100644 (file)
@@ -881,6 +881,19 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
     // it as NO_STRIP so as to ensure that the indirect function table makes it
     // to linked output.
     Sym->setNoStrip();
+
+    // See if we must truncate the function pointer.
+    // CALL_INDIRECT takes an i32, but in wasm64 we represent function pointers
+    // as 64-bit for uniformity with other pointer types.
+    // See also: WebAssemblyISelLowering.cpp: LowerCallResults
+    if (Subtarget->hasAddr64()) {
+      auto Wrap = BuildMI(*FuncInfo.MBB, std::prev(FuncInfo.InsertPt), DbgLoc,
+                          TII.get(WebAssembly::I32_WRAP_I64));
+      unsigned Reg32 = createResultReg(&WebAssembly::I32RegClass);
+      Wrap.addReg(Reg32, RegState::Define);
+      Wrap.addReg(CalleeReg);
+      CalleeReg = Reg32;
+    }
   }
 
   for (unsigned ArgReg : Args)
index e348bba..5eee013 100644 (file)
@@ -455,6 +455,7 @@ static MachineBasicBlock *LowerCallResults(MachineInstr &CallResults,
   // See if we must truncate the function pointer.
   // CALL_INDIRECT takes an i32, but in wasm64 we represent function pointers
   // as 64-bit for uniformity with other pointer types.
+  // See also: WebAssemblyFastISel::selectCall
   if (IsIndirect && MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()) {
     Register Reg32 =
         MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass);
diff --git a/llvm/test/CodeGen/WebAssembly/fast-isel-call-indirect64.ll b/llvm/test/CodeGen/WebAssembly/fast-isel-call-indirect64.ll
new file mode 100644 (file)
index 0000000..f82b05f
--- /dev/null
@@ -0,0 +1,15 @@
+; RUN: llc < %s -fast-isel --mtriple=wasm64 -asm-verbose=false -wasm-keep-registers | FileCheck %s
+
+target datalayout = "e-m:e-p:64:64-i64:64-n32:64-S128"
+target triple = "wasm64"
+
+; Ensure fast isel also lowers function pointers to 32-bit.
+
+; CHECK:       local.get $push[[L0:[0-9]+]]=, 0
+; CHECK-NEXT:  i32.wrap_i64 $push[[L1:[0-9]+]]=, $pop[[L0]]
+; CHECK-NEXT:  call_indirect $pop[[L1]]
+
+define hidden void @f(void ()* %g) {
+  call void %g()
+  ret void
+}