Index: llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp =================================================================== --- llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp +++ llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp @@ -79,8 +79,8 @@ const Function &F = MF.getFunction(); MachineRegisterInfo &MRI = MF.getRegInfo(); const M68kTargetLowering &TLI = *getTLI(); - CCAssignFn *AssignFn = - TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg()); + CCAssignFn *AssignFn = TLI.getCCAssignFn(F.getCallingConv(), true, + F.isVarArg(), F.getReturnType()); auto &DL = F.getParent()->getDataLayout(); if (!VRegs.empty()) { SmallVector SplitArgs; @@ -115,8 +115,8 @@ ++I; } - CCAssignFn *AssignFn = - TLI.getCCAssignFn(F.getCallingConv(), false, F.isVarArg()); + CCAssignFn *AssignFn = TLI.getCCAssignFn(F.getCallingConv(), false, + F.isVarArg(), F.getReturnType()); IncomingValueAssigner ArgAssigner(AssignFn); FormalArgHandler ArgHandler(MIRBuilder, MRI); return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, @@ -196,7 +196,8 @@ .add(Info.Callee) .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); - CCAssignFn *AssignFn = TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg); + CCAssignFn *AssignFn = + TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg, nullptr); OutgoingValueAssigner Assigner(AssignFn); M68kOutgoingArgHandler Handler(MIRBuilder, MRI, MIB); if (!determineAndHandleAssignments(Handler, Assigner, OutArgs, MIRBuilder, @@ -212,7 +213,7 @@ if (!Info.OrigRet.Ty->isVoidTy()) { CCAssignFn *RetAssignFn = - TLI.getCCAssignFn(Info.CallConv, true, Info.IsVarArg); + TLI.getCCAssignFn(Info.CallConv, true, Info.IsVarArg, Info.OrigRet.Ty); OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn); CallReturnHandler Handler(MIRBuilder, MRI, MIB); Index: llvm/lib/Target/M68k/M68kCallingConv.td =================================================================== --- llvm/lib/Target/M68k/M68kCallingConv.td +++ llvm/lib/Target/M68k/M68kCallingConv.td @@ -31,6 +31,11 @@ CCIfType<[i32], CCAssignToReg<[D0, D1]>>, ]>; +def RetCC_M68k_C_PTRRET : CallingConv<[ + CCIfType<[i32], CCAssignToReg<[A0]>>, + CCDelegateTo +]>; + /// M68k fastcc return convention. /// This convention allows to return up to 16 bytes in registers which can be /// split among 16 1-byte values or used for a single 16-byte value. Index: llvm/lib/Target/M68k/M68kISelLowering.h =================================================================== --- llvm/lib/Target/M68k/M68kISelLowering.h +++ llvm/lib/Target/M68k/M68kISelLowering.h @@ -171,8 +171,8 @@ EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; - CCAssignFn *getCCAssignFn(CallingConv::ID CC, bool Return, - bool IsVarArg) const; + CCAssignFn *getCCAssignFn(CallingConv::ID CC, bool IsReturn, bool IsVarArg, + Type *ReturnType) const; AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const override; @@ -238,7 +238,7 @@ SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; - SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + SDValue LowerCallResult(CallLoweringInfo &CLI, SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl &Ins, const SDLoc &DL, SelectionDAG &DAG, Index: llvm/lib/Target/M68k/M68kISelLowering.cpp =================================================================== --- llvm/lib/Target/M68k/M68kISelLowering.cpp +++ llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -873,20 +873,24 @@ // Handle result values, copying them out of physregs into vregs that we // return. - return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, + return LowerCallResult(CLI, Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, InVals); } SDValue M68kTargetLowering::LowerCallResult( - SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, + CallLoweringInfo &CLI, SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl &InVals) const { + MachineFunction &MF = DAG.getMachineFunction(); // Assign locations to each value returned by this call. SmallVector RVLocs; CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, *DAG.getContext()); - CCInfo.AnalyzeCallResult(Ins, RetCC_M68k); + + CCInfo.AnalyzeCallResult( + Ins, getCCAssignFn(CallConv, /*IsReturn=*/true, IsVarArg, CLI.RetTy)); // Copy all of the result registers out of their specified physreg. for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { @@ -1066,7 +1070,9 @@ SmallVector RVLocs; CCState CCInfo(CCID, IsVarArg, MF, RVLocs, *DAG.getContext()); - CCInfo.AnalyzeReturn(Outs, RetCC_M68k); + + CCInfo.AnalyzeReturn(Outs, getCCAssignFn(CCID, /*IsReturn=*/true, IsVarArg, + MF.getFunction().getReturnType())); SDValue Flag; SmallVector RetOps; @@ -3567,10 +3573,11 @@ } } -CCAssignFn *M68kTargetLowering::getCCAssignFn(CallingConv::ID CC, bool Return, - bool IsVarArg) const { - if (Return) - return RetCC_M68k_C; - else - return CC_M68k_C; +CCAssignFn *M68kTargetLowering::getCCAssignFn(CallingConv::ID CC, bool IsReturn, + bool IsVarArg, + Type *ReturnType) const { + if (IsReturn) + return isa(ReturnType) ? RetCC_M68k_C_PTRRET : RetCC_M68k_C; + + return CC_M68k_C; } Index: llvm/test/CodeGen/M68k/CConv/ret-addr-reg.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M68k/CConv/ret-addr-reg.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=m68k -o - %s | FileCheck %s + + +define ptr @get_addr() { +; CHECK-LABEL: get_addr: +; CHECK: .cfi_startproc +; CHECK-NEXT: ; %bb.0: +; CHECK-NEXT: move.l #0, %a0 +; CHECK-NEXT: rts + ret ptr null +} + +define i32 @foo() { +; CHECK-LABEL: foo: +; CHECK: .cfi_startproc +; CHECK-NEXT: ; %bb.0: +; CHECK-NEXT: suba.l #4, %sp +; CHECK-NEXT: .cfi_def_cfa_offset -8 +; CHECK-NEXT: jsr get_addr@PLT +; CHECK-NEXT: move.l (%a0), %d0 +; CHECK-NEXT: adda.l #4, %sp +; CHECK-NEXT: rts + %call = call ptr @get_addr() + %1 = load i32, ptr %call, align 4 + ret i32 %1 +}