104eeddc0SDimitry Andric //===-- M68kCallLowering.cpp - Call lowering --------------------*- C++ -*-===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // 9349cc55cSDimitry Andric /// \file 10349cc55cSDimitry Andric /// This file implements the lowering of LLVM calls to machine code calls for 11349cc55cSDimitry Andric /// GlobalISel. 12349cc55cSDimitry Andric // 13349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 14349cc55cSDimitry Andric 15349cc55cSDimitry Andric #include "M68kCallLowering.h" 16349cc55cSDimitry Andric #include "M68kISelLowering.h" 17349cc55cSDimitry Andric #include "M68kInstrInfo.h" 18349cc55cSDimitry Andric #include "M68kSubtarget.h" 19349cc55cSDimitry Andric #include "M68kTargetMachine.h" 20349cc55cSDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 21349cc55cSDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h" 22349cc55cSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 2381ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 24349cc55cSDimitry Andric #include "llvm/CodeGen/TargetCallingConv.h" 25349cc55cSDimitry Andric 26349cc55cSDimitry Andric using namespace llvm; 27349cc55cSDimitry Andric 285f757f3fSDimitry Andric namespace { 295f757f3fSDimitry Andric 305f757f3fSDimitry Andric struct M68kFormalArgHandler : public M68kIncomingValueHandler { 315f757f3fSDimitry Andric M68kFormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 325f757f3fSDimitry Andric : M68kIncomingValueHandler(MIRBuilder, MRI) {} 335f757f3fSDimitry Andric }; 345f757f3fSDimitry Andric 355f757f3fSDimitry Andric struct CallReturnHandler : public M68kIncomingValueHandler { 365f757f3fSDimitry Andric CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 375f757f3fSDimitry Andric MachineInstrBuilder &MIB) 385f757f3fSDimitry Andric : M68kIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} 395f757f3fSDimitry Andric 405f757f3fSDimitry Andric private: 415f757f3fSDimitry Andric void assignValueToReg(Register ValVReg, Register PhysReg, 425f757f3fSDimitry Andric const CCValAssign &VA) override; 435f757f3fSDimitry Andric 445f757f3fSDimitry Andric MachineInstrBuilder &MIB; 455f757f3fSDimitry Andric }; 465f757f3fSDimitry Andric 475f757f3fSDimitry Andric } // end anonymous namespace 485f757f3fSDimitry Andric 49349cc55cSDimitry Andric M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI) 50349cc55cSDimitry Andric : CallLowering(&TLI) {} 51349cc55cSDimitry Andric 5281ad6265SDimitry Andric struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler { 5381ad6265SDimitry Andric M68kOutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 54349cc55cSDimitry Andric MachineInstrBuilder MIB) 5581ad6265SDimitry Andric : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB), 5681ad6265SDimitry Andric DL(MIRBuilder.getMF().getDataLayout()), 5781ad6265SDimitry Andric STI(MIRBuilder.getMF().getSubtarget<M68kSubtarget>()) {} 58349cc55cSDimitry Andric 59349cc55cSDimitry Andric void assignValueToReg(Register ValVReg, Register PhysReg, 605f757f3fSDimitry Andric const CCValAssign &VA) override { 61349cc55cSDimitry Andric MIB.addUse(PhysReg, RegState::Implicit); 62349cc55cSDimitry Andric Register ExtReg = extendRegister(ValVReg, VA); 63349cc55cSDimitry Andric MIRBuilder.buildCopy(PhysReg, ExtReg); 64349cc55cSDimitry Andric } 65349cc55cSDimitry Andric 66349cc55cSDimitry Andric void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, 675f757f3fSDimitry Andric const MachinePointerInfo &MPO, 685f757f3fSDimitry Andric const CCValAssign &VA) override { 6981ad6265SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 7081ad6265SDimitry Andric Register ExtReg = extendRegister(ValVReg, VA); 7181ad6265SDimitry Andric 7281ad6265SDimitry Andric auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy, 7381ad6265SDimitry Andric inferAlignFromPtrInfo(MF, MPO)); 7481ad6265SDimitry Andric MIRBuilder.buildStore(ExtReg, Addr, *MMO); 75349cc55cSDimitry Andric } 76349cc55cSDimitry Andric 77349cc55cSDimitry Andric Register getStackAddress(uint64_t Size, int64_t Offset, 78349cc55cSDimitry Andric MachinePointerInfo &MPO, 79349cc55cSDimitry Andric ISD::ArgFlagsTy Flags) override { 8081ad6265SDimitry Andric LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0)); 8181ad6265SDimitry Andric LLT SType = LLT::scalar(DL.getPointerSizeInBits(0)); 8281ad6265SDimitry Andric Register StackReg = STI.getRegisterInfo()->getStackRegister(); 8381ad6265SDimitry Andric auto SPReg = MIRBuilder.buildCopy(p0, StackReg).getReg(0); 8481ad6265SDimitry Andric auto OffsetReg = MIRBuilder.buildConstant(SType, Offset); 8581ad6265SDimitry Andric auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg); 8681ad6265SDimitry Andric MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); 8781ad6265SDimitry Andric return AddrReg.getReg(0); 88349cc55cSDimitry Andric } 89349cc55cSDimitry Andric MachineInstrBuilder MIB; 9081ad6265SDimitry Andric const DataLayout &DL; 9181ad6265SDimitry Andric const M68kSubtarget &STI; 92349cc55cSDimitry Andric }; 93349cc55cSDimitry Andric bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 94349cc55cSDimitry Andric const Value *Val, ArrayRef<Register> VRegs, 95349cc55cSDimitry Andric FunctionLoweringInfo &FLI, 96349cc55cSDimitry Andric Register SwiftErrorVReg) const { 97349cc55cSDimitry Andric 98349cc55cSDimitry Andric auto MIB = MIRBuilder.buildInstrNoInsert(M68k::RTS); 99349cc55cSDimitry Andric bool Success = true; 100349cc55cSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 101349cc55cSDimitry Andric const Function &F = MF.getFunction(); 102349cc55cSDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 103349cc55cSDimitry Andric const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>(); 104349cc55cSDimitry Andric CCAssignFn *AssignFn = 105349cc55cSDimitry Andric TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg()); 106*0fca6ea1SDimitry Andric auto &DL = F.getDataLayout(); 107349cc55cSDimitry Andric if (!VRegs.empty()) { 108349cc55cSDimitry Andric SmallVector<ArgInfo, 8> SplitArgs; 109349cc55cSDimitry Andric ArgInfo OrigArg{VRegs, Val->getType(), 0}; 110349cc55cSDimitry Andric setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); 111349cc55cSDimitry Andric splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); 112349cc55cSDimitry Andric OutgoingValueAssigner ArgAssigner(AssignFn); 11381ad6265SDimitry Andric M68kOutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB); 114349cc55cSDimitry Andric Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, 115349cc55cSDimitry Andric MIRBuilder, F.getCallingConv(), 116349cc55cSDimitry Andric F.isVarArg()); 117349cc55cSDimitry Andric } 118349cc55cSDimitry Andric MIRBuilder.insertInstr(MIB); 119349cc55cSDimitry Andric return Success; 120349cc55cSDimitry Andric } 121349cc55cSDimitry Andric 122349cc55cSDimitry Andric bool M68kCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 123349cc55cSDimitry Andric const Function &F, 124349cc55cSDimitry Andric ArrayRef<ArrayRef<Register>> VRegs, 125349cc55cSDimitry Andric FunctionLoweringInfo &FLI) const { 126349cc55cSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 127349cc55cSDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 128*0fca6ea1SDimitry Andric const auto &DL = F.getDataLayout(); 129349cc55cSDimitry Andric auto &TLI = *getTLI<M68kTargetLowering>(); 130349cc55cSDimitry Andric 131349cc55cSDimitry Andric SmallVector<ArgInfo, 8> SplitArgs; 132349cc55cSDimitry Andric unsigned I = 0; 133349cc55cSDimitry Andric for (const auto &Arg : F.args()) { 134349cc55cSDimitry Andric ArgInfo OrigArg{VRegs[I], Arg.getType(), I}; 135349cc55cSDimitry Andric setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F); 136349cc55cSDimitry Andric splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); 137349cc55cSDimitry Andric ++I; 138349cc55cSDimitry Andric } 139349cc55cSDimitry Andric 140349cc55cSDimitry Andric CCAssignFn *AssignFn = 141349cc55cSDimitry Andric TLI.getCCAssignFn(F.getCallingConv(), false, F.isVarArg()); 142349cc55cSDimitry Andric IncomingValueAssigner ArgAssigner(AssignFn); 1435f757f3fSDimitry Andric M68kFormalArgHandler ArgHandler(MIRBuilder, MRI); 144349cc55cSDimitry Andric return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, 145349cc55cSDimitry Andric MIRBuilder, F.getCallingConv(), 146349cc55cSDimitry Andric F.isVarArg()); 147349cc55cSDimitry Andric } 148349cc55cSDimitry Andric 149349cc55cSDimitry Andric void M68kIncomingValueHandler::assignValueToReg(Register ValVReg, 150349cc55cSDimitry Andric Register PhysReg, 1515f757f3fSDimitry Andric const CCValAssign &VA) { 152349cc55cSDimitry Andric MIRBuilder.getMRI()->addLiveIn(PhysReg); 153349cc55cSDimitry Andric MIRBuilder.getMBB().addLiveIn(PhysReg); 154349cc55cSDimitry Andric IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); 155349cc55cSDimitry Andric } 156349cc55cSDimitry Andric 1575f757f3fSDimitry Andric void M68kIncomingValueHandler::assignValueToAddress( 1585f757f3fSDimitry Andric Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO, 1595f757f3fSDimitry Andric const CCValAssign &VA) { 160349cc55cSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 161349cc55cSDimitry Andric auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy, 162349cc55cSDimitry Andric inferAlignFromPtrInfo(MF, MPO)); 163349cc55cSDimitry Andric MIRBuilder.buildLoad(ValVReg, Addr, *MMO); 164349cc55cSDimitry Andric } 165349cc55cSDimitry Andric 166349cc55cSDimitry Andric Register M68kIncomingValueHandler::getStackAddress(uint64_t Size, 167349cc55cSDimitry Andric int64_t Offset, 168349cc55cSDimitry Andric MachinePointerInfo &MPO, 169349cc55cSDimitry Andric ISD::ArgFlagsTy Flags) { 170349cc55cSDimitry Andric auto &MFI = MIRBuilder.getMF().getFrameInfo(); 171349cc55cSDimitry Andric const bool IsImmutable = !Flags.isByVal(); 172349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable); 173349cc55cSDimitry Andric MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 174349cc55cSDimitry Andric 175349cc55cSDimitry Andric // Build Frame Index 176349cc55cSDimitry Andric llvm::LLT FramePtr = LLT::pointer( 177349cc55cSDimitry Andric 0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits()); 178349cc55cSDimitry Andric MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI); 179349cc55cSDimitry Andric StackUsed = std::max(StackUsed, Size + Offset); 180349cc55cSDimitry Andric return AddrReg.getReg(0); 181349cc55cSDimitry Andric } 182349cc55cSDimitry Andric 18381ad6265SDimitry Andric void CallReturnHandler::assignValueToReg(Register ValVReg, Register PhysReg, 1845f757f3fSDimitry Andric const CCValAssign &VA) { 18581ad6265SDimitry Andric MIB.addDef(PhysReg, RegState::Implicit); 18681ad6265SDimitry Andric MIRBuilder.buildCopy(ValVReg, PhysReg); 18781ad6265SDimitry Andric } 18881ad6265SDimitry Andric 189349cc55cSDimitry Andric bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 190349cc55cSDimitry Andric CallLoweringInfo &Info) const { 19181ad6265SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 19281ad6265SDimitry Andric Function &F = MF.getFunction(); 19381ad6265SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 194*0fca6ea1SDimitry Andric auto &DL = F.getDataLayout(); 19581ad6265SDimitry Andric const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>(); 19681ad6265SDimitry Andric const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>(); 19781ad6265SDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 19881ad6265SDimitry Andric const M68kRegisterInfo *TRI = STI.getRegisterInfo(); 19981ad6265SDimitry Andric 20081ad6265SDimitry Andric SmallVector<ArgInfo, 8> OutArgs; 20181ad6265SDimitry Andric for (auto &OrigArg : Info.OrigArgs) 20281ad6265SDimitry Andric splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv); 20381ad6265SDimitry Andric 20481ad6265SDimitry Andric SmallVector<ArgInfo, 8> InArgs; 20581ad6265SDimitry Andric if (!Info.OrigRet.Ty->isVoidTy()) 20681ad6265SDimitry Andric splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv); 20781ad6265SDimitry Andric 20881ad6265SDimitry Andric unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); 20981ad6265SDimitry Andric auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown); 21081ad6265SDimitry Andric 21181ad6265SDimitry Andric unsigned Opc = TLI.getTargetMachine().isPositionIndependent() ? M68k::CALLq 21281ad6265SDimitry Andric : Info.Callee.isReg() ? M68k::CALLj 21381ad6265SDimitry Andric : M68k::CALLb; 21481ad6265SDimitry Andric 21581ad6265SDimitry Andric auto MIB = MIRBuilder.buildInstrNoInsert(Opc) 21681ad6265SDimitry Andric .add(Info.Callee) 21781ad6265SDimitry Andric .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); 21881ad6265SDimitry Andric 21981ad6265SDimitry Andric CCAssignFn *AssignFn = TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg); 22081ad6265SDimitry Andric OutgoingValueAssigner Assigner(AssignFn); 22181ad6265SDimitry Andric M68kOutgoingArgHandler Handler(MIRBuilder, MRI, MIB); 22281ad6265SDimitry Andric if (!determineAndHandleAssignments(Handler, Assigner, OutArgs, MIRBuilder, 22381ad6265SDimitry Andric Info.CallConv, Info.IsVarArg)) 224349cc55cSDimitry Andric return false; 22581ad6265SDimitry Andric 22681ad6265SDimitry Andric if (Info.Callee.isReg()) 22781ad6265SDimitry Andric constrainOperandRegClass(MF, *TRI, MRI, *STI.getInstrInfo(), 22881ad6265SDimitry Andric *STI.getRegBankInfo(), *MIB, MIB->getDesc(), 22981ad6265SDimitry Andric Info.Callee, 0); 23081ad6265SDimitry Andric 23181ad6265SDimitry Andric MIRBuilder.insertInstr(MIB); 23281ad6265SDimitry Andric 23381ad6265SDimitry Andric if (!Info.OrigRet.Ty->isVoidTy()) { 23481ad6265SDimitry Andric CCAssignFn *RetAssignFn = 23581ad6265SDimitry Andric TLI.getCCAssignFn(Info.CallConv, true, Info.IsVarArg); 23681ad6265SDimitry Andric 23781ad6265SDimitry Andric OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn); 23881ad6265SDimitry Andric CallReturnHandler Handler(MIRBuilder, MRI, MIB); 23981ad6265SDimitry Andric if (!determineAndHandleAssignments(Handler, Assigner, InArgs, MIRBuilder, 24081ad6265SDimitry Andric Info.CallConv, Info.IsVarArg)) 24181ad6265SDimitry Andric return false; 24281ad6265SDimitry Andric } 24381ad6265SDimitry Andric 24406c3fb27SDimitry Andric CallSeqStart.addImm(Assigner.StackSize).addImm(0); 24581ad6265SDimitry Andric 24681ad6265SDimitry Andric unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); 24706c3fb27SDimitry Andric MIRBuilder.buildInstr(AdjStackUp).addImm(Assigner.StackSize).addImm(0); 24881ad6265SDimitry Andric 24981ad6265SDimitry Andric return true; 250349cc55cSDimitry Andric } 251349cc55cSDimitry Andric 252349cc55cSDimitry Andric bool M68kCallLowering::enableBigEndian() const { return true; } 253