LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMCallingConv.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 77 79 97.5 %
Date: 2018-06-17 00:07:59 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/CodeGen/TargetInstrInfo.h"
      23             : #include "llvm/IR/CallingConv.h"
      24             : 
      25             : namespace llvm {
      26             : 
      27             : // APCS f64 is in register pairs, possibly split to stack
      28         888 : 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         888 :   if (unsigned Reg = State.AllocateReg(RegList))
      35        1206 :     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
      36             :   else {
      37             :     // For the 2nd half of a v2f64, do not fail.
      38         486 :     if (CanFail)
      39             :       return false;
      40             : 
      41             :     // Put the whole thing on the stack.
      42          10 :     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
      43             :                                            State.AllocateStack(8, 4),
      44           5 :                                            LocVT, LocInfo));
      45           5 :     return true;
      46             :   }
      47             : 
      48             :   // Try to get the second register.
      49         402 :   if (unsigned Reg = State.AllocateReg(RegList))
      50        1092 :     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
      51             :   else
      52          76 :     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
      53             :                                            State.AllocateStack(4, 4),
      54          38 :                                            LocVT, LocInfo));
      55             :   return true;
      56             : }
      57             : 
      58         804 : 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         804 :   if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
      63             :     return false;
      64         407 :   if (LocVT == MVT::v2f64 &&
      65          84 :       !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        1610 : 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        1610 :   unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList);
      80        1610 :   if (Reg == 0) {
      81             : 
      82             :     // If we had R3 unallocated only, now we still must to waste it.
      83         365 :     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         365 :     if (CanFail)
      88             :       return false;
      89             : 
      90             :     // Put the whole thing on the stack.
      91          30 :     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
      92             :                                            State.AllocateStack(8, 8),
      93          15 :                                            LocVT, LocInfo));
      94          15 :     return true;
      95             :   }
      96             : 
      97             :   unsigned i;
      98        2261 :   for (i = 0; i < 2; ++i)
      99        1753 :     if (HiRegList[i] == Reg)
     100             :       break;
     101             : 
     102        1245 :   unsigned T = State.AllocateReg(LoRegList[i]);
     103             :   (void)T;
     104             :   assert(T == LoRegList[i] && "Could not allocate register");
     105             : 
     106        3735 :   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
     107        2490 :   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
     108        1245 :                                          LocVT, LocInfo));
     109        1245 :   return true;
     110             : }
     111             : 
     112        1426 : 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        1426 :   if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
     117             :     return false;
     118        1260 :   if (LocVT == MVT::v2f64 &&
     119         184 :       !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
     120             :     return false;
     121             :   return true;  // we handled it
     122             : }
     123             : 
     124        5835 : 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        5835 :   unsigned Reg = State.AllocateReg(HiRegList, LoRegList);
     130        5835 :   if (Reg == 0)
     131             :     return false; // we didn't handle it
     132             : 
     133             :   unsigned i;
     134        9263 :   for (i = 0; i < 2; ++i)
     135        7527 :     if (HiRegList[i] == Reg)
     136             :       break;
     137             : 
     138       17373 :   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
     139       17373 :   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
     140       11582 :                                          LocVT, LocInfo));
     141        5791 :   return true;
     142             : }
     143             : 
     144        4126 : 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        4126 :   if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
     149             :     return false;
     150        4082 :   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        3674 :                                    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        2934 : 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             :   SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs();
     185             : 
     186             :   // AAPCS HFAs must have 1-4 elements, all of the same type
     187             :   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        5868 :   PendingMembers.push_back(CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo,
     195        2934 :                                                    ArgFlags.getOrigAlign()));
     196             : 
     197        2934 :   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        2786 :   auto &DL = State.getMachineFunction().getDataLayout();
     203        2786 :   unsigned StackAlign = DL.getStackAlignment();
     204        5572 :   unsigned Align = std::min(PendingMembers[0].getExtraInfo(), StackAlign);
     205             : 
     206             :   ArrayRef<MCPhysReg> RegList;
     207        2786 :   switch (LocVT.SimpleTy) {
     208             :   case MVT::i32: {
     209             :     RegList = RRegList;
     210             :     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::f16:
     221             :   case MVT::f32:
     222             :     RegList = SRegList;
     223             :     break;
     224             :   case MVT::v4f16:
     225             :   case MVT::f64:
     226             :     RegList = DRegList;
     227             :     break;
     228             :   case MVT::v8f16:
     229             :   case MVT::v2f64:
     230             :     RegList = QRegList;
     231             :     break;
     232           0 :   default:
     233           0 :     llvm_unreachable("Unexpected member type for block aggregate");
     234             :     break;
     235             :   }
     236             : 
     237        2786 :   unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size());
     238        2786 :   if (RegResult) {
     239        2814 :     for (SmallVectorImpl<CCValAssign>::iterator It = PendingMembers.begin();
     240        5526 :          It != PendingMembers.end(); ++It) {
     241             :       It->convertToReg(RegResult);
     242        2814 :       State.addLoc(*It);
     243        2814 :       ++RegResult;
     244             :     }
     245             :     PendingMembers.clear();
     246             :     return true;
     247             :   }
     248             : 
     249             :   // Register allocation failed, we'll be needing the stack
     250          74 :   unsigned Size = LocVT.getSizeInBits() / 8;
     251          74 :   if (LocVT == MVT::i32 && State.getNextStackOffset() == 0) {
     252             :     // If nothing else has used the stack until this point, a non-HFA aggregate
     253             :     // can be split between regs and stack.
     254             :     unsigned RegIdx = State.getFirstUnallocated(RegList);
     255          58 :     for (auto &It : PendingMembers) {
     256          27 :       if (RegIdx >= RegList.size())
     257          20 :         It.convertToMem(State.AllocateStack(Size, Size));
     258             :       else
     259          14 :         It.convertToReg(State.AllocateReg(RegList[RegIdx++]));
     260             : 
     261          27 :       State.addLoc(It);
     262             :     }
     263             :     PendingMembers.clear();
     264             :     return true;
     265          70 :   } else if (LocVT != MVT::i32)
     266             :     RegList = SRegList;
     267             : 
     268             :   // Mark all regs as unavailable (AAPCS rule C.2.vfp for VFP, C.6 for core)
     269        2238 :   for (auto Reg : RegList)
     270        1084 :     State.AllocateReg(Reg);
     271             : 
     272         256 :   for (auto &It : PendingMembers) {
     273          93 :     It.convertToMem(State.AllocateStack(Size, Align));
     274          93 :     State.addLoc(It);
     275             : 
     276             :     // After the first item has been allocated, the rest are packed as tightly
     277             :     // as possible. (E.g. an incoming i64 would have starting Align of 8, but
     278             :     // we'll be allocating a bunch of i32 slots).
     279             :     Align = Size;
     280             :   }
     281             : 
     282             :   // All pending members have now been allocated
     283             :   PendingMembers.clear();
     284             : 
     285             :   // This will be allocated by the last member of the aggregate
     286             :   return true;
     287             : }
     288             : 
     289             : } // End llvm namespace
     290             : 
     291             : #endif

Generated by: LCOV version 1.13