xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Support/ModRef.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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