[llvm] [SandboxIR][NFC] Move Constant and derived classes into a separate file (PR #110189)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 26 16:44:35 PDT 2024


https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/110189

None

>From a3d6e25c5c338e6740a276d45ea598461820d87c Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Thu, 26 Sep 2024 09:32:37 -0700
Subject: [PATCH] [SandboxIR][NFC] Move Constant and derived classes into a
 separate file

---
 llvm/include/llvm/SandboxIR/Constant.h  | 1283 +++++++++++++++++++++++
 llvm/include/llvm/SandboxIR/SandboxIR.h | 1253 +---------------------
 llvm/lib/SandboxIR/CMakeLists.txt       |    1 +
 llvm/lib/SandboxIR/Constant.cpp         |  509 +++++++++
 llvm/lib/SandboxIR/SandboxIR.cpp        |  495 ---------
 5 files changed, 1794 insertions(+), 1747 deletions(-)
 create mode 100644 llvm/include/llvm/SandboxIR/Constant.h
 create mode 100644 llvm/lib/SandboxIR/Constant.cpp

diff --git a/llvm/include/llvm/SandboxIR/Constant.h b/llvm/include/llvm/SandboxIR/Constant.h
new file mode 100644
index 00000000000000..bc0e3d8849237a
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/Constant.h
@@ -0,0 +1,1283 @@
+//===- Constant.h -----------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SANDBOXIR_CONSTANT_H
+#define LLVM_SANDBOXIR_CONSTANT_H
+
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalIFunc.h"
+#include "llvm/IR/GlobalObject.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/SandboxIR/Context.h"
+#include "llvm/SandboxIR/Type.h"
+#include "llvm/SandboxIR/User.h"
+
+namespace llvm::sandboxir {
+
+class BasicBlock;
+class Function;
+
+class Constant : public sandboxir::User {
+protected:
+  Constant(llvm::Constant *C, sandboxir::Context &SBCtx)
+      : sandboxir::User(ClassID::Constant, C, SBCtx) {}
+  Constant(ClassID ID, llvm::Constant *C, sandboxir::Context &SBCtx)
+      : sandboxir::User(ID, C, SBCtx) {}
+  friend class ConstantInt; // For constructor.
+  friend class Function;    // For constructor
+  friend class Context;     // For constructor.
+  Use getOperandUseInternal(unsigned OpIdx, bool Verify) const override {
+    return getOperandUseDefault(OpIdx, Verify);
+  }
+
+public:
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    switch (From->getSubclassID()) {
+#define DEF_CONST(ID, CLASS) case ClassID::ID:
+#include "llvm/SandboxIR/SandboxIRValues.def"
+      return true;
+    default:
+      return false;
+    }
+  }
+  sandboxir::Context &getParent() const { return getContext(); }
+  unsigned getUseOperandNo(const Use &Use) const override {
+    return getUseOperandNoDefault(Use);
+  }
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::Constant>(Val) && "Expected Constant!");
+  }
+  void dumpOS(raw_ostream &OS) const override;
+#endif
+};
+
+// TODO: This should inherit from ConstantData.
+class ConstantInt : public Constant {
+  ConstantInt(llvm::ConstantInt *C, Context &Ctx)
+      : Constant(ClassID::ConstantInt, C, Ctx) {}
+  friend class Context; // For constructor.
+
+  Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
+    llvm_unreachable("ConstantInt has no operands!");
+  }
+
+public:
+  static ConstantInt *getTrue(Context &Ctx);
+  static ConstantInt *getFalse(Context &Ctx);
+  static ConstantInt *getBool(Context &Ctx, bool V);
+  static Constant *getTrue(Type *Ty);
+  static Constant *getFalse(Type *Ty);
+  static Constant *getBool(Type *Ty, bool V);
+
+  /// If Ty is a vector type, return a Constant with a splat of the given
+  /// value. Otherwise return a ConstantInt for the given value.
+  static ConstantInt *get(Type *Ty, uint64_t V, bool IsSigned = false);
+
+  /// Return a ConstantInt with the specified integer value for the specified
+  /// type. If the type is wider than 64 bits, the value will be zero-extended
+  /// to fit the type, unless IsSigned is true, in which case the value will
+  /// be interpreted as a 64-bit signed integer and sign-extended to fit
+  /// the type.
+  /// Get a ConstantInt for a specific value.
+  static ConstantInt *get(IntegerType *Ty, uint64_t V, bool IsSigned = false);
+
+  /// Return a ConstantInt with the specified value for the specified type. The
+  /// value V will be canonicalized to a an unsigned APInt. Accessing it with
+  /// either getSExtValue() or getZExtValue() will yield a correctly sized and
+  /// signed value for the type Ty.
+  /// Get a ConstantInt for a specific signed value.
+  static ConstantInt *getSigned(IntegerType *Ty, int64_t V);
+  static Constant *getSigned(Type *Ty, int64_t V);
+
+  /// Return a ConstantInt with the specified value and an implied Type. The
+  /// type is the integer type that corresponds to the bit width of the value.
+  static ConstantInt *get(Context &Ctx, const APInt &V);
+
+  /// Return a ConstantInt constructed from the string strStart with the given
+  /// radix.
+  static ConstantInt *get(IntegerType *Ty, StringRef Str, uint8_t Radix);
+
+  /// If Ty is a vector type, return a Constant with a splat of the given
+  /// value. Otherwise return a ConstantInt for the given value.
+  static Constant *get(Type *Ty, const APInt &V);
+
+  /// Return the constant as an APInt value reference. This allows clients to
+  /// obtain a full-precision copy of the value.
+  /// Return the constant's value.
+  inline const APInt &getValue() const {
+    return cast<llvm::ConstantInt>(Val)->getValue();
+  }
+
+  /// getBitWidth - Return the scalar bitwidth of this constant.
+  unsigned getBitWidth() const {
+    return cast<llvm::ConstantInt>(Val)->getBitWidth();
+  }
+  /// Return the constant as a 64-bit unsigned integer value after it
+  /// has been zero extended as appropriate for the type of this constant. Note
+  /// that this method can assert if the value does not fit in 64 bits.
+  /// Return the zero extended value.
+  inline uint64_t getZExtValue() const {
+    return cast<llvm::ConstantInt>(Val)->getZExtValue();
+  }
+
+  /// Return the constant as a 64-bit integer value after it has been sign
+  /// extended as appropriate for the type of this constant. Note that
+  /// this method can assert if the value does not fit in 64 bits.
+  /// Return the sign extended value.
+  inline int64_t getSExtValue() const {
+    return cast<llvm::ConstantInt>(Val)->getSExtValue();
+  }
+
+  /// Return the constant as an llvm::MaybeAlign.
+  /// Note that this method can assert if the value does not fit in 64 bits or
+  /// is not a power of two.
+  inline MaybeAlign getMaybeAlignValue() const {
+    return cast<llvm::ConstantInt>(Val)->getMaybeAlignValue();
+  }
+
+  /// Return the constant as an llvm::Align, interpreting `0` as `Align(1)`.
+  /// Note that this method can assert if the value does not fit in 64 bits or
+  /// is not a power of two.
+  inline Align getAlignValue() const {
+    return cast<llvm::ConstantInt>(Val)->getAlignValue();
+  }
+
+  /// A helper method that can be used to determine if the constant contained
+  /// within is equal to a constant.  This only works for very small values,
+  /// because this is all that can be represented with all types.
+  /// Determine if this constant's value is same as an unsigned char.
+  bool equalsInt(uint64_t V) const {
+    return cast<llvm::ConstantInt>(Val)->equalsInt(V);
+  }
+
+  /// Variant of the getType() method to always return an IntegerType, which
+  /// reduces the amount of casting needed in parts of the compiler.
+  IntegerType *getIntegerType() const;
+
+  /// This static method returns true if the type Ty is big enough to
+  /// represent the value V. This can be used to avoid having the get method
+  /// assert when V is larger than Ty can represent. Note that there are two
+  /// versions of this method, one for unsigned and one for signed integers.
+  /// Although ConstantInt canonicalizes everything to an unsigned integer,
+  /// the signed version avoids callers having to convert a signed quantity
+  /// to the appropriate unsigned type before calling the method.
+  /// @returns true if V is a valid value for type Ty
+  /// Determine if the value is in range for the given type.
+  static bool isValueValidForType(Type *Ty, uint64_t V);
+  static bool isValueValidForType(Type *Ty, int64_t V);
+
+  bool isNegative() const { return cast<llvm::ConstantInt>(Val)->isNegative(); }
+
+  /// This is just a convenience method to make client code smaller for a
+  /// common code. It also correctly performs the comparison without the
+  /// potential for an assertion from getZExtValue().
+  bool isZero() const { return cast<llvm::ConstantInt>(Val)->isZero(); }
+
+  /// This is just a convenience method to make client code smaller for a
+  /// common case. It also correctly performs the comparison without the
+  /// potential for an assertion from getZExtValue().
+  /// Determine if the value is one.
+  bool isOne() const { return cast<llvm::ConstantInt>(Val)->isOne(); }
+
+  /// This function will return true iff every bit in this constant is set
+  /// to true.
+  /// @returns true iff this constant's bits are all set to true.
+  /// Determine if the value is all ones.
+  bool isMinusOne() const { return cast<llvm::ConstantInt>(Val)->isMinusOne(); }
+
+  /// This function will return true iff this constant represents the largest
+  /// value that may be represented by the constant's type.
+  /// @returns true iff this is the largest value that may be represented
+  /// by this type.
+  /// Determine if the value is maximal.
+  bool isMaxValue(bool IsSigned) const {
+    return cast<llvm::ConstantInt>(Val)->isMaxValue(IsSigned);
+  }
+
+  /// This function will return true iff this constant represents the smallest
+  /// value that may be represented by this constant's type.
+  /// @returns true if this is the smallest value that may be represented by
+  /// this type.
+  /// Determine if the value is minimal.
+  bool isMinValue(bool IsSigned) const {
+    return cast<llvm::ConstantInt>(Val)->isMinValue(IsSigned);
+  }
+
+  /// This function will return true iff this constant represents a value with
+  /// active bits bigger than 64 bits or a value greater than the given uint64_t
+  /// value.
+  /// @returns true iff this constant is greater or equal to the given number.
+  /// Determine if the value is greater or equal to the given number.
+  bool uge(uint64_t Num) const {
+    return cast<llvm::ConstantInt>(Val)->uge(Num);
+  }
+
+  /// getLimitedValue - If the value is smaller than the specified limit,
+  /// return it, otherwise return the limit value.  This causes the value
+  /// to saturate to the limit.
+  /// @returns the min of the value of the constant and the specified value
+  /// Get the constant's value with a saturation limit
+  uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
+    return cast<llvm::ConstantInt>(Val)->getLimitedValue(Limit);
+  }
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::ConstantInt;
+  }
+  unsigned getUseOperandNo(const Use &Use) const override {
+    llvm_unreachable("ConstantInt has no operands!");
+  }
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::ConstantInt>(Val) && "Expected a ConstantInst!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+// TODO: This should inherit from ConstantData.
+class ConstantFP final : public Constant {
+  ConstantFP(llvm::ConstantFP *C, Context &Ctx)
+      : Constant(ClassID::ConstantFP, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// This returns a ConstantFP, or a vector containing a splat of a ConstantFP,
+  /// for the specified value in the specified type. This should only be used
+  /// for simple constant values like 2.0/1.0 etc, that are known-valid both as
+  /// host double and as the target format.
+  static Constant *get(Type *Ty, double V);
+
+  /// If Ty is a vector type, return a Constant with a splat of the given
+  /// value. Otherwise return a ConstantFP for the given value.
+  static Constant *get(Type *Ty, const APFloat &V);
+
+  static Constant *get(Type *Ty, StringRef Str);
+
+  static ConstantFP *get(const APFloat &V, Context &Ctx);
+
+  static Constant *getNaN(Type *Ty, bool Negative = false,
+                          uint64_t Payload = 0);
+  static Constant *getQNaN(Type *Ty, bool Negative = false,
+                           APInt *Payload = nullptr);
+  static Constant *getSNaN(Type *Ty, bool Negative = false,
+                           APInt *Payload = nullptr);
+  static Constant *getZero(Type *Ty, bool Negative = false);
+
+  static Constant *getNegativeZero(Type *Ty);
+  static Constant *getInfinity(Type *Ty, bool Negative = false);
+
+  /// Return true if Ty is big enough to represent V.
+  static bool isValueValidForType(Type *Ty, const APFloat &V);
+
+  inline const APFloat &getValueAPF() const {
+    return cast<llvm::ConstantFP>(Val)->getValueAPF();
+  }
+  inline const APFloat &getValue() const {
+    return cast<llvm::ConstantFP>(Val)->getValue();
+  }
+
+  /// Return true if the value is positive or negative zero.
+  bool isZero() const { return cast<llvm::ConstantFP>(Val)->isZero(); }
+
+  /// Return true if the sign bit is set.
+  bool isNegative() const { return cast<llvm::ConstantFP>(Val)->isNegative(); }
+
+  /// Return true if the value is infinity
+  bool isInfinity() const { return cast<llvm::ConstantFP>(Val)->isInfinity(); }
+
+  /// Return true if the value is a NaN.
+  bool isNaN() const { return cast<llvm::ConstantFP>(Val)->isNaN(); }
+
+  /// We don't rely on operator== working on double values, as it returns true
+  /// for things that are clearly not equal, like -0.0 and 0.0.
+  /// As such, this method can be used to do an exact bit-for-bit comparison of
+  /// two floating point values.  The version with a double operand is retained
+  /// because it's so convenient to write isExactlyValue(2.0), but please use
+  /// it only for simple constants.
+  bool isExactlyValue(const APFloat &V) const {
+    return cast<llvm::ConstantFP>(Val)->isExactlyValue(V);
+  }
+
+  bool isExactlyValue(double V) const {
+    return cast<llvm::ConstantFP>(Val)->isExactlyValue(V);
+  }
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::ConstantFP;
+  }
+
+  // TODO: Better name: getOperandNo(const Use&). Should be private.
+  unsigned getUseOperandNo(const Use &Use) const final {
+    llvm_unreachable("ConstantFP has no operands!");
+  }
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::ConstantFP>(Val) && "Expected a ConstantFP!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+/// Base class for aggregate constants (with operands).
+class ConstantAggregate : public Constant {
+protected:
+  ConstantAggregate(ClassID ID, llvm::Constant *C, Context &Ctx)
+      : Constant(ID, C, Ctx) {}
+
+public:
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    auto ID = From->getSubclassID();
+    return ID == ClassID::ConstantVector || ID == ClassID::ConstantStruct ||
+           ID == ClassID::ConstantArray;
+  }
+};
+
+class ConstantArray final : public ConstantAggregate {
+  ConstantArray(llvm::ConstantArray *C, Context &Ctx)
+      : ConstantAggregate(ClassID::ConstantArray, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  static Constant *get(ArrayType *T, ArrayRef<Constant *> V);
+  ArrayType *getType() const;
+
+  // TODO: Missing functions: getType(), getTypeForElements(), getAnon(), get().
+
+  /// For isa/dyn_cast.
+  static bool classof(const Value *From) {
+    return From->getSubclassID() == ClassID::ConstantArray;
+  }
+};
+
+class ConstantStruct final : public ConstantAggregate {
+  ConstantStruct(llvm::ConstantStruct *C, Context &Ctx)
+      : ConstantAggregate(ClassID::ConstantStruct, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  static Constant *get(StructType *T, ArrayRef<Constant *> V);
+
+  template <typename... Csts>
+  static std::enable_if_t<are_base_of<Constant, Csts...>::value, Constant *>
+  get(StructType *T, Csts *...Vs) {
+    return get(T, ArrayRef<Constant *>({Vs...}));
+  }
+  /// Return an anonymous struct that has the specified elements.
+  /// If the struct is possibly empty, then you must specify a context.
+  static Constant *getAnon(ArrayRef<Constant *> V, bool Packed = false) {
+    return get(getTypeForElements(V, Packed), V);
+  }
+  static Constant *getAnon(Context &Ctx, ArrayRef<Constant *> V,
+                           bool Packed = false) {
+    return get(getTypeForElements(Ctx, V, Packed), V);
+  }
+  /// This version of the method allows an empty list.
+  static StructType *getTypeForElements(Context &Ctx, ArrayRef<Constant *> V,
+                                        bool Packed = false);
+  /// Return an anonymous struct type to use for a constant with the specified
+  /// set of elements. The list must not be empty.
+  static StructType *getTypeForElements(ArrayRef<Constant *> V,
+                                        bool Packed = false) {
+    assert(!V.empty() &&
+           "ConstantStruct::getTypeForElements cannot be called on empty list");
+    return getTypeForElements(V[0]->getContext(), V, Packed);
+  }
+
+  /// Specialization - reduce amount of casting.
+  inline StructType *getType() const {
+    return cast<StructType>(Value::getType());
+  }
+
+  /// For isa/dyn_cast.
+  static bool classof(const Value *From) {
+    return From->getSubclassID() == ClassID::ConstantStruct;
+  }
+};
+
+class ConstantVector final : public ConstantAggregate {
+  ConstantVector(llvm::ConstantVector *C, Context &Ctx)
+      : ConstantAggregate(ClassID::ConstantVector, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  // TODO: Missing functions: getSplat(), getType(), getSplatValue(), get().
+
+  /// For isa/dyn_cast.
+  static bool classof(const Value *From) {
+    return From->getSubclassID() == ClassID::ConstantVector;
+  }
+};
+
+// TODO: Inherit from ConstantData.
+class ConstantAggregateZero final : public Constant {
+  ConstantAggregateZero(llvm::ConstantAggregateZero *C, Context &Ctx)
+      : Constant(ClassID::ConstantAggregateZero, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  static ConstantAggregateZero *get(Type *Ty);
+  /// If this CAZ has array or vector type, return a zero with the right element
+  /// type.
+  Constant *getSequentialElement() const;
+  /// If this CAZ has struct type, return a zero with the right element type for
+  /// the specified element.
+  Constant *getStructElement(unsigned Elt) const;
+  /// Return a zero of the right value for the specified GEP index if we can,
+  /// otherwise return null (e.g. if C is a ConstantExpr).
+  Constant *getElementValue(Constant *C) const;
+  /// Return a zero of the right value for the specified GEP index.
+  Constant *getElementValue(unsigned Idx) const;
+  /// Return the number of elements in the array, vector, or struct.
+  ElementCount getElementCount() const {
+    return cast<llvm::ConstantAggregateZero>(Val)->getElementCount();
+  }
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::ConstantAggregateZero;
+  }
+  unsigned getUseOperandNo(const Use &Use) const final {
+    llvm_unreachable("ConstantAggregateZero has no operands!");
+  }
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::ConstantAggregateZero>(Val) && "Expected a CAZ!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+// TODO: Inherit from ConstantData.
+class ConstantPointerNull final : public Constant {
+  ConstantPointerNull(llvm::ConstantPointerNull *C, Context &Ctx)
+      : Constant(ClassID::ConstantPointerNull, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  static ConstantPointerNull *get(PointerType *Ty);
+
+  PointerType *getType() const;
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::ConstantPointerNull;
+  }
+  unsigned getUseOperandNo(const Use &Use) const final {
+    llvm_unreachable("ConstantPointerNull has no operands!");
+  }
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::ConstantPointerNull>(Val) && "Expected a CPNull!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+// TODO: Inherit from ConstantData.
+class UndefValue : public Constant {
+protected:
+  UndefValue(llvm::UndefValue *C, Context &Ctx)
+      : Constant(ClassID::UndefValue, C, Ctx) {}
+  UndefValue(ClassID ID, llvm::Constant *C, Context &Ctx)
+      : Constant(ID, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// Static factory methods - Return an 'undef' object of the specified type.
+  static UndefValue *get(Type *T);
+
+  /// If this Undef has array or vector type, return a undef with the right
+  /// element type.
+  UndefValue *getSequentialElement() const;
+
+  /// If this undef has struct type, return a undef with the right element type
+  /// for the specified element.
+  UndefValue *getStructElement(unsigned Elt) const;
+
+  /// Return an undef of the right value for the specified GEP index if we can,
+  /// otherwise return null (e.g. if C is a ConstantExpr).
+  UndefValue *getElementValue(Constant *C) const;
+
+  /// Return an undef of the right value for the specified GEP index.
+  UndefValue *getElementValue(unsigned Idx) const;
+
+  /// Return the number of elements in the array, vector, or struct.
+  unsigned getNumElements() const {
+    return cast<llvm::UndefValue>(Val)->getNumElements();
+  }
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::UndefValue ||
+           From->getSubclassID() == ClassID::PoisonValue;
+  }
+  unsigned getUseOperandNo(const Use &Use) const final {
+    llvm_unreachable("UndefValue has no operands!");
+  }
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::UndefValue>(Val) && "Expected an UndefValue!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+class PoisonValue final : public UndefValue {
+  PoisonValue(llvm::PoisonValue *C, Context &Ctx)
+      : UndefValue(ClassID::PoisonValue, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// Static factory methods - Return an 'poison' object of the specified type.
+  static PoisonValue *get(Type *T);
+
+  /// If this poison has array or vector type, return a poison with the right
+  /// element type.
+  PoisonValue *getSequentialElement() const;
+
+  /// If this poison has struct type, return a poison with the right element
+  /// type for the specified element.
+  PoisonValue *getStructElement(unsigned Elt) const;
+
+  /// Return an poison of the right value for the specified GEP index if we can,
+  /// otherwise return null (e.g. if C is a ConstantExpr).
+  PoisonValue *getElementValue(Constant *C) const;
+
+  /// Return an poison of the right value for the specified GEP index.
+  PoisonValue *getElementValue(unsigned Idx) const;
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::PoisonValue;
+  }
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::PoisonValue>(Val) && "Expected a PoisonValue!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+class GlobalValue : public Constant {
+protected:
+  GlobalValue(ClassID ID, llvm::GlobalValue *C, Context &Ctx)
+      : Constant(ID, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  using LinkageTypes = llvm::GlobalValue::LinkageTypes;
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    switch (From->getSubclassID()) {
+    case ClassID::Function:
+    case ClassID::GlobalVariable:
+    case ClassID::GlobalAlias:
+    case ClassID::GlobalIFunc:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  unsigned getAddressSpace() const {
+    return cast<llvm::GlobalValue>(Val)->getAddressSpace();
+  }
+  bool hasGlobalUnnamedAddr() const {
+    return cast<llvm::GlobalValue>(Val)->hasGlobalUnnamedAddr();
+  }
+
+  /// Returns true if this value's address is not significant in this module.
+  /// This attribute is intended to be used only by the code generator and LTO
+  /// to allow the linker to decide whether the global needs to be in the symbol
+  /// table. It should probably not be used in optimizations, as the value may
+  /// have uses outside the module; use hasGlobalUnnamedAddr() instead.
+  bool hasAtLeastLocalUnnamedAddr() const {
+    return cast<llvm::GlobalValue>(Val)->hasAtLeastLocalUnnamedAddr();
+  }
+
+  using UnnamedAddr = llvm::GlobalValue::UnnamedAddr;
+
+  UnnamedAddr getUnnamedAddr() const {
+    return cast<llvm::GlobalValue>(Val)->getUnnamedAddr();
+  }
+  void setUnnamedAddr(UnnamedAddr V);
+
+  static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) {
+    return llvm::GlobalValue::getMinUnnamedAddr(A, B);
+  }
+
+  bool hasComdat() const { return cast<llvm::GlobalValue>(Val)->hasComdat(); }
+
+  // TODO: We need a SandboxIR Comdat if we want to implement getComdat().
+  using VisibilityTypes = llvm::GlobalValue::VisibilityTypes;
+  VisibilityTypes getVisibility() const {
+    return cast<llvm::GlobalValue>(Val)->getVisibility();
+  }
+  bool hasDefaultVisibility() const {
+    return cast<llvm::GlobalValue>(Val)->hasDefaultVisibility();
+  }
+  bool hasHiddenVisibility() const {
+    return cast<llvm::GlobalValue>(Val)->hasHiddenVisibility();
+  }
+  bool hasProtectedVisibility() const {
+    return cast<llvm::GlobalValue>(Val)->hasProtectedVisibility();
+  }
+  void setVisibility(VisibilityTypes V);
+
+  // TODO: Add missing functions.
+};
+
+class GlobalObject : public GlobalValue {
+protected:
+  GlobalObject(ClassID ID, llvm::GlobalObject *C, Context &Ctx)
+      : GlobalValue(ID, C, Ctx) {}
+  friend class Context; // For constructor.
+  Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
+    return getOperandUseDefault(OpIdx, Verify);
+  }
+
+public:
+  unsigned getUseOperandNo(const Use &Use) const final {
+    return getUseOperandNoDefault(Use);
+  }
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    switch (From->getSubclassID()) {
+    case ClassID::Function:
+    case ClassID::GlobalVariable:
+    case ClassID::GlobalIFunc:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  /// FIXME: Remove this function once transition to Align is over.
+  uint64_t getAlignment() const {
+    return cast<llvm::GlobalObject>(Val)->getAlignment();
+  }
+
+  /// Returns the alignment of the given variable or function.
+  ///
+  /// Note that for functions this is the alignment of the code, not the
+  /// alignment of a function pointer.
+  MaybeAlign getAlign() const {
+    return cast<llvm::GlobalObject>(Val)->getAlign();
+  }
+
+  // TODO: Add missing: setAlignment(Align)
+
+  /// Sets the alignment attribute of the GlobalObject.
+  /// This method will be deprecated as the alignment property should always be
+  /// defined.
+  void setAlignment(MaybeAlign Align);
+
+  unsigned getGlobalObjectSubClassData() const {
+    return cast<llvm::GlobalObject>(Val)->getGlobalObjectSubClassData();
+  }
+
+  void setGlobalObjectSubClassData(unsigned V);
+
+  /// Check if this global has a custom object file section.
+  ///
+  /// This is more efficient than calling getSection() and checking for an empty
+  /// string.
+  bool hasSection() const {
+    return cast<llvm::GlobalObject>(Val)->hasSection();
+  }
+
+  /// Get the custom section of this global if it has one.
+  ///
+  /// If this global does not have a custom section, this will be empty and the
+  /// default object file section (.text, .data, etc) will be used.
+  StringRef getSection() const {
+    return cast<llvm::GlobalObject>(Val)->getSection();
+  }
+
+  /// Change the section for this global.
+  ///
+  /// Setting the section to the empty string tells LLVM to choose an
+  /// appropriate default object file section.
+  void setSection(StringRef S);
+
+  bool hasComdat() const { return cast<llvm::GlobalObject>(Val)->hasComdat(); }
+
+  // TODO: implement get/setComdat(), etc. once we have a sandboxir::Comdat.
+
+  // TODO: We currently don't support Metadata in sandboxir so all
+  // Metadata-related functions are missing.
+
+  using VCallVisibility = llvm::GlobalObject::VCallVisibility;
+
+  VCallVisibility getVCallVisibility() const {
+    return cast<llvm::GlobalObject>(Val)->getVCallVisibility();
+  }
+
+  /// Returns true if the alignment of the value can be unilaterally
+  /// increased.
+  ///
+  /// Note that for functions this is the alignment of the code, not the
+  /// alignment of a function pointer.
+  bool canIncreaseAlignment() const {
+    return cast<llvm::GlobalObject>(Val)->canIncreaseAlignment();
+  }
+};
+
+/// Provides API functions, like getIterator() and getReverseIterator() to
+/// GlobalIFunc, Function, GlobalVariable and GlobalAlias. In LLVM IR these are
+/// provided by ilist_node.
+template <typename GlobalT, typename LLVMGlobalT, typename ParentT,
+          typename LLVMParentT>
+class GlobalWithNodeAPI : public ParentT {
+  /// Helper for mapped_iterator.
+  struct LLVMGVToGV {
+    Context &Ctx;
+    LLVMGVToGV(Context &Ctx) : Ctx(Ctx) {}
+    GlobalT &operator()(LLVMGlobalT &LLVMGV) const;
+  };
+
+public:
+  GlobalWithNodeAPI(Value::ClassID ID, LLVMParentT *C, Context &Ctx)
+      : ParentT(ID, C, Ctx) {}
+
+  Module *getParent() const {
+    llvm::Module *LLVMM = cast<LLVMGlobalT>(this->Val)->getParent();
+    return this->Ctx.getModule(LLVMM);
+  }
+
+  using iterator = mapped_iterator<
+      decltype(static_cast<LLVMGlobalT *>(nullptr)->getIterator()), LLVMGVToGV>;
+  using reverse_iterator = mapped_iterator<
+      decltype(static_cast<LLVMGlobalT *>(nullptr)->getReverseIterator()),
+      LLVMGVToGV>;
+  iterator getIterator() const {
+    auto *LLVMGV = cast<LLVMGlobalT>(this->Val);
+    LLVMGVToGV ToGV(this->Ctx);
+    return map_iterator(LLVMGV->getIterator(), ToGV);
+  }
+  reverse_iterator getReverseIterator() const {
+    auto *LLVMGV = cast<LLVMGlobalT>(this->Val);
+    LLVMGVToGV ToGV(this->Ctx);
+    return map_iterator(LLVMGV->getReverseIterator(), ToGV);
+  }
+};
+
+class GlobalIFunc final
+    : public GlobalWithNodeAPI<GlobalIFunc, llvm::GlobalIFunc, GlobalObject,
+                               llvm::GlobalObject> {
+  GlobalIFunc(llvm::GlobalObject *C, Context &Ctx)
+      : GlobalWithNodeAPI(ClassID::GlobalIFunc, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::GlobalIFunc;
+  }
+
+  // TODO: Missing create() because we don't have a sandboxir::Module yet.
+
+  // TODO: Missing functions: copyAttributesFrom(), removeFromParent(),
+  // eraseFromParent()
+
+  void setResolver(Constant *Resolver);
+
+  Constant *getResolver() const;
+
+  // Return the resolver function after peeling off potential ConstantExpr
+  // indirection.
+  Function *getResolverFunction();
+  const Function *getResolverFunction() const {
+    return const_cast<GlobalIFunc *>(this)->getResolverFunction();
+  }
+
+  static bool isValidLinkage(LinkageTypes L) {
+    return llvm::GlobalIFunc::isValidLinkage(L);
+  }
+
+  // TODO: Missing applyAlongResolverPath().
+
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::GlobalIFunc>(Val) && "Expected a GlobalIFunc!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+class GlobalVariable final
+    : public GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
+                               GlobalObject, llvm::GlobalObject> {
+  GlobalVariable(llvm::GlobalObject *C, Context &Ctx)
+      : GlobalWithNodeAPI(ClassID::GlobalVariable, C, Ctx) {}
+  friend class Context; // For constructor.
+
+  /// Helper for mapped_iterator.
+  struct LLVMGVToGV {
+    Context &Ctx;
+    LLVMGVToGV(Context &Ctx) : Ctx(Ctx) {}
+    GlobalVariable &operator()(llvm::GlobalVariable &LLVMGV) const;
+  };
+
+public:
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::GlobalVariable;
+  }
+
+  /// Definitions have initializers, declarations don't.
+  ///
+  inline bool hasInitializer() const {
+    return cast<llvm::GlobalVariable>(Val)->hasInitializer();
+  }
+
+  /// hasDefinitiveInitializer - Whether the global variable has an initializer,
+  /// and any other instances of the global (this can happen due to weak
+  /// linkage) are guaranteed to have the same initializer.
+  ///
+  /// Note that if you want to transform a global, you must use
+  /// hasUniqueInitializer() instead, because of the *_odr linkage type.
+  ///
+  /// Example:
+  ///
+  /// @a = global SomeType* null - Initializer is both definitive and unique.
+  ///
+  /// @b = global weak SomeType* null - Initializer is neither definitive nor
+  /// unique.
+  ///
+  /// @c = global weak_odr SomeType* null - Initializer is definitive, but not
+  /// unique.
+  inline bool hasDefinitiveInitializer() const {
+    return cast<llvm::GlobalVariable>(Val)->hasDefinitiveInitializer();
+  }
+
+  /// hasUniqueInitializer - Whether the global variable has an initializer, and
+  /// any changes made to the initializer will turn up in the final executable.
+  inline bool hasUniqueInitializer() const {
+    return cast<llvm::GlobalVariable>(Val)->hasUniqueInitializer();
+  }
+
+  /// getInitializer - Return the initializer for this global variable.  It is
+  /// illegal to call this method if the global is external, because we cannot
+  /// tell what the value is initialized to!
+  ///
+  Constant *getInitializer() const;
+  /// setInitializer - Sets the initializer for this global variable, removing
+  /// any existing initializer if InitVal==NULL. The initializer must have the
+  /// type getValueType().
+  void setInitializer(Constant *InitVal);
+
+  // TODO: Add missing replaceInitializer(). Requires special tracker
+
+  /// If the value is a global constant, its value is immutable throughout the
+  /// runtime execution of the program.  Assigning a value into the constant
+  /// leads to undefined behavior.
+  ///
+  bool isConstant() const {
+    return cast<llvm::GlobalVariable>(Val)->isConstant();
+  }
+  void setConstant(bool V);
+
+  bool isExternallyInitialized() const {
+    return cast<llvm::GlobalVariable>(Val)->isExternallyInitialized();
+  }
+  void setExternallyInitialized(bool Val);
+
+  // TODO: Missing copyAttributesFrom()
+
+  // TODO: Missing removeFromParent(), eraseFromParent(), dropAllReferences()
+
+  // TODO: Missing addDebugInfo(), getDebugInfo()
+
+  // TODO: Missing attribute setter functions: addAttribute(), setAttributes().
+  //       There seems to be no removeAttribute() so we can't undo them.
+
+  /// Return true if the attribute exists.
+  bool hasAttribute(Attribute::AttrKind Kind) const {
+    return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
+  }
+
+  /// Return true if the attribute exists.
+  bool hasAttribute(StringRef Kind) const {
+    return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
+  }
+
+  /// Return true if any attributes exist.
+  bool hasAttributes() const {
+    return cast<llvm::GlobalVariable>(Val)->hasAttributes();
+  }
+
+  /// Return the attribute object.
+  Attribute getAttribute(Attribute::AttrKind Kind) const {
+    return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
+  }
+
+  /// Return the attribute object.
+  Attribute getAttribute(StringRef Kind) const {
+    return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
+  }
+
+  /// Return the attribute set for this global
+  AttributeSet getAttributes() const {
+    return cast<llvm::GlobalVariable>(Val)->getAttributes();
+  }
+
+  /// Return attribute set as list with index.
+  /// FIXME: This may not be required once ValueEnumerators
+  /// in bitcode-writer can enumerate attribute-set.
+  AttributeList getAttributesAsList(unsigned Index) const {
+    return cast<llvm::GlobalVariable>(Val)->getAttributesAsList(Index);
+  }
+
+  /// Check if section name is present
+  bool hasImplicitSection() const {
+    return cast<llvm::GlobalVariable>(Val)->hasImplicitSection();
+  }
+
+  /// Get the custom code model raw value of this global.
+  ///
+  unsigned getCodeModelRaw() const {
+    return cast<llvm::GlobalVariable>(Val)->getCodeModelRaw();
+  }
+
+  /// Get the custom code model of this global if it has one.
+  ///
+  /// If this global does not have a custom code model, the empty instance
+  /// will be returned.
+  std::optional<CodeModel::Model> getCodeModel() const {
+    return cast<llvm::GlobalVariable>(Val)->getCodeModel();
+  }
+
+  // TODO: Missing setCodeModel(). Requires custom tracker.
+
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::GlobalVariable>(Val) && "Expected a GlobalVariable!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+class GlobalAlias final
+    : public GlobalWithNodeAPI<GlobalAlias, llvm::GlobalAlias, GlobalValue,
+                               llvm::GlobalValue> {
+  GlobalAlias(llvm::GlobalAlias *C, Context &Ctx)
+      : GlobalWithNodeAPI(ClassID::GlobalAlias, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::GlobalAlias;
+  }
+
+  // TODO: Missing create() due to unimplemented sandboxir::Module.
+
+  // TODO: Missing copyAttributresFrom().
+  // TODO: Missing removeFromParent(), eraseFromParent().
+
+  void setAliasee(Constant *Aliasee);
+  Constant *getAliasee() const;
+
+  const GlobalObject *getAliaseeObject() const;
+  GlobalObject *getAliaseeObject() {
+    return const_cast<GlobalObject *>(
+        static_cast<const GlobalAlias *>(this)->getAliaseeObject());
+  }
+
+  static bool isValidLinkage(LinkageTypes L) {
+    return llvm::GlobalAlias::isValidLinkage(L);
+  }
+};
+
+class NoCFIValue final : public Constant {
+  NoCFIValue(llvm::NoCFIValue *C, Context &Ctx)
+      : Constant(ClassID::NoCFIValue, C, Ctx) {}
+  friend class Context; // For constructor.
+
+  Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
+    return getOperandUseDefault(OpIdx, Verify);
+  }
+
+public:
+  /// Return a NoCFIValue for the specified function.
+  static NoCFIValue *get(GlobalValue *GV);
+
+  GlobalValue *getGlobalValue() const;
+
+  /// NoCFIValue is always a pointer.
+  PointerType *getType() const;
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::NoCFIValue;
+  }
+
+  unsigned getUseOperandNo(const Use &Use) const final {
+    return getUseOperandNoDefault(Use);
+  }
+
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::NoCFIValue>(Val) && "Expected a NoCFIValue!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+class ConstantPtrAuth final : public Constant {
+  ConstantPtrAuth(llvm::ConstantPtrAuth *C, Context &Ctx)
+      : Constant(ClassID::ConstantPtrAuth, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// Return a pointer signed with the specified parameters.
+  static ConstantPtrAuth *get(Constant *Ptr, ConstantInt *Key,
+                              ConstantInt *Disc, Constant *AddrDisc);
+  /// The pointer that is signed in this ptrauth signed pointer.
+  Constant *getPointer() const;
+
+  /// The Key ID, an i32 constant.
+  ConstantInt *getKey() const;
+
+  /// The integer discriminator, an i64 constant, or 0.
+  ConstantInt *getDiscriminator() const;
+
+  /// The address discriminator if any, or the null constant.
+  /// If present, this must be a value equivalent to the storage location of
+  /// the only global-initializer user of the ptrauth signed pointer.
+  Constant *getAddrDiscriminator() const;
+
+  /// Whether there is any non-null address discriminator.
+  bool hasAddressDiscriminator() const {
+    return cast<llvm::ConstantPtrAuth>(Val)->hasAddressDiscriminator();
+  }
+
+  /// Whether the address uses a special address discriminator.
+  /// These discriminators can't be used in real pointer-auth values; they
+  /// can only be used in "prototype" values that indicate how some real
+  /// schema is supposed to be produced.
+  bool hasSpecialAddressDiscriminator(uint64_t Value) const {
+    return cast<llvm::ConstantPtrAuth>(Val)->hasSpecialAddressDiscriminator(
+        Value);
+  }
+
+  /// Check whether an authentication operation with key \p Key and (possibly
+  /// blended) discriminator \p Discriminator is known to be compatible with
+  /// this ptrauth signed pointer.
+  bool isKnownCompatibleWith(const Value *Key, const Value *Discriminator,
+                             const DataLayout &DL) const {
+    return cast<llvm::ConstantPtrAuth>(Val)->isKnownCompatibleWith(
+        Key->Val, Discriminator->Val, DL);
+  }
+
+  /// Produce a new ptrauth expression signing the given value using
+  /// the same schema as is stored in one.
+  ConstantPtrAuth *getWithSameSchema(Constant *Pointer) const;
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::ConstantPtrAuth;
+  }
+};
+
+class ConstantExpr : public Constant {
+  ConstantExpr(llvm::ConstantExpr *C, Context &Ctx)
+      : Constant(ClassID::ConstantExpr, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::ConstantExpr;
+  }
+  // TODO: Missing functions.
+};
+
+class BlockAddress final : public Constant {
+  BlockAddress(llvm::BlockAddress *C, Context &Ctx)
+      : Constant(ClassID::BlockAddress, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// Return a BlockAddress for the specified function and basic block.
+  static BlockAddress *get(Function *F, BasicBlock *BB);
+
+  /// Return a BlockAddress for the specified basic block.  The basic
+  /// block must be embedded into a function.
+  static BlockAddress *get(BasicBlock *BB);
+
+  /// Lookup an existing \c BlockAddress constant for the given BasicBlock.
+  ///
+  /// \returns 0 if \c !BB->hasAddressTaken(), otherwise the \c BlockAddress.
+  static BlockAddress *lookup(const BasicBlock *BB);
+
+  Function *getFunction() const;
+  BasicBlock *getBasicBlock() const;
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::BlockAddress;
+  }
+};
+
+class DSOLocalEquivalent final : public Constant {
+  DSOLocalEquivalent(llvm::DSOLocalEquivalent *C, Context &Ctx)
+      : Constant(ClassID::DSOLocalEquivalent, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// Return a DSOLocalEquivalent for the specified global value.
+  static DSOLocalEquivalent *get(GlobalValue *GV);
+
+  GlobalValue *getGlobalValue() const;
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::DSOLocalEquivalent;
+  }
+
+  unsigned getUseOperandNo(const Use &Use) const final {
+    llvm_unreachable("DSOLocalEquivalent has no operands!");
+  }
+
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::DSOLocalEquivalent>(Val) &&
+           "Expected a DSOLocalEquivalent!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+// TODO: This should inherit from ConstantData.
+class ConstantTokenNone final : public Constant {
+  ConstantTokenNone(llvm::ConstantTokenNone *C, Context &Ctx)
+      : Constant(ClassID::ConstantTokenNone, C, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// Return the ConstantTokenNone.
+  static ConstantTokenNone *get(Context &Ctx);
+
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::ConstantTokenNone;
+  }
+
+  unsigned getUseOperandNo(const Use &Use) const final {
+    llvm_unreachable("ConstantTokenNone has no operands!");
+  }
+
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::ConstantTokenNone>(Val) &&
+           "Expected a ConstantTokenNone!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif
+};
+
+class Function : public GlobalWithNodeAPI<Function, llvm::Function,
+                                          GlobalObject, llvm::GlobalObject> {
+  /// Helper for mapped_iterator.
+  struct LLVMBBToBB {
+    Context &Ctx;
+    LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {}
+    BasicBlock &operator()(llvm::BasicBlock &LLVMBB) const {
+      return *cast<BasicBlock>(Ctx.getValue(&LLVMBB));
+    }
+  };
+  /// Use Context::createFunction() instead.
+  Function(llvm::Function *F, sandboxir::Context &Ctx)
+      : GlobalWithNodeAPI(ClassID::Function, F, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  /// For isa/dyn_cast.
+  static bool classof(const sandboxir::Value *From) {
+    return From->getSubclassID() == ClassID::Function;
+  }
+
+  Module *getParent() {
+    return Ctx.getModule(cast<llvm::Function>(Val)->getParent());
+  }
+
+  Argument *getArg(unsigned Idx) const {
+    llvm::Argument *Arg = cast<llvm::Function>(Val)->getArg(Idx);
+    return cast<Argument>(Ctx.getValue(Arg));
+  }
+
+  size_t arg_size() const { return cast<llvm::Function>(Val)->arg_size(); }
+  bool arg_empty() const { return cast<llvm::Function>(Val)->arg_empty(); }
+
+  using iterator = mapped_iterator<llvm::Function::iterator, LLVMBBToBB>;
+  iterator begin() const {
+    LLVMBBToBB BBGetter(Ctx);
+    return iterator(cast<llvm::Function>(Val)->begin(), BBGetter);
+  }
+  iterator end() const {
+    LLVMBBToBB BBGetter(Ctx);
+    return iterator(cast<llvm::Function>(Val)->end(), BBGetter);
+  }
+  FunctionType *getFunctionType() const;
+
+#ifndef NDEBUG
+  void verify() const final {
+    assert(isa<llvm::Function>(Val) && "Expected Function!");
+  }
+  void dumpNameAndArgs(raw_ostream &OS) const;
+  void dumpOS(raw_ostream &OS) const final;
+#endif
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_SANDBOXIR_CONSTANT_H
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index 66de9ee078d619..02246c303ab614 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -110,6 +110,7 @@
 #include "llvm/IR/User.h"
 #include "llvm/IR/Value.h"
 #include "llvm/SandboxIR/Argument.h"
+#include "llvm/SandboxIR/Constant.h"
 #include "llvm/SandboxIR/Context.h"
 #include "llvm/SandboxIR/Module.h"
 #include "llvm/SandboxIR/Tracker.h"
@@ -190,1205 +191,6 @@ class CmpInst;
 class ICmpInst;
 class FCmpInst;
 
-class Constant : public sandboxir::User {
-protected:
-  Constant(llvm::Constant *C, sandboxir::Context &SBCtx)
-      : sandboxir::User(ClassID::Constant, C, SBCtx) {}
-  Constant(ClassID ID, llvm::Constant *C, sandboxir::Context &SBCtx)
-      : sandboxir::User(ID, C, SBCtx) {}
-  friend class ConstantInt; // For constructor.
-  friend class Function;    // For constructor
-  friend class Context;     // For constructor.
-  Use getOperandUseInternal(unsigned OpIdx, bool Verify) const override {
-    return getOperandUseDefault(OpIdx, Verify);
-  }
-
-public:
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    switch (From->getSubclassID()) {
-#define DEF_CONST(ID, CLASS) case ClassID::ID:
-#include "llvm/SandboxIR/SandboxIRValues.def"
-      return true;
-    default:
-      return false;
-    }
-  }
-  sandboxir::Context &getParent() const { return getContext(); }
-  unsigned getUseOperandNo(const Use &Use) const override {
-    return getUseOperandNoDefault(Use);
-  }
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::Constant>(Val) && "Expected Constant!");
-  }
-  void dumpOS(raw_ostream &OS) const override;
-#endif
-};
-
-// TODO: This should inherit from ConstantData.
-class ConstantInt : public Constant {
-  ConstantInt(llvm::ConstantInt *C, Context &Ctx)
-      : Constant(ClassID::ConstantInt, C, Ctx) {}
-  friend class Context; // For constructor.
-
-  Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
-    llvm_unreachable("ConstantInt has no operands!");
-  }
-
-public:
-  static ConstantInt *getTrue(Context &Ctx);
-  static ConstantInt *getFalse(Context &Ctx);
-  static ConstantInt *getBool(Context &Ctx, bool V);
-  static Constant *getTrue(Type *Ty);
-  static Constant *getFalse(Type *Ty);
-  static Constant *getBool(Type *Ty, bool V);
-
-  /// If Ty is a vector type, return a Constant with a splat of the given
-  /// value. Otherwise return a ConstantInt for the given value.
-  static ConstantInt *get(Type *Ty, uint64_t V, bool IsSigned = false);
-
-  /// Return a ConstantInt with the specified integer value for the specified
-  /// type. If the type is wider than 64 bits, the value will be zero-extended
-  /// to fit the type, unless IsSigned is true, in which case the value will
-  /// be interpreted as a 64-bit signed integer and sign-extended to fit
-  /// the type.
-  /// Get a ConstantInt for a specific value.
-  static ConstantInt *get(IntegerType *Ty, uint64_t V, bool IsSigned = false);
-
-  /// Return a ConstantInt with the specified value for the specified type. The
-  /// value V will be canonicalized to a an unsigned APInt. Accessing it with
-  /// either getSExtValue() or getZExtValue() will yield a correctly sized and
-  /// signed value for the type Ty.
-  /// Get a ConstantInt for a specific signed value.
-  static ConstantInt *getSigned(IntegerType *Ty, int64_t V);
-  static Constant *getSigned(Type *Ty, int64_t V);
-
-  /// Return a ConstantInt with the specified value and an implied Type. The
-  /// type is the integer type that corresponds to the bit width of the value.
-  static ConstantInt *get(Context &Ctx, const APInt &V);
-
-  /// Return a ConstantInt constructed from the string strStart with the given
-  /// radix.
-  static ConstantInt *get(IntegerType *Ty, StringRef Str, uint8_t Radix);
-
-  /// If Ty is a vector type, return a Constant with a splat of the given
-  /// value. Otherwise return a ConstantInt for the given value.
-  static Constant *get(Type *Ty, const APInt &V);
-
-  /// Return the constant as an APInt value reference. This allows clients to
-  /// obtain a full-precision copy of the value.
-  /// Return the constant's value.
-  inline const APInt &getValue() const {
-    return cast<llvm::ConstantInt>(Val)->getValue();
-  }
-
-  /// getBitWidth - Return the scalar bitwidth of this constant.
-  unsigned getBitWidth() const {
-    return cast<llvm::ConstantInt>(Val)->getBitWidth();
-  }
-  /// Return the constant as a 64-bit unsigned integer value after it
-  /// has been zero extended as appropriate for the type of this constant. Note
-  /// that this method can assert if the value does not fit in 64 bits.
-  /// Return the zero extended value.
-  inline uint64_t getZExtValue() const {
-    return cast<llvm::ConstantInt>(Val)->getZExtValue();
-  }
-
-  /// Return the constant as a 64-bit integer value after it has been sign
-  /// extended as appropriate for the type of this constant. Note that
-  /// this method can assert if the value does not fit in 64 bits.
-  /// Return the sign extended value.
-  inline int64_t getSExtValue() const {
-    return cast<llvm::ConstantInt>(Val)->getSExtValue();
-  }
-
-  /// Return the constant as an llvm::MaybeAlign.
-  /// Note that this method can assert if the value does not fit in 64 bits or
-  /// is not a power of two.
-  inline MaybeAlign getMaybeAlignValue() const {
-    return cast<llvm::ConstantInt>(Val)->getMaybeAlignValue();
-  }
-
-  /// Return the constant as an llvm::Align, interpreting `0` as `Align(1)`.
-  /// Note that this method can assert if the value does not fit in 64 bits or
-  /// is not a power of two.
-  inline Align getAlignValue() const {
-    return cast<llvm::ConstantInt>(Val)->getAlignValue();
-  }
-
-  /// A helper method that can be used to determine if the constant contained
-  /// within is equal to a constant.  This only works for very small values,
-  /// because this is all that can be represented with all types.
-  /// Determine if this constant's value is same as an unsigned char.
-  bool equalsInt(uint64_t V) const {
-    return cast<llvm::ConstantInt>(Val)->equalsInt(V);
-  }
-
-  /// Variant of the getType() method to always return an IntegerType, which
-  /// reduces the amount of casting needed in parts of the compiler.
-  IntegerType *getIntegerType() const;
-
-  /// This static method returns true if the type Ty is big enough to
-  /// represent the value V. This can be used to avoid having the get method
-  /// assert when V is larger than Ty can represent. Note that there are two
-  /// versions of this method, one for unsigned and one for signed integers.
-  /// Although ConstantInt canonicalizes everything to an unsigned integer,
-  /// the signed version avoids callers having to convert a signed quantity
-  /// to the appropriate unsigned type before calling the method.
-  /// @returns true if V is a valid value for type Ty
-  /// Determine if the value is in range for the given type.
-  static bool isValueValidForType(Type *Ty, uint64_t V);
-  static bool isValueValidForType(Type *Ty, int64_t V);
-
-  bool isNegative() const { return cast<llvm::ConstantInt>(Val)->isNegative(); }
-
-  /// This is just a convenience method to make client code smaller for a
-  /// common code. It also correctly performs the comparison without the
-  /// potential for an assertion from getZExtValue().
-  bool isZero() const { return cast<llvm::ConstantInt>(Val)->isZero(); }
-
-  /// This is just a convenience method to make client code smaller for a
-  /// common case. It also correctly performs the comparison without the
-  /// potential for an assertion from getZExtValue().
-  /// Determine if the value is one.
-  bool isOne() const { return cast<llvm::ConstantInt>(Val)->isOne(); }
-
-  /// This function will return true iff every bit in this constant is set
-  /// to true.
-  /// @returns true iff this constant's bits are all set to true.
-  /// Determine if the value is all ones.
-  bool isMinusOne() const { return cast<llvm::ConstantInt>(Val)->isMinusOne(); }
-
-  /// This function will return true iff this constant represents the largest
-  /// value that may be represented by the constant's type.
-  /// @returns true iff this is the largest value that may be represented
-  /// by this type.
-  /// Determine if the value is maximal.
-  bool isMaxValue(bool IsSigned) const {
-    return cast<llvm::ConstantInt>(Val)->isMaxValue(IsSigned);
-  }
-
-  /// This function will return true iff this constant represents the smallest
-  /// value that may be represented by this constant's type.
-  /// @returns true if this is the smallest value that may be represented by
-  /// this type.
-  /// Determine if the value is minimal.
-  bool isMinValue(bool IsSigned) const {
-    return cast<llvm::ConstantInt>(Val)->isMinValue(IsSigned);
-  }
-
-  /// This function will return true iff this constant represents a value with
-  /// active bits bigger than 64 bits or a value greater than the given uint64_t
-  /// value.
-  /// @returns true iff this constant is greater or equal to the given number.
-  /// Determine if the value is greater or equal to the given number.
-  bool uge(uint64_t Num) const {
-    return cast<llvm::ConstantInt>(Val)->uge(Num);
-  }
-
-  /// getLimitedValue - If the value is smaller than the specified limit,
-  /// return it, otherwise return the limit value.  This causes the value
-  /// to saturate to the limit.
-  /// @returns the min of the value of the constant and the specified value
-  /// Get the constant's value with a saturation limit
-  uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
-    return cast<llvm::ConstantInt>(Val)->getLimitedValue(Limit);
-  }
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::ConstantInt;
-  }
-  unsigned getUseOperandNo(const Use &Use) const override {
-    llvm_unreachable("ConstantInt has no operands!");
-  }
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::ConstantInt>(Val) && "Expected a ConstantInst!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-// TODO: This should inherit from ConstantData.
-class ConstantFP final : public Constant {
-  ConstantFP(llvm::ConstantFP *C, Context &Ctx)
-      : Constant(ClassID::ConstantFP, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// This returns a ConstantFP, or a vector containing a splat of a ConstantFP,
-  /// for the specified value in the specified type. This should only be used
-  /// for simple constant values like 2.0/1.0 etc, that are known-valid both as
-  /// host double and as the target format.
-  static Constant *get(Type *Ty, double V);
-
-  /// If Ty is a vector type, return a Constant with a splat of the given
-  /// value. Otherwise return a ConstantFP for the given value.
-  static Constant *get(Type *Ty, const APFloat &V);
-
-  static Constant *get(Type *Ty, StringRef Str);
-
-  static ConstantFP *get(const APFloat &V, Context &Ctx);
-
-  static Constant *getNaN(Type *Ty, bool Negative = false,
-                          uint64_t Payload = 0);
-  static Constant *getQNaN(Type *Ty, bool Negative = false,
-                           APInt *Payload = nullptr);
-  static Constant *getSNaN(Type *Ty, bool Negative = false,
-                           APInt *Payload = nullptr);
-  static Constant *getZero(Type *Ty, bool Negative = false);
-
-  static Constant *getNegativeZero(Type *Ty);
-  static Constant *getInfinity(Type *Ty, bool Negative = false);
-
-  /// Return true if Ty is big enough to represent V.
-  static bool isValueValidForType(Type *Ty, const APFloat &V);
-
-  inline const APFloat &getValueAPF() const {
-    return cast<llvm::ConstantFP>(Val)->getValueAPF();
-  }
-  inline const APFloat &getValue() const {
-    return cast<llvm::ConstantFP>(Val)->getValue();
-  }
-
-  /// Return true if the value is positive or negative zero.
-  bool isZero() const { return cast<llvm::ConstantFP>(Val)->isZero(); }
-
-  /// Return true if the sign bit is set.
-  bool isNegative() const { return cast<llvm::ConstantFP>(Val)->isNegative(); }
-
-  /// Return true if the value is infinity
-  bool isInfinity() const { return cast<llvm::ConstantFP>(Val)->isInfinity(); }
-
-  /// Return true if the value is a NaN.
-  bool isNaN() const { return cast<llvm::ConstantFP>(Val)->isNaN(); }
-
-  /// We don't rely on operator== working on double values, as it returns true
-  /// for things that are clearly not equal, like -0.0 and 0.0.
-  /// As such, this method can be used to do an exact bit-for-bit comparison of
-  /// two floating point values.  The version with a double operand is retained
-  /// because it's so convenient to write isExactlyValue(2.0), but please use
-  /// it only for simple constants.
-  bool isExactlyValue(const APFloat &V) const {
-    return cast<llvm::ConstantFP>(Val)->isExactlyValue(V);
-  }
-
-  bool isExactlyValue(double V) const {
-    return cast<llvm::ConstantFP>(Val)->isExactlyValue(V);
-  }
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::ConstantFP;
-  }
-
-  // TODO: Better name: getOperandNo(const Use&). Should be private.
-  unsigned getUseOperandNo(const Use &Use) const final {
-    llvm_unreachable("ConstantFP has no operands!");
-  }
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::ConstantFP>(Val) && "Expected a ConstantFP!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-/// Base class for aggregate constants (with operands).
-class ConstantAggregate : public Constant {
-protected:
-  ConstantAggregate(ClassID ID, llvm::Constant *C, Context &Ctx)
-      : Constant(ID, C, Ctx) {}
-
-public:
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    auto ID = From->getSubclassID();
-    return ID == ClassID::ConstantVector || ID == ClassID::ConstantStruct ||
-           ID == ClassID::ConstantArray;
-  }
-};
-
-class ConstantArray final : public ConstantAggregate {
-  ConstantArray(llvm::ConstantArray *C, Context &Ctx)
-      : ConstantAggregate(ClassID::ConstantArray, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  static Constant *get(ArrayType *T, ArrayRef<Constant *> V);
-  ArrayType *getType() const;
-
-  // TODO: Missing functions: getType(), getTypeForElements(), getAnon(), get().
-
-  /// For isa/dyn_cast.
-  static bool classof(const Value *From) {
-    return From->getSubclassID() == ClassID::ConstantArray;
-  }
-};
-
-class ConstantStruct final : public ConstantAggregate {
-  ConstantStruct(llvm::ConstantStruct *C, Context &Ctx)
-      : ConstantAggregate(ClassID::ConstantStruct, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  static Constant *get(StructType *T, ArrayRef<Constant *> V);
-
-  template <typename... Csts>
-  static std::enable_if_t<are_base_of<Constant, Csts...>::value, Constant *>
-  get(StructType *T, Csts *...Vs) {
-    return get(T, ArrayRef<Constant *>({Vs...}));
-  }
-  /// Return an anonymous struct that has the specified elements.
-  /// If the struct is possibly empty, then you must specify a context.
-  static Constant *getAnon(ArrayRef<Constant *> V, bool Packed = false) {
-    return get(getTypeForElements(V, Packed), V);
-  }
-  static Constant *getAnon(Context &Ctx, ArrayRef<Constant *> V,
-                           bool Packed = false) {
-    return get(getTypeForElements(Ctx, V, Packed), V);
-  }
-  /// This version of the method allows an empty list.
-  static StructType *getTypeForElements(Context &Ctx, ArrayRef<Constant *> V,
-                                        bool Packed = false);
-  /// Return an anonymous struct type to use for a constant with the specified
-  /// set of elements. The list must not be empty.
-  static StructType *getTypeForElements(ArrayRef<Constant *> V,
-                                        bool Packed = false) {
-    assert(!V.empty() &&
-           "ConstantStruct::getTypeForElements cannot be called on empty list");
-    return getTypeForElements(V[0]->getContext(), V, Packed);
-  }
-
-  /// Specialization - reduce amount of casting.
-  inline StructType *getType() const {
-    return cast<StructType>(Value::getType());
-  }
-
-  /// For isa/dyn_cast.
-  static bool classof(const Value *From) {
-    return From->getSubclassID() == ClassID::ConstantStruct;
-  }
-};
-
-class ConstantVector final : public ConstantAggregate {
-  ConstantVector(llvm::ConstantVector *C, Context &Ctx)
-      : ConstantAggregate(ClassID::ConstantVector, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  // TODO: Missing functions: getSplat(), getType(), getSplatValue(), get().
-
-  /// For isa/dyn_cast.
-  static bool classof(const Value *From) {
-    return From->getSubclassID() == ClassID::ConstantVector;
-  }
-};
-
-// TODO: Inherit from ConstantData.
-class ConstantAggregateZero final : public Constant {
-  ConstantAggregateZero(llvm::ConstantAggregateZero *C, Context &Ctx)
-      : Constant(ClassID::ConstantAggregateZero, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  static ConstantAggregateZero *get(Type *Ty);
-  /// If this CAZ has array or vector type, return a zero with the right element
-  /// type.
-  Constant *getSequentialElement() const;
-  /// If this CAZ has struct type, return a zero with the right element type for
-  /// the specified element.
-  Constant *getStructElement(unsigned Elt) const;
-  /// Return a zero of the right value for the specified GEP index if we can,
-  /// otherwise return null (e.g. if C is a ConstantExpr).
-  Constant *getElementValue(Constant *C) const;
-  /// Return a zero of the right value for the specified GEP index.
-  Constant *getElementValue(unsigned Idx) const;
-  /// Return the number of elements in the array, vector, or struct.
-  ElementCount getElementCount() const {
-    return cast<llvm::ConstantAggregateZero>(Val)->getElementCount();
-  }
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::ConstantAggregateZero;
-  }
-  unsigned getUseOperandNo(const Use &Use) const final {
-    llvm_unreachable("ConstantAggregateZero has no operands!");
-  }
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::ConstantAggregateZero>(Val) && "Expected a CAZ!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-// TODO: Inherit from ConstantData.
-class ConstantPointerNull final : public Constant {
-  ConstantPointerNull(llvm::ConstantPointerNull *C, Context &Ctx)
-      : Constant(ClassID::ConstantPointerNull, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  static ConstantPointerNull *get(PointerType *Ty);
-
-  PointerType *getType() const;
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::ConstantPointerNull;
-  }
-  unsigned getUseOperandNo(const Use &Use) const final {
-    llvm_unreachable("ConstantPointerNull has no operands!");
-  }
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::ConstantPointerNull>(Val) && "Expected a CPNull!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-// TODO: Inherit from ConstantData.
-class UndefValue : public Constant {
-protected:
-  UndefValue(llvm::UndefValue *C, Context &Ctx)
-      : Constant(ClassID::UndefValue, C, Ctx) {}
-  UndefValue(ClassID ID, llvm::Constant *C, Context &Ctx)
-      : Constant(ID, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// Static factory methods - Return an 'undef' object of the specified type.
-  static UndefValue *get(Type *T);
-
-  /// If this Undef has array or vector type, return a undef with the right
-  /// element type.
-  UndefValue *getSequentialElement() const;
-
-  /// If this undef has struct type, return a undef with the right element type
-  /// for the specified element.
-  UndefValue *getStructElement(unsigned Elt) const;
-
-  /// Return an undef of the right value for the specified GEP index if we can,
-  /// otherwise return null (e.g. if C is a ConstantExpr).
-  UndefValue *getElementValue(Constant *C) const;
-
-  /// Return an undef of the right value for the specified GEP index.
-  UndefValue *getElementValue(unsigned Idx) const;
-
-  /// Return the number of elements in the array, vector, or struct.
-  unsigned getNumElements() const {
-    return cast<llvm::UndefValue>(Val)->getNumElements();
-  }
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::UndefValue ||
-           From->getSubclassID() == ClassID::PoisonValue;
-  }
-  unsigned getUseOperandNo(const Use &Use) const final {
-    llvm_unreachable("UndefValue has no operands!");
-  }
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::UndefValue>(Val) && "Expected an UndefValue!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-class PoisonValue final : public UndefValue {
-  PoisonValue(llvm::PoisonValue *C, Context &Ctx)
-      : UndefValue(ClassID::PoisonValue, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// Static factory methods - Return an 'poison' object of the specified type.
-  static PoisonValue *get(Type *T);
-
-  /// If this poison has array or vector type, return a poison with the right
-  /// element type.
-  PoisonValue *getSequentialElement() const;
-
-  /// If this poison has struct type, return a poison with the right element
-  /// type for the specified element.
-  PoisonValue *getStructElement(unsigned Elt) const;
-
-  /// Return an poison of the right value for the specified GEP index if we can,
-  /// otherwise return null (e.g. if C is a ConstantExpr).
-  PoisonValue *getElementValue(Constant *C) const;
-
-  /// Return an poison of the right value for the specified GEP index.
-  PoisonValue *getElementValue(unsigned Idx) const;
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::PoisonValue;
-  }
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::PoisonValue>(Val) && "Expected a PoisonValue!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-class GlobalValue : public Constant {
-protected:
-  GlobalValue(ClassID ID, llvm::GlobalValue *C, Context &Ctx)
-      : Constant(ID, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  using LinkageTypes = llvm::GlobalValue::LinkageTypes;
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    switch (From->getSubclassID()) {
-    case ClassID::Function:
-    case ClassID::GlobalVariable:
-    case ClassID::GlobalAlias:
-    case ClassID::GlobalIFunc:
-      return true;
-    default:
-      return false;
-    }
-  }
-
-  unsigned getAddressSpace() const {
-    return cast<llvm::GlobalValue>(Val)->getAddressSpace();
-  }
-  bool hasGlobalUnnamedAddr() const {
-    return cast<llvm::GlobalValue>(Val)->hasGlobalUnnamedAddr();
-  }
-
-  /// Returns true if this value's address is not significant in this module.
-  /// This attribute is intended to be used only by the code generator and LTO
-  /// to allow the linker to decide whether the global needs to be in the symbol
-  /// table. It should probably not be used in optimizations, as the value may
-  /// have uses outside the module; use hasGlobalUnnamedAddr() instead.
-  bool hasAtLeastLocalUnnamedAddr() const {
-    return cast<llvm::GlobalValue>(Val)->hasAtLeastLocalUnnamedAddr();
-  }
-
-  using UnnamedAddr = llvm::GlobalValue::UnnamedAddr;
-
-  UnnamedAddr getUnnamedAddr() const {
-    return cast<llvm::GlobalValue>(Val)->getUnnamedAddr();
-  }
-  void setUnnamedAddr(UnnamedAddr V);
-
-  static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) {
-    return llvm::GlobalValue::getMinUnnamedAddr(A, B);
-  }
-
-  bool hasComdat() const { return cast<llvm::GlobalValue>(Val)->hasComdat(); }
-
-  // TODO: We need a SandboxIR Comdat if we want to implement getComdat().
-  using VisibilityTypes = llvm::GlobalValue::VisibilityTypes;
-  VisibilityTypes getVisibility() const {
-    return cast<llvm::GlobalValue>(Val)->getVisibility();
-  }
-  bool hasDefaultVisibility() const {
-    return cast<llvm::GlobalValue>(Val)->hasDefaultVisibility();
-  }
-  bool hasHiddenVisibility() const {
-    return cast<llvm::GlobalValue>(Val)->hasHiddenVisibility();
-  }
-  bool hasProtectedVisibility() const {
-    return cast<llvm::GlobalValue>(Val)->hasProtectedVisibility();
-  }
-  void setVisibility(VisibilityTypes V);
-
-  // TODO: Add missing functions.
-};
-
-class GlobalObject : public GlobalValue {
-protected:
-  GlobalObject(ClassID ID, llvm::GlobalObject *C, Context &Ctx)
-      : GlobalValue(ID, C, Ctx) {}
-  friend class Context; // For constructor.
-  Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
-    return getOperandUseDefault(OpIdx, Verify);
-  }
-
-public:
-  unsigned getUseOperandNo(const Use &Use) const final {
-    return getUseOperandNoDefault(Use);
-  }
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    switch (From->getSubclassID()) {
-    case ClassID::Function:
-    case ClassID::GlobalVariable:
-    case ClassID::GlobalIFunc:
-      return true;
-    default:
-      return false;
-    }
-  }
-
-  /// FIXME: Remove this function once transition to Align is over.
-  uint64_t getAlignment() const {
-    return cast<llvm::GlobalObject>(Val)->getAlignment();
-  }
-
-  /// Returns the alignment of the given variable or function.
-  ///
-  /// Note that for functions this is the alignment of the code, not the
-  /// alignment of a function pointer.
-  MaybeAlign getAlign() const {
-    return cast<llvm::GlobalObject>(Val)->getAlign();
-  }
-
-  // TODO: Add missing: setAlignment(Align)
-
-  /// Sets the alignment attribute of the GlobalObject.
-  /// This method will be deprecated as the alignment property should always be
-  /// defined.
-  void setAlignment(MaybeAlign Align);
-
-  unsigned getGlobalObjectSubClassData() const {
-    return cast<llvm::GlobalObject>(Val)->getGlobalObjectSubClassData();
-  }
-
-  void setGlobalObjectSubClassData(unsigned V);
-
-  /// Check if this global has a custom object file section.
-  ///
-  /// This is more efficient than calling getSection() and checking for an empty
-  /// string.
-  bool hasSection() const {
-    return cast<llvm::GlobalObject>(Val)->hasSection();
-  }
-
-  /// Get the custom section of this global if it has one.
-  ///
-  /// If this global does not have a custom section, this will be empty and the
-  /// default object file section (.text, .data, etc) will be used.
-  StringRef getSection() const {
-    return cast<llvm::GlobalObject>(Val)->getSection();
-  }
-
-  /// Change the section for this global.
-  ///
-  /// Setting the section to the empty string tells LLVM to choose an
-  /// appropriate default object file section.
-  void setSection(StringRef S);
-
-  bool hasComdat() const { return cast<llvm::GlobalObject>(Val)->hasComdat(); }
-
-  // TODO: implement get/setComdat(), etc. once we have a sandboxir::Comdat.
-
-  // TODO: We currently don't support Metadata in sandboxir so all
-  // Metadata-related functions are missing.
-
-  using VCallVisibility = llvm::GlobalObject::VCallVisibility;
-
-  VCallVisibility getVCallVisibility() const {
-    return cast<llvm::GlobalObject>(Val)->getVCallVisibility();
-  }
-
-  /// Returns true if the alignment of the value can be unilaterally
-  /// increased.
-  ///
-  /// Note that for functions this is the alignment of the code, not the
-  /// alignment of a function pointer.
-  bool canIncreaseAlignment() const {
-    return cast<llvm::GlobalObject>(Val)->canIncreaseAlignment();
-  }
-};
-
-/// Provides API functions, like getIterator() and getReverseIterator() to
-/// GlobalIFunc, Function, GlobalVariable and GlobalAlias. In LLVM IR these are
-/// provided by ilist_node.
-template <typename GlobalT, typename LLVMGlobalT, typename ParentT,
-          typename LLVMParentT>
-class GlobalWithNodeAPI : public ParentT {
-  /// Helper for mapped_iterator.
-  struct LLVMGVToGV {
-    Context &Ctx;
-    LLVMGVToGV(Context &Ctx) : Ctx(Ctx) {}
-    GlobalT &operator()(LLVMGlobalT &LLVMGV) const;
-  };
-
-public:
-  GlobalWithNodeAPI(Value::ClassID ID, LLVMParentT *C, Context &Ctx)
-      : ParentT(ID, C, Ctx) {}
-
-  Module *getParent() const {
-    llvm::Module *LLVMM = cast<LLVMGlobalT>(this->Val)->getParent();
-    return this->Ctx.getModule(LLVMM);
-  }
-
-  using iterator = mapped_iterator<
-      decltype(static_cast<LLVMGlobalT *>(nullptr)->getIterator()), LLVMGVToGV>;
-  using reverse_iterator = mapped_iterator<
-      decltype(static_cast<LLVMGlobalT *>(nullptr)->getReverseIterator()),
-      LLVMGVToGV>;
-  iterator getIterator() const {
-    auto *LLVMGV = cast<LLVMGlobalT>(this->Val);
-    LLVMGVToGV ToGV(this->Ctx);
-    return map_iterator(LLVMGV->getIterator(), ToGV);
-  }
-  reverse_iterator getReverseIterator() const {
-    auto *LLVMGV = cast<LLVMGlobalT>(this->Val);
-    LLVMGVToGV ToGV(this->Ctx);
-    return map_iterator(LLVMGV->getReverseIterator(), ToGV);
-  }
-};
-
-class GlobalIFunc final
-    : public GlobalWithNodeAPI<GlobalIFunc, llvm::GlobalIFunc, GlobalObject,
-                               llvm::GlobalObject> {
-  GlobalIFunc(llvm::GlobalObject *C, Context &Ctx)
-      : GlobalWithNodeAPI(ClassID::GlobalIFunc, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::GlobalIFunc;
-  }
-
-  // TODO: Missing create() because we don't have a sandboxir::Module yet.
-
-  // TODO: Missing functions: copyAttributesFrom(), removeFromParent(),
-  // eraseFromParent()
-
-  void setResolver(Constant *Resolver);
-
-  Constant *getResolver() const;
-
-  // Return the resolver function after peeling off potential ConstantExpr
-  // indirection.
-  Function *getResolverFunction();
-  const Function *getResolverFunction() const {
-    return const_cast<GlobalIFunc *>(this)->getResolverFunction();
-  }
-
-  static bool isValidLinkage(LinkageTypes L) {
-    return llvm::GlobalIFunc::isValidLinkage(L);
-  }
-
-  // TODO: Missing applyAlongResolverPath().
-
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::GlobalIFunc>(Val) && "Expected a GlobalIFunc!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-class GlobalVariable final
-    : public GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
-                               GlobalObject, llvm::GlobalObject> {
-  GlobalVariable(llvm::GlobalObject *C, Context &Ctx)
-      : GlobalWithNodeAPI(ClassID::GlobalVariable, C, Ctx) {}
-  friend class Context; // For constructor.
-
-  /// Helper for mapped_iterator.
-  struct LLVMGVToGV {
-    Context &Ctx;
-    LLVMGVToGV(Context &Ctx) : Ctx(Ctx) {}
-    GlobalVariable &operator()(llvm::GlobalVariable &LLVMGV) const;
-  };
-
-public:
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::GlobalVariable;
-  }
-
-  /// Definitions have initializers, declarations don't.
-  ///
-  inline bool hasInitializer() const {
-    return cast<llvm::GlobalVariable>(Val)->hasInitializer();
-  }
-
-  /// hasDefinitiveInitializer - Whether the global variable has an initializer,
-  /// and any other instances of the global (this can happen due to weak
-  /// linkage) are guaranteed to have the same initializer.
-  ///
-  /// Note that if you want to transform a global, you must use
-  /// hasUniqueInitializer() instead, because of the *_odr linkage type.
-  ///
-  /// Example:
-  ///
-  /// @a = global SomeType* null - Initializer is both definitive and unique.
-  ///
-  /// @b = global weak SomeType* null - Initializer is neither definitive nor
-  /// unique.
-  ///
-  /// @c = global weak_odr SomeType* null - Initializer is definitive, but not
-  /// unique.
-  inline bool hasDefinitiveInitializer() const {
-    return cast<llvm::GlobalVariable>(Val)->hasDefinitiveInitializer();
-  }
-
-  /// hasUniqueInitializer - Whether the global variable has an initializer, and
-  /// any changes made to the initializer will turn up in the final executable.
-  inline bool hasUniqueInitializer() const {
-    return cast<llvm::GlobalVariable>(Val)->hasUniqueInitializer();
-  }
-
-  /// getInitializer - Return the initializer for this global variable.  It is
-  /// illegal to call this method if the global is external, because we cannot
-  /// tell what the value is initialized to!
-  ///
-  Constant *getInitializer() const;
-  /// setInitializer - Sets the initializer for this global variable, removing
-  /// any existing initializer if InitVal==NULL. The initializer must have the
-  /// type getValueType().
-  void setInitializer(Constant *InitVal);
-
-  // TODO: Add missing replaceInitializer(). Requires special tracker
-
-  /// If the value is a global constant, its value is immutable throughout the
-  /// runtime execution of the program.  Assigning a value into the constant
-  /// leads to undefined behavior.
-  ///
-  bool isConstant() const {
-    return cast<llvm::GlobalVariable>(Val)->isConstant();
-  }
-  void setConstant(bool V);
-
-  bool isExternallyInitialized() const {
-    return cast<llvm::GlobalVariable>(Val)->isExternallyInitialized();
-  }
-  void setExternallyInitialized(bool Val);
-
-  // TODO: Missing copyAttributesFrom()
-
-  // TODO: Missing removeFromParent(), eraseFromParent(), dropAllReferences()
-
-  // TODO: Missing addDebugInfo(), getDebugInfo()
-
-  // TODO: Missing attribute setter functions: addAttribute(), setAttributes().
-  //       There seems to be no removeAttribute() so we can't undo them.
-
-  /// Return true if the attribute exists.
-  bool hasAttribute(Attribute::AttrKind Kind) const {
-    return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
-  }
-
-  /// Return true if the attribute exists.
-  bool hasAttribute(StringRef Kind) const {
-    return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
-  }
-
-  /// Return true if any attributes exist.
-  bool hasAttributes() const {
-    return cast<llvm::GlobalVariable>(Val)->hasAttributes();
-  }
-
-  /// Return the attribute object.
-  Attribute getAttribute(Attribute::AttrKind Kind) const {
-    return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
-  }
-
-  /// Return the attribute object.
-  Attribute getAttribute(StringRef Kind) const {
-    return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
-  }
-
-  /// Return the attribute set for this global
-  AttributeSet getAttributes() const {
-    return cast<llvm::GlobalVariable>(Val)->getAttributes();
-  }
-
-  /// Return attribute set as list with index.
-  /// FIXME: This may not be required once ValueEnumerators
-  /// in bitcode-writer can enumerate attribute-set.
-  AttributeList getAttributesAsList(unsigned Index) const {
-    return cast<llvm::GlobalVariable>(Val)->getAttributesAsList(Index);
-  }
-
-  /// Check if section name is present
-  bool hasImplicitSection() const {
-    return cast<llvm::GlobalVariable>(Val)->hasImplicitSection();
-  }
-
-  /// Get the custom code model raw value of this global.
-  ///
-  unsigned getCodeModelRaw() const {
-    return cast<llvm::GlobalVariable>(Val)->getCodeModelRaw();
-  }
-
-  /// Get the custom code model of this global if it has one.
-  ///
-  /// If this global does not have a custom code model, the empty instance
-  /// will be returned.
-  std::optional<CodeModel::Model> getCodeModel() const {
-    return cast<llvm::GlobalVariable>(Val)->getCodeModel();
-  }
-
-  // TODO: Missing setCodeModel(). Requires custom tracker.
-
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::GlobalVariable>(Val) && "Expected a GlobalVariable!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-class GlobalAlias final
-    : public GlobalWithNodeAPI<GlobalAlias, llvm::GlobalAlias, GlobalValue,
-                               llvm::GlobalValue> {
-  GlobalAlias(llvm::GlobalAlias *C, Context &Ctx)
-      : GlobalWithNodeAPI(ClassID::GlobalAlias, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::GlobalAlias;
-  }
-
-  // TODO: Missing create() due to unimplemented sandboxir::Module.
-
-  // TODO: Missing copyAttributresFrom().
-  // TODO: Missing removeFromParent(), eraseFromParent().
-
-  void setAliasee(Constant *Aliasee);
-  Constant *getAliasee() const;
-
-  const GlobalObject *getAliaseeObject() const;
-  GlobalObject *getAliaseeObject() {
-    return const_cast<GlobalObject *>(
-        static_cast<const GlobalAlias *>(this)->getAliaseeObject());
-  }
-
-  static bool isValidLinkage(LinkageTypes L) {
-    return llvm::GlobalAlias::isValidLinkage(L);
-  }
-};
-
-class NoCFIValue final : public Constant {
-  NoCFIValue(llvm::NoCFIValue *C, Context &Ctx)
-      : Constant(ClassID::NoCFIValue, C, Ctx) {}
-  friend class Context; // For constructor.
-
-  Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
-    return getOperandUseDefault(OpIdx, Verify);
-  }
-
-public:
-  /// Return a NoCFIValue for the specified function.
-  static NoCFIValue *get(GlobalValue *GV);
-
-  GlobalValue *getGlobalValue() const;
-
-  /// NoCFIValue is always a pointer.
-  PointerType *getType() const;
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::NoCFIValue;
-  }
-
-  unsigned getUseOperandNo(const Use &Use) const final {
-    return getUseOperandNoDefault(Use);
-  }
-
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::NoCFIValue>(Val) && "Expected a NoCFIValue!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-class ConstantPtrAuth final : public Constant {
-  ConstantPtrAuth(llvm::ConstantPtrAuth *C, Context &Ctx)
-      : Constant(ClassID::ConstantPtrAuth, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// Return a pointer signed with the specified parameters.
-  static ConstantPtrAuth *get(Constant *Ptr, ConstantInt *Key,
-                              ConstantInt *Disc, Constant *AddrDisc);
-  /// The pointer that is signed in this ptrauth signed pointer.
-  Constant *getPointer() const;
-
-  /// The Key ID, an i32 constant.
-  ConstantInt *getKey() const;
-
-  /// The integer discriminator, an i64 constant, or 0.
-  ConstantInt *getDiscriminator() const;
-
-  /// The address discriminator if any, or the null constant.
-  /// If present, this must be a value equivalent to the storage location of
-  /// the only global-initializer user of the ptrauth signed pointer.
-  Constant *getAddrDiscriminator() const;
-
-  /// Whether there is any non-null address discriminator.
-  bool hasAddressDiscriminator() const {
-    return cast<llvm::ConstantPtrAuth>(Val)->hasAddressDiscriminator();
-  }
-
-  /// Whether the address uses a special address discriminator.
-  /// These discriminators can't be used in real pointer-auth values; they
-  /// can only be used in "prototype" values that indicate how some real
-  /// schema is supposed to be produced.
-  bool hasSpecialAddressDiscriminator(uint64_t Value) const {
-    return cast<llvm::ConstantPtrAuth>(Val)->hasSpecialAddressDiscriminator(
-        Value);
-  }
-
-  /// Check whether an authentication operation with key \p Key and (possibly
-  /// blended) discriminator \p Discriminator is known to be compatible with
-  /// this ptrauth signed pointer.
-  bool isKnownCompatibleWith(const Value *Key, const Value *Discriminator,
-                             const DataLayout &DL) const {
-    return cast<llvm::ConstantPtrAuth>(Val)->isKnownCompatibleWith(
-        Key->Val, Discriminator->Val, DL);
-  }
-
-  /// Produce a new ptrauth expression signing the given value using
-  /// the same schema as is stored in one.
-  ConstantPtrAuth *getWithSameSchema(Constant *Pointer) const;
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::ConstantPtrAuth;
-  }
-};
-
-class ConstantExpr : public Constant {
-  ConstantExpr(llvm::ConstantExpr *C, Context &Ctx)
-      : Constant(ClassID::ConstantExpr, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::ConstantExpr;
-  }
-  // TODO: Missing functions.
-};
-
-class BlockAddress final : public Constant {
-  BlockAddress(llvm::BlockAddress *C, Context &Ctx)
-      : Constant(ClassID::BlockAddress, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// Return a BlockAddress for the specified function and basic block.
-  static BlockAddress *get(Function *F, BasicBlock *BB);
-
-  /// Return a BlockAddress for the specified basic block.  The basic
-  /// block must be embedded into a function.
-  static BlockAddress *get(BasicBlock *BB);
-
-  /// Lookup an existing \c BlockAddress constant for the given BasicBlock.
-  ///
-  /// \returns 0 if \c !BB->hasAddressTaken(), otherwise the \c BlockAddress.
-  static BlockAddress *lookup(const BasicBlock *BB);
-
-  Function *getFunction() const;
-  BasicBlock *getBasicBlock() const;
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::BlockAddress;
-  }
-};
-
-class DSOLocalEquivalent final : public Constant {
-  DSOLocalEquivalent(llvm::DSOLocalEquivalent *C, Context &Ctx)
-      : Constant(ClassID::DSOLocalEquivalent, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// Return a DSOLocalEquivalent for the specified global value.
-  static DSOLocalEquivalent *get(GlobalValue *GV);
-
-  GlobalValue *getGlobalValue() const;
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::DSOLocalEquivalent;
-  }
-
-  unsigned getUseOperandNo(const Use &Use) const final {
-    llvm_unreachable("DSOLocalEquivalent has no operands!");
-  }
-
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::DSOLocalEquivalent>(Val) &&
-           "Expected a DSOLocalEquivalent!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
-// TODO: This should inherit from ConstantData.
-class ConstantTokenNone final : public Constant {
-  ConstantTokenNone(llvm::ConstantTokenNone *C, Context &Ctx)
-      : Constant(ClassID::ConstantTokenNone, C, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// Return the ConstantTokenNone.
-  static ConstantTokenNone *get(Context &Ctx);
-
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::ConstantTokenNone;
-  }
-
-  unsigned getUseOperandNo(const Use &Use) const final {
-    llvm_unreachable("ConstantTokenNone has no operands!");
-  }
-
-#ifndef NDEBUG
-  void verify() const override {
-    assert(isa<llvm::ConstantTokenNone>(Val) &&
-           "Expected a ConstantTokenNone!");
-  }
-  void dumpOS(raw_ostream &OS) const override {
-    dumpCommonPrefix(OS);
-    dumpCommonSuffix(OS);
-  }
-#endif
-};
-
 /// Iterator for `Instruction`s in a `BasicBlock.
 /// \Returns an sandboxir::Instruction & when derereferenced.
 class BBIterator {
@@ -4196,59 +2998,6 @@ class OpaqueInst : public SingleLLVMInstructionImpl<llvm::Instruction> {
   }
 };
 
-class Function : public GlobalWithNodeAPI<Function, llvm::Function,
-                                          GlobalObject, llvm::GlobalObject> {
-  /// Helper for mapped_iterator.
-  struct LLVMBBToBB {
-    Context &Ctx;
-    LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {}
-    BasicBlock &operator()(llvm::BasicBlock &LLVMBB) const {
-      return *cast<BasicBlock>(Ctx.getValue(&LLVMBB));
-    }
-  };
-  /// Use Context::createFunction() instead.
-  Function(llvm::Function *F, sandboxir::Context &Ctx)
-      : GlobalWithNodeAPI(ClassID::Function, F, Ctx) {}
-  friend class Context; // For constructor.
-
-public:
-  /// For isa/dyn_cast.
-  static bool classof(const sandboxir::Value *From) {
-    return From->getSubclassID() == ClassID::Function;
-  }
-
-  Module *getParent() {
-    return Ctx.getModule(cast<llvm::Function>(Val)->getParent());
-  }
-
-  Argument *getArg(unsigned Idx) const {
-    llvm::Argument *Arg = cast<llvm::Function>(Val)->getArg(Idx);
-    return cast<Argument>(Ctx.getValue(Arg));
-  }
-
-  size_t arg_size() const { return cast<llvm::Function>(Val)->arg_size(); }
-  bool arg_empty() const { return cast<llvm::Function>(Val)->arg_empty(); }
-
-  using iterator = mapped_iterator<llvm::Function::iterator, LLVMBBToBB>;
-  iterator begin() const {
-    LLVMBBToBB BBGetter(Ctx);
-    return iterator(cast<llvm::Function>(Val)->begin(), BBGetter);
-  }
-  iterator end() const {
-    LLVMBBToBB BBGetter(Ctx);
-    return iterator(cast<llvm::Function>(Val)->end(), BBGetter);
-  }
-  FunctionType *getFunctionType() const;
-
-#ifndef NDEBUG
-  void verify() const final {
-    assert(isa<llvm::Function>(Val) && "Expected Function!");
-  }
-  void dumpNameAndArgs(raw_ostream &OS) const;
-  void dumpOS(raw_ostream &OS) const final;
-#endif
-};
-
 } // namespace sandboxir
 } // namespace llvm
 
diff --git a/llvm/lib/SandboxIR/CMakeLists.txt b/llvm/lib/SandboxIR/CMakeLists.txt
index d9259db970da58..52afeb395a9a07 100644
--- a/llvm/lib/SandboxIR/CMakeLists.txt
+++ b/llvm/lib/SandboxIR/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMSandboxIR
   Argument.cpp
+  Constant.cpp
   Context.cpp
   Module.cpp
   Pass.cpp
diff --git a/llvm/lib/SandboxIR/Constant.cpp b/llvm/lib/SandboxIR/Constant.cpp
new file mode 100644
index 00000000000000..83b33f72f19d40
--- /dev/null
+++ b/llvm/lib/SandboxIR/Constant.cpp
@@ -0,0 +1,509 @@
+//===- Constant.cpp - The Constant classes of Sandbox IR ------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/SandboxIR/Constant.h"
+#include "llvm/SandboxIR/Context.h"
+#include "llvm/SandboxIR/SandboxIR.h" // TODO: Try to remove this
+
+namespace llvm::sandboxir {
+
+#ifndef NDEBUG
+void Constant::dumpOS(raw_ostream &OS) const {
+  dumpCommonPrefix(OS);
+  dumpCommonSuffix(OS);
+}
+#endif // NDEBUG
+
+ConstantInt *ConstantInt::getTrue(Context &Ctx) {
+  auto *LLVMC = llvm::ConstantInt::getTrue(Ctx.LLVMCtx);
+  return cast<ConstantInt>(Ctx.getOrCreateConstant(LLVMC));
+}
+ConstantInt *ConstantInt::getFalse(Context &Ctx) {
+  auto *LLVMC = llvm::ConstantInt::getFalse(Ctx.LLVMCtx);
+  return cast<ConstantInt>(Ctx.getOrCreateConstant(LLVMC));
+}
+ConstantInt *ConstantInt::getBool(Context &Ctx, bool V) {
+  auto *LLVMC = llvm::ConstantInt::getBool(Ctx.LLVMCtx, V);
+  return cast<ConstantInt>(Ctx.getOrCreateConstant(LLVMC));
+}
+Constant *ConstantInt::getTrue(Type *Ty) {
+  auto *LLVMC = llvm::ConstantInt::getTrue(Ty->LLVMTy);
+  return Ty->getContext().getOrCreateConstant(LLVMC);
+}
+Constant *ConstantInt::getFalse(Type *Ty) {
+  auto *LLVMC = llvm::ConstantInt::getFalse(Ty->LLVMTy);
+  return Ty->getContext().getOrCreateConstant(LLVMC);
+}
+Constant *ConstantInt::getBool(Type *Ty, bool V) {
+  auto *LLVMC = llvm::ConstantInt::getBool(Ty->LLVMTy, V);
+  return Ty->getContext().getOrCreateConstant(LLVMC);
+}
+ConstantInt *ConstantInt::get(Type *Ty, uint64_t V, bool IsSigned) {
+  auto *LLVMC = llvm::ConstantInt::get(Ty->LLVMTy, V, IsSigned);
+  return cast<ConstantInt>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+ConstantInt *ConstantInt::get(IntegerType *Ty, uint64_t V, bool IsSigned) {
+  auto *LLVMC = llvm::ConstantInt::get(Ty->LLVMTy, V, IsSigned);
+  return cast<ConstantInt>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+ConstantInt *ConstantInt::getSigned(IntegerType *Ty, int64_t V) {
+  auto *LLVMC =
+      llvm::ConstantInt::getSigned(cast<llvm::IntegerType>(Ty->LLVMTy), V);
+  return cast<ConstantInt>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+Constant *ConstantInt::getSigned(Type *Ty, int64_t V) {
+  auto *LLVMC = llvm::ConstantInt::getSigned(Ty->LLVMTy, V);
+  return Ty->getContext().getOrCreateConstant(LLVMC);
+}
+ConstantInt *ConstantInt::get(Context &Ctx, const APInt &V) {
+  auto *LLVMC = llvm::ConstantInt::get(Ctx.LLVMCtx, V);
+  return cast<ConstantInt>(Ctx.getOrCreateConstant(LLVMC));
+}
+ConstantInt *ConstantInt::get(IntegerType *Ty, StringRef Str, uint8_t Radix) {
+  auto *LLVMC =
+      llvm::ConstantInt::get(cast<llvm::IntegerType>(Ty->LLVMTy), Str, Radix);
+  return cast<ConstantInt>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+Constant *ConstantInt::get(Type *Ty, const APInt &V) {
+  auto *LLVMC = llvm::ConstantInt::get(Ty->LLVMTy, V);
+  return Ty->getContext().getOrCreateConstant(LLVMC);
+}
+IntegerType *ConstantInt::getIntegerType() const {
+  auto *LLVMTy = cast<llvm::ConstantInt>(Val)->getIntegerType();
+  return cast<IntegerType>(Ctx.getType(LLVMTy));
+}
+
+bool ConstantInt::isValueValidForType(Type *Ty, uint64_t V) {
+  return llvm::ConstantInt::isValueValidForType(Ty->LLVMTy, V);
+}
+bool ConstantInt::isValueValidForType(Type *Ty, int64_t V) {
+  return llvm::ConstantInt::isValueValidForType(Ty->LLVMTy, V);
+}
+
+Constant *ConstantFP::get(Type *Ty, double V) {
+  auto *LLVMC = llvm::ConstantFP::get(Ty->LLVMTy, V);
+  return Ty->getContext().getOrCreateConstant(LLVMC);
+}
+
+Constant *ConstantFP::get(Type *Ty, const APFloat &V) {
+  auto *LLVMC = llvm::ConstantFP::get(Ty->LLVMTy, V);
+  return Ty->getContext().getOrCreateConstant(LLVMC);
+}
+
+Constant *ConstantFP::get(Type *Ty, StringRef Str) {
+  auto *LLVMC = llvm::ConstantFP::get(Ty->LLVMTy, Str);
+  return Ty->getContext().getOrCreateConstant(LLVMC);
+}
+
+ConstantFP *ConstantFP::get(const APFloat &V, Context &Ctx) {
+  auto *LLVMC = llvm::ConstantFP::get(Ctx.LLVMCtx, V);
+  return cast<ConstantFP>(Ctx.getOrCreateConstant(LLVMC));
+}
+
+Constant *ConstantFP::getNaN(Type *Ty, bool Negative, uint64_t Payload) {
+  auto *LLVMC = llvm::ConstantFP::getNaN(Ty->LLVMTy, Negative, Payload);
+  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+Constant *ConstantFP::getQNaN(Type *Ty, bool Negative, APInt *Payload) {
+  auto *LLVMC = llvm::ConstantFP::getQNaN(Ty->LLVMTy, Negative, Payload);
+  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+Constant *ConstantFP::getSNaN(Type *Ty, bool Negative, APInt *Payload) {
+  auto *LLVMC = llvm::ConstantFP::getSNaN(Ty->LLVMTy, Negative, Payload);
+  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+Constant *ConstantFP::getZero(Type *Ty, bool Negative) {
+  auto *LLVMC = llvm::ConstantFP::getZero(Ty->LLVMTy, Negative);
+  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+Constant *ConstantFP::getNegativeZero(Type *Ty) {
+  auto *LLVMC = llvm::ConstantFP::getNegativeZero(Ty->LLVMTy);
+  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+Constant *ConstantFP::getInfinity(Type *Ty, bool Negative) {
+  auto *LLVMC = llvm::ConstantFP::getInfinity(Ty->LLVMTy, Negative);
+  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+bool ConstantFP::isValueValidForType(Type *Ty, const APFloat &V) {
+  return llvm::ConstantFP::isValueValidForType(Ty->LLVMTy, V);
+}
+
+Constant *ConstantArray::get(ArrayType *T, ArrayRef<Constant *> V) {
+  auto &Ctx = T->getContext();
+  SmallVector<llvm::Constant *> LLVMValues;
+  LLVMValues.reserve(V.size());
+  for (auto *Elm : V)
+    LLVMValues.push_back(cast<llvm::Constant>(Elm->Val));
+  auto *LLVMC =
+      llvm::ConstantArray::get(cast<llvm::ArrayType>(T->LLVMTy), LLVMValues);
+  return cast<ConstantArray>(Ctx.getOrCreateConstant(LLVMC));
+}
+
+ArrayType *ConstantArray::getType() const {
+  return cast<ArrayType>(
+      Ctx.getType(cast<llvm::ConstantArray>(Val)->getType()));
+}
+
+Constant *ConstantStruct::get(StructType *T, ArrayRef<Constant *> V) {
+  auto &Ctx = T->getContext();
+  SmallVector<llvm::Constant *> LLVMValues;
+  LLVMValues.reserve(V.size());
+  for (auto *Elm : V)
+    LLVMValues.push_back(cast<llvm::Constant>(Elm->Val));
+  auto *LLVMC =
+      llvm::ConstantStruct::get(cast<llvm::StructType>(T->LLVMTy), LLVMValues);
+  return cast<ConstantStruct>(Ctx.getOrCreateConstant(LLVMC));
+}
+
+StructType *ConstantStruct::getTypeForElements(Context &Ctx,
+                                               ArrayRef<Constant *> V,
+                                               bool Packed) {
+  unsigned VecSize = V.size();
+  SmallVector<Type *, 16> EltTypes;
+  EltTypes.reserve(VecSize);
+  for (Constant *Elm : V)
+    EltTypes.push_back(Elm->getType());
+  return StructType::get(Ctx, EltTypes, Packed);
+}
+
+ConstantAggregateZero *ConstantAggregateZero::get(Type *Ty) {
+  auto *LLVMC = llvm::ConstantAggregateZero::get(Ty->LLVMTy);
+  return cast<ConstantAggregateZero>(
+      Ty->getContext().getOrCreateConstant(LLVMC));
+}
+
+Constant *ConstantAggregateZero::getSequentialElement() const {
+  return cast<Constant>(Ctx.getValue(
+      cast<llvm::ConstantAggregateZero>(Val)->getSequentialElement()));
+}
+Constant *ConstantAggregateZero::getStructElement(unsigned Elt) const {
+  return cast<Constant>(Ctx.getValue(
+      cast<llvm::ConstantAggregateZero>(Val)->getStructElement(Elt)));
+}
+Constant *ConstantAggregateZero::getElementValue(Constant *C) const {
+  return cast<Constant>(
+      Ctx.getValue(cast<llvm::ConstantAggregateZero>(Val)->getElementValue(
+          cast<llvm::Constant>(C->Val))));
+}
+Constant *ConstantAggregateZero::getElementValue(unsigned Idx) const {
+  return cast<Constant>(Ctx.getValue(
+      cast<llvm::ConstantAggregateZero>(Val)->getElementValue(Idx)));
+}
+
+ConstantPointerNull *ConstantPointerNull::get(PointerType *Ty) {
+  auto *LLVMC =
+      llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty->LLVMTy));
+  return cast<ConstantPointerNull>(Ty->getContext().getOrCreateConstant(LLVMC));
+}
+
+PointerType *ConstantPointerNull::getType() const {
+  return cast<PointerType>(
+      Ctx.getType(cast<llvm::ConstantPointerNull>(Val)->getType()));
+}
+
+UndefValue *UndefValue::get(Type *T) {
+  auto *LLVMC = llvm::UndefValue::get(T->LLVMTy);
+  return cast<UndefValue>(T->getContext().getOrCreateConstant(LLVMC));
+}
+
+UndefValue *UndefValue::getSequentialElement() const {
+  return cast<UndefValue>(Ctx.getOrCreateConstant(
+      cast<llvm::UndefValue>(Val)->getSequentialElement()));
+}
+
+UndefValue *UndefValue::getStructElement(unsigned Elt) const {
+  return cast<UndefValue>(Ctx.getOrCreateConstant(
+      cast<llvm::UndefValue>(Val)->getStructElement(Elt)));
+}
+
+UndefValue *UndefValue::getElementValue(Constant *C) const {
+  return cast<UndefValue>(
+      Ctx.getOrCreateConstant(cast<llvm::UndefValue>(Val)->getElementValue(
+          cast<llvm::Constant>(C->Val))));
+}
+
+UndefValue *UndefValue::getElementValue(unsigned Idx) const {
+  return cast<UndefValue>(Ctx.getOrCreateConstant(
+      cast<llvm::UndefValue>(Val)->getElementValue(Idx)));
+}
+
+PoisonValue *PoisonValue::get(Type *T) {
+  auto *LLVMC = llvm::PoisonValue::get(T->LLVMTy);
+  return cast<PoisonValue>(T->getContext().getOrCreateConstant(LLVMC));
+}
+
+PoisonValue *PoisonValue::getSequentialElement() const {
+  return cast<PoisonValue>(Ctx.getOrCreateConstant(
+      cast<llvm::PoisonValue>(Val)->getSequentialElement()));
+}
+
+PoisonValue *PoisonValue::getStructElement(unsigned Elt) const {
+  return cast<PoisonValue>(Ctx.getOrCreateConstant(
+      cast<llvm::PoisonValue>(Val)->getStructElement(Elt)));
+}
+
+PoisonValue *PoisonValue::getElementValue(Constant *C) const {
+  return cast<PoisonValue>(
+      Ctx.getOrCreateConstant(cast<llvm::PoisonValue>(Val)->getElementValue(
+          cast<llvm::Constant>(C->Val))));
+}
+
+PoisonValue *PoisonValue::getElementValue(unsigned Idx) const {
+  return cast<PoisonValue>(Ctx.getOrCreateConstant(
+      cast<llvm::PoisonValue>(Val)->getElementValue(Idx)));
+}
+
+void GlobalObject::setAlignment(MaybeAlign Align) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&GlobalObject::getAlign, &GlobalObject::setAlignment>>(
+          this);
+  cast<llvm::GlobalObject>(Val)->setAlignment(Align);
+}
+
+void GlobalObject::setGlobalObjectSubClassData(unsigned V) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&GlobalObject::getGlobalObjectSubClassData,
+                        &GlobalObject::setGlobalObjectSubClassData>>(this);
+  cast<llvm::GlobalObject>(Val)->setGlobalObjectSubClassData(V);
+}
+
+void GlobalObject::setSection(StringRef S) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&GlobalObject::getSection, &GlobalObject::setSection>>(
+          this);
+  cast<llvm::GlobalObject>(Val)->setSection(S);
+}
+
+template <typename GlobalT, typename LLVMGlobalT, typename ParentT,
+          typename LLVMParentT>
+GlobalT &GlobalWithNodeAPI<GlobalT, LLVMGlobalT, ParentT, LLVMParentT>::
+    LLVMGVToGV::operator()(LLVMGlobalT &LLVMGV) const {
+  return cast<GlobalT>(*Ctx.getValue(&LLVMGV));
+}
+
+// Explicit instantiations.
+template class GlobalWithNodeAPI<GlobalIFunc, llvm::GlobalIFunc, GlobalObject,
+                                 llvm::GlobalObject>;
+template class GlobalWithNodeAPI<Function, llvm::Function, GlobalObject,
+                                 llvm::GlobalObject>;
+template class GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
+                                 GlobalObject, llvm::GlobalObject>;
+template class GlobalWithNodeAPI<GlobalAlias, llvm::GlobalAlias, GlobalValue,
+                                 llvm::GlobalValue>;
+
+void GlobalIFunc::setResolver(Constant *Resolver) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&GlobalIFunc::getResolver, &GlobalIFunc::setResolver>>(
+          this);
+  cast<llvm::GlobalIFunc>(Val)->setResolver(
+      cast<llvm::Constant>(Resolver->Val));
+}
+
+Constant *GlobalIFunc::getResolver() const {
+  return Ctx.getOrCreateConstant(cast<llvm::GlobalIFunc>(Val)->getResolver());
+}
+
+Function *GlobalIFunc::getResolverFunction() {
+  return cast<Function>(Ctx.getOrCreateConstant(
+      cast<llvm::GlobalIFunc>(Val)->getResolverFunction()));
+}
+
+GlobalVariable &
+GlobalVariable::LLVMGVToGV::operator()(llvm::GlobalVariable &LLVMGV) const {
+  return cast<GlobalVariable>(*Ctx.getValue(&LLVMGV));
+}
+
+Constant *GlobalVariable::getInitializer() const {
+  return Ctx.getOrCreateConstant(
+      cast<llvm::GlobalVariable>(Val)->getInitializer());
+}
+
+void GlobalVariable::setInitializer(Constant *InitVal) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&GlobalVariable::getInitializer,
+                                       &GlobalVariable::setInitializer>>(this);
+  cast<llvm::GlobalVariable>(Val)->setInitializer(
+      cast<llvm::Constant>(InitVal->Val));
+}
+
+void GlobalVariable::setConstant(bool V) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&GlobalVariable::isConstant,
+                                       &GlobalVariable::setConstant>>(this);
+  cast<llvm::GlobalVariable>(Val)->setConstant(V);
+}
+
+void GlobalVariable::setExternallyInitialized(bool V) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&GlobalVariable::isExternallyInitialized,
+                        &GlobalVariable::setExternallyInitialized>>(this);
+  cast<llvm::GlobalVariable>(Val)->setExternallyInitialized(V);
+}
+
+void GlobalAlias::setAliasee(Constant *Aliasee) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&GlobalAlias::getAliasee, &GlobalAlias::setAliasee>>(
+          this);
+  cast<llvm::GlobalAlias>(Val)->setAliasee(cast<llvm::Constant>(Aliasee->Val));
+}
+
+Constant *GlobalAlias::getAliasee() const {
+  return cast<Constant>(
+      Ctx.getOrCreateConstant(cast<llvm::GlobalAlias>(Val)->getAliasee()));
+}
+
+const GlobalObject *GlobalAlias::getAliaseeObject() const {
+  return cast<GlobalObject>(Ctx.getOrCreateConstant(
+      cast<llvm::GlobalAlias>(Val)->getAliaseeObject()));
+}
+
+void GlobalValue::setUnnamedAddr(UnnamedAddr V) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&GlobalValue::getUnnamedAddr,
+                                       &GlobalValue::setUnnamedAddr>>(this);
+  cast<llvm::GlobalValue>(Val)->setUnnamedAddr(V);
+}
+
+void GlobalValue::setVisibility(VisibilityTypes V) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&GlobalValue::getVisibility,
+                                       &GlobalValue::setVisibility>>(this);
+  cast<llvm::GlobalValue>(Val)->setVisibility(V);
+}
+
+NoCFIValue *NoCFIValue::get(GlobalValue *GV) {
+  auto *LLVMC = llvm::NoCFIValue::get(cast<llvm::GlobalValue>(GV->Val));
+  return cast<NoCFIValue>(GV->getContext().getOrCreateConstant(LLVMC));
+}
+
+GlobalValue *NoCFIValue::getGlobalValue() const {
+  auto *LLVMC = cast<llvm::NoCFIValue>(Val)->getGlobalValue();
+  return cast<GlobalValue>(Ctx.getOrCreateConstant(LLVMC));
+}
+
+PointerType *NoCFIValue::getType() const {
+  return cast<PointerType>(Ctx.getType(cast<llvm::NoCFIValue>(Val)->getType()));
+}
+
+ConstantPtrAuth *ConstantPtrAuth::get(Constant *Ptr, ConstantInt *Key,
+                                      ConstantInt *Disc, Constant *AddrDisc) {
+  auto *LLVMC = llvm::ConstantPtrAuth::get(
+      cast<llvm::Constant>(Ptr->Val), cast<llvm::ConstantInt>(Key->Val),
+      cast<llvm::ConstantInt>(Disc->Val), cast<llvm::Constant>(AddrDisc->Val));
+  return cast<ConstantPtrAuth>(Ptr->getContext().getOrCreateConstant(LLVMC));
+}
+
+Constant *ConstantPtrAuth::getPointer() const {
+  return Ctx.getOrCreateConstant(
+      cast<llvm::ConstantPtrAuth>(Val)->getPointer());
+}
+
+ConstantInt *ConstantPtrAuth::getKey() const {
+  return cast<ConstantInt>(
+      Ctx.getOrCreateConstant(cast<llvm::ConstantPtrAuth>(Val)->getKey()));
+}
+
+ConstantInt *ConstantPtrAuth::getDiscriminator() const {
+  return cast<ConstantInt>(Ctx.getOrCreateConstant(
+      cast<llvm::ConstantPtrAuth>(Val)->getDiscriminator()));
+}
+
+Constant *ConstantPtrAuth::getAddrDiscriminator() const {
+  return Ctx.getOrCreateConstant(
+      cast<llvm::ConstantPtrAuth>(Val)->getAddrDiscriminator());
+}
+
+ConstantPtrAuth *ConstantPtrAuth::getWithSameSchema(Constant *Pointer) const {
+  auto *LLVMC = cast<llvm::ConstantPtrAuth>(Val)->getWithSameSchema(
+      cast<llvm::Constant>(Pointer->Val));
+  return cast<ConstantPtrAuth>(Ctx.getOrCreateConstant(LLVMC));
+}
+
+BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) {
+  auto *LLVMC = llvm::BlockAddress::get(cast<llvm::Function>(F->Val),
+                                        cast<llvm::BasicBlock>(BB->Val));
+  return cast<BlockAddress>(F->getContext().getOrCreateConstant(LLVMC));
+}
+
+BlockAddress *BlockAddress::get(BasicBlock *BB) {
+  auto *LLVMC = llvm::BlockAddress::get(cast<llvm::BasicBlock>(BB->Val));
+  return cast<BlockAddress>(BB->getContext().getOrCreateConstant(LLVMC));
+}
+
+BlockAddress *BlockAddress::lookup(const BasicBlock *BB) {
+  auto *LLVMC = llvm::BlockAddress::lookup(cast<llvm::BasicBlock>(BB->Val));
+  return cast_or_null<BlockAddress>(BB->getContext().getValue(LLVMC));
+}
+
+Function *BlockAddress::getFunction() const {
+  return cast<Function>(
+      Ctx.getValue(cast<llvm::BlockAddress>(Val)->getFunction()));
+}
+
+BasicBlock *BlockAddress::getBasicBlock() const {
+  return cast<BasicBlock>(
+      Ctx.getValue(cast<llvm::BlockAddress>(Val)->getBasicBlock()));
+}
+
+DSOLocalEquivalent *DSOLocalEquivalent::get(GlobalValue *GV) {
+  auto *LLVMC = llvm::DSOLocalEquivalent::get(cast<llvm::GlobalValue>(GV->Val));
+  return cast<DSOLocalEquivalent>(GV->getContext().getValue(LLVMC));
+}
+
+GlobalValue *DSOLocalEquivalent::getGlobalValue() const {
+  return cast<GlobalValue>(
+      Ctx.getValue(cast<llvm::DSOLocalEquivalent>(Val)->getGlobalValue()));
+}
+
+FunctionType *Function::getFunctionType() const {
+  return cast<FunctionType>(
+      Ctx.getType(cast<llvm::Function>(Val)->getFunctionType()));
+}
+
+#ifndef NDEBUG
+void Function::dumpNameAndArgs(raw_ostream &OS) const {
+  auto *F = cast<llvm::Function>(Val);
+  OS << *F->getReturnType() << " @" << F->getName() << "(";
+  interleave(
+      F->args(),
+      [this, &OS](const llvm::Argument &LLVMArg) {
+        auto *SBArg = cast_or_null<Argument>(Ctx.getValue(&LLVMArg));
+        if (SBArg == nullptr)
+          OS << "NULL";
+        else
+          SBArg->printAsOperand(OS);
+      },
+      [&] { OS << ", "; });
+  OS << ")";
+}
+
+void Function::dumpOS(raw_ostream &OS) const {
+  dumpNameAndArgs(OS);
+  OS << " {\n";
+  auto *LLVMF = cast<llvm::Function>(Val);
+  interleave(
+      *LLVMF,
+      [this, &OS](const llvm::BasicBlock &LLVMBB) {
+        auto *BB = cast_or_null<BasicBlock>(Ctx.getValue(&LLVMBB));
+        if (BB == nullptr)
+          OS << "NULL";
+        else
+          OS << *BB;
+      },
+      [&OS] { OS << "\n"; });
+  OS << "}\n";
+}
+#endif // NDEBUG
+
+} // namespace llvm::sandboxir
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 12cac66480b0c3..42df9df8119733 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -2085,506 +2085,11 @@ Value *InsertValueInst::create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
   return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
 }
 
-#ifndef NDEBUG
-void Constant::dumpOS(raw_ostream &OS) const {
-  dumpCommonPrefix(OS);
-  dumpCommonSuffix(OS);
-}
-#endif // NDEBUG
-
-ConstantInt *ConstantInt::getTrue(Context &Ctx) {
-  auto *LLVMC = llvm::ConstantInt::getTrue(Ctx.LLVMCtx);
-  return cast<ConstantInt>(Ctx.getOrCreateConstant(LLVMC));
-}
-ConstantInt *ConstantInt::getFalse(Context &Ctx) {
-  auto *LLVMC = llvm::ConstantInt::getFalse(Ctx.LLVMCtx);
-  return cast<ConstantInt>(Ctx.getOrCreateConstant(LLVMC));
-}
-ConstantInt *ConstantInt::getBool(Context &Ctx, bool V) {
-  auto *LLVMC = llvm::ConstantInt::getBool(Ctx.LLVMCtx, V);
-  return cast<ConstantInt>(Ctx.getOrCreateConstant(LLVMC));
-}
-Constant *ConstantInt::getTrue(Type *Ty) {
-  auto *LLVMC = llvm::ConstantInt::getTrue(Ty->LLVMTy);
-  return Ty->getContext().getOrCreateConstant(LLVMC);
-}
-Constant *ConstantInt::getFalse(Type *Ty) {
-  auto *LLVMC = llvm::ConstantInt::getFalse(Ty->LLVMTy);
-  return Ty->getContext().getOrCreateConstant(LLVMC);
-}
-Constant *ConstantInt::getBool(Type *Ty, bool V) {
-  auto *LLVMC = llvm::ConstantInt::getBool(Ty->LLVMTy, V);
-  return Ty->getContext().getOrCreateConstant(LLVMC);
-}
-ConstantInt *ConstantInt::get(Type *Ty, uint64_t V, bool IsSigned) {
-  auto *LLVMC = llvm::ConstantInt::get(Ty->LLVMTy, V, IsSigned);
-  return cast<ConstantInt>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-ConstantInt *ConstantInt::get(IntegerType *Ty, uint64_t V, bool IsSigned) {
-  auto *LLVMC = llvm::ConstantInt::get(Ty->LLVMTy, V, IsSigned);
-  return cast<ConstantInt>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-ConstantInt *ConstantInt::getSigned(IntegerType *Ty, int64_t V) {
-  auto *LLVMC =
-      llvm::ConstantInt::getSigned(cast<llvm::IntegerType>(Ty->LLVMTy), V);
-  return cast<ConstantInt>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-Constant *ConstantInt::getSigned(Type *Ty, int64_t V) {
-  auto *LLVMC = llvm::ConstantInt::getSigned(Ty->LLVMTy, V);
-  return Ty->getContext().getOrCreateConstant(LLVMC);
-}
-ConstantInt *ConstantInt::get(Context &Ctx, const APInt &V) {
-  auto *LLVMC = llvm::ConstantInt::get(Ctx.LLVMCtx, V);
-  return cast<ConstantInt>(Ctx.getOrCreateConstant(LLVMC));
-}
-ConstantInt *ConstantInt::get(IntegerType *Ty, StringRef Str, uint8_t Radix) {
-  auto *LLVMC =
-      llvm::ConstantInt::get(cast<llvm::IntegerType>(Ty->LLVMTy), Str, Radix);
-  return cast<ConstantInt>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-Constant *ConstantInt::get(Type *Ty, const APInt &V) {
-  auto *LLVMC = llvm::ConstantInt::get(Ty->LLVMTy, V);
-  return Ty->getContext().getOrCreateConstant(LLVMC);
-}
-IntegerType *ConstantInt::getIntegerType() const {
-  auto *LLVMTy = cast<llvm::ConstantInt>(Val)->getIntegerType();
-  return cast<IntegerType>(Ctx.getType(LLVMTy));
-}
-
-bool ConstantInt::isValueValidForType(Type *Ty, uint64_t V) {
-  return llvm::ConstantInt::isValueValidForType(Ty->LLVMTy, V);
-}
-bool ConstantInt::isValueValidForType(Type *Ty, int64_t V) {
-  return llvm::ConstantInt::isValueValidForType(Ty->LLVMTy, V);
-}
-
-Constant *ConstantFP::get(Type *Ty, double V) {
-  auto *LLVMC = llvm::ConstantFP::get(Ty->LLVMTy, V);
-  return Ty->getContext().getOrCreateConstant(LLVMC);
-}
-
-Constant *ConstantFP::get(Type *Ty, const APFloat &V) {
-  auto *LLVMC = llvm::ConstantFP::get(Ty->LLVMTy, V);
-  return Ty->getContext().getOrCreateConstant(LLVMC);
-}
-
-Constant *ConstantFP::get(Type *Ty, StringRef Str) {
-  auto *LLVMC = llvm::ConstantFP::get(Ty->LLVMTy, Str);
-  return Ty->getContext().getOrCreateConstant(LLVMC);
-}
-
-ConstantFP *ConstantFP::get(const APFloat &V, Context &Ctx) {
-  auto *LLVMC = llvm::ConstantFP::get(Ctx.LLVMCtx, V);
-  return cast<ConstantFP>(Ctx.getOrCreateConstant(LLVMC));
-}
-
-Constant *ConstantFP::getNaN(Type *Ty, bool Negative, uint64_t Payload) {
-  auto *LLVMC = llvm::ConstantFP::getNaN(Ty->LLVMTy, Negative, Payload);
-  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-Constant *ConstantFP::getQNaN(Type *Ty, bool Negative, APInt *Payload) {
-  auto *LLVMC = llvm::ConstantFP::getQNaN(Ty->LLVMTy, Negative, Payload);
-  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-Constant *ConstantFP::getSNaN(Type *Ty, bool Negative, APInt *Payload) {
-  auto *LLVMC = llvm::ConstantFP::getSNaN(Ty->LLVMTy, Negative, Payload);
-  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-Constant *ConstantFP::getZero(Type *Ty, bool Negative) {
-  auto *LLVMC = llvm::ConstantFP::getZero(Ty->LLVMTy, Negative);
-  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-Constant *ConstantFP::getNegativeZero(Type *Ty) {
-  auto *LLVMC = llvm::ConstantFP::getNegativeZero(Ty->LLVMTy);
-  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-Constant *ConstantFP::getInfinity(Type *Ty, bool Negative) {
-  auto *LLVMC = llvm::ConstantFP::getInfinity(Ty->LLVMTy, Negative);
-  return cast<Constant>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-bool ConstantFP::isValueValidForType(Type *Ty, const APFloat &V) {
-  return llvm::ConstantFP::isValueValidForType(Ty->LLVMTy, V);
-}
-
-Constant *ConstantArray::get(ArrayType *T, ArrayRef<Constant *> V) {
-  auto &Ctx = T->getContext();
-  SmallVector<llvm::Constant *> LLVMValues;
-  LLVMValues.reserve(V.size());
-  for (auto *Elm : V)
-    LLVMValues.push_back(cast<llvm::Constant>(Elm->Val));
-  auto *LLVMC =
-      llvm::ConstantArray::get(cast<llvm::ArrayType>(T->LLVMTy), LLVMValues);
-  return cast<ConstantArray>(Ctx.getOrCreateConstant(LLVMC));
-}
-
-ArrayType *ConstantArray::getType() const {
-  return cast<ArrayType>(
-      Ctx.getType(cast<llvm::ConstantArray>(Val)->getType()));
-}
-
-Constant *ConstantStruct::get(StructType *T, ArrayRef<Constant *> V) {
-  auto &Ctx = T->getContext();
-  SmallVector<llvm::Constant *> LLVMValues;
-  LLVMValues.reserve(V.size());
-  for (auto *Elm : V)
-    LLVMValues.push_back(cast<llvm::Constant>(Elm->Val));
-  auto *LLVMC =
-      llvm::ConstantStruct::get(cast<llvm::StructType>(T->LLVMTy), LLVMValues);
-  return cast<ConstantStruct>(Ctx.getOrCreateConstant(LLVMC));
-}
-
-StructType *ConstantStruct::getTypeForElements(Context &Ctx,
-                                               ArrayRef<Constant *> V,
-                                               bool Packed) {
-  unsigned VecSize = V.size();
-  SmallVector<Type *, 16> EltTypes;
-  EltTypes.reserve(VecSize);
-  for (Constant *Elm : V)
-    EltTypes.push_back(Elm->getType());
-  return StructType::get(Ctx, EltTypes, Packed);
-}
-
-ConstantAggregateZero *ConstantAggregateZero::get(Type *Ty) {
-  auto *LLVMC = llvm::ConstantAggregateZero::get(Ty->LLVMTy);
-  return cast<ConstantAggregateZero>(
-      Ty->getContext().getOrCreateConstant(LLVMC));
-}
-
-Constant *ConstantAggregateZero::getSequentialElement() const {
-  return cast<Constant>(Ctx.getValue(
-      cast<llvm::ConstantAggregateZero>(Val)->getSequentialElement()));
-}
-Constant *ConstantAggregateZero::getStructElement(unsigned Elt) const {
-  return cast<Constant>(Ctx.getValue(
-      cast<llvm::ConstantAggregateZero>(Val)->getStructElement(Elt)));
-}
-Constant *ConstantAggregateZero::getElementValue(Constant *C) const {
-  return cast<Constant>(
-      Ctx.getValue(cast<llvm::ConstantAggregateZero>(Val)->getElementValue(
-          cast<llvm::Constant>(C->Val))));
-}
-Constant *ConstantAggregateZero::getElementValue(unsigned Idx) const {
-  return cast<Constant>(Ctx.getValue(
-      cast<llvm::ConstantAggregateZero>(Val)->getElementValue(Idx)));
-}
-
-ConstantPointerNull *ConstantPointerNull::get(PointerType *Ty) {
-  auto *LLVMC =
-      llvm::ConstantPointerNull::get(cast<llvm::PointerType>(Ty->LLVMTy));
-  return cast<ConstantPointerNull>(Ty->getContext().getOrCreateConstant(LLVMC));
-}
-
-PointerType *ConstantPointerNull::getType() const {
-  return cast<PointerType>(
-      Ctx.getType(cast<llvm::ConstantPointerNull>(Val)->getType()));
-}
-
-UndefValue *UndefValue::get(Type *T) {
-  auto *LLVMC = llvm::UndefValue::get(T->LLVMTy);
-  return cast<UndefValue>(T->getContext().getOrCreateConstant(LLVMC));
-}
-
-UndefValue *UndefValue::getSequentialElement() const {
-  return cast<UndefValue>(Ctx.getOrCreateConstant(
-      cast<llvm::UndefValue>(Val)->getSequentialElement()));
-}
-
-UndefValue *UndefValue::getStructElement(unsigned Elt) const {
-  return cast<UndefValue>(Ctx.getOrCreateConstant(
-      cast<llvm::UndefValue>(Val)->getStructElement(Elt)));
-}
-
-UndefValue *UndefValue::getElementValue(Constant *C) const {
-  return cast<UndefValue>(
-      Ctx.getOrCreateConstant(cast<llvm::UndefValue>(Val)->getElementValue(
-          cast<llvm::Constant>(C->Val))));
-}
-
-UndefValue *UndefValue::getElementValue(unsigned Idx) const {
-  return cast<UndefValue>(Ctx.getOrCreateConstant(
-      cast<llvm::UndefValue>(Val)->getElementValue(Idx)));
-}
-
-PoisonValue *PoisonValue::get(Type *T) {
-  auto *LLVMC = llvm::PoisonValue::get(T->LLVMTy);
-  return cast<PoisonValue>(T->getContext().getOrCreateConstant(LLVMC));
-}
-
-PoisonValue *PoisonValue::getSequentialElement() const {
-  return cast<PoisonValue>(Ctx.getOrCreateConstant(
-      cast<llvm::PoisonValue>(Val)->getSequentialElement()));
-}
-
-PoisonValue *PoisonValue::getStructElement(unsigned Elt) const {
-  return cast<PoisonValue>(Ctx.getOrCreateConstant(
-      cast<llvm::PoisonValue>(Val)->getStructElement(Elt)));
-}
-
-PoisonValue *PoisonValue::getElementValue(Constant *C) const {
-  return cast<PoisonValue>(
-      Ctx.getOrCreateConstant(cast<llvm::PoisonValue>(Val)->getElementValue(
-          cast<llvm::Constant>(C->Val))));
-}
-
-PoisonValue *PoisonValue::getElementValue(unsigned Idx) const {
-  return cast<PoisonValue>(Ctx.getOrCreateConstant(
-      cast<llvm::PoisonValue>(Val)->getElementValue(Idx)));
-}
-
-void GlobalObject::setAlignment(MaybeAlign Align) {
-  Ctx.getTracker()
-      .emplaceIfTracking<
-          GenericSetter<&GlobalObject::getAlign, &GlobalObject::setAlignment>>(
-          this);
-  cast<llvm::GlobalObject>(Val)->setAlignment(Align);
-}
-
-void GlobalObject::setGlobalObjectSubClassData(unsigned V) {
-  Ctx.getTracker()
-      .emplaceIfTracking<
-          GenericSetter<&GlobalObject::getGlobalObjectSubClassData,
-                        &GlobalObject::setGlobalObjectSubClassData>>(this);
-  cast<llvm::GlobalObject>(Val)->setGlobalObjectSubClassData(V);
-}
-
-void GlobalObject::setSection(StringRef S) {
-  Ctx.getTracker()
-      .emplaceIfTracking<
-          GenericSetter<&GlobalObject::getSection, &GlobalObject::setSection>>(
-          this);
-  cast<llvm::GlobalObject>(Val)->setSection(S);
-}
-
-template <typename GlobalT, typename LLVMGlobalT, typename ParentT,
-          typename LLVMParentT>
-GlobalT &GlobalWithNodeAPI<GlobalT, LLVMGlobalT, ParentT, LLVMParentT>::
-    LLVMGVToGV::operator()(LLVMGlobalT &LLVMGV) const {
-  return cast<GlobalT>(*Ctx.getValue(&LLVMGV));
-}
-
-namespace llvm::sandboxir {
-// Explicit instantiations.
-template class GlobalWithNodeAPI<GlobalIFunc, llvm::GlobalIFunc, GlobalObject,
-                                 llvm::GlobalObject>;
-template class GlobalWithNodeAPI<Function, llvm::Function, GlobalObject,
-                                 llvm::GlobalObject>;
-template class GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
-                                 GlobalObject, llvm::GlobalObject>;
-template class GlobalWithNodeAPI<GlobalAlias, llvm::GlobalAlias, GlobalValue,
-                                 llvm::GlobalValue>;
-} // namespace llvm::sandboxir
-
-void GlobalIFunc::setResolver(Constant *Resolver) {
-  Ctx.getTracker()
-      .emplaceIfTracking<
-          GenericSetter<&GlobalIFunc::getResolver, &GlobalIFunc::setResolver>>(
-          this);
-  cast<llvm::GlobalIFunc>(Val)->setResolver(
-      cast<llvm::Constant>(Resolver->Val));
-}
-
-Constant *GlobalIFunc::getResolver() const {
-  return Ctx.getOrCreateConstant(cast<llvm::GlobalIFunc>(Val)->getResolver());
-}
-
-Function *GlobalIFunc::getResolverFunction() {
-  return cast<Function>(Ctx.getOrCreateConstant(
-      cast<llvm::GlobalIFunc>(Val)->getResolverFunction()));
-}
-
-GlobalVariable &
-GlobalVariable::LLVMGVToGV::operator()(llvm::GlobalVariable &LLVMGV) const {
-  return cast<GlobalVariable>(*Ctx.getValue(&LLVMGV));
-}
-
-Constant *GlobalVariable::getInitializer() const {
-  return Ctx.getOrCreateConstant(
-      cast<llvm::GlobalVariable>(Val)->getInitializer());
-}
-
-void GlobalVariable::setInitializer(Constant *InitVal) {
-  Ctx.getTracker()
-      .emplaceIfTracking<GenericSetter<&GlobalVariable::getInitializer,
-                                       &GlobalVariable::setInitializer>>(this);
-  cast<llvm::GlobalVariable>(Val)->setInitializer(
-      cast<llvm::Constant>(InitVal->Val));
-}
-
-void GlobalVariable::setConstant(bool V) {
-  Ctx.getTracker()
-      .emplaceIfTracking<GenericSetter<&GlobalVariable::isConstant,
-                                       &GlobalVariable::setConstant>>(this);
-  cast<llvm::GlobalVariable>(Val)->setConstant(V);
-}
-
-void GlobalVariable::setExternallyInitialized(bool V) {
-  Ctx.getTracker()
-      .emplaceIfTracking<
-          GenericSetter<&GlobalVariable::isExternallyInitialized,
-                        &GlobalVariable::setExternallyInitialized>>(this);
-  cast<llvm::GlobalVariable>(Val)->setExternallyInitialized(V);
-}
-
-void GlobalAlias::setAliasee(Constant *Aliasee) {
-  Ctx.getTracker()
-      .emplaceIfTracking<
-          GenericSetter<&GlobalAlias::getAliasee, &GlobalAlias::setAliasee>>(
-          this);
-  cast<llvm::GlobalAlias>(Val)->setAliasee(cast<llvm::Constant>(Aliasee->Val));
-}
-
-Constant *GlobalAlias::getAliasee() const {
-  return cast<Constant>(
-      Ctx.getOrCreateConstant(cast<llvm::GlobalAlias>(Val)->getAliasee()));
-}
-
-const GlobalObject *GlobalAlias::getAliaseeObject() const {
-  return cast<GlobalObject>(Ctx.getOrCreateConstant(
-      cast<llvm::GlobalAlias>(Val)->getAliaseeObject()));
-}
-
-void GlobalValue::setUnnamedAddr(UnnamedAddr V) {
-  Ctx.getTracker()
-      .emplaceIfTracking<GenericSetter<&GlobalValue::getUnnamedAddr,
-                                       &GlobalValue::setUnnamedAddr>>(this);
-  cast<llvm::GlobalValue>(Val)->setUnnamedAddr(V);
-}
-
-void GlobalValue::setVisibility(VisibilityTypes V) {
-  Ctx.getTracker()
-      .emplaceIfTracking<GenericSetter<&GlobalValue::getVisibility,
-                                       &GlobalValue::setVisibility>>(this);
-  cast<llvm::GlobalValue>(Val)->setVisibility(V);
-}
-
-NoCFIValue *NoCFIValue::get(GlobalValue *GV) {
-  auto *LLVMC = llvm::NoCFIValue::get(cast<llvm::GlobalValue>(GV->Val));
-  return cast<NoCFIValue>(GV->getContext().getOrCreateConstant(LLVMC));
-}
-
-GlobalValue *NoCFIValue::getGlobalValue() const {
-  auto *LLVMC = cast<llvm::NoCFIValue>(Val)->getGlobalValue();
-  return cast<GlobalValue>(Ctx.getOrCreateConstant(LLVMC));
-}
-
-PointerType *NoCFIValue::getType() const {
-  return cast<PointerType>(Ctx.getType(cast<llvm::NoCFIValue>(Val)->getType()));
-}
-
-ConstantPtrAuth *ConstantPtrAuth::get(Constant *Ptr, ConstantInt *Key,
-                                      ConstantInt *Disc, Constant *AddrDisc) {
-  auto *LLVMC = llvm::ConstantPtrAuth::get(
-      cast<llvm::Constant>(Ptr->Val), cast<llvm::ConstantInt>(Key->Val),
-      cast<llvm::ConstantInt>(Disc->Val), cast<llvm::Constant>(AddrDisc->Val));
-  return cast<ConstantPtrAuth>(Ptr->getContext().getOrCreateConstant(LLVMC));
-}
-
-Constant *ConstantPtrAuth::getPointer() const {
-  return Ctx.getOrCreateConstant(
-      cast<llvm::ConstantPtrAuth>(Val)->getPointer());
-}
-
-ConstantInt *ConstantPtrAuth::getKey() const {
-  return cast<ConstantInt>(
-      Ctx.getOrCreateConstant(cast<llvm::ConstantPtrAuth>(Val)->getKey()));
-}
-
-ConstantInt *ConstantPtrAuth::getDiscriminator() const {
-  return cast<ConstantInt>(Ctx.getOrCreateConstant(
-      cast<llvm::ConstantPtrAuth>(Val)->getDiscriminator()));
-}
-
-Constant *ConstantPtrAuth::getAddrDiscriminator() const {
-  return Ctx.getOrCreateConstant(
-      cast<llvm::ConstantPtrAuth>(Val)->getAddrDiscriminator());
-}
-
-ConstantPtrAuth *ConstantPtrAuth::getWithSameSchema(Constant *Pointer) const {
-  auto *LLVMC = cast<llvm::ConstantPtrAuth>(Val)->getWithSameSchema(
-      cast<llvm::Constant>(Pointer->Val));
-  return cast<ConstantPtrAuth>(Ctx.getOrCreateConstant(LLVMC));
-}
-
-BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) {
-  auto *LLVMC = llvm::BlockAddress::get(cast<llvm::Function>(F->Val),
-                                        cast<llvm::BasicBlock>(BB->Val));
-  return cast<BlockAddress>(F->getContext().getOrCreateConstant(LLVMC));
-}
-
-BlockAddress *BlockAddress::get(BasicBlock *BB) {
-  auto *LLVMC = llvm::BlockAddress::get(cast<llvm::BasicBlock>(BB->Val));
-  return cast<BlockAddress>(BB->getContext().getOrCreateConstant(LLVMC));
-}
-
-BlockAddress *BlockAddress::lookup(const BasicBlock *BB) {
-  auto *LLVMC = llvm::BlockAddress::lookup(cast<llvm::BasicBlock>(BB->Val));
-  return cast_or_null<BlockAddress>(BB->getContext().getValue(LLVMC));
-}
-
-Function *BlockAddress::getFunction() const {
-  return cast<Function>(
-      Ctx.getValue(cast<llvm::BlockAddress>(Val)->getFunction()));
-}
-
-BasicBlock *BlockAddress::getBasicBlock() const {
-  return cast<BasicBlock>(
-      Ctx.getValue(cast<llvm::BlockAddress>(Val)->getBasicBlock()));
-}
-
-DSOLocalEquivalent *DSOLocalEquivalent::get(GlobalValue *GV) {
-  auto *LLVMC = llvm::DSOLocalEquivalent::get(cast<llvm::GlobalValue>(GV->Val));
-  return cast<DSOLocalEquivalent>(GV->getContext().getValue(LLVMC));
-}
-
-GlobalValue *DSOLocalEquivalent::getGlobalValue() const {
-  return cast<GlobalValue>(
-      Ctx.getValue(cast<llvm::DSOLocalEquivalent>(Val)->getGlobalValue()));
-}
-
 ConstantTokenNone *ConstantTokenNone::get(Context &Ctx) {
   auto *LLVMC = llvm::ConstantTokenNone::get(Ctx.LLVMCtx);
   return cast<ConstantTokenNone>(Ctx.getOrCreateConstant(LLVMC));
 }
 
-FunctionType *Function::getFunctionType() const {
-  return cast<FunctionType>(
-      Ctx.getType(cast<llvm::Function>(Val)->getFunctionType()));
-}
-
-#ifndef NDEBUG
-void Function::dumpNameAndArgs(raw_ostream &OS) const {
-  auto *F = cast<llvm::Function>(Val);
-  OS << *F->getReturnType() << " @" << F->getName() << "(";
-  interleave(
-      F->args(),
-      [this, &OS](const llvm::Argument &LLVMArg) {
-        auto *SBArg = cast_or_null<Argument>(Ctx.getValue(&LLVMArg));
-        if (SBArg == nullptr)
-          OS << "NULL";
-        else
-          SBArg->printAsOperand(OS);
-      },
-      [&] { OS << ", "; });
-  OS << ")";
-}
-void Function::dumpOS(raw_ostream &OS) const {
-  dumpNameAndArgs(OS);
-  OS << " {\n";
-  auto *LLVMF = cast<llvm::Function>(Val);
-  interleave(
-      *LLVMF,
-      [this, &OS](const llvm::BasicBlock &LLVMBB) {
-        auto *BB = cast_or_null<BasicBlock>(Ctx.getValue(&LLVMBB));
-        if (BB == nullptr)
-          OS << "NULL";
-        else
-          OS << *BB;
-      },
-      [&OS] { OS << "\n"; });
-  OS << "}\n";
-}
-#endif // NDEBUG
-
 BasicBlock::iterator::pointer
 BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It) const {
   return cast_or_null<Instruction>(Ctx->getValue(&*It));



More information about the llvm-commits mailing list