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
75 ArgInfo(Kind K = Direct)
76 : TheKind(K), SignExt(false), ZeroExt(false), IndirectByVal(false),
77 IndirectRealign(false) {}
78
79public:
80 /// \param T The type to coerce to. If null, the argument's original type is
81 /// used directly.
82 /// \param Offset Byte offset into the memory representation at which the
83 /// coerced type begins. Used when only part of a larger value
84 /// is passed directly (e.g. the high word of a multi-eightbyte
85 /// return value on x86-64).
86 /// \param Align Override for the argument's alignment. If absent, the
87 /// default alignment for \p T is used.
88 static ArgInfo getDirect(const Type *T = nullptr, unsigned Offset = 0,
89 MaybeAlign Align = std::nullopt) {
90 ArgInfo AI(Direct);
91 AI.CoercionType = T;
92 AI.Alignment = Align;
93 AI.DirectAttr.Offset = Offset;
94 return AI;
95 }
96
97 static ArgInfo getExtend(const Type *T) {
98 assert(T && "Type cannot be null");
99 assert(T->isInteger() && "Unexpected type - only integers can be extended");
100
101 ArgInfo AI(Extend);
102 AI.CoercionType = T;
103 AI.Alignment = std::nullopt;
104 AI.DirectAttr.Offset = 0;
105
106 const IntegerType *IntTy = cast<IntegerType>(T);
107 if (IntTy->isSigned())
108 AI.setSignExt();
109 else
110 AI.setZeroExt();
111
112 return AI;
113 }
114
115 /// Realign: the caller couldn't guarantee sufficient alignment - the callee
116 /// must copy the argument to a properly aligned temporary before use.
117 static ArgInfo getIndirect(Align Align, bool ByVal, unsigned AddrSpace = 0,
118 bool Realign = false) {
119 ArgInfo AI(Indirect);
120 AI.Alignment = Align;
121 AI.IndirectAttr.AddrSpace = AddrSpace;
122 AI.IndirectByVal = ByVal;
123 AI.IndirectRealign = Realign;
124 return AI;
125 }
126
127 static ArgInfo getIgnore() { return ArgInfo(Ignore); }
128
129 ArgInfo &setSignExt(bool SignExtend = true) {
130 this->SignExt = SignExtend;
131 if (SignExtend)
132 this->ZeroExt = false;
133 return *this;
134 }
135
136 ArgInfo &setZeroExt(bool ZeroExtend = true) {
137 this->ZeroExt = ZeroExtend;
138 if (ZeroExtend)
139 this->SignExt = false;
140 return *this;
141 }
142
143 Kind getKind() const { return TheKind; }
144 bool isDirect() const { return TheKind == Direct; }
145 bool isIndirect() const { return TheKind == Indirect; }
146 bool isIgnore() const { return TheKind == Ignore; }
147 bool isExtend() const { return TheKind == Extend; }
148
149 unsigned getDirectOffset() const {
150 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
151 return DirectAttr.Offset;
152 }
153
155 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
156 return Alignment;
157 }
158
160 assert(isIndirect() && "Invalid Kind!");
161 assert(Alignment.has_value() &&
162 "Indirect arguments must have an alignment");
163 return *Alignment;
164 }
165
166 unsigned getIndirectAddrSpace() const {
167 assert(isIndirect() && "Invalid Kind!");
168 return IndirectAttr.AddrSpace;
169 }
170
171 bool getIndirectByVal() const {
172 assert(isIndirect() && "Invalid Kind!");
173 return IndirectByVal;
174 }
175
176 bool getIndirectRealign() const {
177 assert(isIndirect() && "Invalid Kind!");
178 return IndirectRealign;
179 }
180
181 bool isSignExt() const {
182 assert(isExtend() && "Invalid Kind!");
183 return SignExt;
184 }
185
186 bool isZeroExt() const {
187 assert(isExtend() && "Invalid Kind!");
188 return ZeroExt;
189 }
190
191 bool isNoExt() const {
192 assert(isExtend() && "Invalid Kind!");
193 return !SignExt && !ZeroExt;
194 }
195
196 const Type *getCoerceToType() const {
197 assert((isDirect() || isExtend()) && "Invalid Kind!");
198 return CoercionType;
199 }
200};
201
202struct ArgEntry {
203 const Type *ABIType;
205
206 ArgEntry(const Type *T) : ABIType(T), Info(ArgInfo::getDirect()) {}
207 ArgEntry(const Type *T, ArgInfo A) : ABIType(T), Info(A) {}
208};
209
210/// Whether a signature accepts arguments beyond its declared parameters, and
211/// where the declared ones end when it does. An argument past an ellipsis is
212/// unnamed, and some ABI rules pass an unnamed type differently.
213///
214/// A count and All are not interchangeable when the count equals the number of
215/// arguments. FunctionInfo::isVariadic() is true whenever a count was given,
216/// so a signature with no ellipsis has to be spelled All.
218 /// The number of leading arguments that are declared parameters, or ~0U if
219 /// the signature accepts no optional arguments.
220 unsigned NumRequired;
221
222public:
223 enum All_t { All };
224
225 /// A signature with no ellipsis, where every argument is declared.
226 RequiredArgs(All_t) : NumRequired(~0U) {}
227
228 /// A signature whose leading \p N arguments are declared and whose remaining
229 /// arguments pass through an ellipsis.
230 explicit RequiredArgs(unsigned N) : NumRequired(N) {
231 assert(N != ~0U && "~0U is reserved for a signature with no ellipsis");
232 }
233
234 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
235
236 unsigned getNumRequiredArgs() const {
237 assert(allowsOptionalArgs() && "signature accepts no optional arguments");
238 return NumRequired;
239 }
240};
241
242class FunctionInfo final : private TrailingObjects<FunctionInfo, ArgEntry> {
243private:
244 const Type *ReturnType;
245 ArgInfo ReturnInfo;
246 unsigned NumArgs;
248 RequiredArgs Required;
249
250 FunctionInfo(CallingConv::ID CC, const Type *RetTy, unsigned NumArguments,
251 RequiredArgs Required)
252 : ReturnType(RetTy), ReturnInfo(ArgInfo::getDirect()),
253 NumArgs(NumArguments), CC(CC), Required(Required) {}
254
255 friend class TrailingObjects;
256
257public:
260
261 void operator delete(void *p) { ::operator delete(p); }
263 const_arg_iterator arg_end() const { return getTrailingObjects() + NumArgs; }
265 arg_iterator arg_end() { return getTrailingObjects() + NumArgs; }
266
267 unsigned arg_size() const { return NumArgs; }
268
269 LLVM_ABI static std::unique_ptr<FunctionInfo>
270 create(CallingConv::ID CC, const Type *ReturnType,
271 ArrayRef<const Type *> ArgTypes,
273
274 const Type *getReturnType() const { return ReturnType; }
275 ArgInfo &getReturnInfo() { return ReturnInfo; }
276 const ArgInfo &getReturnInfo() const { return ReturnInfo; }
277
279
280 bool isVariadic() const { return Required.allowsOptionalArgs(); }
281
282 unsigned getNumRequiredArgs() const {
283 return isVariadic() ? Required.getNumRequiredArgs() : arg_size();
284 }
285
287 return {getTrailingObjects(), NumArgs};
288 }
289
291 return {getTrailingObjects(), NumArgs};
292 }
293
294 ArgEntry &getArgInfo(unsigned Index) {
295 assert(Index < NumArgs && "Invalid argument index");
296 return arguments()[Index];
297 }
298
299 const ArgEntry &getArgInfo(unsigned Index) const {
300 assert(Index < NumArgs && "Invalid argument index");
301 return arguments()[Index];
302 }
303};
304
305} // namespace abi
306} // namespace llvm
307
308#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
static ArgInfo getDirect(const Type *T=nullptr, unsigned Offset=0, MaybeAlign Align=std::nullopt)
const Type * getCoerceToType() const
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
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:44
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:578
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