LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMCallingConv.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 92 94 97.9 %
Date: 2017-09-14 15:23:50 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //=== ARMCallingConv.h - ARM Custom Calling Convention Routines -*- C++ -*-===//
       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             : // This file contains the custom routines for the ARM Calling Convention that
      11             : // aren't done by tablegen.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #ifndef LLVM_LIB_TARGET_ARM_ARMCALLINGCONV_H
      16             : #define LLVM_LIB_TARGET_ARM_ARMCALLINGCONV_H
      17             : 
      18             : #include "ARM.h"
      19             : #include "ARMBaseInstrInfo.h"
      20             : #include "ARMSubtarget.h"
      21             : #include "llvm/CodeGen/CallingConvLower.h"
      22             : #include "llvm/IR/CallingConv.h"
      23             : #include "llvm/Target/TargetInstrInfo.h"
      24             : 
      25             : namespace llvm {
      26             : 
      27             : // APCS f64 is in register pairs, possibly split to stack
      28         859 : static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
      29             :                           CCValAssign::LocInfo &LocInfo,
      30             :                           CCState &State, bool CanFail) {
      31             :   static const MCPhysReg RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
      32             : 
      33             :   // Try to get the first register.
      34         859 :   if (unsigned Reg = State.AllocateReg(RegList))
      35        1182 :     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
      36             :   else {
      37             :     // For the 2nd half of a v2f64, do not fail.
      38         465 :     if (CanFail)
      39             :       return false;
      40             : 
      41             :     // Put the whole thing on the stack.
      42           6 :     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
      43             :                                            State.AllocateStack(8, 4),
      44           3 :                                            LocVT, LocInfo));
      45           3 :     return true;
      46             :   }
      47             : 
      48             :   // Try to get the second register.
      49         394 :   if (unsigned Reg = State.AllocateReg(RegList))
      50        1077 :     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
      51             :   else
      52          70 :     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
      53             :                                            State.AllocateStack(4, 4),
      54          35 :                                            LocVT, LocInfo));
      55             :   return true;
      56             : }
      57             : 
      58         777 : static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
      59             :                                    CCValAssign::LocInfo &LocInfo,
      60             :                                    ISD::ArgFlagsTy &ArgFlags,
      61             :                                    CCState &State) {
      62         777 :   if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
      63             :     return false;
      64         712 :   if (LocVT == MVT::v2f64 &&
      65          82 :       !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
      66             :     return false;
      67             :   return true;  // we handled it
      68             : }
      69             : 
      70             : // AAPCS f64 is in aligned register pairs
      71        1425 : static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
      72             :                            CCValAssign::LocInfo &LocInfo,
      73             :                            CCState &State, bool CanFail) {
      74             :   static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 };
      75             :   static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 };
      76             :   static const MCPhysReg ShadowRegList[] = { ARM::R0, ARM::R1 };
      77             :   static const MCPhysReg GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
      78             : 
      79        1425 :   unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList);
      80        1425 :   if (Reg == 0) {
      81             : 
      82             :     // If we had R3 unallocated only, now we still must to waste it.
      83         301 :     Reg = State.AllocateReg(GPRArgRegs);
      84             :     assert((!Reg || Reg == ARM::R3) && "Wrong GPRs usage for f64");
      85             : 
      86             :     // For the 2nd half of a v2f64, do not just fail.
      87         301 :     if (CanFail)
      88             :       return false;
      89             : 
      90             :     // Put the whole thing on the stack.
      91           6 :     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
      92             :                                            State.AllocateStack(8, 8),
      93           3 :                                            LocVT, LocInfo));
      94           3 :     return true;
      95             :   }
      96             : 
      97             :   unsigned i;
      98        2048 :   for (i = 0; i < 2; ++i)
      99        1586 :     if (HiRegList[i] == Reg)
     100             :       break;
     101             : 
     102        1124 :   unsigned T = State.AllocateReg(LoRegList[i]);
     103             :   (void)T;
     104             :   assert(T == LoRegList[i] && "Could not allocate register");
     105             : 
     106        3372 :   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
     107        2248 :   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
     108        1124 :                                          LocVT, LocInfo));
     109        1124 :   return true;
     110             : }
     111             : 
     112        1258 : static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
     113             :                                     CCValAssign::LocInfo &LocInfo,
     114             :                                     ISD::ArgFlagsTy &ArgFlags,
     115             :                                     CCState &State) {
     116        1258 :   if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
     117             :     return false;
     118        2087 :   if (LocVT == MVT::v2f64 &&
     119         167 :       !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
     120             :     return false;
     121             :   return true;  // we handled it
     122             : }
     123             : 
     124        5643 : static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
     125             :                          CCValAssign::LocInfo &LocInfo, CCState &State) {
     126             :   static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 };
     127             :   static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 };
     128             : 
     129        5643 :   unsigned Reg = State.AllocateReg(HiRegList, LoRegList);
     130        5643 :   if (Reg == 0)
     131             :     return false; // we didn't handle it
     132             : 
     133             :   unsigned i;
     134        9013 :   for (i = 0; i < 2; ++i)
     135        7317 :     if (HiRegList[i] == Reg)
     136             :       break;
     137             : 
     138       16863 :   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
     139       16863 :   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
     140       11242 :                                          LocVT, LocInfo));
     141        5621 :   return true;
     142             : }
     143             : 
     144        3958 : static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
     145             :                                       CCValAssign::LocInfo &LocInfo,
     146             :                                       ISD::ArgFlagsTy &ArgFlags,
     147             :                                       CCState &State) {
     148        3958 :   if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
     149             :     return false;
     150        7872 :   if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
     151             :     return false;
     152             :   return true;  // we handled it
     153             : }
     154             : 
     155             : static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
     156             :                                        CCValAssign::LocInfo &LocInfo,
     157             :                                        ISD::ArgFlagsTy &ArgFlags,
     158             :                                        CCState &State) {
     159             :   return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags,
     160        3512 :                                    State);
     161             : }
     162             : 
     163             : static const MCPhysReg RRegList[] = { ARM::R0,  ARM::R1,  ARM::R2,  ARM::R3 };
     164             : 
     165             : static const MCPhysReg SRegList[] = { ARM::S0,  ARM::S1,  ARM::S2,  ARM::S3,
     166             :                                       ARM::S4,  ARM::S5,  ARM::S6,  ARM::S7,
     167             :                                       ARM::S8,  ARM::S9,  ARM::S10, ARM::S11,
     168             :                                       ARM::S12, ARM::S13, ARM::S14,  ARM::S15 };
     169             : static const MCPhysReg DRegList[] = { ARM::D0, ARM::D1, ARM::D2, ARM::D3,
     170             :                                       ARM::D4, ARM::D5, ARM::D6, ARM::D7 };
     171             : static const MCPhysReg QRegList[] = { ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3 };
     172             : 
     173             : 
     174             : // Allocate part of an AAPCS HFA or HVA. We assume that each member of the HA
     175             : // has InConsecutiveRegs set, and that the last member also has
     176             : // InConsecutiveRegsLast set. We must process all members of the HA before
     177             : // we can allocate it, as we need to know the total number of registers that
     178             : // will be needed in order to (attempt to) allocate a contiguous block.
     179        2438 : static bool CC_ARM_AAPCS_Custom_Aggregate(unsigned &ValNo, MVT &ValVT,
     180             :                                           MVT &LocVT,
     181             :                                           CCValAssign::LocInfo &LocInfo,
     182             :                                           ISD::ArgFlagsTy &ArgFlags,
     183             :                                           CCState &State) {
     184        2438 :   SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs();
     185             : 
     186             :   // AAPCS HFAs must have 1-4 elements, all of the same type
     187        4876 :   if (PendingMembers.size() > 0)
     188             :     assert(PendingMembers[0].getLocVT() == LocVT);
     189             : 
     190             :   // Add the argument to the list to be allocated once we know the size of the
     191             :   // aggregate. Store the type's required alignmnent as extra info for later: in
     192             :   // the [N x i64] case all trace has been removed by the time we actually get
     193             :   // to do allocation.
     194        4876 :   PendingMembers.push_back(CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo,
     195        2438 :                                                    ArgFlags.getOrigAlign()));
     196             : 
     197        2438 :   if (!ArgFlags.isInConsecutiveRegsLast())
     198             :     return true;
     199             : 
     200             :   // Try to allocate a contiguous block of registers, each of the correct
     201             :   // size to hold one member.
     202        2290 :   auto &DL = State.getMachineFunction().getDataLayout();
     203        2290 :   unsigned StackAlign = DL.getStackAlignment();
     204        6870 :   unsigned Align = std::min(PendingMembers[0].getExtraInfo(), StackAlign);
     205             : 
     206        2290 :   ArrayRef<MCPhysReg> RegList;
     207        2290 :   switch (LocVT.SimpleTy) {
     208             :   case MVT::i32: {
     209             :     RegList = RRegList;
     210          11 :     unsigned RegIdx = State.getFirstUnallocated(RegList);
     211             : 
     212             :     // First consume all registers that would give an unaligned object. Whether
     213             :     // we go on stack or in regs, no-one will be using them in future.
     214          22 :     unsigned RegAlign = alignTo(Align, 4) / 4;
     215          16 :     while (RegIdx % RegAlign != 0 && RegIdx < RegList.size())
     216          10 :       State.AllocateReg(RegList[RegIdx++]);
     217             : 
     218             :     break;
     219             :   }
     220             :   case MVT::f32:
     221             :     RegList = SRegList;
     222             :     break;
     223        1196 :   case MVT::f64:
     224        1196 :     RegList = DRegList;
     225             :     break;
     226         133 :   case MVT::v2f64:
     227         133 :     RegList = QRegList;
     228             :     break;
     229           0 :   default:
     230           0 :     llvm_unreachable("Unexpected member type for block aggregate");
     231             :     break;
     232             :   }
     233             : 
     234        4580 :   unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size());
     235        2290 :   if (RegResult) {
     236        6750 :     for (SmallVectorImpl<CCValAssign>::iterator It = PendingMembers.begin();
     237        9068 :          It != PendingMembers.end(); ++It) {
     238        2318 :       It->convertToReg(RegResult);
     239        4636 :       State.addLoc(*It);
     240        2318 :       ++RegResult;
     241             :     }
     242        2216 :     PendingMembers.clear();
     243             :     return true;
     244             :   }
     245             : 
     246             :   // Register allocation failed, we'll be needing the stack
     247          74 :   unsigned Size = LocVT.getSizeInBits() / 8;
     248         148 :   if (LocVT == MVT::i32 && State.getNextStackOffset() == 0) {
     249             :     // If nothing else has used the stack until this point, a non-HFA aggregate
     250             :     // can be split between regs and stack.
     251           4 :     unsigned RegIdx = State.getFirstUnallocated(RegList);
     252          39 :     for (auto &It : PendingMembers) {
     253          27 :       if (RegIdx >= RegList.size())
     254          20 :         It.convertToMem(State.AllocateStack(Size, Size));
     255             :       else
     256          14 :         It.convertToReg(State.AllocateReg(RegList[RegIdx++]));
     257             : 
     258          54 :       State.addLoc(It);
     259             :     }
     260           4 :     PendingMembers.clear();
     261             :     return true;
     262          70 :   } else if (LocVT != MVT::i32)
     263          67 :     RegList = SRegList;
     264             : 
     265             :   // Mark all regs as unavailable (AAPCS rule C.2.vfp for VFP, C.6 for core)
     266        1224 :   for (auto Reg : RegList)
     267        1084 :     State.AllocateReg(Reg);
     268             : 
     269         303 :   for (auto &It : PendingMembers) {
     270         186 :     It.convertToMem(State.AllocateStack(Size, Align));
     271         186 :     State.addLoc(It);
     272             : 
     273             :     // After the first item has been allocated, the rest are packed as tightly
     274             :     // as possible. (E.g. an incoming i64 would have starting Align of 8, but
     275             :     // we'll be allocating a bunch of i32 slots).
     276          93 :     Align = Size;
     277             :   }
     278             : 
     279             :   // All pending members have now been allocated
     280          70 :   PendingMembers.clear();
     281             : 
     282             :   // This will be allocated by the last member of the aggregate
     283             :   return true;
     284             : }
     285             : 
     286             : } // End llvm namespace
     287             : 
     288             : #endif

Generated by: LCOV version 1.13