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 {
M68kFormalArgHandler__anona60cc7670111::M68kFormalArgHandler315f757f3fSDimitry Andric M68kFormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
325f757f3fSDimitry Andric : M68kIncomingValueHandler(MIRBuilder, MRI) {}
335f757f3fSDimitry Andric };
345f757f3fSDimitry Andric
355f757f3fSDimitry Andric struct CallReturnHandler : public M68kIncomingValueHandler {
CallReturnHandler__anona60cc7670111::CallReturnHandler365f757f3fSDimitry 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
M68kCallLowering(const M68kTargetLowering & TLI)49349cc55cSDimitry Andric M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI)
50349cc55cSDimitry Andric : CallLowering(&TLI) {}
51349cc55cSDimitry Andric
5281ad6265SDimitry Andric struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler {
M68kOutgoingArgHandlerM68kOutgoingArgHandler5381ad6265SDimitry 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
assignValueToRegM68kOutgoingArgHandler59349cc55cSDimitry 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
assignValueToAddressM68kOutgoingArgHandler66349cc55cSDimitry 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
getStackAddressM68kOutgoingArgHandler77349cc55cSDimitry 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 };
lowerReturn(MachineIRBuilder & MIRBuilder,const Value * Val,ArrayRef<Register> VRegs,FunctionLoweringInfo & FLI,Register SwiftErrorVReg) const93349cc55cSDimitry 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
lowerFormalArguments(MachineIRBuilder & MIRBuilder,const Function & F,ArrayRef<ArrayRef<Register>> VRegs,FunctionLoweringInfo & FLI) const122349cc55cSDimitry 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
assignValueToReg(Register ValVReg,Register PhysReg,const CCValAssign & VA)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
assignValueToAddress(Register ValVReg,Register Addr,LLT MemTy,const MachinePointerInfo & MPO,const CCValAssign & VA)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
getStackAddress(uint64_t Size,int64_t Offset,MachinePointerInfo & MPO,ISD::ArgFlagsTy Flags)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
assignValueToReg(Register ValVReg,Register PhysReg,const CCValAssign & VA)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
lowerCall(MachineIRBuilder & MIRBuilder,CallLoweringInfo & Info) const189349cc55cSDimitry 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
enableBigEndian() const252349cc55cSDimitry Andric bool M68kCallLowering::enableBigEndian() const { return true; }
253