1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
|
#pragma once
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
//===-- llvm/CodeGen/TargetCallingConv.h - Calling Convention ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines types for working with calling-convention information.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_TARGETCALLINGCONV_H
#define LLVM_CODEGEN_TARGETCALLINGCONV_H
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <climits>
#include <cstdint>
namespace llvm {
namespace ISD {
struct ArgFlagsTy {
private:
unsigned IsZExt : 1; ///< Zero extended
unsigned IsSExt : 1; ///< Sign extended
unsigned IsInReg : 1; ///< Passed in register
unsigned IsSRet : 1; ///< Hidden struct-ret ptr
unsigned IsByVal : 1; ///< Struct passed by value
unsigned IsByRef : 1; ///< Passed in memory
unsigned IsNest : 1; ///< Nested fn static chain
unsigned IsReturned : 1; ///< Always returned
unsigned IsSplit : 1;
unsigned IsInAlloca : 1; ///< Passed with inalloca
unsigned IsPreallocated : 1; ///< ByVal without the copy
unsigned IsSplitEnd : 1; ///< Last part of a split
unsigned IsSwiftSelf : 1; ///< Swift self parameter
unsigned IsSwiftAsync : 1; ///< Swift async context parameter
unsigned IsSwiftError : 1; ///< Swift error parameter
unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target
unsigned IsHva : 1; ///< HVA field for
unsigned IsHvaStart : 1; ///< HVA structure start
unsigned IsSecArgPass : 1; ///< Second argument
unsigned MemAlign : 4; ///< Log 2 of alignment when arg is passed in memory
///< (including byval/byref)
unsigned OrigAlign : 5; ///< Log 2 of original alignment
unsigned IsInConsecutiveRegsLast : 1;
unsigned IsInConsecutiveRegs : 1;
unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
unsigned IsPointer : 1;
unsigned ByValOrByRefSize = 0; ///< Byval or byref struct size
unsigned PointerAddrSpace = 0; ///< Address space of pointer argument
public:
ArgFlagsTy()
: IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0),
IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0),
IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0),
IsSecArgPass(0), MemAlign(0), OrigAlign(0),
IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
IsCopyElisionCandidate(0), IsPointer(0) {
static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
}
bool isZExt() const { return IsZExt; }
void setZExt() { IsZExt = 1; }
bool isSExt() const { return IsSExt; }
void setSExt() { IsSExt = 1; }
bool isInReg() const { return IsInReg; }
void setInReg() { IsInReg = 1; }
bool isSRet() const { return IsSRet; }
void setSRet() { IsSRet = 1; }
bool isByVal() const { return IsByVal; }
void setByVal() { IsByVal = 1; }
bool isByRef() const { return IsByRef; }
void setByRef() { IsByRef = 1; }
bool isInAlloca() const { return IsInAlloca; }
void setInAlloca() { IsInAlloca = 1; }
bool isPreallocated() const { return IsPreallocated; }
void setPreallocated() { IsPreallocated = 1; }
bool isSwiftSelf() const { return IsSwiftSelf; }
void setSwiftSelf() { IsSwiftSelf = 1; }
bool isSwiftAsync() const { return IsSwiftAsync; }
void setSwiftAsync() { IsSwiftAsync = 1; }
bool isSwiftError() const { return IsSwiftError; }
void setSwiftError() { IsSwiftError = 1; }
bool isCFGuardTarget() const { return IsCFGuardTarget; }
void setCFGuardTarget() { IsCFGuardTarget = 1; }
bool isHva() const { return IsHva; }
void setHva() { IsHva = 1; }
bool isHvaStart() const { return IsHvaStart; }
void setHvaStart() { IsHvaStart = 1; }
bool isSecArgPass() const { return IsSecArgPass; }
void setSecArgPass() { IsSecArgPass = 1; }
bool isNest() const { return IsNest; }
void setNest() { IsNest = 1; }
bool isReturned() const { return IsReturned; }
void setReturned(bool V = true) { IsReturned = V; }
bool isInConsecutiveRegs() const { return IsInConsecutiveRegs; }
void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; }
bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
void setInConsecutiveRegsLast(bool Flag = true) {
IsInConsecutiveRegsLast = Flag;
}
bool isSplit() const { return IsSplit; }
void setSplit() { IsSplit = 1; }
bool isSplitEnd() const { return IsSplitEnd; }
void setSplitEnd() { IsSplitEnd = 1; }
bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; }
void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; }
bool isPointer() const { return IsPointer; }
void setPointer() { IsPointer = 1; }
Align getNonZeroMemAlign() const {
return decodeMaybeAlign(MemAlign).valueOrOne();
}
void setMemAlign(Align A) {
MemAlign = encode(A);
assert(getNonZeroMemAlign() == A && "bitfield overflow");
}
Align getNonZeroByValAlign() const {
assert(isByVal());
MaybeAlign A = decodeMaybeAlign(MemAlign);
assert(A && "ByValAlign must be defined");
return *A;
}
Align getNonZeroOrigAlign() const {
return decodeMaybeAlign(OrigAlign).valueOrOne();
}
void setOrigAlign(Align A) {
OrigAlign = encode(A);
assert(getNonZeroOrigAlign() == A && "bitfield overflow");
}
unsigned getByValSize() const {
assert(isByVal() && !isByRef());
return ByValOrByRefSize;
}
void setByValSize(unsigned S) {
assert(isByVal() && !isByRef());
ByValOrByRefSize = S;
}
unsigned getByRefSize() const {
assert(!isByVal() && isByRef());
return ByValOrByRefSize;
}
void setByRefSize(unsigned S) {
assert(!isByVal() && isByRef());
ByValOrByRefSize = S;
}
unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; }
};
/// InputArg - This struct carries flags and type information about a
/// single incoming (formal) argument or incoming (from the perspective
/// of the caller) return value virtual register.
///
struct InputArg {
ArgFlagsTy Flags;
MVT VT = MVT::Other;
EVT ArgVT;
bool Used = false;
/// Index original Function's argument.
unsigned OrigArgIndex;
/// Sentinel value for implicit machine-level input arguments.
static const unsigned NoArgIndex = UINT_MAX;
/// Offset in bytes of current input value relative to the beginning of
/// original argument. E.g. if argument was splitted into four 32 bit
/// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12.
unsigned PartOffset;
InputArg() = default;
InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
unsigned origIdx, unsigned partOffs)
: Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) {
VT = vt.getSimpleVT();
ArgVT = argvt;
}
bool isOrigArg() const {
return OrigArgIndex != NoArgIndex;
}
unsigned getOrigArgIndex() const {
assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument");
return OrigArgIndex;
}
};
/// OutputArg - This struct carries flags and a value for a
/// single outgoing (actual) argument or outgoing (from the perspective
/// of the caller) return value virtual register.
///
struct OutputArg {
ArgFlagsTy Flags;
MVT VT;
EVT ArgVT;
/// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
bool IsFixed = false;
/// Index original Function's argument.
unsigned OrigArgIndex;
/// Offset in bytes of current output value relative to the beginning of
/// original argument. E.g. if argument was splitted into four 32 bit
/// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12.
unsigned PartOffset;
OutputArg() = default;
OutputArg(ArgFlagsTy flags, MVT vt, EVT argvt, bool isfixed,
unsigned origIdx, unsigned partOffs)
: Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx),
PartOffset(partOffs) {
VT = vt;
ArgVT = argvt;
}
};
} // end namespace ISD
} // end namespace llvm
#endif // LLVM_CODEGEN_TARGETCALLINGCONV_H
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
|