LLVM API Documentation
00001 //=== ARMCallingConv.h - ARM Custom Calling Convention Routines -*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains the custom routines for the ARM Calling Convention that 00011 // aren't done by tablegen. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_LIB_TARGET_ARM_ARMCALLINGCONV_H 00016 #define LLVM_LIB_TARGET_ARM_ARMCALLINGCONV_H 00017 00018 #include "ARM.h" 00019 #include "ARMBaseInstrInfo.h" 00020 #include "ARMSubtarget.h" 00021 #include "llvm/CodeGen/CallingConvLower.h" 00022 #include "llvm/IR/CallingConv.h" 00023 #include "llvm/Target/TargetInstrInfo.h" 00024 00025 namespace llvm { 00026 00027 // APCS f64 is in register pairs, possibly split to stack 00028 static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 00029 CCValAssign::LocInfo &LocInfo, 00030 CCState &State, bool CanFail) { 00031 static const MCPhysReg RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; 00032 00033 // Try to get the first register. 00034 if (unsigned Reg = State.AllocateReg(RegList, 4)) 00035 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 00036 else { 00037 // For the 2nd half of a v2f64, do not fail. 00038 if (CanFail) 00039 return false; 00040 00041 // Put the whole thing on the stack. 00042 State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 00043 State.AllocateStack(8, 4), 00044 LocVT, LocInfo)); 00045 return true; 00046 } 00047 00048 // Try to get the second register. 00049 if (unsigned Reg = State.AllocateReg(RegList, 4)) 00050 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 00051 else 00052 State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 00053 State.AllocateStack(4, 4), 00054 LocVT, LocInfo)); 00055 return true; 00056 } 00057 00058 static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 00059 CCValAssign::LocInfo &LocInfo, 00060 ISD::ArgFlagsTy &ArgFlags, 00061 CCState &State) { 00062 if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) 00063 return false; 00064 if (LocVT == MVT::v2f64 && 00065 !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) 00066 return false; 00067 return true; // we handled it 00068 } 00069 00070 // AAPCS f64 is in aligned register pairs 00071 static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 00072 CCValAssign::LocInfo &LocInfo, 00073 CCState &State, bool CanFail) { 00074 static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 }; 00075 static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 }; 00076 static const MCPhysReg ShadowRegList[] = { ARM::R0, ARM::R1 }; 00077 static const MCPhysReg GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; 00078 00079 unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2); 00080 if (Reg == 0) { 00081 00082 // If we had R3 unallocated only, now we still must to waste it. 00083 Reg = State.AllocateReg(GPRArgRegs, 4); 00084 assert((!Reg || Reg == ARM::R3) && "Wrong GPRs usage for f64"); 00085 00086 // For the 2nd half of a v2f64, do not just fail. 00087 if (CanFail) 00088 return false; 00089 00090 // Put the whole thing on the stack. 00091 State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 00092 State.AllocateStack(8, 8), 00093 LocVT, LocInfo)); 00094 return true; 00095 } 00096 00097 unsigned i; 00098 for (i = 0; i < 2; ++i) 00099 if (HiRegList[i] == Reg) 00100 break; 00101 00102 unsigned T = State.AllocateReg(LoRegList[i]); 00103 (void)T; 00104 assert(T == LoRegList[i] && "Could not allocate register"); 00105 00106 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 00107 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], 00108 LocVT, LocInfo)); 00109 return true; 00110 } 00111 00112 static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 00113 CCValAssign::LocInfo &LocInfo, 00114 ISD::ArgFlagsTy &ArgFlags, 00115 CCState &State) { 00116 if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) 00117 return false; 00118 if (LocVT == MVT::v2f64 && 00119 !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) 00120 return false; 00121 return true; // we handled it 00122 } 00123 00124 static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 00125 CCValAssign::LocInfo &LocInfo, CCState &State) { 00126 static const MCPhysReg HiRegList[] = { ARM::R0, ARM::R2 }; 00127 static const MCPhysReg LoRegList[] = { ARM::R1, ARM::R3 }; 00128 00129 unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2); 00130 if (Reg == 0) 00131 return false; // we didn't handle it 00132 00133 unsigned i; 00134 for (i = 0; i < 2; ++i) 00135 if (HiRegList[i] == Reg) 00136 break; 00137 00138 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 00139 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], 00140 LocVT, LocInfo)); 00141 return true; 00142 } 00143 00144 static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 00145 CCValAssign::LocInfo &LocInfo, 00146 ISD::ArgFlagsTy &ArgFlags, 00147 CCState &State) { 00148 if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) 00149 return false; 00150 if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) 00151 return false; 00152 return true; // we handled it 00153 } 00154 00155 static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 00156 CCValAssign::LocInfo &LocInfo, 00157 ISD::ArgFlagsTy &ArgFlags, 00158 CCState &State) { 00159 return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, 00160 State); 00161 } 00162 00163 static const uint16_t SRegList[] = { ARM::S0, ARM::S1, ARM::S2, ARM::S3, 00164 ARM::S4, ARM::S5, ARM::S6, ARM::S7, 00165 ARM::S8, ARM::S9, ARM::S10, ARM::S11, 00166 ARM::S12, ARM::S13, ARM::S14, ARM::S15 }; 00167 static const uint16_t DRegList[] = { ARM::D0, ARM::D1, ARM::D2, ARM::D3, 00168 ARM::D4, ARM::D5, ARM::D6, ARM::D7 }; 00169 static const uint16_t QRegList[] = { ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3 }; 00170 00171 // Allocate part of an AAPCS HFA or HVA. We assume that each member of the HA 00172 // has InConsecutiveRegs set, and that the last member also has 00173 // InConsecutiveRegsLast set. We must process all members of the HA before 00174 // we can allocate it, as we need to know the total number of registers that 00175 // will be needed in order to (attempt to) allocate a contiguous block. 00176 static bool CC_ARM_AAPCS_Custom_HA(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 00177 CCValAssign::LocInfo &LocInfo, 00178 ISD::ArgFlagsTy &ArgFlags, CCState &State) { 00179 SmallVectorImpl<CCValAssign> &PendingHAMembers = State.getPendingLocs(); 00180 00181 // AAPCS HFAs must have 1-4 elements, all of the same type 00182 assert(PendingHAMembers.size() < 4); 00183 if (PendingHAMembers.size() > 0) 00184 assert(PendingHAMembers[0].getLocVT() == LocVT); 00185 00186 // Add the argument to the list to be allocated once we know the size of the 00187 // HA 00188 PendingHAMembers.push_back( 00189 CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo)); 00190 00191 if (ArgFlags.isInConsecutiveRegsLast()) { 00192 assert(PendingHAMembers.size() > 0 && PendingHAMembers.size() <= 4 && 00193 "Homogeneous aggregates must have between 1 and 4 members"); 00194 00195 // Try to allocate a contiguous block of registers, each of the correct 00196 // size to hold one member. 00197 const uint16_t *RegList; 00198 unsigned NumRegs; 00199 switch (LocVT.SimpleTy) { 00200 case MVT::f32: 00201 RegList = SRegList; 00202 NumRegs = 16; 00203 break; 00204 case MVT::f64: 00205 RegList = DRegList; 00206 NumRegs = 8; 00207 break; 00208 case MVT::v2f64: 00209 RegList = QRegList; 00210 NumRegs = 4; 00211 break; 00212 default: 00213 llvm_unreachable("Unexpected member type for HA"); 00214 break; 00215 } 00216 00217 unsigned RegResult = 00218 State.AllocateRegBlock(RegList, NumRegs, PendingHAMembers.size()); 00219 00220 if (RegResult) { 00221 for (SmallVectorImpl<CCValAssign>::iterator It = PendingHAMembers.begin(); 00222 It != PendingHAMembers.end(); ++It) { 00223 It->convertToReg(RegResult); 00224 State.addLoc(*It); 00225 ++RegResult; 00226 } 00227 PendingHAMembers.clear(); 00228 return true; 00229 } 00230 00231 // Register allocation failed, fall back to the stack 00232 00233 // Mark all VFP regs as unavailable (AAPCS rule C.2.vfp) 00234 for (unsigned regNo = 0; regNo < 16; ++regNo) 00235 State.AllocateReg(SRegList[regNo]); 00236 00237 unsigned Size = LocVT.getSizeInBits() / 8; 00238 unsigned Align = std::min(Size, 8U); 00239 00240 for (auto It : PendingHAMembers) { 00241 It.convertToMem(State.AllocateStack(Size, Align)); 00242 State.addLoc(It); 00243 } 00244 00245 // All pending members have now been allocated 00246 PendingHAMembers.clear(); 00247 } 00248 00249 // This will be allocated by the last member of the HA 00250 return true; 00251 } 00252 00253 } // End llvm namespace 00254 00255 #endif