1 | //===-- PPCCallingConv.cpp - ------------------------------------*- 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 "PPCCallingConv.h" |
10 | #include "PPCSubtarget.h" |
11 | #include "PPCCCState.h" |
12 | using namespace llvm; |
13 | |
14 | inline bool CC_PPC_AnyReg_Error(unsigned &, MVT &, MVT &, |
15 | CCValAssign::LocInfo &, ISD::ArgFlagsTy &, |
16 | CCState &) { |
17 | llvm_unreachable("The AnyReg calling convention is only supported by the " \ |
18 | "stackmap and patchpoint intrinsics." ); |
19 | // gracefully fallback to PPC C calling convention on Release builds. |
20 | return false; |
21 | } |
22 | |
23 | // This function handles the shadowing of GPRs for fp and vector types, |
24 | // and is a depiction of the algorithm described in the ELFv2 ABI, |
25 | // Section 2.2.4.1: Parameter Passing Register Selection Algorithm. |
26 | inline bool CC_PPC64_ELF_Shadow_GPR_Regs(unsigned &ValNo, MVT &ValVT, |
27 | MVT &LocVT, |
28 | CCValAssign::LocInfo &LocInfo, |
29 | ISD::ArgFlagsTy &ArgFlags, |
30 | CCState &State) { |
31 | |
32 | // The 64-bit ELFv2 ABI-defined parameter passing general purpose registers. |
33 | static const MCPhysReg ELF64ArgGPRs[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6, |
34 | PPC::X7, PPC::X8, PPC::X9, PPC::X10}; |
35 | const unsigned ELF64NumArgGPRs = std::size(ELF64ArgGPRs); |
36 | |
37 | unsigned FirstUnallocGPR = State.getFirstUnallocated(Regs: ELF64ArgGPRs); |
38 | if (FirstUnallocGPR == ELF64NumArgGPRs) |
39 | return false; |
40 | |
41 | // As described in 2.2.4.1 under the "float" section, shadow a single GPR |
42 | // for single/double precision. ppcf128 gets broken up into two doubles |
43 | // and will also shadow GPRs within this section. |
44 | if (LocVT == MVT::f32 || LocVT == MVT::f64) |
45 | State.AllocateReg(Regs: ELF64ArgGPRs); |
46 | else if (LocVT.is128BitVector() || (LocVT == MVT::f128)) { |
47 | // For vector and __float128 (which is represents the "vector" section |
48 | // in 2.2.4.1), shadow two even GPRs (skipping the odd one if it is next |
49 | // in the allocation order). To check if the GPR is even, the specific |
50 | // condition checks if the register allocated is odd, because the even |
51 | // physical registers are odd values. |
52 | if ((State.AllocateReg(Regs: ELF64ArgGPRs) - PPC::X3) % 2 == 1) |
53 | State.AllocateReg(Regs: ELF64ArgGPRs); |
54 | State.AllocateReg(Regs: ELF64ArgGPRs); |
55 | } |
56 | return false; |
57 | } |
58 | |
59 | static bool CC_PPC32_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT, |
60 | CCValAssign::LocInfo &LocInfo, |
61 | ISD::ArgFlagsTy &ArgFlags, |
62 | CCState &State) { |
63 | return true; |
64 | } |
65 | |
66 | static bool CC_PPC32_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT, |
67 | MVT &LocVT, |
68 | CCValAssign::LocInfo &LocInfo, |
69 | ISD::ArgFlagsTy &ArgFlags, |
70 | CCState &State) { |
71 | static const MCPhysReg ArgRegs[] = { |
72 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, |
73 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, |
74 | }; |
75 | const unsigned NumArgRegs = std::size(ArgRegs); |
76 | |
77 | unsigned RegNum = State.getFirstUnallocated(Regs: ArgRegs); |
78 | |
79 | // Skip one register if the first unallocated register has an even register |
80 | // number and there are still argument registers available which have not been |
81 | // allocated yet. RegNum is actually an index into ArgRegs, which means we |
82 | // need to skip a register if RegNum is odd. |
83 | if (RegNum != NumArgRegs && RegNum % 2 == 1) { |
84 | State.AllocateReg(Reg: ArgRegs[RegNum]); |
85 | } |
86 | |
87 | // Always return false here, as this function only makes sure that the first |
88 | // unallocated register has an odd register number and does not actually |
89 | // allocate a register for the current argument. |
90 | return false; |
91 | } |
92 | |
93 | static bool CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128( |
94 | unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, |
95 | ISD::ArgFlagsTy &ArgFlags, CCState &State) { |
96 | static const MCPhysReg ArgRegs[] = { |
97 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, |
98 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, |
99 | }; |
100 | const unsigned NumArgRegs = std::size(ArgRegs); |
101 | |
102 | unsigned RegNum = State.getFirstUnallocated(Regs: ArgRegs); |
103 | int RegsLeft = NumArgRegs - RegNum; |
104 | |
105 | // Skip if there is not enough registers left for long double type (4 gpr regs |
106 | // in soft float mode) and put long double argument on the stack. |
107 | if (RegNum != NumArgRegs && RegsLeft < 4) { |
108 | for (int i = 0; i < RegsLeft; i++) { |
109 | State.AllocateReg(Reg: ArgRegs[RegNum + i]); |
110 | } |
111 | } |
112 | |
113 | return false; |
114 | } |
115 | |
116 | static bool CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, |
117 | MVT &LocVT, |
118 | CCValAssign::LocInfo &LocInfo, |
119 | ISD::ArgFlagsTy &ArgFlags, |
120 | CCState &State) { |
121 | static const MCPhysReg ArgRegs[] = { |
122 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, |
123 | PPC::F8 |
124 | }; |
125 | |
126 | const unsigned NumArgRegs = std::size(ArgRegs); |
127 | |
128 | unsigned RegNum = State.getFirstUnallocated(Regs: ArgRegs); |
129 | |
130 | // If there is only one Floating-point register left we need to put both f64 |
131 | // values of a split ppc_fp128 value on the stack. |
132 | if (RegNum != NumArgRegs && ArgRegs[RegNum] == PPC::F8) { |
133 | State.AllocateReg(Reg: ArgRegs[RegNum]); |
134 | } |
135 | |
136 | // Always return false here, as this function only makes sure that the two f64 |
137 | // values a ppc_fp128 value is split into are both passed in registers or both |
138 | // passed on the stack and does not actually allocate a register for the |
139 | // current argument. |
140 | return false; |
141 | } |
142 | |
143 | // Split F64 arguments into two 32-bit consecutive registers. |
144 | static bool CC_PPC32_SPE_CustomSplitFP64(unsigned &ValNo, MVT &ValVT, |
145 | MVT &LocVT, |
146 | CCValAssign::LocInfo &LocInfo, |
147 | ISD::ArgFlagsTy &ArgFlags, |
148 | CCState &State) { |
149 | static const MCPhysReg HiRegList[] = { PPC::R3, PPC::R5, PPC::R7, PPC::R9 }; |
150 | static const MCPhysReg LoRegList[] = { PPC::R4, PPC::R6, PPC::R8, PPC::R10 }; |
151 | |
152 | // Try to get the first register. |
153 | MCRegister Reg = State.AllocateReg(Regs: HiRegList); |
154 | if (!Reg) |
155 | return false; |
156 | |
157 | unsigned i; |
158 | for (i = 0; i < std::size(HiRegList); ++i) |
159 | if (HiRegList[i] == Reg) |
160 | break; |
161 | |
162 | MCRegister T = State.AllocateReg(Reg: LoRegList[i]); |
163 | (void)T; |
164 | assert(T == LoRegList[i] && "Could not allocate register" ); |
165 | |
166 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, HTP: LocInfo)); |
167 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, Reg: LoRegList[i], |
168 | LocVT, HTP: LocInfo)); |
169 | return true; |
170 | } |
171 | |
172 | // Same as above, but for return values, so only allocate for R3 and R4 |
173 | static bool CC_PPC32_SPE_RetF64(unsigned &ValNo, MVT &ValVT, |
174 | MVT &LocVT, |
175 | CCValAssign::LocInfo &LocInfo, |
176 | ISD::ArgFlagsTy &ArgFlags, |
177 | CCState &State) { |
178 | static const MCPhysReg HiRegList[] = { PPC::R3 }; |
179 | static const MCPhysReg LoRegList[] = { PPC::R4 }; |
180 | |
181 | // Try to get the first register. |
182 | MCRegister Reg = State.AllocateReg(Regs: HiRegList, ShadowRegs: LoRegList); |
183 | if (!Reg) |
184 | return false; |
185 | |
186 | unsigned i; |
187 | for (i = 0; i < std::size(HiRegList); ++i) |
188 | if (HiRegList[i] == Reg) |
189 | break; |
190 | |
191 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, HTP: LocInfo)); |
192 | State.addLoc(V: CCValAssign::getCustomReg(ValNo, ValVT, Reg: LoRegList[i], |
193 | LocVT, HTP: LocInfo)); |
194 | return true; |
195 | } |
196 | |
197 | #include "PPCGenCallingConv.inc" |
198 | |