Thanks to visit codestin.com
Credit goes to llvm.org

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