1 //===-- llvm/lib/Target/X86/X86CallLowering.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 "X86CallLowering.h"
17 #include "X86CallingConv.h"
18 #include "X86ISelLowering.h"
19 #include "X86InstrInfo.h"
20 #include "X86TargetMachine.h"
21 
22 #include "llvm/CodeGen/Analysis.h"
23 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/MachineValueType.h"
26 #include "llvm/Target/TargetSubtargetInfo.h"
27 
28 using namespace llvm;
29 
30 #include "X86GenCallingConv.inc"
31 
32 #ifndef LLVM_BUILD_GLOBAL_ISEL
33 #error "This shouldn't be built without GISel"
34 #endif
35 
36 X86CallLowering::X86CallLowering(const X86TargetLowering &TLI)
37     : CallLowering(&TLI) {}
38 
39 bool X86CallLowering::splitToValueTypes(const ArgInfo &OrigArg,
40                                         SmallVectorImpl<ArgInfo> &SplitArgs,
41                                         const DataLayout &DL,
42                                         MachineRegisterInfo &MRI,
43                                         SplitArgTy PerformArgSplit) const {
44 
45   const X86TargetLowering &TLI = *getTLI<X86TargetLowering>();
46   LLVMContext &Context = OrigArg.Ty->getContext();
47 
48   SmallVector<EVT, 4> SplitVTs;
49   SmallVector<uint64_t, 4> Offsets;
50   ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0);
51 
52   if (SplitVTs.size() != 1) {
53     // TODO: support struct/array split
54     return false;
55   }
56 
57   EVT VT = SplitVTs[0];
58   unsigned NumParts = TLI.getNumRegisters(Context, VT);
59 
60   if (NumParts == 1) {
61     // replace the original type ( pointer -> GPR ).
62     SplitArgs.emplace_back(OrigArg.Reg, VT.getTypeForEVT(Context),
63                            OrigArg.Flags, OrigArg.IsFixed);
64     return true;
65   }
66 
67   SmallVector<unsigned, 8> SplitRegs;
68 
69   EVT PartVT = TLI.getRegisterType(Context, VT);
70   Type *PartTy = PartVT.getTypeForEVT(Context);
71 
72   for (unsigned i = 0; i < NumParts; ++i) {
73     ArgInfo Info =
74         ArgInfo{MRI.createGenericVirtualRegister(getLLTForType(*PartTy, DL)),
75                 PartTy, OrigArg.Flags};
76     SplitArgs.push_back(Info);
77     SplitRegs.push_back(Info.Reg);
78   }
79 
80   PerformArgSplit(SplitRegs);
81   return true;
82 }
83 
84 namespace {
85 struct FuncReturnHandler : public CallLowering::ValueHandler {
86   FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
87                     MachineInstrBuilder &MIB, CCAssignFn *AssignFn)
88       : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
89 
90   unsigned getStackAddress(uint64_t Size, int64_t Offset,
91                            MachinePointerInfo &MPO) override {
92     llvm_unreachable("Don't know how to get a stack address yet");
93   }
94 
95   void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
96                         CCValAssign &VA) override {
97     MIB.addUse(PhysReg, RegState::Implicit);
98     unsigned ExtReg = extendRegister(ValVReg, VA);
99     MIRBuilder.buildCopy(PhysReg, ExtReg);
100   }
101 
102   void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
103                             MachinePointerInfo &MPO, CCValAssign &VA) override {
104     llvm_unreachable("Don't know how to assign a value to an address yet");
105   }
106 
107   MachineInstrBuilder &MIB;
108 };
109 } // End anonymous namespace.
110 
111 bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
112                                   const Value *Val, unsigned VReg) const {
113 
114   assert(((Val && VReg) || (!Val && !VReg)) && "Return value without a vreg");
115 
116   auto MIB = MIRBuilder.buildInstrNoInsert(X86::RET).addImm(0);
117 
118   if (VReg) {
119     MachineFunction &MF = MIRBuilder.getMF();
120     MachineRegisterInfo &MRI = MF.getRegInfo();
121     auto &DL = MF.getDataLayout();
122     const Function &F = *MF.getFunction();
123 
124     ArgInfo OrigArg{VReg, Val->getType()};
125     setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F);
126 
127     SmallVector<ArgInfo, 8> SplitArgs;
128     if (!splitToValueTypes(OrigArg, SplitArgs, DL, MRI,
129                            [&](ArrayRef<unsigned> Regs) {
130                              MIRBuilder.buildUnmerge(Regs, VReg);
131                            }))
132       return false;
133 
134     FuncReturnHandler Handler(MIRBuilder, MRI, MIB, RetCC_X86);
135     if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
136       return false;
137   }
138 
139   MIRBuilder.insertInstr(MIB);
140   return true;
141 }
142 
143 namespace {
144 struct FormalArgHandler : public CallLowering::ValueHandler {
145   FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
146                    CCAssignFn *AssignFn, const DataLayout &DL)
147       : ValueHandler(MIRBuilder, MRI, AssignFn), DL(DL) {}
148 
149   unsigned getStackAddress(uint64_t Size, int64_t Offset,
150                            MachinePointerInfo &MPO) override {
151 
152     auto &MFI = MIRBuilder.getMF().getFrameInfo();
153     int FI = MFI.CreateFixedObject(Size, Offset, true);
154     MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
155 
156     unsigned AddrReg = MRI.createGenericVirtualRegister(
157         LLT::pointer(0, DL.getPointerSizeInBits(0)));
158     MIRBuilder.buildFrameIndex(AddrReg, FI);
159     return AddrReg;
160   }
161 
162   void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
163                             MachinePointerInfo &MPO, CCValAssign &VA) override {
164 
165     auto MMO = MIRBuilder.getMF().getMachineMemOperand(
166         MPO, MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant, Size,
167         0);
168     MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
169   }
170 
171   void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
172                         CCValAssign &VA) override {
173     MIRBuilder.getMBB().addLiveIn(PhysReg);
174     MIRBuilder.buildCopy(ValVReg, PhysReg);
175   }
176 
177   const DataLayout &DL;
178 };
179 } // namespace
180 
181 bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
182                                            const Function &F,
183                                            ArrayRef<unsigned> VRegs) const {
184   if (F.arg_empty())
185     return true;
186 
187   // TODO: handle variadic function
188   if (F.isVarArg())
189     return false;
190 
191   MachineFunction &MF = MIRBuilder.getMF();
192   MachineRegisterInfo &MRI = MF.getRegInfo();
193   auto DL = MF.getDataLayout();
194 
195   SmallVector<ArgInfo, 8> SplitArgs;
196   unsigned Idx = 0;
197   for (auto &Arg : F.args()) {
198 
199     // TODO: handle not simple cases.
200     if (Arg.hasAttribute(Attribute::ByVal) ||
201         Arg.hasAttribute(Attribute::InReg) ||
202         Arg.hasAttribute(Attribute::StructRet) ||
203         Arg.hasAttribute(Attribute::SwiftSelf) ||
204         Arg.hasAttribute(Attribute::SwiftError) ||
205         Arg.hasAttribute(Attribute::Nest))
206       return false;
207 
208     ArgInfo OrigArg(VRegs[Idx], Arg.getType());
209     setArgFlags(OrigArg, Idx + AttributeList::FirstArgIndex, DL, F);
210     if (!splitToValueTypes(OrigArg, SplitArgs, DL, MRI,
211                            [&](ArrayRef<unsigned> Regs) {
212                              MIRBuilder.buildMerge(VRegs[Idx], Regs);
213                            }))
214       return false;
215     Idx++;
216   }
217 
218   MachineBasicBlock &MBB = MIRBuilder.getMBB();
219   if (!MBB.empty())
220     MIRBuilder.setInstr(*MBB.begin());
221 
222   FormalArgHandler Handler(MIRBuilder, MRI, CC_X86, DL);
223   if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
224     return false;
225 
226   // Move back to the end of the basic block.
227   MIRBuilder.setMBB(MBB);
228 
229   return true;
230 }
231