//===- MemoryLocation.h - Memory location descriptions ----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file /// This file provides utility analysis objects describing memory locations. /// These are used both by the Alias Analysis infrastructure and more /// specialized memory analysis layers. /// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_MEMORYLOCATION_H #define LLVM_ANALYSIS_MEMORYLOCATION_H #include "llvm/ADT/DenseMapInfo.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/TypeSize.h" #include <optional> namespace llvm { class CallBase; class Instruction; class LoadInst; class StoreInst; class MemTransferInst; class MemIntrinsic; class AtomicCmpXchgInst; class AtomicMemTransferInst; class AtomicMemIntrinsic; class AtomicRMWInst; class AnyMemTransferInst; class AnyMemIntrinsic; class TargetLibraryInfo; class VAArgInst; // Represents the size of a MemoryLocation. Logically, it's an // std::optional<uint63_t> that also carries a bit to represent whether the // integer it contains, N, is 'precise'. Precise, in this context, means that we // know that the area of storage referenced by the given MemoryLocation must be // precisely N bytes. An imprecise value is formed as the union of two or more // precise values, and can conservatively represent all of the values unioned // into it. Importantly, imprecise values are an *upper-bound* on the size of a // MemoryLocation. // // Concretely, a precise MemoryLocation is (%p, 4) in // store i32 0, i32* %p // // Since we know that %p must be at least 4 bytes large at this point. // Otherwise, we have UB. An example of an imprecise MemoryLocation is (%p, 4) // at the memcpy in // // %n = select i1 %foo, i64 1, i64 4 // call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %baz, i64 %n, i32 1, // i1 false) // // ...Since we'll copy *up to* 4 bytes into %p, but we can't guarantee that // we'll ever actually do so. // // If asked to represent a pathologically large value, this will degrade to // std::nullopt. // Store Scalable information in bit 62 of Value. Scalable information is // required to do Alias Analysis on Scalable quantities class LocationSize { … }; inline raw_ostream &operator<<(raw_ostream &OS, LocationSize Size) { … } /// Representation for a specific memory location. /// /// This abstraction can be used to represent a specific location in memory. /// The goal of the location is to represent enough information to describe /// abstract aliasing, modification, and reference behaviors of whatever /// value(s) are stored in memory at the particular location. /// /// The primary user of this interface is LLVM's Alias Analysis, but other /// memory analyses such as MemoryDependence can use it as well. class MemoryLocation { … }; // Specialize DenseMapInfo. template <> struct DenseMapInfo<LocationSize> { … }; template <> struct DenseMapInfo<MemoryLocation> { … }; } // namespace llvm #endif