LLVM 24.0.0git
FunctionInfo.h
Go to the documentation of this file.
1//===----- FunctionInfo.h - ABI Function Information --------- 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// Defines FunctionInfo and associated types used in representing the
10// ABI-coerced types for function arguments and return values.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ABI_FUNCTIONINFO_H
15#define LLVM_ABI_FUNCTIONINFO_H
16
17#include "llvm/ABI/Types.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/IR/CallingConv.h"
23#include <optional>
24
25namespace llvm {
26namespace abi {
27
28/// Helper class to encapsulate information about how a specific type should be
29/// passed to or returned from a function.
30class ArgInfo {
31public:
32 enum Kind {
33 /// Pass the argument directly using the normal converted LLVM type, or by
34 /// coercing to another specified type stored in 'CoerceToType'.
36 /// Valid only for integer argument types. Same as 'direct' but also emit a
37 /// zero/sign extension attribute.
39 /// Pass the argument indirectly via a hidden pointer with the specified
40 /// alignment and address space.
42 /// Like Indirect, but the pointer may alias an object referenced
43 /// elsewhere. The callee must not modify it and never treats it as byval.
45 /// Ignore the argument (treat as void). Useful for void and empty structs.
47
48 /// Only valid for aggregate argument types. The value is expanded into
49 /// one argument per non-padding element of CoerceToType. Arrays of i8 are
50 /// assumed to be padding.
52 };
53
54private:
55 const Type *CoercionType = nullptr;
56 const Type *UnpaddedCoerceAndExpandType = nullptr;
57 // Alignment is optional for direct arguments, but required for indirect
58 // arguments. This invariant is enforced by the methods of this class.
59 //
60 // The field is not part of DirectAttrInfo/IndirectAttrInfo because it would
61 // make the union non-trivial, disabling implicit copy/move constructors and
62 // assignment operators for the entire class.
63 MaybeAlign Alignment;
64
65 struct DirectAttrInfo {
66 unsigned Offset;
67 };
68
69 struct IndirectAttrInfo {
70 unsigned AddrSpace;
71 };
72
73 union {
74 DirectAttrInfo DirectAttr;
75 IndirectAttrInfo IndirectAttr;
76 };
77
78 Kind TheKind;
79 bool SignExt : 1;
80 bool ZeroExt : 1;
81 bool IndirectByVal : 1;
82 bool IndirectRealign : 1;
83 bool CanBeFlattened : 1;
84 unsigned NeededIntRegs : 3;
85 unsigned NeededSseRegs : 3;
86
87 ArgInfo(Kind K = Direct)
88 : TheKind(K), SignExt(false), ZeroExt(false), IndirectByVal(false),
89 IndirectRealign(false), CanBeFlattened(false), NeededIntRegs(0),
90 NeededSseRegs(0) {}
91
92public:
93 /// \param T The type to coerce to. If null, the argument's original type is
94 /// used directly.
95 /// \param Offset Byte offset into the memory representation at which the
96 /// coerced type begins. Used when only part of a larger value
97 /// is passed directly (e.g. the high word of a multi-eightbyte
98 /// return value on x86-64).
99 /// \param Align Override for the argument's alignment. If absent, the
100 /// default alignment for \p T is used.
101 /// \param CanBeFlattened Whether a record coercion may be split into one
102 /// wire argument per field. See getCanBeFlattened.
103 static ArgInfo getDirect(const Type *T = nullptr, unsigned Offset = 0,
104 MaybeAlign Align = std::nullopt,
105 bool CanBeFlattened = true) {
106 ArgInfo AI(Direct);
107 AI.CoercionType = T;
108 AI.Alignment = Align;
109 AI.DirectAttr.Offset = Offset;
110 AI.CanBeFlattened = CanBeFlattened;
111 return AI;
112 }
113
114 static ArgInfo getExtend(const Type *T) {
115 assert(T && "Type cannot be null");
116 assert(T->isInteger() && "Unexpected type - only integers can be extended");
117
118 ArgInfo AI(Extend);
119 AI.CoercionType = T;
120 AI.Alignment = std::nullopt;
121 AI.DirectAttr.Offset = 0;
122
123 const IntegerType *IntTy = cast<IntegerType>(T);
124 if (IntTy->isSigned())
125 AI.setSignExt();
126 else
127 AI.setZeroExt();
128
129 return AI;
130 }
131
132 /// Realign: the caller couldn't guarantee sufficient alignment - the callee
133 /// must copy the argument to a properly aligned temporary before use.
134 static ArgInfo getIndirect(Align Align, bool ByVal, unsigned AddrSpace = 0,
135 bool Realign = false) {
136 ArgInfo AI(Indirect);
137 AI.Alignment = Align;
138 AI.IndirectAttr.AddrSpace = AddrSpace;
139 AI.IndirectByVal = ByVal;
140 AI.IndirectRealign = Realign;
141 return AI;
142 }
143
144 /// An aliased indirect argument. It carries an address space but no byval,
145 /// since the pointer refers to an object the caller owns.
146 static ArgInfo getIndirectAliased(Align Align, unsigned AddrSpace,
147 bool Realign = false) {
148 ArgInfo AI(IndirectAliased);
149 AI.Alignment = Align;
150 AI.IndirectAttr.AddrSpace = AddrSpace;
151 AI.IndirectRealign = Realign;
152 return AI;
153 }
154
155 static ArgInfo getIgnore() { return ArgInfo(Ignore); }
156
157 /// \param CoerceToType Aggregate type whose non-padding elements are the
158 /// in-memory pieces of the value, in order. Padding elements are
159 /// arrays of i8.
160 /// \param UnpaddedCoerceToType \p CoerceToType with padding elements
161 /// removed. A single element is stored as that element; two or more
162 /// are a packed record.
163 static ArgInfo getCoerceAndExpand(const Type *CoerceToType,
164 const Type *UnpaddedCoerceToType) {
165 assert(CoerceToType && UnpaddedCoerceToType &&
166 "coerce-and-expand types cannot be null");
167 assert(isa<RecordType>(CoerceToType) &&
168 "coerce-and-expand coerce type must be a record");
169 ArgInfo AI(CoerceAndExpand);
170 AI.CoercionType = CoerceToType;
171 AI.UnpaddedCoerceAndExpandType = UnpaddedCoerceToType;
172 return AI;
173 }
174
175 ArgInfo &setSignExt(bool SignExtend = true) {
176 this->SignExt = SignExtend;
177 if (SignExtend)
178 this->ZeroExt = false;
179 return *this;
180 }
181
182 ArgInfo &setZeroExt(bool ZeroExtend = true) {
183 this->ZeroExt = ZeroExtend;
184 if (ZeroExtend)
185 this->SignExt = false;
186 return *this;
187 }
188
189 /// See getCanBeFlattened.
190 ArgInfo &setCanBeFlattened(bool Flatten) {
191 assert(isDirect() && "Invalid Kind!");
192 CanBeFlattened = Flatten;
193 return *this;
194 }
195
196 Kind getKind() const { return TheKind; }
197 bool isDirect() const { return TheKind == Direct; }
198 bool isIndirect() const { return TheKind == Indirect; }
199 bool isIndirectAliased() const { return TheKind == IndirectAliased; }
200 bool isIgnore() const { return TheKind == Ignore; }
201 bool isExtend() const { return TheKind == Extend; }
202 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
203
204 unsigned getDirectOffset() const {
205 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
206 return DirectAttr.Offset;
207 }
208
209 /// How many integer and vector argument registers this argument occupies.
210 /// Both zero means it occupies none and travels in memory, which is also
211 /// what a target whose classifier does not record the demand reports.
212 unsigned getNeededIntRegs() const { return NeededIntRegs; }
213 unsigned getNeededSseRegs() const { return NeededSseRegs; }
214
215 void setNeededRegs(unsigned IntRegs, unsigned SseRegs) {
216 assert(IntRegs <= 7 && SseRegs <= 7 && "Register demand does not fit");
217 NeededIntRegs = IntRegs;
218 NeededSseRegs = SseRegs;
219 }
220
222 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
223 return Alignment;
224 }
225
227 assert((isIndirect() || isIndirectAliased()) && "Invalid Kind!");
228 assert(Alignment.has_value() &&
229 "Indirect arguments must have an alignment");
230 return *Alignment;
231 }
232
233 unsigned getIndirectAddrSpace() const {
234 assert((isIndirect() || isIndirectAliased()) && "Invalid Kind!");
235 return IndirectAttr.AddrSpace;
236 }
237
238 bool getIndirectByVal() const {
239 // Aliased pointers are never byval.
240 assert(isIndirect() && "Invalid Kind!");
241 return IndirectByVal;
242 }
243
244 bool getIndirectRealign() const {
245 assert((isIndirect() || isIndirectAliased()) && "Invalid Kind!");
246 return IndirectRealign;
247 }
248
249 /// Whether a Direct record coercion may be split into one wire argument
250 /// per field. Mirrors clang::CodeGen::ABIArgInfo::CanBeFlattened.
251 bool getCanBeFlattened() const {
252 assert(isDirect() && "Invalid Kind!");
253 return CanBeFlattened;
254 }
255
256 bool isSignExt() const {
257 assert(isExtend() && "Invalid Kind!");
258 return SignExt;
259 }
260
261 bool isZeroExt() const {
262 assert(isExtend() && "Invalid Kind!");
263 return ZeroExt;
264 }
265
266 bool isNoExt() const {
267 assert(isExtend() && "Invalid Kind!");
268 return !SignExt && !ZeroExt;
269 }
270
271 const Type *getCoerceToType() const {
273 "Invalid Kind!");
274 return CoercionType;
275 }
276
278 assert(isCoerceAndExpand() && "Invalid Kind!");
279 return UnpaddedCoerceAndExpandType;
280 }
281
282 /// True if \p Ty is an array of i8, the padding element of a
283 /// coerce-and-expand type. A matrix is an array in this type system
284 /// and lowers to a vector, so it is not padding.
285 static bool isPaddingForCoerceAndExpand(const Type *Ty) {
286 const auto *AT = dyn_cast<ArrayType>(Ty);
287 if (!AT || AT->isMatrixType())
288 return false;
289 const auto *Elt = dyn_cast<IntegerType>(AT->getElementType());
290 return Elt && Elt->getSizeInBits().getFixedValue() == 8;
291 }
292};
293
294struct ArgEntry {
295 const Type *ABIType;
297
298 ArgEntry(const Type *T) : ABIType(T), Info(ArgInfo::getDirect()) {}
299 ArgEntry(const Type *T, ArgInfo A) : ABIType(T), Info(A) {}
300};
301
302/// Whether a signature accepts arguments beyond its declared parameters, and
303/// where the declared ones end when it does. An argument past an ellipsis is
304/// unnamed, and some ABI rules pass an unnamed type differently.
305///
306/// A count and All are not interchangeable when the count equals the number of
307/// arguments. FunctionInfo::isVariadic() is true whenever a count was given,
308/// so a signature with no ellipsis has to be spelled All.
310 /// The number of leading arguments that are declared parameters, or ~0U if
311 /// the signature accepts no optional arguments.
312 unsigned NumRequired;
313
314public:
315 enum All_t { All };
316
317 /// A signature with no ellipsis, where every argument is declared.
318 RequiredArgs(All_t) : NumRequired(~0U) {}
319
320 /// A signature whose leading \p N arguments are declared and whose remaining
321 /// arguments pass through an ellipsis.
322 explicit RequiredArgs(unsigned N) : NumRequired(N) {
323 assert(N != ~0U && "~0U is reserved for a signature with no ellipsis");
324 }
325
326 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
327
328 unsigned getNumRequiredArgs() const {
329 assert(allowsOptionalArgs() && "signature accepts no optional arguments");
330 return NumRequired;
331 }
332};
333
334class FunctionInfo final : private TrailingObjects<FunctionInfo, ArgEntry> {
335private:
336 const Type *ReturnType;
337 ArgInfo ReturnInfo;
338 unsigned NumArgs;
340 RequiredArgs Required;
341
342 FunctionInfo(CallingConv::ID CC, const Type *RetTy, unsigned NumArguments,
343 RequiredArgs Required)
344 : ReturnType(RetTy), ReturnInfo(ArgInfo::getDirect()),
345 NumArgs(NumArguments), CC(CC), Required(Required) {}
346
347 friend class TrailingObjects;
348
349public:
352
353 void operator delete(void *p) { ::operator delete(p); }
355 const_arg_iterator arg_end() const { return getTrailingObjects() + NumArgs; }
357 arg_iterator arg_end() { return getTrailingObjects() + NumArgs; }
358
359 unsigned arg_size() const { return NumArgs; }
360
361 LLVM_ABI static std::unique_ptr<FunctionInfo>
362 create(CallingConv::ID CC, const Type *ReturnType,
363 ArrayRef<const Type *> ArgTypes,
365
366 const Type *getReturnType() const { return ReturnType; }
367 ArgInfo &getReturnInfo() { return ReturnInfo; }
368 const ArgInfo &getReturnInfo() const { return ReturnInfo; }
369
371
372 bool isVariadic() const { return Required.allowsOptionalArgs(); }
373
374 unsigned getNumRequiredArgs() const {
375 return isVariadic() ? Required.getNumRequiredArgs() : arg_size();
376 }
377
379 return {getTrailingObjects(), NumArgs};
380 }
381
383 return {getTrailingObjects(), NumArgs};
384 }
385
386 ArgEntry &getArgInfo(unsigned Index) {
387 assert(Index < NumArgs && "Invalid argument index");
388 return arguments()[Index];
389 }
390
391 const ArgEntry &getArgInfo(unsigned Index) const {
392 assert(Index < NumArgs && "Invalid argument index");
393 return arguments()[Index];
394 }
395};
396
397} // namespace abi
398} // namespace llvm
399
400#endif // LLVM_ABI_FUNCTIONINFO_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_ABI
Definition Compiler.h:215
#define T
static const MCPhysReg IntRegs[32]
This header defines support for implementing classes that have some trailing object (or arrays of obj...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
Helper class to encapsulate information about how a specific type should be passed to or returned fro...
bool isDirect() const
bool getCanBeFlattened() const
Whether a Direct record coercion may be split into one wire argument per field.
const Type * getCoerceToType() const
bool isCoerceAndExpand() const
ArgInfo & setCanBeFlattened(bool Flatten)
See getCanBeFlattened.
static bool isPaddingForCoerceAndExpand(const Type *Ty)
True if Ty is an array of i8, the padding element of a coerce-and-expand type.
Align getIndirectAlign() const
const Type * getUnpaddedCoerceAndExpandType() const
DirectAttrInfo DirectAttr
bool isSignExt() const
ArgInfo & setZeroExt(bool ZeroExtend=true)
static ArgInfo getIgnore()
bool isIgnore() const
static ArgInfo getIndirectAliased(Align Align, unsigned AddrSpace, bool Realign=false)
An aliased indirect argument.
void setNeededRegs(unsigned IntRegs, unsigned SseRegs)
unsigned getIndirectAddrSpace() const
static ArgInfo getCoerceAndExpand(const Type *CoerceToType, const Type *UnpaddedCoerceToType)
IndirectAttrInfo IndirectAttr
Kind getKind() const
@ IndirectAliased
Like Indirect, but the pointer may alias an object referenced elsewhere.
@ Extend
Valid only for integer argument types.
@ CoerceAndExpand
Only valid for aggregate argument types.
@ Direct
Pass the argument directly using the normal converted LLVM type, or by coercing to another specified ...
@ Ignore
Ignore the argument (treat as void). Useful for void and empty structs.
@ Indirect
Pass the argument indirectly via a hidden pointer with the specified alignment and address space.
static ArgInfo getExtend(const Type *T)
static ArgInfo getIndirect(Align Align, bool ByVal, unsigned AddrSpace=0, bool Realign=false)
Realign: the caller couldn't guarantee sufficient alignment - the callee must copy the argument to a ...
MaybeAlign getDirectAlign() const
bool isExtend() const
static ArgInfo getDirect(const Type *T=nullptr, unsigned Offset=0, MaybeAlign Align=std::nullopt, bool CanBeFlattened=true)
unsigned getNeededIntRegs() const
How many integer and vector argument registers this argument occupies.
bool getIndirectRealign() const
ArgInfo & setSignExt(bool SignExtend=true)
bool isNoExt() const
bool getIndirectByVal() const
bool isIndirect() const
unsigned getNeededSseRegs() const
bool isIndirectAliased() const
unsigned getDirectOffset() const
bool isZeroExt() const
ArrayRef< ArgEntry > arguments() const
unsigned getNumRequiredArgs() const
const ArgInfo & getReturnInfo() const
const ArgEntry * const_arg_iterator
MutableArrayRef< ArgEntry > arguments()
CallingConv::ID getCallingConvention() const
const_arg_iterator arg_begin() const
const ArgEntry & getArgInfo(unsigned Index) const
friend class TrailingObjects
const_arg_iterator arg_end() const
unsigned arg_size() const
arg_iterator arg_begin()
ArgEntry & getArgInfo(unsigned Index)
const Type * getReturnType() const
static LLVM_ABI std::unique_ptr< FunctionInfo > create(CallingConv::ID CC, const Type *ReturnType, ArrayRef< const Type * > ArgTypes, RequiredArgs Required=RequiredArgs::All)
Whether a signature accepts arguments beyond its declared parameters, and where the declared ones end...
bool allowsOptionalArgs() const
RequiredArgs(unsigned N)
A signature whose leading N arguments are declared and whose remaining arguments pass through an elli...
unsigned getNumRequiredArgs() const
RequiredArgs(All_t)
A signature with no ellipsis, where every argument is declared.
Represents the ABI-specific view of a type in LLVM.
Definition Types.h:47
This file defines the type system for the LLVMABI library, which mirrors ABI-relevant aspects of fron...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:111
ArgEntry(const Type *T)
ArgEntry(const Type *T, ArgInfo A)
const Type * ABIType