1 //===-- PPCCallingConv.h - --------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PPCRegisterInfo.h" 10 #include "PPCCallingConv.h" 11 #include "PPCSubtarget.h" 12 #include "PPCCCState.h" 13 using namespace llvm; 14 15 inline bool CC_PPC_AnyReg_Error(unsigned &, MVT &, MVT &, 16 CCValAssign::LocInfo &, ISD::ArgFlagsTy &, 17 CCState &) { 18 llvm_unreachable("The AnyReg calling convention is only supported by the " \ 19 "stackmap and patchpoint intrinsics."); 20 // gracefully fallback to PPC C calling convention on Release builds. 21 return false; 22 } 23 24 static bool CC_PPC32_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 25 CCValAssign::LocInfo &LocInfo, 26 ISD::ArgFlagsTy &ArgFlags, 27 CCState &State) { 28 return true; 29 } 30 31 static bool CC_PPC32_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT, 32 MVT &LocVT, 33 CCValAssign::LocInfo &LocInfo, 34 ISD::ArgFlagsTy &ArgFlags, 35 CCState &State) { 36 static const MCPhysReg ArgRegs[] = { 37 PPC::R3, PPC::R4, PPC::R5, PPC::R6, 38 PPC::R7, PPC::R8, PPC::R9, PPC::R10, 39 }; 40 const unsigned NumArgRegs = array_lengthof(ArgRegs); 41 42 unsigned RegNum = State.getFirstUnallocated(ArgRegs); 43 44 // Skip one register if the first unallocated register has an even register 45 // number and there are still argument registers available which have not been 46 // allocated yet. RegNum is actually an index into ArgRegs, which means we 47 // need to skip a register if RegNum is odd. 48 if (RegNum != NumArgRegs && RegNum % 2 == 1) { 49 State.AllocateReg(ArgRegs[RegNum]); 50 } 51 52 // Always return false here, as this function only makes sure that the first 53 // unallocated register has an odd register number and does not actually 54 // allocate a register for the current argument. 55 return false; 56 } 57 58 static bool CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128( 59 unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, 60 ISD::ArgFlagsTy &ArgFlags, CCState &State) { 61 static const MCPhysReg ArgRegs[] = { 62 PPC::R3, PPC::R4, PPC::R5, PPC::R6, 63 PPC::R7, PPC::R8, PPC::R9, PPC::R10, 64 }; 65 const unsigned NumArgRegs = array_lengthof(ArgRegs); 66 67 unsigned RegNum = State.getFirstUnallocated(ArgRegs); 68 int RegsLeft = NumArgRegs - RegNum; 69 70 // Skip if there is not enough registers left for long double type (4 gpr regs 71 // in soft float mode) and put long double argument on the stack. 72 if (RegNum != NumArgRegs && RegsLeft < 4) { 73 for (int i = 0; i < RegsLeft; i++) { 74 State.AllocateReg(ArgRegs[RegNum + i]); 75 } 76 } 77 78 return false; 79 } 80 81 static bool CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, 82 MVT &LocVT, 83 CCValAssign::LocInfo &LocInfo, 84 ISD::ArgFlagsTy &ArgFlags, 85 CCState &State) { 86 static const MCPhysReg ArgRegs[] = { 87 PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, 88 PPC::F8 89 }; 90 91 const unsigned NumArgRegs = array_lengthof(ArgRegs); 92 93 unsigned RegNum = State.getFirstUnallocated(ArgRegs); 94 95 // If there is only one Floating-point register left we need to put both f64 96 // values of a split ppc_fp128 value on the stack. 97 if (RegNum != NumArgRegs && ArgRegs[RegNum] == PPC::F8) { 98 State.AllocateReg(ArgRegs[RegNum]); 99 } 100 101 // Always return false here, as this function only makes sure that the two f64 102 // values a ppc_fp128 value is split into are both passed in registers or both 103 // passed on the stack and does not actually allocate a register for the 104 // current argument. 105 return false; 106 } 107 108 // Split F64 arguments into two 32-bit consecutive registers. 109 static bool CC_PPC32_SPE_CustomSplitFP64(unsigned &ValNo, MVT &ValVT, 110 MVT &LocVT, 111 CCValAssign::LocInfo &LocInfo, 112 ISD::ArgFlagsTy &ArgFlags, 113 CCState &State) { 114 static const MCPhysReg HiRegList[] = { PPC::R3, PPC::R5, PPC::R7, PPC::R9 }; 115 static const MCPhysReg LoRegList[] = { PPC::R4, PPC::R6, PPC::R8, PPC::R10 }; 116 117 // Try to get the first register. 118 unsigned Reg = State.AllocateReg(HiRegList); 119 if (!Reg) 120 return false; 121 122 unsigned i; 123 for (i = 0; i < sizeof(HiRegList) / sizeof(HiRegList[0]); ++i) 124 if (HiRegList[i] == Reg) 125 break; 126 127 unsigned T = State.AllocateReg(LoRegList[i]); 128 (void)T; 129 assert(T == LoRegList[i] && "Could not allocate register"); 130 131 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 132 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], 133 LocVT, LocInfo)); 134 return true; 135 } 136 137 // Same as above, but for return values, so only allocate for R3 and R4 138 static bool CC_PPC32_SPE_RetF64(unsigned &ValNo, MVT &ValVT, 139 MVT &LocVT, 140 CCValAssign::LocInfo &LocInfo, 141 ISD::ArgFlagsTy &ArgFlags, 142 CCState &State) { 143 static const MCPhysReg HiRegList[] = { PPC::R3 }; 144 static const MCPhysReg LoRegList[] = { PPC::R4 }; 145 146 // Try to get the first register. 147 unsigned Reg = State.AllocateReg(HiRegList, LoRegList); 148 if (!Reg) 149 return false; 150 151 unsigned i; 152 for (i = 0; i < sizeof(HiRegList) / sizeof(HiRegList[0]); ++i) 153 if (HiRegList[i] == Reg) 154 break; 155 156 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 157 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], 158 LocVT, LocInfo)); 159 return true; 160 } 161 162 #include "PPCGenCallingConv.inc" 163