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