| //===-- ARMCallingConv.h - ARM Custom Calling Convention Routines ---------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file contains the custom routines for the ARM Calling Convention that | |
| // aren't done by tablegen. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef ARMCALLINGCONV_H | |
| #define ARMCALLINGCONV_H | |
| #include "llvm/CallingConv.h" | |
| #include "llvm/CodeGen/CallingConvLower.h" | |
| #include "llvm/Target/TargetInstrInfo.h" | |
| #include "ARMBaseInstrInfo.h" | |
| #include "ARMRegisterInfo.h" | |
| #include "ARMSubtarget.h" | |
| #include "ARM.h" | |
| namespace llvm { | |
| // APCS f64 is in register pairs, possibly split to stack | |
| static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | |
| CCValAssign::LocInfo &LocInfo, | |
| CCState &State, bool CanFail) { | |
| static const unsigned RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; | |
| // Try to get the first register. | |
| if (unsigned Reg = State.AllocateReg(RegList, 4)) | |
| State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | |
| else { | |
| // For the 2nd half of a v2f64, do not fail. | |
| if (CanFail) | |
| return false; | |
| // Put the whole thing on the stack. | |
| State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | |
| State.AllocateStack(8, 4), | |
| LocVT, LocInfo)); | |
| return true; | |
| } | |
| // Try to get the second register. | |
| if (unsigned Reg = State.AllocateReg(RegList, 4)) | |
| State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | |
| else | |
| State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | |
| State.AllocateStack(4, 4), | |
| LocVT, LocInfo)); | |
| return true; | |
| } | |
| static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | |
| CCValAssign::LocInfo &LocInfo, | |
| ISD::ArgFlagsTy &ArgFlags, | |
| CCState &State) { | |
| if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) | |
| return false; | |
| if (LocVT == MVT::v2f64 && | |
| !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) | |
| return false; | |
| return true; // we handled it | |
| } | |
| // AAPCS f64 is in aligned register pairs | |
| static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | |
| CCValAssign::LocInfo &LocInfo, | |
| CCState &State, bool CanFail) { | |
| static const unsigned HiRegList[] = { ARM::R0, ARM::R2 }; | |
| static const unsigned LoRegList[] = { ARM::R1, ARM::R3 }; | |
| static const unsigned ShadowRegList[] = { ARM::R0, ARM::R1 }; | |
| unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2); | |
| if (Reg == 0) { | |
| // For the 2nd half of a v2f64, do not just fail. | |
| if (CanFail) | |
| return false; | |
| // Put the whole thing on the stack. | |
| State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, | |
| State.AllocateStack(8, 8), | |
| LocVT, LocInfo)); | |
| return true; | |
| } | |
| unsigned i; | |
| for (i = 0; i < 2; ++i) | |
| if (HiRegList[i] == Reg) | |
| break; | |
| unsigned T = State.AllocateReg(LoRegList[i]); | |
| (void)T; | |
| assert(T == LoRegList[i] && "Could not allocate register"); | |
| State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | |
| State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], | |
| LocVT, LocInfo)); | |
| return true; | |
| } | |
| static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | |
| CCValAssign::LocInfo &LocInfo, | |
| ISD::ArgFlagsTy &ArgFlags, | |
| CCState &State) { | |
| if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) | |
| return false; | |
| if (LocVT == MVT::v2f64 && | |
| !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) | |
| return false; | |
| return true; // we handled it | |
| } | |
| static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | |
| CCValAssign::LocInfo &LocInfo, CCState &State) { | |
| static const unsigned HiRegList[] = { ARM::R0, ARM::R2 }; | |
| static const unsigned LoRegList[] = { ARM::R1, ARM::R3 }; | |
| unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2); | |
| if (Reg == 0) | |
| return false; // we didn't handle it | |
| unsigned i; | |
| for (i = 0; i < 2; ++i) | |
| if (HiRegList[i] == Reg) | |
| break; | |
| State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); | |
| State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], | |
| LocVT, LocInfo)); | |
| return true; | |
| } | |
| static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | |
| CCValAssign::LocInfo &LocInfo, | |
| ISD::ArgFlagsTy &ArgFlags, | |
| CCState &State) { | |
| if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) | |
| return false; | |
| if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) | |
| return false; | |
| return true; // we handled it | |
| } | |
| static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | |
| CCValAssign::LocInfo &LocInfo, | |
| ISD::ArgFlagsTy &ArgFlags, | |
| CCState &State) { | |
| return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, | |
| State); | |
| } | |
| } // End llvm namespace | |
| #endif |