]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp
MFV r315633, 315635:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / ARM / ARMCallLowering.cpp
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
21 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23
24 using namespace llvm;
25
26 #ifndef LLVM_BUILD_GLOBAL_ISEL
27 #error "This shouldn't be built without GISel"
28 #endif
29
30 ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI)
31     : CallLowering(&TLI) {}
32
33 static bool isSupportedType(const DataLayout DL, const ARMTargetLowering &TLI,
34                             Type *T) {
35   EVT VT = TLI.getValueType(DL, T);
36   if (!VT.isSimple() || !VT.isInteger() || VT.isVector())
37     return false;
38
39   unsigned VTSize = VT.getSimpleVT().getSizeInBits();
40   return VTSize == 8 || VTSize == 16 || VTSize == 32;
41 }
42
43 namespace {
44 struct FuncReturnHandler : public CallLowering::ValueHandler {
45   FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
46                     MachineInstrBuilder &MIB)
47       : ValueHandler(MIRBuilder, MRI), MIB(MIB) {}
48
49   unsigned getStackAddress(uint64_t Size, int64_t Offset,
50                            MachinePointerInfo &MPO) override {
51     llvm_unreachable("Don't know how to get a stack address yet");
52   }
53
54   void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
55                         CCValAssign &VA) override {
56     assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
57     assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
58
59     assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size");
60     assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size");
61
62     assert(VA.getLocInfo() != CCValAssign::SExt &&
63            VA.getLocInfo() != CCValAssign::ZExt &&
64            "ABI extensions not supported yet");
65
66     MIRBuilder.buildCopy(PhysReg, ValVReg);
67     MIB.addUse(PhysReg, RegState::Implicit);
68   }
69
70   void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
71                             MachinePointerInfo &MPO, CCValAssign &VA) override {
72     llvm_unreachable("Don't know how to assign a value to an address yet");
73   }
74
75   MachineInstrBuilder &MIB;
76 };
77 } // End anonymous namespace.
78
79 /// Lower the return value for the already existing \p Ret. This assumes that
80 /// \p MIRBuilder's insertion point is correct.
81 bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
82                                      const Value *Val, unsigned VReg,
83                                      MachineInstrBuilder &Ret) const {
84   if (!Val)
85     // Nothing to do here.
86     return true;
87
88   auto &MF = MIRBuilder.getMF();
89   const auto &F = *MF.getFunction();
90
91   auto DL = MF.getDataLayout();
92   auto &TLI = *getTLI<ARMTargetLowering>();
93   if (!isSupportedType(DL, TLI, Val->getType()))
94     return false;
95
96   CCAssignFn *AssignFn =
97       TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg());
98
99   ArgInfo RetInfo(VReg, Val->getType());
100   setArgFlags(RetInfo, AttributeSet::ReturnIndex, DL, F);
101
102   FuncReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
103   return handleAssignments(MIRBuilder, AssignFn, RetInfo, RetHandler);
104 }
105
106 bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
107                                   const Value *Val, unsigned VReg) const {
108   assert(!Val == !VReg && "Return value without a vreg");
109
110   auto Ret = AddDefaultPred(MIRBuilder.buildInstrNoInsert(ARM::BX_RET));
111
112   if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret))
113     return false;
114
115   MIRBuilder.insertInstr(Ret);
116   return true;
117 }
118
119 namespace {
120 struct FormalArgHandler : public CallLowering::ValueHandler {
121   FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
122       : ValueHandler(MIRBuilder, MRI) {}
123
124   unsigned getStackAddress(uint64_t Size, int64_t Offset,
125                            MachinePointerInfo &MPO) override {
126     assert(Size == 4 && "Unsupported size");
127
128     auto &MFI = MIRBuilder.getMF().getFrameInfo();
129
130     int FI = MFI.CreateFixedObject(Size, Offset, true);
131     MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
132
133     unsigned AddrReg =
134         MRI.createGenericVirtualRegister(LLT::pointer(MPO.getAddrSpace(), 32));
135     MIRBuilder.buildFrameIndex(AddrReg, FI);
136
137     return AddrReg;
138   }
139
140   void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
141                             MachinePointerInfo &MPO, CCValAssign &VA) override {
142     assert(Size == 4 && "Unsupported size");
143
144     auto MMO = MIRBuilder.getMF().getMachineMemOperand(
145         MPO, MachineMemOperand::MOLoad, Size, /* Alignment */ 0);
146     MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
147   }
148
149   void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
150                         CCValAssign &VA) override {
151     assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
152     assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
153
154     assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size");
155     assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size");
156
157     MIRBuilder.getMBB().addLiveIn(PhysReg);
158     MIRBuilder.buildCopy(ValVReg, PhysReg);
159   }
160 };
161 } // End anonymous namespace
162
163 bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
164                                            const Function &F,
165                                            ArrayRef<unsigned> VRegs) const {
166   // Quick exit if there aren't any args
167   if (F.arg_empty())
168     return true;
169
170   if (F.isVarArg())
171     return false;
172
173   auto DL = MIRBuilder.getMF().getDataLayout();
174   auto &TLI = *getTLI<ARMTargetLowering>();
175
176   auto &Args = F.getArgumentList();
177   unsigned ArgIdx = 0;
178   for (auto &Arg : Args) {
179     ArgIdx++;
180     if (!isSupportedType(DL, TLI, Arg.getType()))
181       return false;
182
183     // FIXME: This check as well as ArgIdx are going away as soon as we support
184     // loading values < 32 bits.
185     if (ArgIdx > 4 && Arg.getType()->getIntegerBitWidth() != 32)
186       return false;
187   }
188
189   CCAssignFn *AssignFn =
190       TLI.CCAssignFnForCall(F.getCallingConv(), F.isVarArg());
191
192   SmallVector<ArgInfo, 8> ArgInfos;
193   unsigned Idx = 0;
194   for (auto &Arg : Args) {
195     ArgInfo AInfo(VRegs[Idx], Arg.getType());
196     setArgFlags(AInfo, Idx + 1, DL, F);
197     ArgInfos.push_back(AInfo);
198     Idx++;
199   }
200
201   FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo());
202   return handleAssignments(MIRBuilder, AssignFn, ArgInfos, ArgHandler);
203 }