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/CodeGen/CallingConvLower.h" 22 #include "llvm/IR/CallingConv.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 static const uint16_t GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; 78 79 unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2); 80 if (Reg == 0) { 81 82 // If we had R3 unallocated only, now we still must to waste it. 83 Reg = State.AllocateReg(GPRArgRegs, 4); 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 if (CanFail) 88 return false; 89 90 // Put the whole thing on the stack. 91 State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 92 State.AllocateStack(8, 8), 93 LocVT, LocInfo)); 94 return true; 95 } 96 97 unsigned i; 98 for (i = 0; i < 2; ++i) 99 if (HiRegList[i] == Reg) 100 break; 101 102 unsigned T = State.AllocateReg(LoRegList[i]); 103 (void)T; 104 assert(T == LoRegList[i] && "Could not allocate register"); 105 106 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 107 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], 108 LocVT, LocInfo)); 109 return true; 110 } 111 112 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 if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) 117 return false; 118 if (LocVT == MVT::v2f64 && 119 !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) 120 return false; 121 return true; // we handled it 122 } 123 124 static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 125 CCValAssign::LocInfo &LocInfo, CCState &State) { 126 static const uint16_t HiRegList[] = { ARM::R0, ARM::R2 }; 127 static const uint16_t LoRegList[] = { ARM::R1, ARM::R3 }; 128 129 unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2); 130 if (Reg == 0) 131 return false; // we didn't handle it 132 133 unsigned i; 134 for (i = 0; i < 2; ++i) 135 if (HiRegList[i] == Reg) 136 break; 137 138 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 139 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], 140 LocVT, LocInfo)); 141 return true; 142 } 143 144 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 if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) 149 return false; 150 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 State); 161 } 162 163 } // End llvm namespace 164 165 #endif 166