1 //===-- 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"
20 #include "ARMSubtarget.h"
21 
22 #include "llvm/CodeGen/Analysis.h"
23 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 
26 using namespace llvm;
27 
28 #ifndef LLVM_BUILD_GLOBAL_ISEL
29 #error "This shouldn't be built without GISel"
30 #endif
31 
32 ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI)
33     : CallLowering(&TLI) {}
34 
35 static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI,
36                             Type *T) {
37   EVT VT = TLI.getValueType(DL, T, true);
38   if (!VT.isSimple() || VT.isVector())
39     return false;
40 
41   unsigned VTSize = VT.getSimpleVT().getSizeInBits();
42   return VTSize == 1 || VTSize == 8 || VTSize == 16 || VTSize == 32;
43 }
44 
45 namespace {
46 struct FuncReturnHandler : public CallLowering::ValueHandler {
47   FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
48                     MachineInstrBuilder &MIB, CCAssignFn *AssignFn)
49     : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
50 
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 
61     assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size");
62     assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size");
63 
64     unsigned ExtReg = extendRegister(ValVReg, VA);
65     MIRBuilder.buildCopy(PhysReg, ExtReg);
66     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 
78 void 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 
97 /// Lower the return value for the already existing \p Ret. This assumes that
98 /// \p MIRBuilder's insertion point is correct.
99 bool 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()))
112     return false;
113 
114   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 
119   CCAssignFn *AssignFn =
120       TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg());
121 
122   FuncReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret, AssignFn);
123   return handleAssignments(MIRBuilder, SplitVTs, RetHandler);
124 }
125 
126 bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
127                                   const Value *Val, unsigned VReg) const {
128   assert(!Val == !VReg && "Return value without a vreg");
129 
130   auto Ret = MIRBuilder.buildInstrNoInsert(ARM::BX_RET).add(predOps(ARMCC::AL));
131 
132   if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret))
133     return false;
134 
135   MIRBuilder.insertInstr(Ret);
136   return true;
137 }
138 
139 namespace {
140 struct FormalArgHandler : public CallLowering::ValueHandler {
141   FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
142                    CCAssignFn AssignFn)
143       : ValueHandler(MIRBuilder, MRI, AssignFn) {}
144 
145   unsigned getStackAddress(uint64_t Size, int64_t Offset,
146                            MachinePointerInfo &MPO) override {
147     assert((Size == 1 || Size == 2 || Size == 4) && "Unsupported size");
148 
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 {
163     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     }
173 
174     auto MMO = MIRBuilder.getMF().getMachineMemOperand(
175         MPO, MachineMemOperand::MOLoad, Size, /* Alignment */ 0);
176     MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
177   }
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 
184     assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size");
185     assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size");
186 
187     // The caller should handle all necesary extensions.
188     MIRBuilder.getMBB().addLiveIn(PhysReg);
189     MIRBuilder.buildCopy(ValVReg, PhysReg);
190   }
191 };
192 } // End anonymous namespace
193 
194 bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
195                                            const Function &F,
196                                            ArrayRef<unsigned> VRegs) const {
197   // Quick exit if there aren't any args
198   if (F.arg_empty())
199     return true;
200 
201   if (F.isVarArg())
202     return false;
203 
204   auto &MF = MIRBuilder.getMF();
205   auto DL = MF.getDataLayout();
206   auto &TLI = *getTLI<ARMTargetLowering>();
207 
208   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())
215     return false;
216 
217   auto &Args = F.getArgumentList();
218   for (auto &Arg : Args)
219     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);
230     splitToValueTypes(AInfo, ArgInfos, DL, MF.getRegInfo());
231     Idx++;
232   }
233 
234   FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo(),
235                               AssignFn);
236   return handleAssignments(MIRBuilder, ArgInfos, ArgHandler);
237 }
238