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 /// Ignore the argument (treat as void). Useful for void and empty structs.
44 };
45
46private:
47 const Type *CoercionType = nullptr;
48 // Alignment is optional for direct arguments, but required for indirect
49 // arguments. This invariant is enforced by the methods of this class.
50 //
51 // The field is not part of DirectAttrInfo/IndirectAttrInfo because it would
52 // make the union non-trivial, disabling implicit copy/move constructors and
53 // assignment operators for the entire class.
54 MaybeAlign Alignment;
55
56 struct DirectAttrInfo {
57 unsigned Offset;
58 };
59
60 struct IndirectAttrInfo {
61 unsigned AddrSpace;
62 };
63
64 union {
65 DirectAttrInfo DirectAttr;
66 IndirectAttrInfo IndirectAttr;
67 };
68
69 Kind TheKind;
70 bool SignExt : 1;
71 bool ZeroExt : 1;
72 bool IndirectByVal : 1;
73 bool IndirectRealign : 1;
74 bool CanBeFlattened : 1;
75
76 ArgInfo(Kind K = Direct)
77 : TheKind(K), SignExt(false), ZeroExt(false), IndirectByVal(false),
78 IndirectRealign(false), CanBeFlattened(false) {}
79
80public:
81 /// \param T The type to coerce to. If null, the argument's original type is
82 /// used directly.
83 /// \param Offset Byte offset into the memory representation at which the
84 /// coerced type begins. Used when only part of a larger value
85 /// is passed directly (e.g. the high word of a multi-eightbyte
86 /// return value on x86-64).
87 /// \param Align Override for the argument's alignment. If absent, the
88 /// default alignment for \p T is used.
89 /// \param CanBeFlattened Whether a record coercion may be split into one
90 /// wire argument per field. See getCanBeFlattened.
91 static ArgInfo getDirect(const Type *T = nullptr, unsigned Offset = 0,
92 MaybeAlign Align = std::nullopt,
93 bool CanBeFlattened = true) {
94 ArgInfo AI(Direct);
95 AI.CoercionType = T;
96 AI.Alignment = Align;
97 AI.DirectAttr.Offset = Offset;
98 AI.CanBeFlattened = CanBeFlattened;
99 return AI;
100 }
101
102 static ArgInfo getExtend(const Type *T) {
103 assert(T && "Type cannot be null");
104 assert(T->isInteger() && "Unexpected type - only integers can be extended");
105
106 ArgInfo AI(Extend);
107 AI.CoercionType = T;
108 AI.Alignment = std::nullopt;
109 AI.DirectAttr.Offset = 0;
110
111 const IntegerType *IntTy = cast<IntegerType>(T);
112 if (IntTy->isSigned())
113 AI.setSignExt();
114 else
115 AI.setZeroExt();
116
117 return AI;
118 }
119
120 /// Realign: the caller couldn't guarantee sufficient alignment - the callee
121 /// must copy the argument to a properly aligned temporary before use.
122 static ArgInfo getIndirect(Align Align, bool ByVal, unsigned AddrSpace = 0,
123 bool Realign = false) {
124 ArgInfo AI(Indirect);
125 AI.Alignment = Align;
126 AI.IndirectAttr.AddrSpace = AddrSpace;
127 AI.IndirectByVal = ByVal;
128 AI.IndirectRealign = Realign;
129 return AI;
130 }
131
132 static ArgInfo getIgnore() { return ArgInfo(Ignore); }
133
134 ArgInfo &setSignExt(bool SignExtend = true) {
135 this->SignExt = SignExtend;
136 if (SignExtend)
137 this->ZeroExt = false;
138 return *this;
139 }
140
141 ArgInfo &setZeroExt(bool ZeroExtend = true) {
142 this->ZeroExt = ZeroExtend;
143 if (ZeroExtend)
144 this->SignExt = false;
145 return *this;
146 }
147
148 /// See getCanBeFlattened.
149 ArgInfo &setCanBeFlattened(bool Flatten) {
150 assert(isDirect() && "Invalid Kind!");
151 CanBeFlattened = Flatten;
152 return *this;
153 }
154
155 Kind getKind() const { return TheKind; }
156 bool isDirect() const { return TheKind == Direct; }
157 bool isIndirect() const { return TheKind == Indirect; }
158 bool isIgnore() const { return TheKind == Ignore; }
159 bool isExtend() const { return TheKind == Extend; }
160
161 unsigned getDirectOffset() const {
162 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
163 return DirectAttr.Offset;
164 }
165
167 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
168 return Alignment;
169 }
170
172 assert(isIndirect() && "Invalid Kind!");
173 assert(Alignment.has_value() &&
174 "Indirect arguments must have an alignment");
175 return *Alignment;
176 }
177
178 unsigned getIndirectAddrSpace() const {
179 assert(isIndirect() && "Invalid Kind!");
180 return IndirectAttr.AddrSpace;
181 }
182
183 bool getIndirectByVal() const {
184 assert(isIndirect() && "Invalid Kind!");
185 return IndirectByVal;
186 }
187
188 bool getIndirectRealign() const {
189 assert(isIndirect() && "Invalid Kind!");
190 return IndirectRealign;
191 }
192
193 /// Whether a Direct record coercion may be split into one wire argument
194 /// per field. Mirrors clang::CodeGen::ABIArgInfo::CanBeFlattened.
195 bool getCanBeFlattened() const {
196 assert(isDirect() && "Invalid Kind!");
197 return CanBeFlattened;
198 }
199
200 bool isSignExt() const {
201 assert(isExtend() && "Invalid Kind!");
202 return SignExt;
203 }
204
205 bool isZeroExt() const {
206 assert(isExtend() && "Invalid Kind!");
207 return ZeroExt;
208 }
209
210 bool isNoExt() const {
211 assert(isExtend() && "Invalid Kind!");
212 return !SignExt && !ZeroExt;
213 }
214
215 const Type *getCoerceToType() const {
216 assert((isDirect() || isExtend()) && "Invalid Kind!");
217 return CoercionType;
218 }
219};
220
221struct ArgEntry {
222 const Type *ABIType;
224
225 ArgEntry(const Type *T) : ABIType(T), Info(ArgInfo::getDirect()) {}
226 ArgEntry(const Type *T, ArgInfo A) : ABIType(T), Info(A) {}
227};
228
229/// Whether a signature accepts arguments beyond its declared parameters, and
230/// where the declared ones end when it does. An argument past an ellipsis is
231/// unnamed, and some ABI rules pass an unnamed type differently.
232///
233/// A count and All are not interchangeable when the count equals the number of
234/// arguments. FunctionInfo::isVariadic() is true whenever a count was given,
235/// so a signature with no ellipsis has to be spelled All.
237 /// The number of leading arguments that are declared parameters, or ~0U if
238 /// the signature accepts no optional arguments.
239 unsigned NumRequired;
240
241public:
242 enum All_t { All };
243
244 /// A signature with no ellipsis, where every argument is declared.
245 RequiredArgs(All_t) : NumRequired(~0U) {}
246
247 /// A signature whose leading \p N arguments are declared and whose remaining
248 /// arguments pass through an ellipsis.
249 explicit RequiredArgs(unsigned N) : NumRequired(N) {
250 assert(N != ~0U && "~0U is reserved for a signature with no ellipsis");
251 }
252
253 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
254
255 unsigned getNumRequiredArgs() const {
256 assert(allowsOptionalArgs() && "signature accepts no optional arguments");
257 return NumRequired;
258 }
259};
260
261class FunctionInfo final : private TrailingObjects<FunctionInfo, ArgEntry> {
262private:
263 const Type *ReturnType;
264 ArgInfo ReturnInfo;
265 unsigned NumArgs;
267 RequiredArgs Required;
268
269 FunctionInfo(CallingConv::ID CC, const Type *RetTy, unsigned NumArguments,
270 RequiredArgs Required)
271 : ReturnType(RetTy), ReturnInfo(ArgInfo::getDirect()),
272 NumArgs(NumArguments), CC(CC), Required(Required) {}
273
274 friend class TrailingObjects;
275
276public:
279
280 void operator delete(void *p) { ::operator delete(p); }
282 const_arg_iterator arg_end() const { return getTrailingObjects() + NumArgs; }
284 arg_iterator arg_end() { return getTrailingObjects() + NumArgs; }
285
286 unsigned arg_size() const { return NumArgs; }
287
288 LLVM_ABI static std::unique_ptr<FunctionInfo>
289 create(CallingConv::ID CC, const Type *ReturnType,
290 ArrayRef<const Type *> ArgTypes,
292
293 const Type *getReturnType() const { return ReturnType; }
294 ArgInfo &getReturnInfo() { return ReturnInfo; }
295 const ArgInfo &getReturnInfo() const { return ReturnInfo; }
296
298
299 bool isVariadic() const { return Required.allowsOptionalArgs(); }
300
301 unsigned getNumRequiredArgs() const {
302 return isVariadic() ? Required.getNumRequiredArgs() : arg_size();
303 }
304
306 return {getTrailingObjects(), NumArgs};
307 }
308
310 return {getTrailingObjects(), NumArgs};
311 }
312
313 ArgEntry &getArgInfo(unsigned Index) {
314 assert(Index < NumArgs && "Invalid argument index");
315 return arguments()[Index];
316 }
317
318 const ArgEntry &getArgInfo(unsigned Index) const {
319 assert(Index < NumArgs && "Invalid argument index");
320 return arguments()[Index];
321 }
322};
323
324} // namespace abi
325} // namespace llvm
326
327#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
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
ArgInfo & setCanBeFlattened(bool Flatten)
See getCanBeFlattened.
Align getIndirectAlign() const
DirectAttrInfo DirectAttr
bool isSignExt() const
ArgInfo & setZeroExt(bool ZeroExtend=true)
static ArgInfo getIgnore()
bool isIgnore() const
unsigned getIndirectAddrSpace() const
IndirectAttrInfo IndirectAttr
Kind getKind() const
@ Extend
Valid only for integer 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)
bool getIndirectRealign() const
ArgInfo & setSignExt(bool SignExtend=true)
bool isNoExt() const
bool getIndirectByVal() const
bool isIndirect() 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:46
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) 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:106
ArgEntry(const Type *T)
ArgEntry(const Type *T, ArgInfo A)
const Type * ABIType