Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZCallingConv.h
35267 views
1
//===-- SystemZCallingConv.h - Calling conventions for SystemZ --*- 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
#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZCALLINGCONV_H
10
#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZCALLINGCONV_H
11
12
#include "SystemZSubtarget.h"
13
#include "llvm/ADT/SmallVector.h"
14
#include "llvm/CodeGen/CallingConvLower.h"
15
#include "llvm/MC/MCRegisterInfo.h"
16
17
namespace llvm {
18
namespace SystemZ {
19
const unsigned ELFNumArgGPRs = 5;
20
extern const MCPhysReg ELFArgGPRs[ELFNumArgGPRs];
21
22
const unsigned ELFNumArgFPRs = 4;
23
extern const MCPhysReg ELFArgFPRs[ELFNumArgFPRs];
24
25
const unsigned XPLINK64NumArgGPRs = 3;
26
extern const MCPhysReg XPLINK64ArgGPRs[XPLINK64NumArgGPRs];
27
28
const unsigned XPLINK64NumArgFPRs = 4;
29
extern const MCPhysReg XPLINK64ArgFPRs[XPLINK64NumArgFPRs];
30
} // end namespace SystemZ
31
32
class SystemZCCState : public CCState {
33
private:
34
/// Records whether the value was a fixed argument.
35
/// See ISD::OutputArg::IsFixed.
36
SmallVector<bool, 4> ArgIsFixed;
37
38
/// Records whether the value was widened from a short vector type.
39
SmallVector<bool, 4> ArgIsShortVector;
40
41
// Check whether ArgVT is a short vector type.
42
bool IsShortVectorType(EVT ArgVT) {
43
return ArgVT.isVector() && ArgVT.getStoreSize() <= 8;
44
}
45
46
public:
47
SystemZCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
48
SmallVectorImpl<CCValAssign> &locs, LLVMContext &C)
49
: CCState(CC, isVarArg, MF, locs, C) {}
50
51
void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
52
CCAssignFn Fn) {
53
// Formal arguments are always fixed.
54
ArgIsFixed.clear();
55
for (unsigned i = 0; i < Ins.size(); ++i)
56
ArgIsFixed.push_back(true);
57
// Record whether the call operand was a short vector.
58
ArgIsShortVector.clear();
59
for (unsigned i = 0; i < Ins.size(); ++i)
60
ArgIsShortVector.push_back(IsShortVectorType(Ins[i].ArgVT));
61
62
CCState::AnalyzeFormalArguments(Ins, Fn);
63
}
64
65
void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
66
CCAssignFn Fn) {
67
// Record whether the call operand was a fixed argument.
68
ArgIsFixed.clear();
69
for (unsigned i = 0; i < Outs.size(); ++i)
70
ArgIsFixed.push_back(Outs[i].IsFixed);
71
// Record whether the call operand was a short vector.
72
ArgIsShortVector.clear();
73
for (unsigned i = 0; i < Outs.size(); ++i)
74
ArgIsShortVector.push_back(IsShortVectorType(Outs[i].ArgVT));
75
76
CCState::AnalyzeCallOperands(Outs, Fn);
77
}
78
79
// This version of AnalyzeCallOperands in the base class is not usable
80
// since we must provide a means of accessing ISD::OutputArg::IsFixed.
81
void AnalyzeCallOperands(const SmallVectorImpl<MVT> &Outs,
82
SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
83
CCAssignFn Fn) = delete;
84
85
bool IsFixed(unsigned ValNo) { return ArgIsFixed[ValNo]; }
86
bool IsShortVector(unsigned ValNo) { return ArgIsShortVector[ValNo]; }
87
};
88
89
// Handle i128 argument types. These need to be passed by implicit
90
// reference. This could be as simple as the following .td line:
91
// CCIfType<[i128], CCPassIndirect<i64>>,
92
// except that i128 is not a legal type, and therefore gets split by
93
// common code into a pair of i64 arguments.
94
inline bool CC_SystemZ_I128Indirect(unsigned &ValNo, MVT &ValVT,
95
MVT &LocVT,
96
CCValAssign::LocInfo &LocInfo,
97
ISD::ArgFlagsTy &ArgFlags,
98
CCState &State) {
99
SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs();
100
101
// ArgFlags.isSplit() is true on the first part of a i128 argument;
102
// PendingMembers.empty() is false on all subsequent parts.
103
if (!ArgFlags.isSplit() && PendingMembers.empty())
104
return false;
105
106
// Push a pending Indirect value location for each part.
107
LocVT = MVT::i64;
108
LocInfo = CCValAssign::Indirect;
109
PendingMembers.push_back(CCValAssign::getPending(ValNo, ValVT,
110
LocVT, LocInfo));
111
if (!ArgFlags.isSplitEnd())
112
return true;
113
114
// OK, we've collected all parts in the pending list. Allocate
115
// the location (register or stack slot) for the indirect pointer.
116
// (This duplicates the usual i64 calling convention rules.)
117
unsigned Reg;
118
const SystemZSubtarget &Subtarget =
119
State.getMachineFunction().getSubtarget<SystemZSubtarget>();
120
if (Subtarget.isTargetELF())
121
Reg = State.AllocateReg(SystemZ::ELFArgGPRs);
122
else if (Subtarget.isTargetXPLINK64())
123
Reg = State.AllocateReg(SystemZ::XPLINK64ArgGPRs);
124
else
125
llvm_unreachable("Unknown Calling Convention!");
126
127
unsigned Offset = Reg && !Subtarget.isTargetXPLINK64()
128
? 0
129
: State.AllocateStack(8, Align(8));
130
131
// Use that same location for all the pending parts.
132
for (auto &It : PendingMembers) {
133
if (Reg)
134
It.convertToReg(Reg);
135
else
136
It.convertToMem(Offset);
137
State.addLoc(It);
138
}
139
140
PendingMembers.clear();
141
142
return true;
143
}
144
145
inline bool CC_XPLINK64_Shadow_Reg(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
146
CCValAssign::LocInfo &LocInfo,
147
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
148
if (LocVT == MVT::f32 || LocVT == MVT::f64) {
149
State.AllocateReg(SystemZ::XPLINK64ArgGPRs);
150
}
151
if (LocVT == MVT::f128 || LocVT.is128BitVector()) {
152
// Shadow next two GPRs, if available.
153
State.AllocateReg(SystemZ::XPLINK64ArgGPRs);
154
State.AllocateReg(SystemZ::XPLINK64ArgGPRs);
155
156
// Quad precision floating point needs to
157
// go inside pre-defined FPR pair.
158
if (LocVT == MVT::f128) {
159
for (unsigned I = 0; I < SystemZ::XPLINK64NumArgFPRs; I += 2)
160
if (State.isAllocated(SystemZ::XPLINK64ArgFPRs[I]))
161
State.AllocateReg(SystemZ::XPLINK64ArgFPRs[I + 1]);
162
}
163
}
164
return false;
165
}
166
167
inline bool CC_XPLINK64_Allocate128BitVararg(unsigned &ValNo, MVT &ValVT,
168
MVT &LocVT,
169
CCValAssign::LocInfo &LocInfo,
170
ISD::ArgFlagsTy &ArgFlags,
171
CCState &State) {
172
// For any C or C++ program, this should always be
173
// false, since it is illegal to have a function
174
// where the first argument is variadic. Therefore
175
// the first fixed argument should already have
176
// allocated GPR1 either through shadowing it or
177
// using it for parameter passing.
178
State.AllocateReg(SystemZ::R1D);
179
180
bool AllocGPR2 = State.AllocateReg(SystemZ::R2D);
181
bool AllocGPR3 = State.AllocateReg(SystemZ::R3D);
182
183
// If GPR2 and GPR3 are available, then we may pass vararg in R2Q.
184
// If only GPR3 is available, we need to set custom handling to copy
185
// hi bits into GPR3.
186
// Either way, we allocate on the stack.
187
if (AllocGPR3) {
188
// For f128 and vector var arg case, set the bitcast flag to bitcast to
189
// i128.
190
LocVT = MVT::i128;
191
LocInfo = CCValAssign::BCvt;
192
auto Offset = State.AllocateStack(16, Align(8));
193
if (AllocGPR2)
194
State.addLoc(
195
CCValAssign::getReg(ValNo, ValVT, SystemZ::R2Q, LocVT, LocInfo));
196
else
197
State.addLoc(
198
CCValAssign::getCustomMem(ValNo, ValVT, Offset, LocVT, LocInfo));
199
return true;
200
}
201
202
return false;
203
}
204
205
inline bool RetCC_SystemZ_Error(unsigned &, MVT &, MVT &,
206
CCValAssign::LocInfo &, ISD::ArgFlagsTy &,
207
CCState &) {
208
llvm_unreachable("Return value calling convention currently unsupported.");
209
}
210
211
inline bool CC_SystemZ_Error(unsigned &, MVT &, MVT &, CCValAssign::LocInfo &,
212
ISD::ArgFlagsTy &, CCState &) {
213
llvm_unreachable("Argument calling convention currently unsupported.");
214
}
215
216
inline bool CC_SystemZ_GHC_Error(unsigned &, MVT &, MVT &,
217
CCValAssign::LocInfo &, ISD::ArgFlagsTy &,
218
CCState &) {
219
report_fatal_error("No registers left in GHC calling convention");
220
return false;
221
}
222
223
} // end namespace llvm
224
225
#endif
226
227