1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
//===- LibCallSemantics.h - Describe library semantics --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces that can be used to describe language specific
// runtime library interfaces (e.g. libc, libm, etc) to LLVM optimizers.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LIBCALLSEMANTICS_H
#define LLVM_ANALYSIS_LIBCALLSEMANTICS_H
#include "llvm/Analysis/AliasAnalysis.h"
namespace llvm {
class InvokeInst;
/// LibCallLocationInfo - This struct describes a set of memory locations that
/// are accessed by libcalls. Identification of a location is doing with a
/// simple callback function.
///
/// For example, the LibCallInfo may be set up to model the behavior of
/// standard libm functions. The location that they may be interested in is
/// an abstract location that represents errno for the current target. In
/// this case, a location for errno is anything such that the predicate
/// returns true. On Mac OS X, this predicate would return true if the
/// pointer is the result of a call to "__error()".
///
/// Locations can also be defined in a constant-sensitive way. For example,
/// it is possible to define a location that returns true iff it is passed
/// into the call as a specific argument. This is useful for modeling things
/// like "printf", which can store to memory, but only through pointers passed
/// with a '%n' constraint.
///
struct LibCallLocationInfo {
// TODO: Flags: isContextSensitive etc.
/// isLocation - Return a LocResult if the specified pointer refers to this
/// location for the specified call site. This returns "Yes" if we can tell
/// that the pointer *does definitely* refer to the location, "No" if we can
/// tell that the location *definitely does not* refer to the location, and
/// returns "Unknown" if we cannot tell for certain.
enum LocResult {
Yes, No, Unknown
};
LocResult (*isLocation)(ImmutableCallSite CS,
const AliasAnalysis::Location &Loc);
};
/// LibCallFunctionInfo - Each record in the array of FunctionInfo structs
/// records the behavior of one libcall that is known by the optimizer. This
/// captures things like the side effects of the call. Side effects are
/// modeled both universally (in the readnone/readonly) sense, but also
/// potentially against a set of abstract locations defined by the optimizer.
/// This allows an optimizer to define that some libcall (e.g. sqrt) is
/// side-effect free except that it might modify errno (thus, the call is
/// *not* universally readonly). Or it might say that the side effects
/// are unknown other than to say that errno is not modified.
///
struct LibCallFunctionInfo {
/// Name - This is the name of the libcall this describes.
const char *Name;
/// TODO: Constant folding function: Constant* vector -> Constant*.
/// UniversalBehavior - This captures the absolute mod/ref behavior without
/// any specific context knowledge. For example, if the function is known
/// to be readonly, this would be set to 'ref'. If known to be readnone,
/// this is set to NoModRef.
AliasAnalysis::ModRefResult UniversalBehavior;
/// LocationMRInfo - This pair captures info about whether a specific
/// location is modified or referenced by a libcall.
struct LocationMRInfo {
/// LocationID - ID # of the accessed location or ~0U for array end.
unsigned LocationID;
/// MRInfo - Mod/Ref info for this location.
AliasAnalysis::ModRefResult MRInfo;
};
/// DetailsType - Indicate the sense of the LocationDetails array. This
/// controls how the LocationDetails array is interpreted.
enum {
/// DoesOnly - If DetailsType is set to DoesOnly, then we know that the
/// *only* mod/ref behavior of this function is captured by the
/// LocationDetails array. If we are trying to say that 'sqrt' can only
/// modify errno, we'd have the {errnoloc,mod} in the LocationDetails
/// array and have DetailsType set to DoesOnly.
DoesOnly,
/// DoesNot - If DetailsType is set to DoesNot, then the sense of the
/// LocationDetails array is completely inverted. This means that we *do
/// not* know everything about the side effects of this libcall, but we do
/// know things that the libcall cannot do. This is useful for complex
/// functions like 'ctime' which have crazy mod/ref behavior, but are
/// known to never read or write errno. In this case, we'd have
/// {errnoloc,modref} in the LocationDetails array and DetailsType would
/// be set to DoesNot, indicating that ctime does not read or write the
/// errno location.
DoesNot
} DetailsType;
/// LocationDetails - This is a pointer to an array of LocationMRInfo
/// structs which indicates the behavior of the libcall w.r.t. specific
/// locations. For example, if this libcall is known to only modify
/// 'errno', it would have a LocationDetails array with the errno ID and
/// 'mod' in it. See the DetailsType field for how this is interpreted.
///
/// In the "DoesOnly" case, this information is 'may' information for: there
/// is no guarantee that the specified side effect actually does happen,
/// just that it could. In the "DoesNot" case, this is 'must not' info.
///
/// If this pointer is null, no details are known.
///
const LocationMRInfo *LocationDetails;
};
/// LibCallInfo - Abstract interface to query about library call information.
/// Instances of this class return known information about some set of
/// libcalls.
///
class LibCallInfo {
// Implementation details of this object, private.
mutable void *Impl;
mutable const LibCallLocationInfo *Locations;
mutable unsigned NumLocations;
public:
LibCallInfo() : Impl(nullptr), Locations(nullptr), NumLocations(0) {}
virtual ~LibCallInfo();
//===------------------------------------------------------------------===//
// Accessor Methods: Efficient access to contained data.
//===------------------------------------------------------------------===//
/// getLocationInfo - Return information about the specified LocationID.
const LibCallLocationInfo &getLocationInfo(unsigned LocID) const;
/// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to
/// the specified function if we have it. If not, return null.
const LibCallFunctionInfo *getFunctionInfo(const Function *F) const;
//===------------------------------------------------------------------===//
// Implementation Methods: Subclasses should implement these.
//===------------------------------------------------------------------===//
/// getLocationInfo - Return descriptors for the locations referenced by
/// this set of libcalls.
virtual unsigned getLocationInfo(const LibCallLocationInfo *&Array) const {
return 0;
}
/// getFunctionInfoArray - Return an array of descriptors that describe the
/// set of libcalls represented by this LibCallInfo object. This array is
/// terminated by an entry with a NULL name.
virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0;
};
enum class EHPersonality {
Unknown,
GNU_Ada,
GNU_C,
GNU_CXX,
GNU_ObjC,
MSVC_X86SEH,
MSVC_Win64SEH,
MSVC_CXX,
};
/// \brief See if the given exception handling personality function is one
/// that we understand. If so, return a description of it; otherwise return
/// Unknown.
EHPersonality classifyEHPersonality(const Value *Pers);
/// \brief Returns true if this personality function catches asynchronous
/// exceptions.
inline bool isAsynchronousEHPersonality(EHPersonality Pers) {
// The two SEH personality functions can catch asynch exceptions. We assume
// unknown personalities don't catch asynch exceptions.
switch (Pers) {
case EHPersonality::MSVC_X86SEH:
case EHPersonality::MSVC_Win64SEH:
return true;
default: return false;
}
llvm_unreachable("invalid enum");
}
/// \brief Returns true if this is an MSVC personality function.
inline bool isMSVCEHPersonality(EHPersonality Pers) {
// The two SEH personality functions can catch asynch exceptions. We assume
// unknown personalities don't catch asynch exceptions.
switch (Pers) {
case EHPersonality::MSVC_CXX:
case EHPersonality::MSVC_X86SEH:
case EHPersonality::MSVC_Win64SEH:
return true;
default: return false;
}
llvm_unreachable("invalid enum");
}
bool canSimplifyInvokeNoUnwind(const InvokeInst *II);
} // end namespace llvm
#endif
|