Home | History | Annotate | Download | only in ARM
      1 //===-- ARMCallingConv.h - ARM Custom Calling Convention Routines ---------===//
      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 ARMCALLINGCONV_H
     16 #define ARMCALLINGCONV_H
     17 
     18 #include "llvm/CallingConv.h"
     19 #include "llvm/CodeGen/CallingConvLower.h"
     20 #include "llvm/Target/TargetInstrInfo.h"
     21 #include "ARMBaseInstrInfo.h"
     22 #include "ARMRegisterInfo.h"
     23 #include "ARMSubtarget.h"
     24 #include "ARM.h"
     25 
     26 namespace llvm {
     27 
     28 // APCS f64 is in register pairs, possibly split to stack
     29 static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
     30                           CCValAssign::LocInfo &LocInfo,
     31                           CCState &State, bool CanFail) {
     32   static const unsigned RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
     33 
     34   // Try to get the first register.
     35   if (unsigned Reg = State.AllocateReg(RegList, 4))
     36     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
     37   else {
     38     // For the 2nd half of a v2f64, do not fail.
     39     if (CanFail)
     40       return false;
     41 
     42     // Put the whole thing on the stack.
     43     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
     44                                            State.AllocateStack(8, 4),
     45                                            LocVT, LocInfo));
     46     return true;
     47   }
     48 
     49   // Try to get the second register.
     50   if (unsigned Reg = State.AllocateReg(RegList, 4))
     51     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
     52   else
     53     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
     54                                            State.AllocateStack(4, 4),
     55                                            LocVT, LocInfo));
     56   return true;
     57 }
     58 
     59 static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
     60                                    CCValAssign::LocInfo &LocInfo,
     61                                    ISD::ArgFlagsTy &ArgFlags,
     62                                    CCState &State) {
     63   if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
     64     return false;
     65   if (LocVT == MVT::v2f64 &&
     66       !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
     67     return false;
     68   return true;  // we handled it
     69 }
     70 
     71 // AAPCS f64 is in aligned register pairs
     72 static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
     73                            CCValAssign::LocInfo &LocInfo,
     74                            CCState &State, bool CanFail) {
     75   static const unsigned HiRegList[] = { ARM::R0, ARM::R2 };
     76   static const unsigned LoRegList[] = { ARM::R1, ARM::R3 };
     77   static const unsigned ShadowRegList[] = { ARM::R0, ARM::R1 };
     78 
     79   unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2);
     80   if (Reg == 0) {
     81     // For the 2nd half of a v2f64, do not just fail.
     82     if (CanFail)
     83       return false;
     84 
     85     // Put the whole thing on the stack.
     86     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
     87                                            State.AllocateStack(8, 8),
     88                                            LocVT, LocInfo));
     89     return true;
     90   }
     91 
     92   unsigned i;
     93   for (i = 0; i < 2; ++i)
     94     if (HiRegList[i] == Reg)
     95       break;
     96 
     97   unsigned T = State.AllocateReg(LoRegList[i]);
     98   (void)T;
     99   assert(T == LoRegList[i] && "Could not allocate register");
    100 
    101   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
    102   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
    103                                          LocVT, LocInfo));
    104   return true;
    105 }
    106 
    107 static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
    108                                     CCValAssign::LocInfo &LocInfo,
    109                                     ISD::ArgFlagsTy &ArgFlags,
    110                                     CCState &State) {
    111   if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
    112     return false;
    113   if (LocVT == MVT::v2f64 &&
    114       !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
    115     return false;
    116   return true;  // we handled it
    117 }
    118 
    119 static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
    120                          CCValAssign::LocInfo &LocInfo, CCState &State) {
    121   static const unsigned HiRegList[] = { ARM::R0, ARM::R2 };
    122   static const unsigned LoRegList[] = { ARM::R1, ARM::R3 };
    123 
    124   unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2);
    125   if (Reg == 0)
    126     return false; // we didn't handle it
    127 
    128   unsigned i;
    129   for (i = 0; i < 2; ++i)
    130     if (HiRegList[i] == Reg)
    131       break;
    132 
    133   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
    134   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
    135                                          LocVT, LocInfo));
    136   return true;
    137 }
    138 
    139 static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
    140                                       CCValAssign::LocInfo &LocInfo,
    141                                       ISD::ArgFlagsTy &ArgFlags,
    142                                       CCState &State) {
    143   if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
    144     return false;
    145   if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
    146     return false;
    147   return true;  // we handled it
    148 }
    149 
    150 static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
    151                                        CCValAssign::LocInfo &LocInfo,
    152                                        ISD::ArgFlagsTy &ArgFlags,
    153                                        CCState &State) {
    154   return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags,
    155                                    State);
    156 }
    157 
    158 } // End llvm namespace
    159 
    160 #endif
    161