blob: 34b816819489237c2e17ef5fbdfe72e19797c564 [file] [log] [blame]
Diana Picus22274932016-11-11 08:27:37 +00001//===-- llvm/lib/Target/ARM/ARMCallLowering.cpp - Call lowering -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// This file implements the lowering of LLVM calls to machine code calls for
12/// GlobalISel.
13///
14//===----------------------------------------------------------------------===//
15
16#include "ARMCallLowering.h"
17
18#include "ARMBaseInstrInfo.h"
19#include "ARMISelLowering.h"
Diana Picus1d8eaf42017-01-25 07:08:53 +000020#include "ARMSubtarget.h"
Diana Picus22274932016-11-11 08:27:37 +000021
Diana Picus32cd9b42017-02-02 14:01:00 +000022#include "llvm/CodeGen/Analysis.h"
Diana Picus22274932016-11-11 08:27:37 +000023#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
Diana Picus1437f6d2016-12-19 11:55:41 +000024#include "llvm/CodeGen/MachineRegisterInfo.h"
Diana Picus22274932016-11-11 08:27:37 +000025
26using namespace llvm;
27
28#ifndef LLVM_BUILD_GLOBAL_ISEL
29#error "This shouldn't be built without GISel"
30#endif
31
32ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI)
33 : CallLowering(&TLI) {}
34
Benjamin Kramer061f4a52017-01-13 14:39:03 +000035static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI,
Diana Picus812caee2016-12-16 12:54:46 +000036 Type *T) {
Diana Picus0c11c7b2017-02-02 14:00:54 +000037 EVT VT = TLI.getValueType(DL, T, true);
Diana Picus7232af32017-02-09 13:09:59 +000038 if (!VT.isSimple() || VT.isVector())
Diana Picus97ae95c2016-12-19 14:08:02 +000039 return false;
40
41 unsigned VTSize = VT.getSimpleVT().getSizeInBits();
Diana Picusd83df5d2017-01-25 08:47:40 +000042 return VTSize == 1 || VTSize == 8 || VTSize == 16 || VTSize == 32;
Diana Picus812caee2016-12-16 12:54:46 +000043}
44
45namespace {
46struct FuncReturnHandler : public CallLowering::ValueHandler {
47 FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
Tim Northoverd9433542017-01-17 22:30:10 +000048 MachineInstrBuilder &MIB, CCAssignFn *AssignFn)
49 : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
Diana Picus812caee2016-12-16 12:54:46 +000050
51 unsigned getStackAddress(uint64_t Size, int64_t Offset,
52 MachinePointerInfo &MPO) override {
53 llvm_unreachable("Don't know how to get a stack address yet");
54 }
55
56 void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
57 CCValAssign &VA) override {
58 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
59 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
60
Diana Picus97ae95c2016-12-19 14:08:02 +000061 assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size");
Diana Picus812caee2016-12-16 12:54:46 +000062 assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size");
63
Diana Picus8b6c6be2017-01-25 08:10:40 +000064 unsigned ExtReg = extendRegister(ValVReg, VA);
65 MIRBuilder.buildCopy(PhysReg, ExtReg);
Diana Picus812caee2016-12-16 12:54:46 +000066 MIB.addUse(PhysReg, RegState::Implicit);
67 }
68
69 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
70 MachinePointerInfo &MPO, CCValAssign &VA) override {
71 llvm_unreachable("Don't know how to assign a value to an address yet");
72 }
73
74 MachineInstrBuilder &MIB;
75};
76} // End anonymous namespace.
77
Diana Picus32cd9b42017-02-02 14:01:00 +000078void ARMCallLowering::splitToValueTypes(const ArgInfo &OrigArg,
79 SmallVectorImpl<ArgInfo> &SplitArgs,
80 const DataLayout &DL,
81 MachineRegisterInfo &MRI) const {
82 const ARMTargetLowering &TLI = *getTLI<ARMTargetLowering>();
83 LLVMContext &Ctx = OrigArg.Ty->getContext();
84
85 SmallVector<EVT, 4> SplitVTs;
86 SmallVector<uint64_t, 4> Offsets;
87 ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0);
88
89 assert(SplitVTs.size() == 1 && "Unsupported type");
90
91 // Even if there is no splitting to do, we still want to replace the original
92 // type (e.g. pointer type -> integer).
93 SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx),
94 OrigArg.Flags, OrigArg.IsFixed);
95}
96
Diana Picus812caee2016-12-16 12:54:46 +000097/// Lower the return value for the already existing \p Ret. This assumes that
98/// \p MIRBuilder's insertion point is correct.
99bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
100 const Value *Val, unsigned VReg,
101 MachineInstrBuilder &Ret) const {
102 if (!Val)
103 // Nothing to do here.
104 return true;
105
106 auto &MF = MIRBuilder.getMF();
107 const auto &F = *MF.getFunction();
108
109 auto DL = MF.getDataLayout();
110 auto &TLI = *getTLI<ARMTargetLowering>();
111 if (!isSupportedType(DL, TLI, Val->getType()))
Diana Picus22274932016-11-11 08:27:37 +0000112 return false;
113
Diana Picus32cd9b42017-02-02 14:01:00 +0000114 SmallVector<ArgInfo, 4> SplitVTs;
115 ArgInfo RetInfo(VReg, Val->getType());
116 setArgFlags(RetInfo, AttributeSet::ReturnIndex, DL, F);
117 splitToValueTypes(RetInfo, SplitVTs, DL, MF.getRegInfo());
118
Diana Picus812caee2016-12-16 12:54:46 +0000119 CCAssignFn *AssignFn =
120 TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg());
Diana Picus22274932016-11-11 08:27:37 +0000121
Tim Northoverd9433542017-01-17 22:30:10 +0000122 FuncReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret, AssignFn);
Diana Picus32cd9b42017-02-02 14:01:00 +0000123 return handleAssignments(MIRBuilder, SplitVTs, RetHandler);
Diana Picus812caee2016-12-16 12:54:46 +0000124}
125
126bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
127 const Value *Val, unsigned VReg) const {
128 assert(!Val == !VReg && "Return value without a vreg");
129
Diana Picus4f8c3e12017-01-13 09:37:56 +0000130 auto Ret = MIRBuilder.buildInstrNoInsert(ARM::BX_RET).add(predOps(ARMCC::AL));
Diana Picus812caee2016-12-16 12:54:46 +0000131
132 if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret))
133 return false;
134
135 MIRBuilder.insertInstr(Ret);
Diana Picus22274932016-11-11 08:27:37 +0000136 return true;
137}
138
Diana Picus812caee2016-12-16 12:54:46 +0000139namespace {
140struct FormalArgHandler : public CallLowering::ValueHandler {
Tim Northoverd9433542017-01-17 22:30:10 +0000141 FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
142 CCAssignFn AssignFn)
143 : ValueHandler(MIRBuilder, MRI, AssignFn) {}
Diana Picus812caee2016-12-16 12:54:46 +0000144
145 unsigned getStackAddress(uint64_t Size, int64_t Offset,
146 MachinePointerInfo &MPO) override {
Diana Picus278c7222017-01-26 09:20:47 +0000147 assert((Size == 1 || Size == 2 || Size == 4) && "Unsupported size");
Diana Picus1437f6d2016-12-19 11:55:41 +0000148
149 auto &MFI = MIRBuilder.getMF().getFrameInfo();
150
151 int FI = MFI.CreateFixedObject(Size, Offset, true);
152 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
153
154 unsigned AddrReg =
155 MRI.createGenericVirtualRegister(LLT::pointer(MPO.getAddrSpace(), 32));
156 MIRBuilder.buildFrameIndex(AddrReg, FI);
157
158 return AddrReg;
159 }
160
161 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
162 MachinePointerInfo &MPO, CCValAssign &VA) override {
Diana Picus278c7222017-01-26 09:20:47 +0000163 assert((Size == 1 || Size == 2 || Size == 4) && "Unsupported size");
164
165 if (VA.getLocInfo() == CCValAssign::SExt ||
166 VA.getLocInfo() == CCValAssign::ZExt) {
167 // If the argument is zero- or sign-extended by the caller, its size
168 // becomes 4 bytes, so that's what we should load.
169 Size = 4;
170 assert(MRI.getType(ValVReg).isScalar() && "Only scalars supported atm");
171 MRI.setType(ValVReg, LLT::scalar(32));
172 }
Diana Picus1437f6d2016-12-19 11:55:41 +0000173
174 auto MMO = MIRBuilder.getMF().getMachineMemOperand(
175 MPO, MachineMemOperand::MOLoad, Size, /* Alignment */ 0);
176 MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
Diana Picus812caee2016-12-16 12:54:46 +0000177 }
178
179 void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
180 CCValAssign &VA) override {
181 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
182 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
183
Diana Picus97ae95c2016-12-19 14:08:02 +0000184 assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size");
Diana Picus812caee2016-12-16 12:54:46 +0000185 assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size");
186
Diana Picus8b6c6be2017-01-25 08:10:40 +0000187 // The caller should handle all necesary extensions.
Diana Picus812caee2016-12-16 12:54:46 +0000188 MIRBuilder.getMBB().addLiveIn(PhysReg);
189 MIRBuilder.buildCopy(ValVReg, PhysReg);
190 }
Diana Picus812caee2016-12-16 12:54:46 +0000191};
192} // End anonymous namespace
193
Diana Picus22274932016-11-11 08:27:37 +0000194bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
195 const Function &F,
196 ArrayRef<unsigned> VRegs) const {
Diana Picus812caee2016-12-16 12:54:46 +0000197 // Quick exit if there aren't any args
198 if (F.arg_empty())
199 return true;
200
Diana Picus812caee2016-12-16 12:54:46 +0000201 if (F.isVarArg())
202 return false;
203
Diana Picus32cd9b42017-02-02 14:01:00 +0000204 auto &MF = MIRBuilder.getMF();
205 auto DL = MF.getDataLayout();
Diana Picus812caee2016-12-16 12:54:46 +0000206 auto &TLI = *getTLI<ARMTargetLowering>();
207
Diana Picus7232af32017-02-09 13:09:59 +0000208 auto Subtarget = TLI.getSubtarget();
209
210 if (Subtarget->isThumb())
211 return false;
212
213 // FIXME: Support soft float (when we're ready to generate libcalls)
214 if (Subtarget->useSoftFloat() || !Subtarget->hasVFP2())
Diana Picus1d8eaf42017-01-25 07:08:53 +0000215 return false;
216
Diana Picus812caee2016-12-16 12:54:46 +0000217 auto &Args = F.getArgumentList();
Diana Picus278c7222017-01-26 09:20:47 +0000218 for (auto &Arg : Args)
Diana Picus812caee2016-12-16 12:54:46 +0000219 if (!isSupportedType(DL, TLI, Arg.getType()))
220 return false;
221
222 CCAssignFn *AssignFn =
223 TLI.CCAssignFnForCall(F.getCallingConv(), F.isVarArg());
224
225 SmallVector<ArgInfo, 8> ArgInfos;
226 unsigned Idx = 0;
227 for (auto &Arg : Args) {
228 ArgInfo AInfo(VRegs[Idx], Arg.getType());
229 setArgFlags(AInfo, Idx + 1, DL, F);
Diana Picus32cd9b42017-02-02 14:01:00 +0000230 splitToValueTypes(AInfo, ArgInfos, DL, MF.getRegInfo());
Diana Picus812caee2016-12-16 12:54:46 +0000231 Idx++;
232 }
233
Tim Northoverd9433542017-01-17 22:30:10 +0000234 FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo(),
235 AssignFn);
236 return handleAssignments(MIRBuilder, ArgInfos, ArgHandler);
Diana Picus22274932016-11-11 08:27:37 +0000237}