LLVM 23.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
210class FunctionInfo final : private TrailingObjects<FunctionInfo, ArgEntry> {
211private:
212 const Type *ReturnType;
213 ArgInfo ReturnInfo;
214 unsigned NumArgs;
216 std::optional<unsigned> NumRequired;
217
218 FunctionInfo(CallingConv::ID CC, const Type *RetTy, unsigned NumArguments,
219 std::optional<unsigned> NumRequired)
220 : ReturnType(RetTy), ReturnInfo(ArgInfo::getDirect()),
221 NumArgs(NumArguments), CC(CC), NumRequired(NumRequired) {}
222
223 friend class TrailingObjects;
224
225public:
228
229 void operator delete(void *p) { ::operator delete(p); }
231 const_arg_iterator arg_end() const { return getTrailingObjects() + NumArgs; }
233 arg_iterator arg_end() { return getTrailingObjects() + NumArgs; }
234
235 unsigned arg_size() const { return NumArgs; }
236
237 static FunctionInfo *
238 create(CallingConv::ID CC, const Type *ReturnType,
239 ArrayRef<const Type *> ArgTypes,
240 std::optional<unsigned> NumRequired = std::nullopt);
241
242 const Type *getReturnType() const { return ReturnType; }
243 ArgInfo &getReturnInfo() { return ReturnInfo; }
244 const ArgInfo &getReturnInfo() const { return ReturnInfo; }
245
247
248 bool isVariadic() const { return NumRequired.has_value(); }
249
250 unsigned getNumRequiredArgs() const {
251 return isVariadic() ? *NumRequired : arg_size();
252 }
253
255 return {getTrailingObjects(), NumArgs};
256 }
257
259 return {getTrailingObjects(), NumArgs};
260 }
261
262 ArgEntry &getArgInfo(unsigned Index) {
263 assert(Index < NumArgs && "Invalid argument index");
264 return arguments()[Index];
265 }
266
267 const ArgEntry &getArgInfo(unsigned Index) const {
268 assert(Index < NumArgs && "Invalid argument index");
269 return arguments()[Index];
270 }
271};
272
273} // namespace abi
274} // namespace llvm
275
276#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 T
This header defines support for implementing classes that have some trailing object (or arrays of obj...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition ArrayRef.h:298
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
static FunctionInfo * create(CallingConv::ID CC, const Type *ReturnType, ArrayRef< const Type * > ArgTypes, std::optional< unsigned > NumRequired=std::nullopt)
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
Represents the ABI-specific view of a type in LLVM.
Definition Types.h:45
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:532
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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