[M68k] Override `CanLowerReturn` to fix assertion with large return
authorIan Douglas Scott <ian@iandouglasscott.com>
Sat, 22 Apr 2023 19:01:28 +0000 (12:01 -0700)
committerMin-Yih Hsu <minyihh@uci.edu>
Sat, 22 Apr 2023 19:23:04 +0000 (12:23 -0700)
If it couldn't fit the return value in two registers, this caused an
error during codegen. It seems this method is implemented in other
backends but not here, and allows it to pass return values in memory
when it isn't able to do so in registers.

Seems to fix compilation of Rust code with certain return types:
https://github.com/rust-lang/rust/issues/89498

Differential Revision: https://reviews.llvm.org/D148856

llvm/lib/Target/M68k/M68kISelLowering.cpp
llvm/lib/Target/M68k/M68kISelLowering.h
llvm/test/CodeGen/M68k/multiple-return.ll [new file with mode: 0644]

index 0ee3a07e15f43cf83ba6ba3921bc0252edecae87..c37ec304bf1983a31797870362b24e1e1dc71d41 100644 (file)
@@ -1058,6 +1058,14 @@ SDValue M68kTargetLowering::LowerFormalArguments(
 //              Return Value Calling Convention Implementation
 //===----------------------------------------------------------------------===//
 
+bool M68kTargetLowering::CanLowerReturn(
+    CallingConv::ID CCID, MachineFunction &MF, bool IsVarArg,
+    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
+  SmallVector<CCValAssign, 16> RVLocs;
+  CCState CCInfo(CCID, IsVarArg, MF, RVLocs, Context);
+  return CCInfo.CheckReturn(Outs, RetCC_M68k);
+}
+
 SDValue
 M68kTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CCID,
                                 bool IsVarArg,
index f9037e7ff49734c3ded513f5aa2904e78a5de35b..d43160fe48d2e2c233ad524ee9f9dda22cf6e7d1 100644 (file)
@@ -257,6 +257,11 @@ private:
   SDValue LowerCall(CallLoweringInfo &CLI,
                     SmallVectorImpl<SDValue> &InVals) const override;
 
+  bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+                      bool isVarArg,
+                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      LLVMContext &Context) const override;
+
   /// Lower the result values of a call into the
   /// appropriate copies out of appropriate physical registers.
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CCID, bool IsVarArg,
diff --git a/llvm/test/CodeGen/M68k/multiple-return.ll b/llvm/test/CodeGen/M68k/multiple-return.ll
new file mode 100644 (file)
index 0000000..f52f422
--- /dev/null
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=m68k-linux -verify-machineinstrs | FileCheck %s
+
+define { i32, i32, i32, i32 } @test() {
+; CHECK-LABEL: test:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0: ; %start
+; CHECK-NEXT:    move.l (4,%sp), %a0
+; CHECK-NEXT:    move.l #23, (12,%a0)
+; CHECK-NEXT:    move.l #19, (8,%a0)
+; CHECK-NEXT:    move.l #17, (4,%a0)
+; CHECK-NEXT:    move.l #13, (%a0)
+; CHECK-NEXT:    move.l %a0, %d0
+; CHECK-NEXT:    move.l (%sp), %a1
+; CHECK-NEXT:    adda.l #4, %sp
+; CHECK-NEXT:    move.l %a1, (%sp)
+; CHECK-NEXT:    rts
+start:
+  ret { i32, i32, i32, i32 } { i32 13, i32 17, i32 19, i32 23 }
+}