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