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<uint64_t, 4> BitOffsets; 57 SmallVector<unsigned, 8> SplitRegs; 58 59 EVT PartVT = TLI.getRegisterType(Context, VT); 60 Type *PartTy = PartVT.getTypeForEVT(Context); 61 62 for (unsigned i = 0; i < NumParts; ++i) { 63 ArgInfo Info = 64 ArgInfo{MRI.createGenericVirtualRegister(getLLTForType(*PartTy, DL)), 65 PartTy, OrigArg.Flags}; 66 SplitArgs.push_back(Info); 67 PerformArgSplit(Info.Reg, PartVT.getSizeInBits() * i); 68 } 69 } 70 71 namespace { 72 struct FuncReturnHandler : public CallLowering::ValueHandler { 73 FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 74 MachineInstrBuilder &MIB, CCAssignFn *AssignFn) 75 : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {} 76 77 unsigned getStackAddress(uint64_t Size, int64_t Offset, 78 MachinePointerInfo &MPO) override { 79 llvm_unreachable("Don't know how to get a stack address yet"); 80 } 81 82 void assignValueToReg(unsigned ValVReg, unsigned PhysReg, 83 CCValAssign &VA) override { 84 MIB.addUse(PhysReg, RegState::Implicit); 85 unsigned ExtReg = extendRegister(ValVReg, VA); 86 MIRBuilder.buildCopy(PhysReg, ExtReg); 87 } 88 89 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, 90 MachinePointerInfo &MPO, CCValAssign &VA) override { 91 llvm_unreachable("Don't know how to assign a value to an address yet"); 92 } 93 94 MachineInstrBuilder &MIB; 95 }; 96 } // End anonymous namespace. 97 98 bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 99 const Value *Val, unsigned VReg) const { 100 101 assert(((Val && VReg) || (!Val && !VReg)) && "Return value without a vreg"); 102 103 auto MIB = MIRBuilder.buildInstrNoInsert(X86::RET).addImm(0); 104 105 if (VReg) { 106 MachineFunction &MF = MIRBuilder.getMF(); 107 MachineRegisterInfo &MRI = MF.getRegInfo(); 108 auto &DL = MF.getDataLayout(); 109 const Function &F = *MF.getFunction(); 110 111 ArgInfo OrigArg{VReg, Val->getType()}; 112 setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); 113 114 SmallVector<ArgInfo, 8> SplitArgs; 115 splitToValueTypes(OrigArg, SplitArgs, DL, MRI, 116 [&](unsigned Reg, uint64_t Offset) { 117 MIRBuilder.buildExtract(Reg, VReg, Offset); 118 }); 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 LLT Ty = MRI.getType(VRegs[Idx]); 187 unsigned Dst = VRegs[Idx]; 188 bool Split = false; 189 splitToValueTypes(OrigArg, SplitArgs, DL, MRI, 190 [&](unsigned Reg, uint64_t Offset) { 191 if (!Split) { 192 Split = true; 193 Dst = MRI.createGenericVirtualRegister(Ty); 194 MIRBuilder.buildUndef(Dst); 195 } 196 unsigned Tmp = MRI.createGenericVirtualRegister(Ty); 197 MIRBuilder.buildInsert(Tmp, Dst, Reg, Offset); 198 Dst = Tmp; 199 }); 200 if (Dst != VRegs[Idx]) 201 MIRBuilder.buildCopy(VRegs[Idx], Dst); 202 Idx++; 203 } 204 205 MachineBasicBlock &MBB = MIRBuilder.getMBB(); 206 if (!MBB.empty()) 207 MIRBuilder.setInstr(*MBB.begin()); 208 209 FormalArgHandler Handler(MIRBuilder, MRI, CC_X86, DL); 210 if (!handleAssignments(MIRBuilder, SplitArgs, Handler)) 211 return false; 212 213 // Move back to the end of the basic block. 214 MIRBuilder.setMBB(MBB); 215 216 return true; 217 } 218