LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMCallLowering.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 222 228 97.4 %
Date: 2018-10-20 13:21:21 Functions: 18 19 94.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13