Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:32

0001 //===--- ModRef.h - Memory effect modeling ----------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Definitions of ModRefInfo and MemoryEffects, which are used to
0010 // describe the memory effects of instructions.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_SUPPORT_MODREF_H
0015 #define LLVM_SUPPORT_MODREF_H
0016 
0017 #include "llvm/ADT/BitmaskEnum.h"
0018 #include "llvm/ADT/Sequence.h"
0019 #include "llvm/Support/raw_ostream.h"
0020 
0021 namespace llvm {
0022 
0023 /// Flags indicating whether a memory access modifies or references memory.
0024 ///
0025 /// This is no access at all, a modification, a reference, or both
0026 /// a modification and a reference.
0027 enum class ModRefInfo : uint8_t {
0028   /// The access neither references nor modifies the value stored in memory.
0029   NoModRef = 0,
0030   /// The access may reference the value stored in memory.
0031   Ref = 1,
0032   /// The access may modify the value stored in memory.
0033   Mod = 2,
0034   /// The access may reference and may modify the value stored in memory.
0035   ModRef = Ref | Mod,
0036   LLVM_MARK_AS_BITMASK_ENUM(ModRef),
0037 };
0038 
0039 [[nodiscard]] inline bool isNoModRef(const ModRefInfo MRI) {
0040   return MRI == ModRefInfo::NoModRef;
0041 }
0042 [[nodiscard]] inline bool isModOrRefSet(const ModRefInfo MRI) {
0043   return MRI != ModRefInfo::NoModRef;
0044 }
0045 [[nodiscard]] inline bool isModAndRefSet(const ModRefInfo MRI) {
0046   return MRI == ModRefInfo::ModRef;
0047 }
0048 [[nodiscard]] inline bool isModSet(const ModRefInfo MRI) {
0049   return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Mod);
0050 }
0051 [[nodiscard]] inline bool isRefSet(const ModRefInfo MRI) {
0052   return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Ref);
0053 }
0054 
0055 /// Debug print ModRefInfo.
0056 raw_ostream &operator<<(raw_ostream &OS, ModRefInfo MR);
0057 
0058 /// The locations at which a function might access memory.
0059 enum class IRMemLocation {
0060   /// Access to memory via argument pointers.
0061   ArgMem = 0,
0062   /// Memory that is inaccessible via LLVM IR.
0063   InaccessibleMem = 1,
0064   /// Any other memory.
0065   Other = 2,
0066 
0067   /// Helpers to iterate all locations in the MemoryEffectsBase class.
0068   First = ArgMem,
0069   Last = Other,
0070 };
0071 
0072 template <typename LocationEnum> class MemoryEffectsBase {
0073 public:
0074   using Location = LocationEnum;
0075 
0076 private:
0077   uint32_t Data = 0;
0078 
0079   static constexpr uint32_t BitsPerLoc = 2;
0080   static constexpr uint32_t LocMask = (1 << BitsPerLoc) - 1;
0081 
0082   static uint32_t getLocationPos(Location Loc) {
0083     return (uint32_t)Loc * BitsPerLoc;
0084   }
0085 
0086   MemoryEffectsBase(uint32_t Data) : Data(Data) {}
0087 
0088   void setModRef(Location Loc, ModRefInfo MR) {
0089     Data &= ~(LocMask << getLocationPos(Loc));
0090     Data |= static_cast<uint32_t>(MR) << getLocationPos(Loc);
0091   }
0092 
0093 public:
0094   /// Returns iterator over all supported location kinds.
0095   static auto locations() {
0096     return enum_seq_inclusive(Location::First, Location::Last,
0097                               force_iteration_on_noniterable_enum);
0098   }
0099 
0100   /// Create MemoryEffectsBase that can access only the given location with the
0101   /// given ModRefInfo.
0102   MemoryEffectsBase(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
0103 
0104   /// Create MemoryEffectsBase that can access any location with the given
0105   /// ModRefInfo.
0106   explicit MemoryEffectsBase(ModRefInfo MR) {
0107     for (Location Loc : locations())
0108       setModRef(Loc, MR);
0109   }
0110 
0111   /// Create MemoryEffectsBase that can read and write any memory.
0112   static MemoryEffectsBase unknown() {
0113     return MemoryEffectsBase(ModRefInfo::ModRef);
0114   }
0115 
0116   /// Create MemoryEffectsBase that cannot read or write any memory.
0117   static MemoryEffectsBase none() {
0118     return MemoryEffectsBase(ModRefInfo::NoModRef);
0119   }
0120 
0121   /// Create MemoryEffectsBase that can read any memory.
0122   static MemoryEffectsBase readOnly() {
0123     return MemoryEffectsBase(ModRefInfo::Ref);
0124   }
0125 
0126   /// Create MemoryEffectsBase that can write any memory.
0127   static MemoryEffectsBase writeOnly() {
0128     return MemoryEffectsBase(ModRefInfo::Mod);
0129   }
0130 
0131   /// Create MemoryEffectsBase that can only access argument memory.
0132   static MemoryEffectsBase argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
0133     return MemoryEffectsBase(Location::ArgMem, MR);
0134   }
0135 
0136   /// Create MemoryEffectsBase that can only access inaccessible memory.
0137   static MemoryEffectsBase
0138   inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
0139     return MemoryEffectsBase(Location::InaccessibleMem, MR);
0140   }
0141 
0142   /// Create MemoryEffectsBase that can only access inaccessible or argument
0143   /// memory.
0144   static MemoryEffectsBase
0145   inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
0146     MemoryEffectsBase FRMB = none();
0147     FRMB.setModRef(Location::ArgMem, MR);
0148     FRMB.setModRef(Location::InaccessibleMem, MR);
0149     return FRMB;
0150   }
0151 
0152   /// Create MemoryEffectsBase from an encoded integer value (used by memory
0153   /// attribute).
0154   static MemoryEffectsBase createFromIntValue(uint32_t Data) {
0155     return MemoryEffectsBase(Data);
0156   }
0157 
0158   /// Convert MemoryEffectsBase into an encoded integer value (used by memory
0159   /// attribute).
0160   uint32_t toIntValue() const {
0161     return Data;
0162   }
0163 
0164   /// Get ModRefInfo for the given Location.
0165   ModRefInfo getModRef(Location Loc) const {
0166     return ModRefInfo((Data >> getLocationPos(Loc)) & LocMask);
0167   }
0168 
0169   /// Get new MemoryEffectsBase with modified ModRefInfo for Loc.
0170   MemoryEffectsBase getWithModRef(Location Loc, ModRefInfo MR) const {
0171     MemoryEffectsBase ME = *this;
0172     ME.setModRef(Loc, MR);
0173     return ME;
0174   }
0175 
0176   /// Get new MemoryEffectsBase with NoModRef on the given Loc.
0177   MemoryEffectsBase getWithoutLoc(Location Loc) const {
0178     MemoryEffectsBase ME = *this;
0179     ME.setModRef(Loc, ModRefInfo::NoModRef);
0180     return ME;
0181   }
0182 
0183   /// Get ModRefInfo for any location.
0184   ModRefInfo getModRef() const {
0185     ModRefInfo MR = ModRefInfo::NoModRef;
0186     for (Location Loc : locations())
0187       MR |= getModRef(Loc);
0188     return MR;
0189   }
0190 
0191   /// Whether this function accesses no memory.
0192   bool doesNotAccessMemory() const { return Data == 0; }
0193 
0194   /// Whether this function only (at most) reads memory.
0195   bool onlyReadsMemory() const { return !isModSet(getModRef()); }
0196 
0197   /// Whether this function only (at most) writes memory.
0198   bool onlyWritesMemory() const { return !isRefSet(getModRef()); }
0199 
0200   /// Whether this function only (at most) accesses argument memory.
0201   bool onlyAccessesArgPointees() const {
0202     return getWithoutLoc(Location::ArgMem).doesNotAccessMemory();
0203   }
0204 
0205   /// Whether this function may access argument memory.
0206   bool doesAccessArgPointees() const {
0207     return isModOrRefSet(getModRef(Location::ArgMem));
0208   }
0209 
0210   /// Whether this function only (at most) accesses inaccessible memory.
0211   bool onlyAccessesInaccessibleMem() const {
0212     return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
0213   }
0214 
0215   /// Whether this function only (at most) accesses argument and inaccessible
0216   /// memory.
0217   bool onlyAccessesInaccessibleOrArgMem() const {
0218     return getWithoutLoc(Location::InaccessibleMem)
0219         .getWithoutLoc(Location::ArgMem)
0220         .doesNotAccessMemory();
0221   }
0222 
0223   /// Intersect with other MemoryEffectsBase.
0224   MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
0225     return MemoryEffectsBase(Data & Other.Data);
0226   }
0227 
0228   /// Intersect (in-place) with other MemoryEffectsBase.
0229   MemoryEffectsBase &operator&=(MemoryEffectsBase Other) {
0230     Data &= Other.Data;
0231     return *this;
0232   }
0233 
0234   /// Union with other MemoryEffectsBase.
0235   MemoryEffectsBase operator|(MemoryEffectsBase Other) const {
0236     return MemoryEffectsBase(Data | Other.Data);
0237   }
0238 
0239   /// Union (in-place) with other MemoryEffectsBase.
0240   MemoryEffectsBase &operator|=(MemoryEffectsBase Other) {
0241     Data |= Other.Data;
0242     return *this;
0243   }
0244 
0245   /// Subtract other MemoryEffectsBase.
0246   MemoryEffectsBase operator-(MemoryEffectsBase Other) const {
0247     return MemoryEffectsBase(Data & ~Other.Data);
0248   }
0249 
0250   /// Subtract (in-place) with other MemoryEffectsBase.
0251   MemoryEffectsBase &operator-=(MemoryEffectsBase Other) {
0252     Data &= ~Other.Data;
0253     return *this;
0254   }
0255 
0256   /// Check whether this is the same as other MemoryEffectsBase.
0257   bool operator==(MemoryEffectsBase Other) const { return Data == Other.Data; }
0258 
0259   /// Check whether this is different from other MemoryEffectsBase.
0260   bool operator!=(MemoryEffectsBase Other) const { return !operator==(Other); }
0261 };
0262 
0263 /// Summary of how a function affects memory in the program.
0264 ///
0265 /// Loads from constant globals are not considered memory accesses for this
0266 /// interface. Also, functions may freely modify stack space local to their
0267 /// invocation without having to report it through these interfaces.
0268 using MemoryEffects = MemoryEffectsBase<IRMemLocation>;
0269 
0270 /// Debug print MemoryEffects.
0271 raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
0272 
0273 // Legacy alias.
0274 using FunctionModRefBehavior = MemoryEffects;
0275 
0276 /// Components of the pointer that may be captured.
0277 enum class CaptureComponents : uint8_t {
0278   None = 0,
0279   AddressIsNull = (1 << 0),
0280   Address = (1 << 1) | AddressIsNull,
0281   ReadProvenance = (1 << 2),
0282   Provenance = (1 << 3) | ReadProvenance,
0283   All = Address | Provenance,
0284   LLVM_MARK_AS_BITMASK_ENUM(Provenance),
0285 };
0286 
0287 inline bool capturesNothing(CaptureComponents CC) {
0288   return CC == CaptureComponents::None;
0289 }
0290 
0291 inline bool capturesAnything(CaptureComponents CC) {
0292   return CC != CaptureComponents::None;
0293 }
0294 
0295 inline bool capturesAddressIsNullOnly(CaptureComponents CC) {
0296   return (CC & CaptureComponents::Address) == CaptureComponents::AddressIsNull;
0297 }
0298 
0299 inline bool capturesAddress(CaptureComponents CC) {
0300   return (CC & CaptureComponents::Address) != CaptureComponents::None;
0301 }
0302 
0303 inline bool capturesReadProvenanceOnly(CaptureComponents CC) {
0304   return (CC & CaptureComponents::Provenance) ==
0305          CaptureComponents::ReadProvenance;
0306 }
0307 
0308 inline bool capturesFullProvenance(CaptureComponents CC) {
0309   return (CC & CaptureComponents::Provenance) == CaptureComponents::Provenance;
0310 }
0311 
0312 raw_ostream &operator<<(raw_ostream &OS, CaptureComponents CC);
0313 
0314 /// Represents which components of the pointer may be captured in which
0315 /// location. This represents the captures(...) attribute in IR.
0316 ///
0317 /// For more information on the precise semantics see LangRef.
0318 class CaptureInfo {
0319   CaptureComponents OtherComponents;
0320   CaptureComponents RetComponents;
0321 
0322 public:
0323   CaptureInfo(CaptureComponents OtherComponents,
0324               CaptureComponents RetComponents)
0325       : OtherComponents(OtherComponents), RetComponents(RetComponents) {}
0326 
0327   CaptureInfo(CaptureComponents Components)
0328       : OtherComponents(Components), RetComponents(Components) {}
0329 
0330   /// Create CaptureInfo that may capture all components of the pointer.
0331   static CaptureInfo all() { return CaptureInfo(CaptureComponents::All); }
0332 
0333   /// Get components potentially captured by the return value.
0334   CaptureComponents getRetComponents() const { return RetComponents; }
0335 
0336   /// Get components potentially captured through locations other than the
0337   /// return value.
0338   CaptureComponents getOtherComponents() const { return OtherComponents; }
0339 
0340   /// Get the potentially captured components of the pointer (regardless of
0341   /// location).
0342   operator CaptureComponents() const { return OtherComponents | RetComponents; }
0343 
0344   bool operator==(CaptureInfo Other) const {
0345     return OtherComponents == Other.OtherComponents &&
0346            RetComponents == Other.RetComponents;
0347   }
0348 
0349   bool operator!=(CaptureInfo Other) const { return !(*this == Other); }
0350 
0351   /// Compute union of CaptureInfos.
0352   CaptureInfo operator|(CaptureInfo Other) const {
0353     return CaptureInfo(OtherComponents | Other.OtherComponents,
0354                        RetComponents | Other.RetComponents);
0355   }
0356 
0357   /// Compute intersection of CaptureInfos.
0358   CaptureInfo operator&(CaptureInfo Other) const {
0359     return CaptureInfo(OtherComponents & Other.OtherComponents,
0360                        RetComponents & Other.RetComponents);
0361   }
0362 
0363   static CaptureInfo createFromIntValue(uint32_t Data) {
0364     return CaptureInfo(CaptureComponents(Data >> 4),
0365                        CaptureComponents(Data & 0xf));
0366   }
0367 
0368   /// Convert CaptureInfo into an encoded integer value (used by captures
0369   /// attribute).
0370   uint32_t toIntValue() const {
0371     return (uint32_t(OtherComponents) << 4) | uint32_t(RetComponents);
0372   }
0373 };
0374 
0375 raw_ostream &operator<<(raw_ostream &OS, CaptureInfo Info);
0376 
0377 } // namespace llvm
0378 
0379 #endif