LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64CallLowering.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 175 175 100.0 %
Date: 2018-06-17 00:07:59 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        1435 : AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI)
      51        2870 :   : CallLowering(&TLI) {}
      52             : 
      53             : namespace {
      54             : struct IncomingArgHandler : public CallLowering::ValueHandler {
      55             :   IncomingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
      56             :                      CCAssignFn *AssignFn)
      57         572 :       : 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         396 :   void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
      71             :                         CCValAssign &VA) override {
      72         396 :     markPhysRegUsed(PhysReg);
      73         396 :     switch (VA.getLocInfo()) {
      74         367 :     default:
      75         367 :       MIRBuilder.buildCopy(ValVReg, PhysReg);
      76         367 :       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         396 :   }
      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         267 : struct FormalArgHandler : public IncomingArgHandler {
     104             :   FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
     105             :                    CCAssignFn *AssignFn)
     106         267 :     : IncomingArgHandler(MIRBuilder, MRI, AssignFn) {}
     107             : 
     108         376 :   void markPhysRegUsed(unsigned PhysReg) override {
     109         376 :     MIRBuilder.getMBB().addLiveIn(PhysReg);
     110         376 :   }
     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         197 : struct OutgoingArgHandler : public CallLowering::ValueHandler {
     126             :   OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
     127             :                      MachineInstrBuilder MIB, CCAssignFn *AssignFn,
     128             :                      CCAssignFn *AssignFnVarArg)
     129         197 :       : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB),
     130         197 :         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         260 :   void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
     150             :                         CCValAssign &VA) override {
     151         260 :     MIB.addUse(PhysReg, RegState::Implicit);
     152         260 :     unsigned ExtReg = extendRegister(ValVReg, VA);
     153         260 :     MIRBuilder.buildCopy(PhysReg, ExtReg);
     154         260 :   }
     155             : 
     156          17 :   void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
     157             :                             MachinePointerInfo &MPO, CCValAssign &VA) override {
     158          34 :     auto MMO = MIRBuilder.getMF().getMachineMemOperand(
     159          17 :         MPO, MachineMemOperand::MOStore, Size, 0);
     160          17 :     MIRBuilder.buildStore(ValVReg, Addr, *MMO);
     161          17 :   }
     162             : 
     163         281 :   bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT,
     164             :                  CCValAssign::LocInfo LocInfo,
     165             :                  const CallLowering::ArgInfo &Info,
     166             :                  CCState &State) override {
     167             :     bool Res;
     168         281 :     if (Info.IsFixed)
     169         261 :       Res = AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State);
     170             :     else
     171          20 :       Res = AssignFnVarArg(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State);
     172             : 
     173         281 :     StackSize = State.getNextStackOffset();
     174         281 :     return Res;
     175             :   }
     176             : 
     177             :   MachineInstrBuilder MIB;
     178             :   CCAssignFn *AssignFnVarArg;
     179             :   uint64_t StackSize;
     180             : };
     181             : } // namespace
     182             : 
     183         617 : void AArch64CallLowering::splitToValueTypes(
     184             :     const ArgInfo &OrigArg, SmallVectorImpl<ArgInfo> &SplitArgs,
     185             :     const DataLayout &DL, MachineRegisterInfo &MRI, CallingConv::ID CallConv,
     186             :     const SplitArgTy &PerformArgSplit) const {
     187         617 :   const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
     188         617 :   LLVMContext &Ctx = OrigArg.Ty->getContext();
     189             : 
     190         617 :   if (OrigArg.Ty->isVoidTy())
     191         595 :     return;
     192             : 
     193             :   SmallVector<EVT, 4> SplitVTs;
     194             :   SmallVector<uint64_t, 4> Offsets;
     195         615 :   ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0);
     196             : 
     197         615 :   if (SplitVTs.size() == 1) {
     198             :     // No splitting to do, but we want to replace the original type (e.g. [1 x
     199             :     // double] -> double).
     200         593 :     SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx),
     201             :                            OrigArg.Flags, OrigArg.IsFixed);
     202             :     return;
     203             :   }
     204             : 
     205          22 :   unsigned FirstRegIdx = SplitArgs.size();
     206             :   bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters(
     207          22 :       OrigArg.Ty, CallConv, false);
     208         218 :   for (auto SplitVT : SplitVTs) {
     209          98 :     Type *SplitTy = SplitVT.getTypeForEVT(Ctx);
     210         196 :     SplitArgs.push_back(
     211         196 :         ArgInfo{MRI.createGenericVirtualRegister(getLLTForType(*SplitTy, DL)),
     212          98 :                 SplitTy, OrigArg.Flags, OrigArg.IsFixed});
     213          98 :     if (NeedsRegBlock)
     214          88 :       SplitArgs.back().Flags.setInConsecutiveRegs();
     215             :   }
     216             : 
     217          22 :   SplitArgs.back().Flags.setInConsecutiveRegsLast();
     218             : 
     219         338 :   for (unsigned i = 0; i < Offsets.size(); ++i)
     220         196 :     PerformArgSplit(SplitArgs[FirstRegIdx + i].Reg, Offsets[i] * 8);
     221             : }
     222             : 
     223         265 : bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
     224             :                                       const Value *Val, unsigned VReg) const {
     225         265 :   MachineFunction &MF = MIRBuilder.getMF();
     226         265 :   const Function &F = MF.getFunction();
     227             : 
     228         265 :   auto MIB = MIRBuilder.buildInstrNoInsert(AArch64::RET_ReallyLR);
     229             :   assert(((Val && VReg) || (!Val && !VReg)) && "Return value without a vreg");
     230             :   bool Success = true;
     231         265 :   if (VReg) {
     232         154 :     MachineRegisterInfo &MRI = MF.getRegInfo();
     233             : 
     234             :     // We zero-extend i1s to i8.
     235         154 :     if (MRI.getType(VReg).getSizeInBits() == 1)
     236           2 :       VReg = MIRBuilder.buildZExt(LLT::scalar(8), VReg)->getOperand(0).getReg();
     237             : 
     238         154 :     const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
     239         154 :     CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());
     240         154 :     auto &DL = F.getParent()->getDataLayout();
     241             : 
     242         154 :     ArgInfo OrigArg{VReg, Val->getType()};
     243         154 :     setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F);
     244             : 
     245             :     SmallVector<ArgInfo, 8> SplitArgs;
     246         308 :     splitToValueTypes(OrigArg, SplitArgs, DL, MRI, F.getCallingConv(),
     247             :                       [&](unsigned Reg, uint64_t Offset) {
     248           7 :                         MIRBuilder.buildExtract(Reg, VReg, Offset);
     249             :                       });
     250             : 
     251             :     OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFn, AssignFn);
     252         154 :     Success = handleAssignments(MIRBuilder, SplitArgs, Handler);
     253             :   }
     254             : 
     255         265 :   MIRBuilder.insertInstr(MIB);
     256         265 :   return Success;
     257             : }
     258             : 
     259         267 : bool AArch64CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
     260             :                                                const Function &F,
     261             :                                                ArrayRef<unsigned> VRegs) const {
     262         267 :   MachineFunction &MF = MIRBuilder.getMF();
     263         267 :   MachineBasicBlock &MBB = MIRBuilder.getMBB();
     264         267 :   MachineRegisterInfo &MRI = MF.getRegInfo();
     265         267 :   auto &DL = F.getParent()->getDataLayout();
     266             : 
     267             :   SmallVector<ArgInfo, 8> SplitArgs;
     268             :   unsigned i = 0;
     269         617 :   for (auto &Arg : F.args()) {
     270         700 :     if (DL.getTypeStoreSize(Arg.getType()) == 0)
     271           1 :       continue;
     272         698 :     ArgInfo OrigArg{VRegs[i], Arg.getType()};
     273         349 :     setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F);
     274         349 :     bool Split = false;
     275         698 :     LLT Ty = MRI.getType(VRegs[i]);
     276         349 :     unsigned Dst = VRegs[i];
     277             : 
     278         698 :     splitToValueTypes(OrigArg, SplitArgs, DL, MRI, F.getCallingConv(),
     279          51 :                       [&](unsigned Reg, uint64_t Offset) {
     280          51 :                         if (!Split) {
     281          10 :                           Split = true;
     282         234 :                           Dst = MRI.createGenericVirtualRegister(Ty);
     283          71 :                           MIRBuilder.buildUndef(Dst);
     284             :                         }
     285          51 :                         unsigned Tmp = MRI.createGenericVirtualRegister(Ty);
     286         102 :                         MIRBuilder.buildInsert(Tmp, Dst, Reg, Offset);
     287          51 :                         Dst = Tmp;
     288          51 :                       });
     289             : 
     290         349 :     if (Dst != VRegs[i])
     291          10 :       MIRBuilder.buildCopy(VRegs[i], Dst);
     292             :     ++i;
     293             :   }
     294             : 
     295         267 :   if (!MBB.empty())
     296          20 :     MIRBuilder.setInstr(*MBB.begin());
     297             : 
     298         267 :   const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
     299             :   CCAssignFn *AssignFn =
     300         267 :       TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);
     301             : 
     302             :   FormalArgHandler Handler(MIRBuilder, MRI, AssignFn);
     303         534 :   if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
     304             :     return false;
     305             : 
     306         264 :   if (F.isVarArg()) {
     307           1 :     if (!MF.getSubtarget<AArch64Subtarget>().isTargetDarwin()) {
     308             :       // FIXME: we need to reimplement saveVarArgsRegisters from
     309             :       // AArch64ISelLowering.
     310             :       return false;
     311             :     }
     312             : 
     313             :     // We currently pass all varargs at 8-byte alignment.
     314           1 :     uint64_t StackOffset = alignTo(Handler.StackUsed, 8);
     315             : 
     316           1 :     auto &MFI = MIRBuilder.getMF().getFrameInfo();
     317           1 :     AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
     318           1 :     FuncInfo->setVarArgsStackIndex(MFI.CreateFixedObject(4, StackOffset, true));
     319             :   }
     320             : 
     321             :   // Move back to the end of the basic block.
     322         264 :   MIRBuilder.setMBB(MBB);
     323             : 
     324         264 :   return true;
     325             : }
     326             : 
     327          43 : bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
     328             :                                     CallingConv::ID CallConv,
     329             :                                     const MachineOperand &Callee,
     330             :                                     const ArgInfo &OrigRet,
     331             :                                     ArrayRef<ArgInfo> OrigArgs) const {
     332          43 :   MachineFunction &MF = MIRBuilder.getMF();
     333          43 :   const Function &F = MF.getFunction();
     334          43 :   MachineRegisterInfo &MRI = MF.getRegInfo();
     335          43 :   auto &DL = F.getParent()->getDataLayout();
     336             : 
     337             :   SmallVector<ArgInfo, 8> SplitArgs;
     338         233 :   for (auto &OrigArg : OrigArgs) {
     339         190 :     splitToValueTypes(OrigArg, SplitArgs, DL, MRI, CallConv,
     340             :                       [&](unsigned Reg, uint64_t Offset) {
     341          36 :                         MIRBuilder.buildExtract(Reg, OrigArg.Reg, Offset);
     342             :                       });
     343             :   }
     344             : 
     345             :   // Find out which ABI gets to decide where things go.
     346          43 :   const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
     347             :   CCAssignFn *AssignFnFixed =
     348          43 :       TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/false);
     349             :   CCAssignFn *AssignFnVarArg =
     350          43 :       TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/true);
     351             : 
     352          43 :   auto CallSeqStart = MIRBuilder.buildInstr(AArch64::ADJCALLSTACKDOWN);
     353             : 
     354             :   // Create a temporarily-floating call instruction so we can add the implicit
     355             :   // uses of arg registers.
     356             :   auto MIB = MIRBuilder.buildInstrNoInsert(Callee.isReg() ? AArch64::BLR
     357          43 :                                                           : AArch64::BL);
     358             :   MIB.add(Callee);
     359             : 
     360             :   // Tell the call which registers are clobbered.
     361          43 :   auto TRI = MF.getSubtarget().getRegisterInfo();
     362          86 :   MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));
     363             : 
     364             :   // Do the actual argument marshalling.
     365             :   SmallVector<unsigned, 8> PhysRegs;
     366             :   OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFnFixed,
     367             :                              AssignFnVarArg);
     368          86 :   if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
     369             :     return false;
     370             : 
     371             :   // Now we can add the actual call instruction to the correct basic block.
     372          41 :   MIRBuilder.insertInstr(MIB);
     373             : 
     374             :   // If Callee is a reg, since it is used by a target specific
     375             :   // instruction, it must have a register class matching the
     376             :   // constraint of that instruction.
     377          41 :   if (Callee.isReg())
     378           4 :     MIB->getOperand(0).setReg(constrainOperandRegClass(
     379           2 :         MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(),
     380           2 :         *MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), Callee, 0));
     381             : 
     382             :   // Finally we can copy the returned value back into its virtual-register. In
     383             :   // symmetry with the arugments, the physical register must be an
     384             :   // implicit-define of the call instruction.
     385          41 :   CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());
     386          41 :   if (OrigRet.Reg) {
     387             :     SplitArgs.clear();
     388             : 
     389             :     SmallVector<uint64_t, 8> RegOffsets;
     390             :     SmallVector<unsigned, 8> SplitRegs;
     391          38 :     splitToValueTypes(OrigRet, SplitArgs, DL, MRI, F.getCallingConv(),
     392             :                       [&](unsigned Reg, uint64_t Offset) {
     393           4 :                         RegOffsets.push_back(Offset);
     394           4 :                         SplitRegs.push_back(Reg);
     395             :                       });
     396             : 
     397             :     CallReturnHandler Handler(MIRBuilder, MRI, MIB, RetAssignFn);
     398          19 :     if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
     399             :       return false;
     400             : 
     401          19 :     if (!RegOffsets.empty())
     402           1 :       MIRBuilder.buildSequence(OrigRet.Reg, SplitRegs, RegOffsets);
     403             :   }
     404             : 
     405          41 :   CallSeqStart.addImm(Handler.StackSize).addImm(0);
     406          41 :   MIRBuilder.buildInstr(AArch64::ADJCALLSTACKUP)
     407          41 :       .addImm(Handler.StackSize)
     408             :       .addImm(0);
     409             : 
     410          41 :   return true;
     411             : }

Generated by: LCOV version 1.13