LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64CallLowering.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 180 180 100.0 %
Date: 2018-07-13 00:08:38 Functions: 15 21 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- AArch64CallLowering.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 "AArch64CallLowering.h"
      17             : #include "AArch64ISelLowering.h"
      18             : #include "AArch64MachineFunctionInfo.h"
      19             : #include "AArch64Subtarget.h"
      20             : #include "llvm/ADT/ArrayRef.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/Argument.h"
      38             : #include "llvm/IR/Attributes.h"
      39             : #include "llvm/IR/Function.h"
      40             : #include "llvm/IR/Type.h"
      41             : #include "llvm/IR/Value.h"
      42             : #include "llvm/Support/MachineValueType.h"
      43             : #include <algorithm>
      44             : #include <cassert>
      45             : #include <cstdint>
      46             : #include <iterator>
      47             : 
      48             : using namespace llvm;
      49             : 
      50        1438 : AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI)
      51        2876 :   : CallLowering(&TLI) {}
      52             : 
      53             : namespace {
      54             : struct IncomingArgHandler : public CallLowering::ValueHandler {
      55             :   IncomingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
      56             :                      CCAssignFn *AssignFn)
      57         602 :       : ValueHandler(MIRBuilder, MRI, AssignFn), StackUsed(0) {}
      58             : 
      59          11 :   unsigned getStackAddress(uint64_t Size, int64_t Offset,
      60             :                            MachinePointerInfo &MPO) override {
      61          11 :     auto &MFI = MIRBuilder.getMF().getFrameInfo();
      62          11 :     int FI = MFI.CreateFixedObject(Size, Offset, true);
      63          11 :     MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
      64          22 :     unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 64));
      65          11 :     MIRBuilder.buildFrameIndex(AddrReg, FI);
      66          22 :     StackUsed = std::max(StackUsed, Size + Offset);
      67          11 :     return AddrReg;
      68             :   }
      69             : 
      70         411 :   void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
      71             :                         CCValAssign &VA) override {
      72         411 :     markPhysRegUsed(PhysReg);
      73         411 :     switch (VA.getLocInfo()) {
      74         382 :     default:
      75         382 :       MIRBuilder.buildCopy(ValVReg, PhysReg);
      76         382 :       break;
      77          29 :     case CCValAssign::LocInfo::SExt:
      78             :     case CCValAssign::LocInfo::ZExt:
      79             :     case CCValAssign::LocInfo::AExt: {
      80          29 :       auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg);
      81          29 :       MIRBuilder.buildTrunc(ValVReg, Copy);
      82             :       break;
      83             :     }
      84             :     }
      85         411 :   }
      86             : 
      87          11 :   void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
      88             :                             MachinePointerInfo &MPO, CCValAssign &VA) override {
      89          22 :     auto MMO = MIRBuilder.getMF().getMachineMemOperand(
      90             :         MPO, MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant, Size,
      91          11 :         0);
      92          11 :     MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
      93          11 :   }
      94             : 
      95             :   /// How the physical register gets marked varies between formal
      96             :   /// parameters (it's a basic-block live-in), and a call instruction
      97             :   /// (it's an implicit-def of the BL).
      98             :   virtual void markPhysRegUsed(unsigned PhysReg) = 0;
      99             : 
     100             :   uint64_t StackUsed;
     101             : };
     102             : 
     103         282 : struct FormalArgHandler : public IncomingArgHandler {
     104             :   FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
     105             :                    CCAssignFn *AssignFn)
     106         282 :     : IncomingArgHandler(MIRBuilder, MRI, AssignFn) {}
     107             : 
     108         391 :   void markPhysRegUsed(unsigned PhysReg) override {
     109         391 :     MIRBuilder.getMBB().addLiveIn(PhysReg);
     110         391 :   }
     111             : };
     112             : 
     113          19 : struct CallReturnHandler : public IncomingArgHandler {
     114             :   CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
     115             :                     MachineInstrBuilder MIB, CCAssignFn *AssignFn)
     116          38 :     : IncomingArgHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
     117             : 
     118          20 :   void markPhysRegUsed(unsigned PhysReg) override {
     119          20 :     MIB.addDef(PhysReg, RegState::Implicit);
     120          20 :   }
     121             : 
     122             :   MachineInstrBuilder MIB;
     123             : };
     124             : 
     125         212 : struct OutgoingArgHandler : public CallLowering::ValueHandler {
     126             :   OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
     127             :                      MachineInstrBuilder MIB, CCAssignFn *AssignFn,
     128             :                      CCAssignFn *AssignFnVarArg)
     129         212 :       : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB),
     130         212 :         AssignFnVarArg(AssignFnVarArg), StackSize(0) {}
     131             : 
     132          17 :   unsigned getStackAddress(uint64_t Size, int64_t Offset,
     133             :                            MachinePointerInfo &MPO) override {
     134          17 :     LLT p0 = LLT::pointer(0, 64);
     135          17 :     LLT s64 = LLT::scalar(64);
     136          34 :     unsigned SPReg = MRI.createGenericVirtualRegister(p0);
     137          17 :     MIRBuilder.buildCopy(SPReg, AArch64::SP);
     138             : 
     139          34 :     unsigned OffsetReg = MRI.createGenericVirtualRegister(s64);
     140          17 :     MIRBuilder.buildConstant(OffsetReg, Offset);
     141             : 
     142          34 :     unsigned AddrReg = MRI.createGenericVirtualRegister(p0);
     143          17 :     MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg);
     144             : 
     145          17 :     MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
     146          17 :     return AddrReg;
     147             :   }
     148             : 
     149         275 :   void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
     150             :                         CCValAssign &VA) override {
     151         275 :     MIB.addUse(PhysReg, RegState::Implicit);
     152         275 :     unsigned ExtReg = extendRegister(ValVReg, VA);
     153         275 :     MIRBuilder.buildCopy(PhysReg, ExtReg);
     154         275 :   }
     155             : 
     156          17 :   void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
     157             :                             MachinePointerInfo &MPO, CCValAssign &VA) override {
     158          17 :     if (VA.getLocInfo() == CCValAssign::LocInfo::AExt) {
     159           4 :       Size = VA.getLocVT().getSizeInBits() / 8;
     160          12 :       ValVReg = MIRBuilder.buildAnyExt(LLT::scalar(Size * 8), ValVReg)
     161           4 :                     ->getOperand(0)
     162           4 :                     .getReg();
     163             :     }
     164          34 :     auto MMO = MIRBuilder.getMF().getMachineMemOperand(
     165          17 :         MPO, MachineMemOperand::MOStore, Size, 0);
     166          17 :     MIRBuilder.buildStore(ValVReg, Addr, *MMO);
     167          17 :   }
     168             : 
     169         296 :   bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT,
     170             :                  CCValAssign::LocInfo LocInfo,
     171             :                  const CallLowering::ArgInfo &Info,
     172             :                  CCState &State) override {
     173             :     bool Res;
     174         296 :     if (Info.IsFixed)
     175         276 :       Res = AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State);
     176             :     else
     177          20 :       Res = AssignFnVarArg(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State);
     178             : 
     179         296 :     StackSize = State.getNextStackOffset();
     180         296 :     return Res;
     181             :   }
     182             : 
     183             :   MachineInstrBuilder MIB;
     184             :   CCAssignFn *AssignFnVarArg;
     185             :   uint64_t StackSize;
     186             : };
     187             : } // namespace
     188             : 
     189         647 : void AArch64CallLowering::splitToValueTypes(
     190             :     const ArgInfo &OrigArg, SmallVectorImpl<ArgInfo> &SplitArgs,
     191             :     const DataLayout &DL, MachineRegisterInfo &MRI, CallingConv::ID CallConv,
     192             :     const SplitArgTy &PerformArgSplit) const {
     193         647 :   const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
     194         647 :   LLVMContext &Ctx = OrigArg.Ty->getContext();
     195             : 
     196         647 :   if (OrigArg.Ty->isVoidTy())
     197         625 :     return;
     198             : 
     199             :   SmallVector<EVT, 4> SplitVTs;
     200             :   SmallVector<uint64_t, 4> Offsets;
     201         645 :   ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0);
     202             : 
     203         645 :   if (SplitVTs.size() == 1) {
     204             :     // No splitting to do, but we want to replace the original type (e.g. [1 x
     205             :     // double] -> double).
     206         623 :     SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx),
     207             :                            OrigArg.Flags, OrigArg.IsFixed);
     208             :     return;
     209             :   }
     210             : 
     211          22 :   unsigned FirstRegIdx = SplitArgs.size();
     212             :   bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters(
     213          22 :       OrigArg.Ty, CallConv, false);
     214         218 :   for (auto SplitVT : SplitVTs) {
     215          98 :     Type *SplitTy = SplitVT.getTypeForEVT(Ctx);
     216         196 :     SplitArgs.push_back(
     217         196 :         ArgInfo{MRI.createGenericVirtualRegister(getLLTForType(*SplitTy, DL)),
     218          98 :                 SplitTy, OrigArg.Flags, OrigArg.IsFixed});
     219          98 :     if (NeedsRegBlock)
     220          88 :       SplitArgs.back().Flags.setInConsecutiveRegs();
     221             :   }
     222             : 
     223          22 :   SplitArgs.back().Flags.setInConsecutiveRegsLast();
     224             : 
     225         338 :   for (unsigned i = 0; i < Offsets.size(); ++i)
     226         196 :     PerformArgSplit(SplitArgs[FirstRegIdx + i].Reg, Offsets[i] * 8);
     227             : }
     228             : 
     229         280 : bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
     230             :                                       const Value *Val, unsigned VReg) const {
     231         280 :   MachineFunction &MF = MIRBuilder.getMF();
     232         280 :   const Function &F = MF.getFunction();
     233             : 
     234         280 :   auto MIB = MIRBuilder.buildInstrNoInsert(AArch64::RET_ReallyLR);
     235             :   assert(((Val && VReg) || (!Val && !VReg)) && "Return value without a vreg");
     236             :   bool Success = true;
     237         280 :   if (VReg) {
     238         169 :     MachineRegisterInfo &MRI = MF.getRegInfo();
     239             : 
     240             :     // We zero-extend i1s to i8.
     241         169 :     if (MRI.getType(VReg).getSizeInBits() == 1)
     242           2 :       VReg = MIRBuilder.buildZExt(LLT::scalar(8), VReg)->getOperand(0).getReg();
     243             : 
     244         169 :     const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
     245         169 :     CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());
     246         169 :     auto &DL = F.getParent()->getDataLayout();
     247             : 
     248         169 :     ArgInfo OrigArg{VReg, Val->getType()};
     249         169 :     setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F);
     250             : 
     251             :     SmallVector<ArgInfo, 8> SplitArgs;
     252         338 :     splitToValueTypes(OrigArg, SplitArgs, DL, MRI, F.getCallingConv(),
     253             :                       [&](unsigned Reg, uint64_t Offset) {
     254           7 :                         MIRBuilder.buildExtract(Reg, VReg, Offset);
     255             :                       });
     256             : 
     257             :     OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFn, AssignFn);
     258         169 :     Success = handleAssignments(MIRBuilder, SplitArgs, Handler);
     259             :   }
     260             : 
     261         280 :   MIRBuilder.insertInstr(MIB);
     262         280 :   return Success;
     263             : }
     264             : 
     265         282 : bool AArch64CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
     266             :                                                const Function &F,
     267             :                                                ArrayRef<unsigned> VRegs) const {
     268         282 :   MachineFunction &MF = MIRBuilder.getMF();
     269         282 :   MachineBasicBlock &MBB = MIRBuilder.getMBB();
     270         282 :   MachineRegisterInfo &MRI = MF.getRegInfo();
     271         282 :   auto &DL = F.getParent()->getDataLayout();
     272             : 
     273             :   SmallVector<ArgInfo, 8> SplitArgs;
     274             :   unsigned i = 0;
     275         647 :   for (auto &Arg : F.args()) {
     276         730 :     if (DL.getTypeStoreSize(Arg.getType()) == 0)
     277           1 :       continue;
     278         728 :     ArgInfo OrigArg{VRegs[i], Arg.getType()};
     279         364 :     setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F);
     280         364 :     bool Split = false;
     281         728 :     LLT Ty = MRI.getType(VRegs[i]);
     282         364 :     unsigned Dst = VRegs[i];
     283             : 
     284         728 :     splitToValueTypes(OrigArg, SplitArgs, DL, MRI, F.getCallingConv(),
     285          51 :                       [&](unsigned Reg, uint64_t Offset) {
     286          51 :                         if (!Split) {
     287          10 :                           Split = true;
     288         234 :                           Dst = MRI.createGenericVirtualRegister(Ty);
     289          71 :                           MIRBuilder.buildUndef(Dst);
     290             :                         }
     291          51 :                         unsigned Tmp = MRI.createGenericVirtualRegister(Ty);
     292         102 :                         MIRBuilder.buildInsert(Tmp, Dst, Reg, Offset);
     293          51 :                         Dst = Tmp;
     294          51 :                       });
     295             : 
     296         364 :     if (Dst != VRegs[i])
     297          10 :       MIRBuilder.buildCopy(VRegs[i], Dst);
     298             :     ++i;
     299             :   }
     300             : 
     301         282 :   if (!MBB.empty())
     302          20 :     MIRBuilder.setInstr(*MBB.begin());
     303             : 
     304         282 :   const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
     305             :   CCAssignFn *AssignFn =
     306         282 :       TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);
     307             : 
     308             :   FormalArgHandler Handler(MIRBuilder, MRI, AssignFn);
     309         564 :   if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
     310             :     return false;
     311             : 
     312         279 :   if (F.isVarArg()) {
     313           1 :     if (!MF.getSubtarget<AArch64Subtarget>().isTargetDarwin()) {
     314             :       // FIXME: we need to reimplement saveVarArgsRegisters from
     315             :       // AArch64ISelLowering.
     316             :       return false;
     317             :     }
     318             : 
     319             :     // We currently pass all varargs at 8-byte alignment.
     320           1 :     uint64_t StackOffset = alignTo(Handler.StackUsed, 8);
     321             : 
     322           1 :     auto &MFI = MIRBuilder.getMF().getFrameInfo();
     323           1 :     AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
     324           1 :     FuncInfo->setVarArgsStackIndex(MFI.CreateFixedObject(4, StackOffset, true));
     325             :   }
     326             : 
     327             :   // Move back to the end of the basic block.
     328         279 :   MIRBuilder.setMBB(MBB);
     329             : 
     330         279 :   return true;
     331             : }
     332             : 
     333          43 : bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
     334             :                                     CallingConv::ID CallConv,
     335             :                                     const MachineOperand &Callee,
     336             :                                     const ArgInfo &OrigRet,
     337             :                                     ArrayRef<ArgInfo> OrigArgs) const {
     338          43 :   MachineFunction &MF = MIRBuilder.getMF();
     339          43 :   const Function &F = MF.getFunction();
     340          43 :   MachineRegisterInfo &MRI = MF.getRegInfo();
     341          43 :   auto &DL = F.getParent()->getDataLayout();
     342             : 
     343             :   SmallVector<ArgInfo, 8> SplitArgs;
     344         233 :   for (auto &OrigArg : OrigArgs) {
     345         190 :     splitToValueTypes(OrigArg, SplitArgs, DL, MRI, CallConv,
     346             :                       [&](unsigned Reg, uint64_t Offset) {
     347          36 :                         MIRBuilder.buildExtract(Reg, OrigArg.Reg, Offset);
     348             :                       });
     349             :   }
     350             : 
     351             :   // Find out which ABI gets to decide where things go.
     352          43 :   const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
     353             :   CCAssignFn *AssignFnFixed =
     354          43 :       TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/false);
     355             :   CCAssignFn *AssignFnVarArg =
     356          43 :       TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/true);
     357             : 
     358          43 :   auto CallSeqStart = MIRBuilder.buildInstr(AArch64::ADJCALLSTACKDOWN);
     359             : 
     360             :   // Create a temporarily-floating call instruction so we can add the implicit
     361             :   // uses of arg registers.
     362             :   auto MIB = MIRBuilder.buildInstrNoInsert(Callee.isReg() ? AArch64::BLR
     363          43 :                                                           : AArch64::BL);
     364             :   MIB.add(Callee);
     365             : 
     366             :   // Tell the call which registers are clobbered.
     367          43 :   auto TRI = MF.getSubtarget().getRegisterInfo();
     368          86 :   MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));
     369             : 
     370             :   // Do the actual argument marshalling.
     371             :   SmallVector<unsigned, 8> PhysRegs;
     372             :   OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFnFixed,
     373             :                              AssignFnVarArg);
     374          86 :   if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
     375             :     return false;
     376             : 
     377             :   // Now we can add the actual call instruction to the correct basic block.
     378          41 :   MIRBuilder.insertInstr(MIB);
     379             : 
     380             :   // If Callee is a reg, since it is used by a target specific
     381             :   // instruction, it must have a register class matching the
     382             :   // constraint of that instruction.
     383          41 :   if (Callee.isReg())
     384           4 :     MIB->getOperand(0).setReg(constrainOperandRegClass(
     385           2 :         MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(),
     386           2 :         *MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), Callee, 0));
     387             : 
     388             :   // Finally we can copy the returned value back into its virtual-register. In
     389             :   // symmetry with the arugments, the physical register must be an
     390             :   // implicit-define of the call instruction.
     391          41 :   CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());
     392          41 :   if (OrigRet.Reg) {
     393             :     SplitArgs.clear();
     394             : 
     395             :     SmallVector<uint64_t, 8> RegOffsets;
     396             :     SmallVector<unsigned, 8> SplitRegs;
     397          38 :     splitToValueTypes(OrigRet, SplitArgs, DL, MRI, F.getCallingConv(),
     398             :                       [&](unsigned Reg, uint64_t Offset) {
     399           4 :                         RegOffsets.push_back(Offset);
     400           4 :                         SplitRegs.push_back(Reg);
     401             :                       });
     402             : 
     403             :     CallReturnHandler Handler(MIRBuilder, MRI, MIB, RetAssignFn);
     404          19 :     if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
     405             :       return false;
     406             : 
     407          19 :     if (!RegOffsets.empty())
     408           1 :       MIRBuilder.buildSequence(OrigRet.Reg, SplitRegs, RegOffsets);
     409             :   }
     410             : 
     411          41 :   CallSeqStart.addImm(Handler.StackSize).addImm(0);
     412          41 :   MIRBuilder.buildInstr(AArch64::ADJCALLSTACKUP)
     413          41 :       .addImm(Handler.StackSize)
     414             :       .addImm(0);
     415             : 
     416          41 :   return true;
     417             : }

Generated by: LCOV version 1.13