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