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

Generated by: LCOV version 1.13