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