Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 8b54999

Browse files
committed
Add CodeGenABITypes.h for use in LLDB.
CodeGenABITypes is a wrapper built on top of CodeGenModule that exposes some of the functionality of CodeGenTypes (held by CodeGenModule), specifically methods that determine the LLVM types appropriate for function argument and return values. I addition to CodeGenABITypes.h, CGFunctionInfo.h is introduced, and the definitions of ABIArgInfo, RequiredArgs, and CGFunctionInfo are moved into this new header from the private headers ABIInfo.h and CGCall.h. Exposing this functionality is one part of making it possible for LLDB to determine the actual ABI locations of function arguments and return values, making it possible for it to determine this for any supported target without hard-coding ABI knowledge in the LLDB code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193717 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 6334fd6 commit 8b54999

19 files changed

+524
-325
lines changed
+361
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
//==-- CGFunctionInfo.h - Representation of function argument/return types -==//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// Defines CGFunctionInfo and associated types used in representing the
11+
// LLVM source types and ABI-coerced types for function arguments and
12+
// return values.
13+
//
14+
//===----------------------------------------------------------------------===//
15+
16+
#ifndef LLVM_CLANG_CODEGEN_FUNCTION_INFO_H
17+
#define LLVM_CLANG_CODEGEN_FUNCTION_INFO_H
18+
19+
#include "clang/AST/CanonicalType.h"
20+
#include "clang/AST/Type.h"
21+
#include "llvm/ADT/FoldingSet.h"
22+
23+
#include <cassert>
24+
25+
namespace llvm {
26+
class Type;
27+
}
28+
29+
namespace clang {
30+
namespace CodeGen {
31+
32+
/// ABIArgInfo - Helper class to encapsulate information about how a
33+
/// specific C type should be passed to or returned from a function.
34+
class ABIArgInfo {
35+
public:
36+
enum Kind {
37+
/// Direct - Pass the argument directly using the normal converted LLVM
38+
/// type, or by coercing to another specified type stored in
39+
/// 'CoerceToType'). If an offset is specified (in UIntData), then the
40+
/// argument passed is offset by some number of bytes in the memory
41+
/// representation. A dummy argument is emitted before the real argument
42+
/// if the specified type stored in "PaddingType" is not zero.
43+
Direct,
44+
45+
/// Extend - Valid only for integer argument types. Same as 'direct'
46+
/// but also emit a zero/sign extension attribute.
47+
Extend,
48+
49+
/// Indirect - Pass the argument indirectly via a hidden pointer
50+
/// with the specified alignment (0 indicates default alignment).
51+
Indirect,
52+
53+
/// Ignore - Ignore the argument (treat as void). Useful for void and
54+
/// empty structs.
55+
Ignore,
56+
57+
/// Expand - Only valid for aggregate argument types. The structure should
58+
/// be expanded into consecutive arguments for its constituent fields.
59+
/// Currently expand is only allowed on structures whose fields
60+
/// are all scalar types or are themselves expandable types.
61+
Expand,
62+
63+
KindFirst=Direct, KindLast=Expand
64+
};
65+
66+
private:
67+
Kind TheKind;
68+
llvm::Type *TypeData;
69+
llvm::Type *PaddingType;
70+
unsigned UIntData;
71+
bool BoolData0;
72+
bool BoolData1;
73+
bool InReg;
74+
bool PaddingInReg;
75+
76+
ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR,
77+
bool PIR, llvm::Type* P)
78+
: TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0),
79+
BoolData1(B1), InReg(IR), PaddingInReg(PIR) {}
80+
81+
public:
82+
ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
83+
84+
static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0,
85+
llvm::Type *Padding = 0) {
86+
return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding);
87+
}
88+
static ABIArgInfo getDirectInReg(llvm::Type *T = 0) {
89+
return ABIArgInfo(Direct, T, 0, false, false, true, false, 0);
90+
}
91+
static ABIArgInfo getExtend(llvm::Type *T = 0) {
92+
return ABIArgInfo(Extend, T, 0, false, false, false, false, 0);
93+
}
94+
static ABIArgInfo getExtendInReg(llvm::Type *T = 0) {
95+
return ABIArgInfo(Extend, T, 0, false, false, true, false, 0);
96+
}
97+
static ABIArgInfo getIgnore() {
98+
return ABIArgInfo(Ignore, 0, 0, false, false, false, false, 0);
99+
}
100+
static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
101+
, bool Realign = false
102+
, llvm::Type *Padding = 0) {
103+
return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false,
104+
Padding);
105+
}
106+
static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true
107+
, bool Realign = false) {
108+
return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0);
109+
}
110+
static ABIArgInfo getExpand() {
111+
return ABIArgInfo(Expand, 0, 0, false, false, false, false, 0);
112+
}
113+
static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
114+
llvm::Type *Padding) {
115+
return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg,
116+
Padding);
117+
}
118+
119+
Kind getKind() const { return TheKind; }
120+
bool isDirect() const { return TheKind == Direct; }
121+
bool isExtend() const { return TheKind == Extend; }
122+
bool isIgnore() const { return TheKind == Ignore; }
123+
bool isIndirect() const { return TheKind == Indirect; }
124+
bool isExpand() const { return TheKind == Expand; }
125+
126+
bool canHaveCoerceToType() const {
127+
return TheKind == Direct || TheKind == Extend;
128+
}
129+
130+
// Direct/Extend accessors
131+
unsigned getDirectOffset() const {
132+
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
133+
return UIntData;
134+
}
135+
136+
llvm::Type *getPaddingType() const {
137+
return PaddingType;
138+
}
139+
140+
bool getPaddingInReg() const {
141+
return PaddingInReg;
142+
}
143+
144+
llvm::Type *getCoerceToType() const {
145+
assert(canHaveCoerceToType() && "Invalid kind!");
146+
return TypeData;
147+
}
148+
149+
void setCoerceToType(llvm::Type *T) {
150+
assert(canHaveCoerceToType() && "Invalid kind!");
151+
TypeData = T;
152+
}
153+
154+
bool getInReg() const {
155+
assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
156+
return InReg;
157+
}
158+
159+
// Indirect accessors
160+
unsigned getIndirectAlign() const {
161+
assert(TheKind == Indirect && "Invalid kind!");
162+
return UIntData;
163+
}
164+
165+
bool getIndirectByVal() const {
166+
assert(TheKind == Indirect && "Invalid kind!");
167+
return BoolData0;
168+
}
169+
170+
bool getIndirectRealign() const {
171+
assert(TheKind == Indirect && "Invalid kind!");
172+
return BoolData1;
173+
}
174+
175+
void dump() const;
176+
};
177+
178+
/// A class for recording the number of arguments that a function
179+
/// signature requires.
180+
class RequiredArgs {
181+
/// The number of required arguments, or ~0 if the signature does
182+
/// not permit optional arguments.
183+
unsigned NumRequired;
184+
public:
185+
enum All_t { All };
186+
187+
RequiredArgs(All_t _) : NumRequired(~0U) {}
188+
explicit RequiredArgs(unsigned n) : NumRequired(n) {
189+
assert(n != ~0U);
190+
}
191+
192+
/// Compute the arguments required by the given formal prototype,
193+
/// given that there may be some additional, non-formal arguments
194+
/// in play.
195+
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
196+
unsigned additional) {
197+
if (!prototype->isVariadic()) return All;
198+
return RequiredArgs(prototype->getNumArgs() + additional);
199+
}
200+
201+
static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
202+
return forPrototypePlus(prototype, 0);
203+
}
204+
205+
static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
206+
return forPrototype(prototype.getTypePtr());
207+
}
208+
209+
static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
210+
unsigned additional) {
211+
return forPrototypePlus(prototype.getTypePtr(), additional);
212+
}
213+
214+
bool allowsOptionalArgs() const { return NumRequired != ~0U; }
215+
unsigned getNumRequiredArgs() const {
216+
assert(allowsOptionalArgs());
217+
return NumRequired;
218+
}
219+
220+
unsigned getOpaqueData() const { return NumRequired; }
221+
static RequiredArgs getFromOpaqueData(unsigned value) {
222+
if (value == ~0U) return All;
223+
return RequiredArgs(value);
224+
}
225+
};
226+
227+
/// CGFunctionInfo - Class to encapsulate the information about a
228+
/// function definition.
229+
class CGFunctionInfo : public llvm::FoldingSetNode {
230+
struct ArgInfo {
231+
CanQualType type;
232+
ABIArgInfo info;
233+
};
234+
235+
/// The LLVM::CallingConv to use for this function (as specified by the
236+
/// user).
237+
unsigned CallingConvention : 8;
238+
239+
/// The LLVM::CallingConv to actually use for this function, which may
240+
/// depend on the ABI.
241+
unsigned EffectiveCallingConvention : 8;
242+
243+
/// The clang::CallingConv that this was originally created with.
244+
unsigned ASTCallingConvention : 8;
245+
246+
/// Whether this function is noreturn.
247+
unsigned NoReturn : 1;
248+
249+
/// Whether this function is returns-retained.
250+
unsigned ReturnsRetained : 1;
251+
252+
/// How many arguments to pass inreg.
253+
unsigned HasRegParm : 1;
254+
unsigned RegParm : 4;
255+
256+
RequiredArgs Required;
257+
258+
unsigned NumArgs;
259+
ArgInfo *getArgsBuffer() {
260+
return reinterpret_cast<ArgInfo*>(this+1);
261+
}
262+
const ArgInfo *getArgsBuffer() const {
263+
return reinterpret_cast<const ArgInfo*>(this + 1);
264+
}
265+
266+
CGFunctionInfo() : Required(RequiredArgs::All) {}
267+
268+
public:
269+
static CGFunctionInfo *create(unsigned llvmCC,
270+
const FunctionType::ExtInfo &extInfo,
271+
CanQualType resultType,
272+
ArrayRef<CanQualType> argTypes,
273+
RequiredArgs required);
274+
275+
typedef const ArgInfo *const_arg_iterator;
276+
typedef ArgInfo *arg_iterator;
277+
278+
const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
279+
const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
280+
arg_iterator arg_begin() { return getArgsBuffer() + 1; }
281+
arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
282+
283+
unsigned arg_size() const { return NumArgs; }
284+
285+
bool isVariadic() const { return Required.allowsOptionalArgs(); }
286+
RequiredArgs getRequiredArgs() const { return Required; }
287+
288+
bool isNoReturn() const { return NoReturn; }
289+
290+
/// In ARC, whether this function retains its return value. This
291+
/// is not always reliable for call sites.
292+
bool isReturnsRetained() const { return ReturnsRetained; }
293+
294+
/// getASTCallingConvention() - Return the AST-specified calling
295+
/// convention.
296+
CallingConv getASTCallingConvention() const {
297+
return CallingConv(ASTCallingConvention);
298+
}
299+
300+
/// getCallingConvention - Return the user specified calling
301+
/// convention, which has been translated into an LLVM CC.
302+
unsigned getCallingConvention() const { return CallingConvention; }
303+
304+
/// getEffectiveCallingConvention - Return the actual calling convention to
305+
/// use, which may depend on the ABI.
306+
unsigned getEffectiveCallingConvention() const {
307+
return EffectiveCallingConvention;
308+
}
309+
void setEffectiveCallingConvention(unsigned Value) {
310+
EffectiveCallingConvention = Value;
311+
}
312+
313+
bool getHasRegParm() const { return HasRegParm; }
314+
unsigned getRegParm() const { return RegParm; }
315+
316+
FunctionType::ExtInfo getExtInfo() const {
317+
return FunctionType::ExtInfo(isNoReturn(),
318+
getHasRegParm(), getRegParm(),
319+
getASTCallingConvention(),
320+
isReturnsRetained());
321+
}
322+
323+
CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
324+
325+
ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
326+
const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
327+
328+
void Profile(llvm::FoldingSetNodeID &ID) {
329+
ID.AddInteger(getASTCallingConvention());
330+
ID.AddBoolean(NoReturn);
331+
ID.AddBoolean(ReturnsRetained);
332+
ID.AddBoolean(HasRegParm);
333+
ID.AddInteger(RegParm);
334+
ID.AddInteger(Required.getOpaqueData());
335+
getReturnType().Profile(ID);
336+
for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
337+
it->type.Profile(ID);
338+
}
339+
static void Profile(llvm::FoldingSetNodeID &ID,
340+
const FunctionType::ExtInfo &info,
341+
RequiredArgs required,
342+
CanQualType resultType,
343+
ArrayRef<CanQualType> argTypes) {
344+
ID.AddInteger(info.getCC());
345+
ID.AddBoolean(info.getNoReturn());
346+
ID.AddBoolean(info.getProducesResult());
347+
ID.AddBoolean(info.getHasRegParm());
348+
ID.AddInteger(info.getRegParm());
349+
ID.AddInteger(required.getOpaqueData());
350+
resultType.Profile(ID);
351+
for (ArrayRef<CanQualType>::iterator
352+
i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
353+
i->Profile(ID);
354+
}
355+
}
356+
};
357+
358+
} // end namespace CodeGen
359+
} // end namespace clang
360+
361+
#endif

0 commit comments

Comments
 (0)