1 //===- 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"
17 #include "MipsCCState.h"
18 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
19 
20 using namespace llvm;
21 
22 MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
23     : CallLowering(&TLI) {}
24 
25 bool 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 
35 namespace {
36 class IncomingValueHandler : public MipsCallLowering::MipsHandler {
37 public:
38   IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
39       : MipsHandler(MIRBuilder, MRI) {}
40 
41   bool handle(ArrayRef<CCValAssign> ArgLocs,
42               ArrayRef<CallLowering::ArgInfo> Args);
43 
44 private:
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 
53 void IncomingValueHandler::assignValueToReg(unsigned ValVReg,
54                                             unsigned PhysReg) {
55   MIRBuilder.buildCopy(ValVReg, PhysReg);
56   markPhysRegUsed(PhysReg);
57 }
58 
59 bool 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 
68 namespace {
69 class OutgoingValueHandler : public MipsCallLowering::MipsHandler {
70 public:
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 
78 private:
79   virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
80 
81   MachineInstrBuilder &MIB;
82 };
83 } // end anonymous namespace
84 
85 void OutgoingValueHandler::assignValueToReg(unsigned ValVReg,
86                                             unsigned PhysReg) {
87   MIRBuilder.buildCopy(PhysReg, ValVReg);
88   MIB.addUse(PhysReg, RegState::Implicit);
89 }
90 
91 bool 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 
100 static bool isSupportedType(Type *T) {
101   if (T->isIntegerTy() && T->getScalarSizeInBits() == 32)
102     return true;
103   return false;
104 }
105 
106 bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
107                                    const Value *Val, unsigned VReg) const {
108 
109   MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
110 
111   if (Val != nullptr) {
112     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     }
144   }
145   MIRBuilder.insertInstr(Ret);
146   return true;
147 }
148 
149 bool 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 
157   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 
194   IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
195   if (!Handler.handle(ArgLocs, ArgInfos))
196     return false;
197 
198   return true;
199 }
200 
201 void 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 
224 void 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);
233 }
234