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 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