1 //===--- ModRef.h - Memory effect modeling ----------------------*- 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 // Definitions of ModRefInfo and MemoryEffects, which are used to
10 // describe the memory effects of instructions.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_SUPPORT_MODREF_H
15 #define LLVM_SUPPORT_MODREF_H
16
17 #include "llvm/ADT/BitmaskEnum.h"
18 #include "llvm/ADT/Sequence.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/raw_ostream.h"
21
22 namespace llvm {
23
24 /// Flags indicating whether a memory access modifies or references memory.
25 ///
26 /// This is no access at all, a modification, a reference, or both
27 /// a modification and a reference.
28 enum class ModRefInfo : uint8_t {
29 /// The access neither references nor modifies the value stored in memory.
30 NoModRef = 0,
31 /// The access may reference the value stored in memory.
32 Ref = 1,
33 /// The access may modify the value stored in memory.
34 Mod = 2,
35 /// The access may reference and may modify the value stored in memory.
36 ModRef = Ref | Mod,
37 LLVM_MARK_AS_BITMASK_ENUM(ModRef),
38 };
39
isNoModRef(const ModRefInfo MRI)40 [[nodiscard]] inline bool isNoModRef(const ModRefInfo MRI) {
41 return MRI == ModRefInfo::NoModRef;
42 }
isModOrRefSet(const ModRefInfo MRI)43 [[nodiscard]] inline bool isModOrRefSet(const ModRefInfo MRI) {
44 return MRI != ModRefInfo::NoModRef;
45 }
isModAndRefSet(const ModRefInfo MRI)46 [[nodiscard]] inline bool isModAndRefSet(const ModRefInfo MRI) {
47 return MRI == ModRefInfo::ModRef;
48 }
isModSet(const ModRefInfo MRI)49 [[nodiscard]] inline bool isModSet(const ModRefInfo MRI) {
50 return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Mod);
51 }
isRefSet(const ModRefInfo MRI)52 [[nodiscard]] inline bool isRefSet(const ModRefInfo MRI) {
53 return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Ref);
54 }
55
56 /// Debug print ModRefInfo.
57 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, ModRefInfo MR);
58
59 /// The locations at which a function might access memory.
60 enum class IRMemLocation {
61 /// Access to memory via argument pointers.
62 ArgMem = 0,
63 /// Memory that is inaccessible via LLVM IR.
64 InaccessibleMem = 1,
65 /// Errno memory.
66 ErrnoMem = 2,
67 /// Any other memory.
68 Other = 3,
69
70 /// Helpers to iterate all locations in the MemoryEffectsBase class.
71 First = ArgMem,
72 Last = Other,
73 };
74
75 template <typename LocationEnum> class MemoryEffectsBase {
76 public:
77 using Location = LocationEnum;
78
79 private:
80 uint32_t Data = 0;
81
82 static constexpr uint32_t BitsPerLoc = 2;
83 static constexpr uint32_t LocMask = (1 << BitsPerLoc) - 1;
84
getLocationPos(Location Loc)85 static uint32_t getLocationPos(Location Loc) {
86 return (uint32_t)Loc * BitsPerLoc;
87 }
88
MemoryEffectsBase(uint32_t Data)89 MemoryEffectsBase(uint32_t Data) : Data(Data) {}
90
setModRef(Location Loc,ModRefInfo MR)91 void setModRef(Location Loc, ModRefInfo MR) {
92 Data &= ~(LocMask << getLocationPos(Loc));
93 Data |= static_cast<uint32_t>(MR) << getLocationPos(Loc);
94 }
95
96 public:
97 /// Returns iterator over all supported location kinds.
locations()98 static auto locations() {
99 return enum_seq_inclusive(Location::First, Location::Last,
100 force_iteration_on_noniterable_enum);
101 }
102
103 /// Create MemoryEffectsBase that can access only the given location with the
104 /// given ModRefInfo.
MemoryEffectsBase(Location Loc,ModRefInfo MR)105 MemoryEffectsBase(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
106
107 /// Create MemoryEffectsBase that can access any location with the given
108 /// ModRefInfo.
MemoryEffectsBase(ModRefInfo MR)109 explicit MemoryEffectsBase(ModRefInfo MR) {
110 for (Location Loc : locations())
111 setModRef(Loc, MR);
112 }
113
114 /// Create MemoryEffectsBase that can read and write any memory.
unknown()115 static MemoryEffectsBase unknown() {
116 return MemoryEffectsBase(ModRefInfo::ModRef);
117 }
118
119 /// Create MemoryEffectsBase that cannot read or write any memory.
none()120 static MemoryEffectsBase none() {
121 return MemoryEffectsBase(ModRefInfo::NoModRef);
122 }
123
124 /// Create MemoryEffectsBase that can read any memory.
readOnly()125 static MemoryEffectsBase readOnly() {
126 return MemoryEffectsBase(ModRefInfo::Ref);
127 }
128
129 /// Create MemoryEffectsBase that can write any memory.
writeOnly()130 static MemoryEffectsBase writeOnly() {
131 return MemoryEffectsBase(ModRefInfo::Mod);
132 }
133
134 /// Create MemoryEffectsBase that can only access argument memory.
135 static MemoryEffectsBase argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
136 return MemoryEffectsBase(Location::ArgMem, MR);
137 }
138
139 /// Create MemoryEffectsBase that can only access inaccessible memory.
140 static MemoryEffectsBase
141 inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
142 return MemoryEffectsBase(Location::InaccessibleMem, MR);
143 }
144
145 /// Create MemoryEffectsBase that can only access errno memory.
146 static MemoryEffectsBase errnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
147 return MemoryEffectsBase(Location::ErrnoMem, MR);
148 }
149
150 /// Create MemoryEffectsBase that can only access other memory.
151 static MemoryEffectsBase otherMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
152 return MemoryEffectsBase(Location::Other, MR);
153 }
154
155 /// Create MemoryEffectsBase that can only access inaccessible or argument
156 /// memory.
157 static MemoryEffectsBase
158 inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
159 MemoryEffectsBase FRMB = none();
160 FRMB.setModRef(Location::ArgMem, MR);
161 FRMB.setModRef(Location::InaccessibleMem, MR);
162 return FRMB;
163 }
164
165 /// Create MemoryEffectsBase that can only access argument or errno memory.
166 static MemoryEffectsBase
167 argumentOrErrnoMemOnly(ModRefInfo ArgMR = ModRefInfo::ModRef,
168 ModRefInfo ErrnoMR = ModRefInfo::ModRef) {
169 MemoryEffectsBase FRMB = none();
170 FRMB.setModRef(Location::ArgMem, ArgMR);
171 FRMB.setModRef(Location::ErrnoMem, ErrnoMR);
172 return FRMB;
173 }
174
175 /// Create MemoryEffectsBase from an encoded integer value (used by memory
176 /// attribute).
createFromIntValue(uint32_t Data)177 static MemoryEffectsBase createFromIntValue(uint32_t Data) {
178 return MemoryEffectsBase(Data);
179 }
180
181 /// Convert MemoryEffectsBase into an encoded integer value (used by memory
182 /// attribute).
toIntValue()183 uint32_t toIntValue() const {
184 return Data;
185 }
186
187 /// Get ModRefInfo for the given Location.
getModRef(Location Loc)188 ModRefInfo getModRef(Location Loc) const {
189 return ModRefInfo((Data >> getLocationPos(Loc)) & LocMask);
190 }
191
192 /// Get new MemoryEffectsBase with modified ModRefInfo for Loc.
getWithModRef(Location Loc,ModRefInfo MR)193 MemoryEffectsBase getWithModRef(Location Loc, ModRefInfo MR) const {
194 MemoryEffectsBase ME = *this;
195 ME.setModRef(Loc, MR);
196 return ME;
197 }
198
199 /// Get new MemoryEffectsBase with NoModRef on the given Loc.
getWithoutLoc(Location Loc)200 MemoryEffectsBase getWithoutLoc(Location Loc) const {
201 MemoryEffectsBase ME = *this;
202 ME.setModRef(Loc, ModRefInfo::NoModRef);
203 return ME;
204 }
205
206 /// Get ModRefInfo for any location.
getModRef()207 ModRefInfo getModRef() const {
208 ModRefInfo MR = ModRefInfo::NoModRef;
209 for (Location Loc : locations())
210 MR |= getModRef(Loc);
211 return MR;
212 }
213
214 /// Whether this function accesses no memory.
doesNotAccessMemory()215 bool doesNotAccessMemory() const { return Data == 0; }
216
217 /// Whether this function only (at most) reads memory.
onlyReadsMemory()218 bool onlyReadsMemory() const { return !isModSet(getModRef()); }
219
220 /// Whether this function only (at most) writes memory.
onlyWritesMemory()221 bool onlyWritesMemory() const { return !isRefSet(getModRef()); }
222
223 /// Whether this function only (at most) accesses argument memory.
onlyAccessesArgPointees()224 bool onlyAccessesArgPointees() const {
225 return getWithoutLoc(Location::ArgMem).doesNotAccessMemory();
226 }
227
228 /// Whether this function may access argument memory.
doesAccessArgPointees()229 bool doesAccessArgPointees() const {
230 return isModOrRefSet(getModRef(Location::ArgMem));
231 }
232
233 /// Whether this function only (at most) accesses inaccessible memory.
onlyAccessesInaccessibleMem()234 bool onlyAccessesInaccessibleMem() const {
235 return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
236 }
237
238 /// Whether this function only (at most) accesses errno memory.
onlyAccessesErrnoMem()239 bool onlyAccessesErrnoMem() const {
240 return getWithoutLoc(Location::ErrnoMem).doesNotAccessMemory();
241 }
242
243 /// Whether this function only (at most) accesses argument and inaccessible
244 /// memory.
onlyAccessesInaccessibleOrArgMem()245 bool onlyAccessesInaccessibleOrArgMem() const {
246 return getWithoutLoc(Location::InaccessibleMem)
247 .getWithoutLoc(Location::ArgMem)
248 .doesNotAccessMemory();
249 }
250
251 /// Intersect with other MemoryEffectsBase.
252 MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
253 return MemoryEffectsBase(Data & Other.Data);
254 }
255
256 /// Intersect (in-place) with other MemoryEffectsBase.
257 MemoryEffectsBase &operator&=(MemoryEffectsBase Other) {
258 Data &= Other.Data;
259 return *this;
260 }
261
262 /// Union with other MemoryEffectsBase.
263 MemoryEffectsBase operator|(MemoryEffectsBase Other) const {
264 return MemoryEffectsBase(Data | Other.Data);
265 }
266
267 /// Union (in-place) with other MemoryEffectsBase.
268 MemoryEffectsBase &operator|=(MemoryEffectsBase Other) {
269 Data |= Other.Data;
270 return *this;
271 }
272
273 /// Subtract other MemoryEffectsBase.
274 MemoryEffectsBase operator-(MemoryEffectsBase Other) const {
275 return MemoryEffectsBase(Data & ~Other.Data);
276 }
277
278 /// Subtract (in-place) with other MemoryEffectsBase.
279 MemoryEffectsBase &operator-=(MemoryEffectsBase Other) {
280 Data &= ~Other.Data;
281 return *this;
282 }
283
284 /// Check whether this is the same as other MemoryEffectsBase.
285 bool operator==(MemoryEffectsBase Other) const { return Data == Other.Data; }
286
287 /// Check whether this is different from other MemoryEffectsBase.
288 bool operator!=(MemoryEffectsBase Other) const { return !operator==(Other); }
289 };
290
291 /// Summary of how a function affects memory in the program.
292 ///
293 /// Loads from constant globals are not considered memory accesses for this
294 /// interface. Also, functions may freely modify stack space local to their
295 /// invocation without having to report it through these interfaces.
296 using MemoryEffects = MemoryEffectsBase<IRMemLocation>;
297
298 /// Debug print MemoryEffects.
299 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
300
301 // Legacy alias.
302 using FunctionModRefBehavior = MemoryEffects;
303
304 /// Components of the pointer that may be captured.
305 enum class CaptureComponents : uint8_t {
306 None = 0,
307 AddressIsNull = (1 << 0),
308 Address = (1 << 1) | AddressIsNull,
309 ReadProvenance = (1 << 2),
310 Provenance = (1 << 3) | ReadProvenance,
311 All = Address | Provenance,
312 LLVM_MARK_AS_BITMASK_ENUM(Provenance),
313 };
314
capturesNothing(CaptureComponents CC)315 inline bool capturesNothing(CaptureComponents CC) {
316 return CC == CaptureComponents::None;
317 }
318
capturesAnything(CaptureComponents CC)319 inline bool capturesAnything(CaptureComponents CC) {
320 return CC != CaptureComponents::None;
321 }
322
capturesAddressIsNullOnly(CaptureComponents CC)323 inline bool capturesAddressIsNullOnly(CaptureComponents CC) {
324 return (CC & CaptureComponents::Address) == CaptureComponents::AddressIsNull;
325 }
326
capturesAddress(CaptureComponents CC)327 inline bool capturesAddress(CaptureComponents CC) {
328 return (CC & CaptureComponents::Address) != CaptureComponents::None;
329 }
330
capturesReadProvenanceOnly(CaptureComponents CC)331 inline bool capturesReadProvenanceOnly(CaptureComponents CC) {
332 return (CC & CaptureComponents::Provenance) ==
333 CaptureComponents::ReadProvenance;
334 }
335
capturesFullProvenance(CaptureComponents CC)336 inline bool capturesFullProvenance(CaptureComponents CC) {
337 return (CC & CaptureComponents::Provenance) == CaptureComponents::Provenance;
338 }
339
capturesAnyProvenance(CaptureComponents CC)340 inline bool capturesAnyProvenance(CaptureComponents CC) {
341 return (CC & CaptureComponents::Provenance) != CaptureComponents::None;
342 }
343
capturesAll(CaptureComponents CC)344 inline bool capturesAll(CaptureComponents CC) {
345 return CC == CaptureComponents::All;
346 }
347
348 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, CaptureComponents CC);
349
350 /// Represents which components of the pointer may be captured in which
351 /// location. This represents the captures(...) attribute in IR.
352 ///
353 /// For more information on the precise semantics see LangRef.
354 class CaptureInfo {
355 CaptureComponents OtherComponents;
356 CaptureComponents RetComponents;
357
358 public:
CaptureInfo(CaptureComponents OtherComponents,CaptureComponents RetComponents)359 CaptureInfo(CaptureComponents OtherComponents,
360 CaptureComponents RetComponents)
361 : OtherComponents(OtherComponents), RetComponents(RetComponents) {}
362
CaptureInfo(CaptureComponents Components)363 CaptureInfo(CaptureComponents Components)
364 : OtherComponents(Components), RetComponents(Components) {}
365
366 /// Create CaptureInfo that does not capture any components of the pointer
none()367 static CaptureInfo none() { return CaptureInfo(CaptureComponents::None); }
368
369 /// Create CaptureInfo that may capture all components of the pointer.
all()370 static CaptureInfo all() { return CaptureInfo(CaptureComponents::All); }
371
372 /// Create CaptureInfo that may only capture via the return value.
373 static CaptureInfo
374 retOnly(CaptureComponents RetComponents = CaptureComponents::All) {
375 return CaptureInfo(CaptureComponents::None, RetComponents);
376 }
377
378 /// Whether the pointer is only captured via the return value.
isRetOnly()379 bool isRetOnly() const { return capturesNothing(OtherComponents); }
380
381 /// Get components potentially captured by the return value.
getRetComponents()382 CaptureComponents getRetComponents() const { return RetComponents; }
383
384 /// Get components potentially captured through locations other than the
385 /// return value.
getOtherComponents()386 CaptureComponents getOtherComponents() const { return OtherComponents; }
387
388 /// Get the potentially captured components of the pointer (regardless of
389 /// location).
CaptureComponents()390 operator CaptureComponents() const { return OtherComponents | RetComponents; }
391
392 bool operator==(CaptureInfo Other) const {
393 return OtherComponents == Other.OtherComponents &&
394 RetComponents == Other.RetComponents;
395 }
396
397 bool operator!=(CaptureInfo Other) const { return !(*this == Other); }
398
399 /// Compute union of CaptureInfos.
400 CaptureInfo operator|(CaptureInfo Other) const {
401 return CaptureInfo(OtherComponents | Other.OtherComponents,
402 RetComponents | Other.RetComponents);
403 }
404
405 /// Compute intersection of CaptureInfos.
406 CaptureInfo operator&(CaptureInfo Other) const {
407 return CaptureInfo(OtherComponents & Other.OtherComponents,
408 RetComponents & Other.RetComponents);
409 }
410
411 /// Compute union of CaptureInfos in-place.
412 CaptureInfo &operator|=(CaptureInfo Other) {
413 OtherComponents |= Other.OtherComponents;
414 RetComponents |= Other.RetComponents;
415 return *this;
416 }
417
418 /// Compute intersection of CaptureInfos in-place.
419 CaptureInfo &operator&=(CaptureInfo Other) {
420 OtherComponents &= Other.OtherComponents;
421 RetComponents &= Other.RetComponents;
422 return *this;
423 }
424
createFromIntValue(uint32_t Data)425 static CaptureInfo createFromIntValue(uint32_t Data) {
426 return CaptureInfo(CaptureComponents(Data >> 4),
427 CaptureComponents(Data & 0xf));
428 }
429
430 /// Convert CaptureInfo into an encoded integer value (used by captures
431 /// attribute).
toIntValue()432 uint32_t toIntValue() const {
433 return (uint32_t(OtherComponents) << 4) | uint32_t(RetComponents);
434 }
435 };
436
437 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, CaptureInfo Info);
438
439 } // namespace llvm
440
441 #endif
442