blob: 561b15bacb27c7c3eb3a5c2f67ed4f1381874c55 [file] [log] [blame]
Petar Jovanovicfac93e22018-02-23 11:06:40 +00001//===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===//
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 "MipsCallLowering.h"
Petar Jovanovic366857a2018-04-11 15:12:32 +000017#include "MipsCCState.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000018#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
19
20using namespace llvm;
21
22MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
23 : CallLowering(&TLI) {}
24
Petar Jovanovic366857a2018-04-11 15:12:32 +000025bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA,
26 unsigned vreg) {
27 if (VA.isRegLoc()) {
28 assignValueToReg(vreg, VA.getLocReg());
29 } else {
30 return false;
31 }
32 return true;
33}
34
35namespace {
36class IncomingValueHandler : public MipsCallLowering::MipsHandler {
37public:
38 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
39 : MipsHandler(MIRBuilder, MRI) {}
40
41 bool handle(ArrayRef<CCValAssign> ArgLocs,
42 ArrayRef<CallLowering::ArgInfo> Args);
43
44private:
45 virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
46
47 void markPhysRegUsed(unsigned PhysReg) {
48 MIRBuilder.getMBB().addLiveIn(PhysReg);
49 }
50};
51} // end anonymous namespace
52
53void IncomingValueHandler::assignValueToReg(unsigned ValVReg,
54 unsigned PhysReg) {
55 MIRBuilder.buildCopy(ValVReg, PhysReg);
56 markPhysRegUsed(PhysReg);
57}
58
59bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
60 ArrayRef<CallLowering::ArgInfo> Args) {
61 for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) {
62 if (!assign(ArgLocs[i], Args[i].Reg))
63 return false;
64 }
65 return true;
66}
67
68namespace {
69class OutgoingValueHandler : public MipsCallLowering::MipsHandler {
70public:
71 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
72 MachineInstrBuilder &MIB)
73 : MipsHandler(MIRBuilder, MRI), MIB(MIB) {}
74
75 bool handle(ArrayRef<CCValAssign> ArgLocs,
76 ArrayRef<CallLowering::ArgInfo> Args);
77
78private:
79 virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
80
81 MachineInstrBuilder &MIB;
82};
83} // end anonymous namespace
84
85void OutgoingValueHandler::assignValueToReg(unsigned ValVReg,
86 unsigned PhysReg) {
87 MIRBuilder.buildCopy(PhysReg, ValVReg);
88 MIB.addUse(PhysReg, RegState::Implicit);
89}
90
91bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
92 ArrayRef<CallLowering::ArgInfo> Args) {
93 for (unsigned i = 0; i < Args.size(); ++i) {
94 if (!assign(ArgLocs[i], Args[i].Reg))
95 return false;
96 }
97 return true;
98}
99
100static bool isSupportedType(Type *T) {
101 if (T->isIntegerTy() && T->getScalarSizeInBits() == 32)
102 return true;
103 return false;
104}
105
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000106bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
107 const Value *Val, unsigned VReg) const {
108
109 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
110
111 if (Val != nullptr) {
Petar Jovanovic366857a2018-04-11 15:12:32 +0000112 if (!isSupportedType(Val->getType()))
113 return false;
114
115 MachineFunction &MF = MIRBuilder.getMF();
116 const Function &F = MF.getFunction();
117 const DataLayout &DL = MF.getDataLayout();
118 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
119
120 SmallVector<ArgInfo, 8> RetInfos;
121 SmallVector<unsigned, 8> OrigArgIndices;
122
123 ArgInfo ArgRetInfo(VReg, Val->getType());
124 setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);
125 splitToValueTypes(ArgRetInfo, 0, RetInfos, OrigArgIndices);
126
127 SmallVector<ISD::OutputArg, 8> Outs;
128 subTargetRegTypeForCallingConv(
129 MIRBuilder, RetInfos, OrigArgIndices,
130 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
131 unsigned origIdx, unsigned partOffs) {
132 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
133 });
134
135 SmallVector<CCValAssign, 16> ArgLocs;
136 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
137 F.getContext());
138 CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn());
139
140 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
141 if (!RetHandler.handle(ArgLocs, RetInfos)) {
142 return false;
143 }
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000144 }
145 MIRBuilder.insertInstr(Ret);
146 return true;
147}
148
149bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
150 const Function &F,
151 ArrayRef<unsigned> VRegs) const {
152
153 // Quick exit if there aren't any args.
154 if (F.arg_empty())
155 return true;
156
Petar Jovanovic366857a2018-04-11 15:12:32 +0000157 if (F.isVarArg()) {
158 return false;
159 }
160
161 for (auto &Arg : F.args()) {
162 if (!isSupportedType(Arg.getType()))
163 return false;
164 }
165
166 MachineFunction &MF = MIRBuilder.getMF();
167 const DataLayout &DL = MF.getDataLayout();
168 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
169
170 SmallVector<ArgInfo, 8> ArgInfos;
171 SmallVector<unsigned, 8> OrigArgIndices;
172 unsigned i = 0;
173 for (auto &Arg : F.args()) {
174 ArgInfo AInfo(VRegs[i], Arg.getType());
175 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
176 splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices);
177 ++i;
178 }
179
180 SmallVector<ISD::InputArg, 8> Ins;
181 subTargetRegTypeForCallingConv(
182 MIRBuilder, ArgInfos, OrigArgIndices,
183 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx,
184 unsigned partOffs) {
185 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
186 });
187
188 SmallVector<CCValAssign, 16> ArgLocs;
189 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
190 F.getContext());
191
192 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall());
193
Petar Jovanovic667e2132018-04-12 17:01:46 +0000194 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
Petar Jovanovic366857a2018-04-11 15:12:32 +0000195 if (!Handler.handle(ArgLocs, ArgInfos))
196 return false;
197
198 return true;
199}
200
201void MipsCallLowering::subTargetRegTypeForCallingConv(
202 MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args,
203 ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const {
204 MachineFunction &MF = MIRBuilder.getMF();
205 const Function &F = MF.getFunction();
206 const DataLayout &DL = F.getParent()->getDataLayout();
207 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
208
209 unsigned ArgNo = 0;
210 for (auto &Arg : Args) {
211
212 EVT VT = TLI.getValueType(DL, Arg.Ty);
213 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), VT);
214
215 ISD::ArgFlagsTy Flags = Arg.Flags;
216 Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL));
217
218 PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0);
219
220 ++ArgNo;
221 }
222}
223
224void MipsCallLowering::splitToValueTypes(
225 const ArgInfo &OrigArg, unsigned OriginalIndex,
226 SmallVectorImpl<ArgInfo> &SplitArgs,
227 SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const {
228
229 // TODO : perform structure and array split. For now we only deal with
230 // types that pass isSupportedType check.
231 SplitArgs.push_back(OrigArg);
232 SplitArgsOrigIndices.push_back(OriginalIndex);
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000233}