1 //===-- llvm/lib/Target/ARM/ARMCallLowering.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 "ARMCallLowering.h" 17 18 #include "ARMBaseInstrInfo.h" 19 #include "ARMISelLowering.h" 20 #include "ARMSubtarget.h" 21 22 #include "llvm/CodeGen/Analysis.h" 23 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 24 #include "llvm/CodeGen/MachineRegisterInfo.h" 25 26 using namespace llvm; 27 28 #ifndef LLVM_BUILD_GLOBAL_ISEL 29 #error "This shouldn't be built without GISel" 30 #endif 31 32 ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI) 33 : CallLowering(&TLI) {} 34 35 static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI, 36 Type *T) { 37 EVT VT = TLI.getValueType(DL, T, true); 38 if (!VT.isSimple() || VT.isVector() || 39 !(VT.isInteger() || VT.isFloatingPoint())) 40 return false; 41 42 unsigned VTSize = VT.getSimpleVT().getSizeInBits(); 43 44 if (VTSize == 64) 45 // FIXME: Support i64 too 46 return VT.isFloatingPoint(); 47 48 return VTSize == 1 || VTSize == 8 || VTSize == 16 || VTSize == 32; 49 } 50 51 namespace { 52 /// Helper class for values going out through an ABI boundary (used for handling 53 /// function return values and call parameters). 54 struct OutgoingValueHandler : public CallLowering::ValueHandler { 55 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 56 MachineInstrBuilder &MIB, CCAssignFn *AssignFn) 57 : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB), StackSize(0) {} 58 59 unsigned getStackAddress(uint64_t Size, int64_t Offset, 60 MachinePointerInfo &MPO) override { 61 assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) && 62 "Unsupported size"); 63 64 LLT p0 = LLT::pointer(0, 32); 65 LLT s32 = LLT::scalar(32); 66 unsigned SPReg = MRI.createGenericVirtualRegister(p0); 67 MIRBuilder.buildCopy(SPReg, ARM::SP); 68 69 unsigned OffsetReg = MRI.createGenericVirtualRegister(s32); 70 MIRBuilder.buildConstant(OffsetReg, Offset); 71 72 unsigned AddrReg = MRI.createGenericVirtualRegister(p0); 73 MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); 74 75 MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); 76 return AddrReg; 77 } 78 79 void assignValueToReg(unsigned ValVReg, unsigned PhysReg, 80 CCValAssign &VA) override { 81 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg"); 82 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?"); 83 84 assert(VA.getValVT().getSizeInBits() <= 64 && "Unsupported value size"); 85 assert(VA.getLocVT().getSizeInBits() <= 64 && "Unsupported location size"); 86 87 unsigned ExtReg = extendRegister(ValVReg, VA); 88 MIRBuilder.buildCopy(PhysReg, ExtReg); 89 MIB.addUse(PhysReg, RegState::Implicit); 90 } 91 92 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, 93 MachinePointerInfo &MPO, CCValAssign &VA) override { 94 assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) && 95 "Unsupported size"); 96 97 unsigned ExtReg = extendRegister(ValVReg, VA); 98 auto MMO = MIRBuilder.getMF().getMachineMemOperand( 99 MPO, MachineMemOperand::MOStore, VA.getLocVT().getStoreSize(), 100 /* Alignment */ 0); 101 MIRBuilder.buildStore(ExtReg, Addr, *MMO); 102 } 103 104 unsigned assignCustomValue(const CallLowering::ArgInfo &Arg, 105 ArrayRef<CCValAssign> VAs) override { 106 CCValAssign VA = VAs[0]; 107 assert(VA.needsCustom() && "Value doesn't need custom handling"); 108 assert(VA.getValVT() == MVT::f64 && "Unsupported type"); 109 110 CCValAssign NextVA = VAs[1]; 111 assert(NextVA.needsCustom() && "Value doesn't need custom handling"); 112 assert(NextVA.getValVT() == MVT::f64 && "Unsupported type"); 113 114 assert(VA.getValNo() == NextVA.getValNo() && 115 "Values belong to different arguments"); 116 117 assert(VA.isRegLoc() && "Value should be in reg"); 118 assert(NextVA.isRegLoc() && "Value should be in reg"); 119 120 unsigned NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)), 121 MRI.createGenericVirtualRegister(LLT::scalar(32))}; 122 MIRBuilder.buildExtract(NewRegs[0], Arg.Reg, 0); 123 MIRBuilder.buildExtract(NewRegs[1], Arg.Reg, 32); 124 125 bool IsLittle = MIRBuilder.getMF().getSubtarget<ARMSubtarget>().isLittle(); 126 if (!IsLittle) 127 std::swap(NewRegs[0], NewRegs[1]); 128 129 assignValueToReg(NewRegs[0], VA.getLocReg(), VA); 130 assignValueToReg(NewRegs[1], NextVA.getLocReg(), NextVA); 131 132 return 1; 133 } 134 135 bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT, 136 CCValAssign::LocInfo LocInfo, 137 const CallLowering::ArgInfo &Info, CCState &State) override { 138 if (AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State)) 139 return true; 140 141 StackSize = 142 std::max(StackSize, static_cast<uint64_t>(State.getNextStackOffset())); 143 return false; 144 } 145 146 MachineInstrBuilder &MIB; 147 uint64_t StackSize; 148 }; 149 } // End anonymous namespace. 150 151 void ARMCallLowering::splitToValueTypes(const ArgInfo &OrigArg, 152 SmallVectorImpl<ArgInfo> &SplitArgs, 153 const DataLayout &DL, 154 MachineRegisterInfo &MRI) const { 155 const ARMTargetLowering &TLI = *getTLI<ARMTargetLowering>(); 156 LLVMContext &Ctx = OrigArg.Ty->getContext(); 157 158 SmallVector<EVT, 4> SplitVTs; 159 SmallVector<uint64_t, 4> Offsets; 160 ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0); 161 162 assert(SplitVTs.size() == 1 && "Unsupported type"); 163 164 // Even if there is no splitting to do, we still want to replace the original 165 // type (e.g. pointer type -> integer). 166 SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx), 167 OrigArg.Flags, OrigArg.IsFixed); 168 } 169 170 /// Lower the return value for the already existing \p Ret. This assumes that 171 /// \p MIRBuilder's insertion point is correct. 172 bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, 173 const Value *Val, unsigned VReg, 174 MachineInstrBuilder &Ret) const { 175 if (!Val) 176 // Nothing to do here. 177 return true; 178 179 auto &MF = MIRBuilder.getMF(); 180 const auto &F = *MF.getFunction(); 181 182 auto DL = MF.getDataLayout(); 183 auto &TLI = *getTLI<ARMTargetLowering>(); 184 if (!isSupportedType(DL, TLI, Val->getType())) 185 return false; 186 187 SmallVector<ArgInfo, 4> SplitVTs; 188 ArgInfo RetInfo(VReg, Val->getType()); 189 setArgFlags(RetInfo, AttributeList::ReturnIndex, DL, F); 190 splitToValueTypes(RetInfo, SplitVTs, DL, MF.getRegInfo()); 191 192 CCAssignFn *AssignFn = 193 TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); 194 195 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret, AssignFn); 196 return handleAssignments(MIRBuilder, SplitVTs, RetHandler); 197 } 198 199 bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 200 const Value *Val, unsigned VReg) const { 201 assert(!Val == !VReg && "Return value without a vreg"); 202 203 auto Ret = MIRBuilder.buildInstrNoInsert(ARM::BX_RET).add(predOps(ARMCC::AL)); 204 205 if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret)) 206 return false; 207 208 MIRBuilder.insertInstr(Ret); 209 return true; 210 } 211 212 namespace { 213 /// Helper class for values coming in through an ABI boundary (used for handling 214 /// formal arguments and call return values). 215 struct IncomingValueHandler : public CallLowering::ValueHandler { 216 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 217 CCAssignFn AssignFn) 218 : ValueHandler(MIRBuilder, MRI, AssignFn) {} 219 220 unsigned getStackAddress(uint64_t Size, int64_t Offset, 221 MachinePointerInfo &MPO) override { 222 assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) && 223 "Unsupported size"); 224 225 auto &MFI = MIRBuilder.getMF().getFrameInfo(); 226 227 int FI = MFI.CreateFixedObject(Size, Offset, true); 228 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 229 230 unsigned AddrReg = 231 MRI.createGenericVirtualRegister(LLT::pointer(MPO.getAddrSpace(), 32)); 232 MIRBuilder.buildFrameIndex(AddrReg, FI); 233 234 return AddrReg; 235 } 236 237 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, 238 MachinePointerInfo &MPO, CCValAssign &VA) override { 239 assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) && 240 "Unsupported size"); 241 242 if (VA.getLocInfo() == CCValAssign::SExt || 243 VA.getLocInfo() == CCValAssign::ZExt) { 244 // If the value is zero- or sign-extended, its size becomes 4 bytes, so 245 // that's what we should load. 246 Size = 4; 247 assert(MRI.getType(ValVReg).isScalar() && "Only scalars supported atm"); 248 MRI.setType(ValVReg, LLT::scalar(32)); 249 } 250 251 auto MMO = MIRBuilder.getMF().getMachineMemOperand( 252 MPO, MachineMemOperand::MOLoad, Size, /* Alignment */ 0); 253 MIRBuilder.buildLoad(ValVReg, Addr, *MMO); 254 } 255 256 void assignValueToReg(unsigned ValVReg, unsigned PhysReg, 257 CCValAssign &VA) override { 258 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg"); 259 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?"); 260 261 assert(VA.getValVT().getSizeInBits() <= 64 && "Unsupported value size"); 262 assert(VA.getLocVT().getSizeInBits() <= 64 && "Unsupported location size"); 263 264 // The necesary extensions are handled on the other side of the ABI 265 // boundary. 266 markPhysRegUsed(PhysReg); 267 MIRBuilder.buildCopy(ValVReg, PhysReg); 268 } 269 270 unsigned assignCustomValue(const ARMCallLowering::ArgInfo &Arg, 271 ArrayRef<CCValAssign> VAs) override { 272 CCValAssign VA = VAs[0]; 273 assert(VA.needsCustom() && "Value doesn't need custom handling"); 274 assert(VA.getValVT() == MVT::f64 && "Unsupported type"); 275 276 CCValAssign NextVA = VAs[1]; 277 assert(NextVA.needsCustom() && "Value doesn't need custom handling"); 278 assert(NextVA.getValVT() == MVT::f64 && "Unsupported type"); 279 280 assert(VA.getValNo() == NextVA.getValNo() && 281 "Values belong to different arguments"); 282 283 assert(VA.isRegLoc() && "Value should be in reg"); 284 assert(NextVA.isRegLoc() && "Value should be in reg"); 285 286 unsigned NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)), 287 MRI.createGenericVirtualRegister(LLT::scalar(32))}; 288 289 assignValueToReg(NewRegs[0], VA.getLocReg(), VA); 290 assignValueToReg(NewRegs[1], NextVA.getLocReg(), NextVA); 291 292 bool IsLittle = MIRBuilder.getMF().getSubtarget<ARMSubtarget>().isLittle(); 293 if (!IsLittle) 294 std::swap(NewRegs[0], NewRegs[1]); 295 296 MIRBuilder.buildSequence(Arg.Reg, NewRegs, {0, 32}); 297 298 return 1; 299 } 300 301 /// Marking a physical register as used is different between formal 302 /// parameters, where it's a basic block live-in, and call returns, where it's 303 /// an implicit-def of the call instruction. 304 virtual void markPhysRegUsed(unsigned PhysReg) = 0; 305 }; 306 307 struct FormalArgHandler : public IncomingValueHandler { 308 FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 309 CCAssignFn AssignFn) 310 : IncomingValueHandler(MIRBuilder, MRI, AssignFn) {} 311 312 void markPhysRegUsed(unsigned PhysReg) override { 313 MIRBuilder.getMBB().addLiveIn(PhysReg); 314 } 315 }; 316 } // End anonymous namespace 317 318 bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 319 const Function &F, 320 ArrayRef<unsigned> VRegs) const { 321 // Quick exit if there aren't any args 322 if (F.arg_empty()) 323 return true; 324 325 if (F.isVarArg()) 326 return false; 327 328 auto &MF = MIRBuilder.getMF(); 329 auto DL = MF.getDataLayout(); 330 auto &TLI = *getTLI<ARMTargetLowering>(); 331 332 auto Subtarget = TLI.getSubtarget(); 333 334 if (Subtarget->isThumb()) 335 return false; 336 337 for (auto &Arg : F.args()) 338 if (!isSupportedType(DL, TLI, Arg.getType())) 339 return false; 340 341 CCAssignFn *AssignFn = 342 TLI.CCAssignFnForCall(F.getCallingConv(), F.isVarArg()); 343 344 SmallVector<ArgInfo, 8> ArgInfos; 345 unsigned Idx = 0; 346 for (auto &Arg : F.args()) { 347 ArgInfo AInfo(VRegs[Idx], Arg.getType()); 348 setArgFlags(AInfo, Idx + 1, DL, F); 349 splitToValueTypes(AInfo, ArgInfos, DL, MF.getRegInfo()); 350 Idx++; 351 } 352 353 FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo(), 354 AssignFn); 355 return handleAssignments(MIRBuilder, ArgInfos, ArgHandler); 356 } 357 358 namespace { 359 struct CallReturnHandler : public IncomingValueHandler { 360 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 361 MachineInstrBuilder MIB, CCAssignFn *AssignFn) 362 : IncomingValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {} 363 364 void markPhysRegUsed(unsigned PhysReg) override { 365 MIB.addDef(PhysReg, RegState::Implicit); 366 } 367 368 MachineInstrBuilder MIB; 369 }; 370 } // End anonymous namespace. 371 372 bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 373 CallingConv::ID CallConv, 374 const MachineOperand &Callee, 375 const ArgInfo &OrigRet, 376 ArrayRef<ArgInfo> OrigArgs) const { 377 MachineFunction &MF = MIRBuilder.getMF(); 378 const auto &TLI = *getTLI<ARMTargetLowering>(); 379 const auto &DL = MF.getDataLayout(); 380 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 381 MachineRegisterInfo &MRI = MF.getRegInfo(); 382 383 if (MF.getSubtarget<ARMSubtarget>().genLongCalls()) 384 return false; 385 386 auto CallSeqStart = MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN); 387 388 // Create the call instruction so we can add the implicit uses of arg 389 // registers, but don't insert it yet. 390 auto MIB = MIRBuilder.buildInstrNoInsert(ARM::BLX).add(Callee).addRegMask( 391 TRI->getCallPreservedMask(MF, CallConv)); 392 393 SmallVector<ArgInfo, 8> ArgInfos; 394 for (auto Arg : OrigArgs) { 395 if (!isSupportedType(DL, TLI, Arg.Ty)) 396 return false; 397 398 if (!Arg.IsFixed) 399 return false; 400 401 splitToValueTypes(Arg, ArgInfos, DL, MRI); 402 } 403 404 auto ArgAssignFn = TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/false); 405 OutgoingValueHandler ArgHandler(MIRBuilder, MRI, MIB, ArgAssignFn); 406 if (!handleAssignments(MIRBuilder, ArgInfos, ArgHandler)) 407 return false; 408 409 // Now we can add the actual call instruction to the correct basic block. 410 MIRBuilder.insertInstr(MIB); 411 412 if (!OrigRet.Ty->isVoidTy()) { 413 if (!isSupportedType(DL, TLI, OrigRet.Ty)) 414 return false; 415 416 ArgInfos.clear(); 417 splitToValueTypes(OrigRet, ArgInfos, DL, MRI); 418 419 auto RetAssignFn = TLI.CCAssignFnForReturn(CallConv, /*IsVarArg=*/false); 420 CallReturnHandler RetHandler(MIRBuilder, MRI, MIB, RetAssignFn); 421 if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler)) 422 return false; 423 } 424 425 // We now know the size of the stack - update the ADJCALLSTACKDOWN 426 // accordingly. 427 CallSeqStart.addImm(ArgHandler.StackSize).add(predOps(ARMCC::AL)); 428 429 MIRBuilder.buildInstr(ARM::ADJCALLSTACKUP) 430 .addImm(ArgHandler.StackSize) 431 .addImm(0) 432 .add(predOps(ARMCC::AL)); 433 434 return true; 435 } 436