ARMCallingConv.h revision c5eaae4e9bc75b203b3a9922b480729bc4f340e2
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 "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 26namespace llvm { 27 28// APCS f64 is in register pairs, possibly split to stack 29static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 30 CCValAssign::LocInfo &LocInfo, 31 CCState &State, bool CanFail) { 32 static const uint16_t 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 59static 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 72static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 73 CCValAssign::LocInfo &LocInfo, 74 CCState &State, bool CanFail) { 75 static const uint16_t HiRegList[] = { ARM::R0, ARM::R2 }; 76 static const uint16_t LoRegList[] = { ARM::R1, ARM::R3 }; 77 static const uint16_t 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 107static 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 119static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 120 CCValAssign::LocInfo &LocInfo, CCState &State) { 121 static const uint16_t HiRegList[] = { ARM::R0, ARM::R2 }; 122 static const uint16_t 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 139static 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 150static 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