1 //===- llvm/lib/Target/ARM/ARMCallLowering.cpp - Call lowering ------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file 10 /// This file implements the lowering of LLVM calls to machine code calls for 11 /// GlobalISel. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "ARMCallLowering.h" 16 #include "ARMBaseInstrInfo.h" 17 #include "ARMISelLowering.h" 18 #include "ARMSubtarget.h" 19 #include "Utils/ARMBaseInfo.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/CodeGen/Analysis.h" 22 #include "llvm/CodeGen/CallingConvLower.h" 23 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 24 #include "llvm/CodeGen/GlobalISel/Utils.h" 25 #include "llvm/CodeGen/LowLevelTypeUtils.h" 26 #include "llvm/CodeGen/MachineBasicBlock.h" 27 #include "llvm/CodeGen/MachineFrameInfo.h" 28 #include "llvm/CodeGen/MachineFunction.h" 29 #include "llvm/CodeGen/MachineInstrBuilder.h" 30 #include "llvm/CodeGen/MachineMemOperand.h" 31 #include "llvm/CodeGen/MachineOperand.h" 32 #include "llvm/CodeGen/MachineRegisterInfo.h" 33 #include "llvm/CodeGen/TargetRegisterInfo.h" 34 #include "llvm/CodeGen/TargetSubtargetInfo.h" 35 #include "llvm/CodeGen/ValueTypes.h" 36 #include "llvm/CodeGenTypes/LowLevelType.h" 37 #include "llvm/CodeGenTypes/MachineValueType.h" 38 #include "llvm/IR/Attributes.h" 39 #include "llvm/IR/DataLayout.h" 40 #include "llvm/IR/DerivedTypes.h" 41 #include "llvm/IR/Function.h" 42 #include "llvm/IR/Type.h" 43 #include "llvm/IR/Value.h" 44 #include "llvm/Support/Casting.h" 45 #include <algorithm> 46 #include <cassert> 47 #include <cstdint> 48 #include <functional> 49 #include <utility> 50 51 using namespace llvm; 52 53 // Whether Big-endian GISel is enabled, defaults to off, can be enabled for 54 // testing. 55 static cl::opt<bool> 56 EnableGISelBigEndian("enable-arm-gisel-bigendian", cl::Hidden, 57 cl::init(false), 58 cl::desc("Enable Global-ISel Big Endian Lowering")); 59 60 ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI) 61 : CallLowering(&TLI) {} 62 63 static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI, 64 Type *T) { 65 if (T->isArrayTy()) 66 return isSupportedType(DL, TLI, T->getArrayElementType()); 67 68 if (T->isStructTy()) { 69 // For now we only allow homogeneous structs that we can manipulate with 70 // G_MERGE_VALUES and G_UNMERGE_VALUES 71 auto StructT = cast<StructType>(T); 72 for (unsigned i = 1, e = StructT->getNumElements(); i != e; ++i) 73 if (StructT->getElementType(i) != StructT->getElementType(0)) 74 return false; 75 return isSupportedType(DL, TLI, StructT->getElementType(0)); 76 } 77 78 EVT VT = TLI.getValueType(DL, T, true); 79 if (!VT.isSimple() || VT.isVector() || 80 !(VT.isInteger() || VT.isFloatingPoint())) 81 return false; 82 83 unsigned VTSize = VT.getSimpleVT().getSizeInBits(); 84 85 if (VTSize == 64) 86 // FIXME: Support i64 too 87 return VT.isFloatingPoint(); 88 89 return VTSize == 1 || VTSize == 8 || VTSize == 16 || VTSize == 32; 90 } 91 92 namespace { 93 94 /// Helper class for values going out through an ABI boundary (used for handling 95 /// function return values and call parameters). 96 struct ARMOutgoingValueHandler : public CallLowering::OutgoingValueHandler { 97 ARMOutgoingValueHandler(MachineIRBuilder &MIRBuilder, 98 MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) 99 : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {} 100 101 Register getStackAddress(uint64_t Size, int64_t Offset, 102 MachinePointerInfo &MPO, 103 ISD::ArgFlagsTy Flags) override { 104 assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) && 105 "Unsupported size"); 106 107 LLT p0 = LLT::pointer(0, 32); 108 LLT s32 = LLT::scalar(32); 109 auto SPReg = MIRBuilder.buildCopy(p0, Register(ARM::SP)); 110 111 auto OffsetReg = MIRBuilder.buildConstant(s32, Offset); 112 113 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg); 114 115 MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); 116 return AddrReg.getReg(0); 117 } 118 119 void assignValueToReg(Register ValVReg, Register PhysReg, 120 const CCValAssign &VA) override { 121 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg"); 122 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?"); 123 124 assert(VA.getValVT().getSizeInBits() <= 64 && "Unsupported value size"); 125 assert(VA.getLocVT().getSizeInBits() <= 64 && "Unsupported location size"); 126 127 Register ExtReg = extendRegister(ValVReg, VA); 128 MIRBuilder.buildCopy(PhysReg, ExtReg); 129 MIB.addUse(PhysReg, RegState::Implicit); 130 } 131 132 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, 133 const MachinePointerInfo &MPO, 134 const CCValAssign &VA) override { 135 Register ExtReg = extendRegister(ValVReg, VA); 136 auto MMO = MIRBuilder.getMF().getMachineMemOperand( 137 MPO, MachineMemOperand::MOStore, MemTy, Align(1)); 138 MIRBuilder.buildStore(ExtReg, Addr, *MMO); 139 } 140 141 unsigned assignCustomValue(CallLowering::ArgInfo &Arg, 142 ArrayRef<CCValAssign> VAs, 143 std::function<void()> *Thunk) override { 144 assert(Arg.Regs.size() == 1 && "Can't handle multple regs yet"); 145 146 const CCValAssign &VA = VAs[0]; 147 assert(VA.needsCustom() && "Value doesn't need custom handling"); 148 149 // Custom lowering for other types, such as f16, is currently not supported 150 if (VA.getValVT() != MVT::f64) 151 return 0; 152 153 const CCValAssign &NextVA = VAs[1]; 154 assert(NextVA.needsCustom() && "Value doesn't need custom handling"); 155 assert(NextVA.getValVT() == MVT::f64 && "Unsupported type"); 156 157 assert(VA.getValNo() == NextVA.getValNo() && 158 "Values belong to different arguments"); 159 160 assert(VA.isRegLoc() && "Value should be in reg"); 161 assert(NextVA.isRegLoc() && "Value should be in reg"); 162 163 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)), 164 MRI.createGenericVirtualRegister(LLT::scalar(32))}; 165 MIRBuilder.buildUnmerge(NewRegs, Arg.Regs[0]); 166 167 bool IsLittle = MIRBuilder.getMF().getSubtarget<ARMSubtarget>().isLittle(); 168 if (!IsLittle) 169 std::swap(NewRegs[0], NewRegs[1]); 170 171 if (Thunk) { 172 *Thunk = [=]() { 173 assignValueToReg(NewRegs[0], VA.getLocReg(), VA); 174 assignValueToReg(NewRegs[1], NextVA.getLocReg(), NextVA); 175 }; 176 return 2; 177 } 178 assignValueToReg(NewRegs[0], VA.getLocReg(), VA); 179 assignValueToReg(NewRegs[1], NextVA.getLocReg(), NextVA); 180 return 2; 181 } 182 183 MachineInstrBuilder MIB; 184 }; 185 186 } // end anonymous namespace 187 188 /// Lower the return value for the already existing \p Ret. This assumes that 189 /// \p MIRBuilder's insertion point is correct. 190 bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, 191 const Value *Val, ArrayRef<Register> VRegs, 192 MachineInstrBuilder &Ret) const { 193 if (!Val) 194 // Nothing to do here. 195 return true; 196 197 auto &MF = MIRBuilder.getMF(); 198 const auto &F = MF.getFunction(); 199 200 const auto &DL = MF.getDataLayout(); 201 auto &TLI = *getTLI<ARMTargetLowering>(); 202 if (!isSupportedType(DL, TLI, Val->getType())) 203 return false; 204 205 ArgInfo OrigRetInfo(VRegs, Val->getType(), 0); 206 setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F); 207 208 SmallVector<ArgInfo, 4> SplitRetInfos; 209 splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, F.getCallingConv()); 210 211 CCAssignFn *AssignFn = 212 TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); 213 214 OutgoingValueAssigner RetAssigner(AssignFn); 215 ARMOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); 216 return determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos, 217 MIRBuilder, F.getCallingConv(), 218 F.isVarArg()); 219 } 220 221 bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 222 const Value *Val, ArrayRef<Register> VRegs, 223 FunctionLoweringInfo &FLI) const { 224 assert(!Val == VRegs.empty() && "Return value without a vreg"); 225 226 auto const &ST = MIRBuilder.getMF().getSubtarget<ARMSubtarget>(); 227 unsigned Opcode = ST.getReturnOpcode(); 228 auto Ret = MIRBuilder.buildInstrNoInsert(Opcode).add(predOps(ARMCC::AL)); 229 230 if (!lowerReturnVal(MIRBuilder, Val, VRegs, Ret)) 231 return false; 232 233 MIRBuilder.insertInstr(Ret); 234 return true; 235 } 236 237 namespace { 238 239 /// Helper class for values coming in through an ABI boundary (used for handling 240 /// formal arguments and call return values). 241 struct ARMIncomingValueHandler : public CallLowering::IncomingValueHandler { 242 ARMIncomingValueHandler(MachineIRBuilder &MIRBuilder, 243 MachineRegisterInfo &MRI) 244 : IncomingValueHandler(MIRBuilder, MRI) {} 245 246 Register getStackAddress(uint64_t Size, int64_t Offset, 247 MachinePointerInfo &MPO, 248 ISD::ArgFlagsTy Flags) override { 249 assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) && 250 "Unsupported size"); 251 252 auto &MFI = MIRBuilder.getMF().getFrameInfo(); 253 254 // Byval is assumed to be writable memory, but other stack passed arguments 255 // are not. 256 const bool IsImmutable = !Flags.isByVal(); 257 258 int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable); 259 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 260 261 return MIRBuilder.buildFrameIndex(LLT::pointer(MPO.getAddrSpace(), 32), FI) 262 .getReg(0); 263 } 264 265 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, 266 const MachinePointerInfo &MPO, 267 const CCValAssign &VA) override { 268 if (VA.getLocInfo() == CCValAssign::SExt || 269 VA.getLocInfo() == CCValAssign::ZExt) { 270 // If the value is zero- or sign-extended, its size becomes 4 bytes, so 271 // that's what we should load. 272 MemTy = LLT::scalar(32); 273 assert(MRI.getType(ValVReg).isScalar() && "Only scalars supported atm"); 274 275 auto LoadVReg = buildLoad(LLT::scalar(32), Addr, MemTy, MPO); 276 MIRBuilder.buildTrunc(ValVReg, LoadVReg); 277 } else { 278 // If the value is not extended, a simple load will suffice. 279 buildLoad(ValVReg, Addr, MemTy, MPO); 280 } 281 } 282 283 MachineInstrBuilder buildLoad(const DstOp &Res, Register Addr, LLT MemTy, 284 const MachinePointerInfo &MPO) { 285 MachineFunction &MF = MIRBuilder.getMF(); 286 287 auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy, 288 inferAlignFromPtrInfo(MF, MPO)); 289 return MIRBuilder.buildLoad(Res, Addr, *MMO); 290 } 291 292 void assignValueToReg(Register ValVReg, Register PhysReg, 293 const CCValAssign &VA) override { 294 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg"); 295 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?"); 296 297 uint64_t ValSize = VA.getValVT().getFixedSizeInBits(); 298 uint64_t LocSize = VA.getLocVT().getFixedSizeInBits(); 299 300 assert(ValSize <= 64 && "Unsupported value size"); 301 assert(LocSize <= 64 && "Unsupported location size"); 302 303 markPhysRegUsed(PhysReg); 304 if (ValSize == LocSize) { 305 MIRBuilder.buildCopy(ValVReg, PhysReg); 306 } else { 307 assert(ValSize < LocSize && "Extensions not supported"); 308 309 // We cannot create a truncating copy, nor a trunc of a physical register. 310 // Therefore, we need to copy the content of the physical register into a 311 // virtual one and then truncate that. 312 auto PhysRegToVReg = MIRBuilder.buildCopy(LLT::scalar(LocSize), PhysReg); 313 MIRBuilder.buildTrunc(ValVReg, PhysRegToVReg); 314 } 315 } 316 317 unsigned assignCustomValue(ARMCallLowering::ArgInfo &Arg, 318 ArrayRef<CCValAssign> VAs, 319 std::function<void()> *Thunk) override { 320 assert(Arg.Regs.size() == 1 && "Can't handle multple regs yet"); 321 322 const CCValAssign &VA = VAs[0]; 323 assert(VA.needsCustom() && "Value doesn't need custom handling"); 324 325 // Custom lowering for other types, such as f16, is currently not supported 326 if (VA.getValVT() != MVT::f64) 327 return 0; 328 329 const CCValAssign &NextVA = VAs[1]; 330 assert(NextVA.needsCustom() && "Value doesn't need custom handling"); 331 assert(NextVA.getValVT() == MVT::f64 && "Unsupported type"); 332 333 assert(VA.getValNo() == NextVA.getValNo() && 334 "Values belong to different arguments"); 335 336 assert(VA.isRegLoc() && "Value should be in reg"); 337 assert(NextVA.isRegLoc() && "Value should be in reg"); 338 339 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)), 340 MRI.createGenericVirtualRegister(LLT::scalar(32))}; 341 342 assignValueToReg(NewRegs[0], VA.getLocReg(), VA); 343 assignValueToReg(NewRegs[1], NextVA.getLocReg(), NextVA); 344 345 bool IsLittle = MIRBuilder.getMF().getSubtarget<ARMSubtarget>().isLittle(); 346 if (!IsLittle) 347 std::swap(NewRegs[0], NewRegs[1]); 348 349 MIRBuilder.buildMergeLikeInstr(Arg.Regs[0], NewRegs); 350 351 return 2; 352 } 353 354 /// Marking a physical register as used is different between formal 355 /// parameters, where it's a basic block live-in, and call returns, where it's 356 /// an implicit-def of the call instruction. 357 virtual void markPhysRegUsed(unsigned PhysReg) = 0; 358 }; 359 360 struct FormalArgHandler : public ARMIncomingValueHandler { 361 FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 362 : ARMIncomingValueHandler(MIRBuilder, MRI) {} 363 364 void markPhysRegUsed(unsigned PhysReg) override { 365 MIRBuilder.getMRI()->addLiveIn(PhysReg); 366 MIRBuilder.getMBB().addLiveIn(PhysReg); 367 } 368 }; 369 370 } // end anonymous namespace 371 372 bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 373 const Function &F, 374 ArrayRef<ArrayRef<Register>> VRegs, 375 FunctionLoweringInfo &FLI) const { 376 auto &TLI = *getTLI<ARMTargetLowering>(); 377 auto Subtarget = TLI.getSubtarget(); 378 379 if (Subtarget->isThumb1Only()) 380 return false; 381 382 // Quick exit if there aren't any args 383 if (F.arg_empty()) 384 return true; 385 386 if (F.isVarArg()) 387 return false; 388 389 auto &MF = MIRBuilder.getMF(); 390 auto &MBB = MIRBuilder.getMBB(); 391 const auto &DL = MF.getDataLayout(); 392 393 for (auto &Arg : F.args()) { 394 if (!isSupportedType(DL, TLI, Arg.getType())) 395 return false; 396 if (Arg.hasPassPointeeByValueCopyAttr()) 397 return false; 398 } 399 400 CCAssignFn *AssignFn = 401 TLI.CCAssignFnForCall(F.getCallingConv(), F.isVarArg()); 402 403 OutgoingValueAssigner ArgAssigner(AssignFn); 404 FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo()); 405 406 SmallVector<ArgInfo, 8> SplitArgInfos; 407 unsigned Idx = 0; 408 for (auto &Arg : F.args()) { 409 ArgInfo OrigArgInfo(VRegs[Idx], Arg.getType(), Idx); 410 411 setArgFlags(OrigArgInfo, Idx + AttributeList::FirstArgIndex, DL, F); 412 splitToValueTypes(OrigArgInfo, SplitArgInfos, DL, F.getCallingConv()); 413 414 Idx++; 415 } 416 417 if (!MBB.empty()) 418 MIRBuilder.setInstr(*MBB.begin()); 419 420 if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos, 421 MIRBuilder, F.getCallingConv(), 422 F.isVarArg())) 423 return false; 424 425 // Move back to the end of the basic block. 426 MIRBuilder.setMBB(MBB); 427 return true; 428 } 429 430 namespace { 431 432 struct CallReturnHandler : public ARMIncomingValueHandler { 433 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 434 MachineInstrBuilder MIB) 435 : ARMIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} 436 437 void markPhysRegUsed(unsigned PhysReg) override { 438 MIB.addDef(PhysReg, RegState::Implicit); 439 } 440 441 MachineInstrBuilder MIB; 442 }; 443 444 // FIXME: This should move to the ARMSubtarget when it supports all the opcodes. 445 unsigned getCallOpcode(const MachineFunction &MF, const ARMSubtarget &STI, 446 bool isDirect) { 447 if (isDirect) 448 return STI.isThumb() ? ARM::tBL : ARM::BL; 449 450 if (STI.isThumb()) 451 return gettBLXrOpcode(MF); 452 453 if (STI.hasV5TOps()) 454 return getBLXOpcode(MF); 455 456 if (STI.hasV4TOps()) 457 return ARM::BX_CALL; 458 459 return ARM::BMOVPCRX_CALL; 460 } 461 } // end anonymous namespace 462 463 bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const { 464 MachineFunction &MF = MIRBuilder.getMF(); 465 const auto &TLI = *getTLI<ARMTargetLowering>(); 466 const auto &DL = MF.getDataLayout(); 467 const auto &STI = MF.getSubtarget<ARMSubtarget>(); 468 const TargetRegisterInfo *TRI = STI.getRegisterInfo(); 469 MachineRegisterInfo &MRI = MF.getRegInfo(); 470 471 if (STI.genLongCalls()) 472 return false; 473 474 if (STI.isThumb1Only()) 475 return false; 476 477 auto CallSeqStart = MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN); 478 479 // Create the call instruction so we can add the implicit uses of arg 480 // registers, but don't insert it yet. 481 bool IsDirect = !Info.Callee.isReg(); 482 auto CallOpcode = getCallOpcode(MF, STI, IsDirect); 483 auto MIB = MIRBuilder.buildInstrNoInsert(CallOpcode); 484 485 bool IsThumb = STI.isThumb(); 486 if (IsThumb) 487 MIB.add(predOps(ARMCC::AL)); 488 489 MIB.add(Info.Callee); 490 if (!IsDirect) { 491 auto CalleeReg = Info.Callee.getReg(); 492 if (CalleeReg && !CalleeReg.isPhysical()) { 493 unsigned CalleeIdx = IsThumb ? 2 : 0; 494 MIB->getOperand(CalleeIdx).setReg(constrainOperandRegClass( 495 MF, *TRI, MRI, *STI.getInstrInfo(), *STI.getRegBankInfo(), 496 *MIB.getInstr(), MIB->getDesc(), Info.Callee, CalleeIdx)); 497 } 498 } 499 500 MIB.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); 501 502 SmallVector<ArgInfo, 8> ArgInfos; 503 for (auto Arg : Info.OrigArgs) { 504 if (!isSupportedType(DL, TLI, Arg.Ty)) 505 return false; 506 507 if (Arg.Flags[0].isByVal()) 508 return false; 509 510 splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv); 511 } 512 513 auto ArgAssignFn = TLI.CCAssignFnForCall(Info.CallConv, Info.IsVarArg); 514 OutgoingValueAssigner ArgAssigner(ArgAssignFn); 515 ARMOutgoingValueHandler ArgHandler(MIRBuilder, MRI, MIB); 516 if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, ArgInfos, 517 MIRBuilder, Info.CallConv, Info.IsVarArg)) 518 return false; 519 520 // Now we can add the actual call instruction to the correct basic block. 521 MIRBuilder.insertInstr(MIB); 522 523 if (!Info.OrigRet.Ty->isVoidTy()) { 524 if (!isSupportedType(DL, TLI, Info.OrigRet.Ty)) 525 return false; 526 527 ArgInfos.clear(); 528 splitToValueTypes(Info.OrigRet, ArgInfos, DL, Info.CallConv); 529 auto RetAssignFn = TLI.CCAssignFnForReturn(Info.CallConv, Info.IsVarArg); 530 OutgoingValueAssigner Assigner(RetAssignFn); 531 CallReturnHandler RetHandler(MIRBuilder, MRI, MIB); 532 if (!determineAndHandleAssignments(RetHandler, Assigner, ArgInfos, 533 MIRBuilder, Info.CallConv, 534 Info.IsVarArg)) 535 return false; 536 } 537 538 // We now know the size of the stack - update the ADJCALLSTACKDOWN 539 // accordingly. 540 CallSeqStart.addImm(ArgAssigner.StackSize).addImm(0).add(predOps(ARMCC::AL)); 541 542 MIRBuilder.buildInstr(ARM::ADJCALLSTACKUP) 543 .addImm(ArgAssigner.StackSize) 544 .addImm(-1ULL) 545 .add(predOps(ARMCC::AL)); 546 547 return true; 548 } 549 550 bool ARMCallLowering::enableBigEndian() const { return EnableGISelBigEndian; }