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