llvm/llvm/include/llvm/Analysis/MemoryLocation.h

//===- 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