From a3d6e25c5c338e6740a276d45ea598461820d87c Mon Sep 17 00:00:00 2001 From: Vasileios Porpodas 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 0000000000000..bc0e3d8849237 --- /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(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(Val)->getValue(); + } + + /// getBitWidth - Return the scalar bitwidth of this constant. + unsigned getBitWidth() const { + return cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(Val)->getValueAPF(); + } + inline const APFloat &getValue() const { + return cast(Val)->getValue(); + } + + /// Return true if the value is positive or negative zero. + bool isZero() const { return cast(Val)->isZero(); } + + /// Return true if the sign bit is set. + bool isNegative() const { return cast(Val)->isNegative(); } + + /// Return true if the value is infinity + bool isInfinity() const { return cast(Val)->isInfinity(); } + + /// Return true if the value is a NaN. + bool isNaN() const { return cast(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(Val)->isExactlyValue(V); + } + + bool isExactlyValue(double V) const { + return cast(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(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 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 V); + + template + static std::enable_if_t::value, Constant *> + get(StructType *T, Csts *...Vs) { + return get(T, ArrayRef({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 V, bool Packed = false) { + return get(getTypeForElements(V, Packed), V); + } + static Constant *getAnon(Context &Ctx, ArrayRef 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 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 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(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(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(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(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(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(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(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(Val)->getAddressSpace(); + } + bool hasGlobalUnnamedAddr() const { + return cast(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(Val)->hasAtLeastLocalUnnamedAddr(); + } + + using UnnamedAddr = llvm::GlobalValue::UnnamedAddr; + + UnnamedAddr getUnnamedAddr() const { + return cast(Val)->getUnnamedAddr(); + } + void setUnnamedAddr(UnnamedAddr V); + + static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) { + return llvm::GlobalValue::getMinUnnamedAddr(A, B); + } + + bool hasComdat() const { return cast(Val)->hasComdat(); } + + // TODO: We need a SandboxIR Comdat if we want to implement getComdat(). + using VisibilityTypes = llvm::GlobalValue::VisibilityTypes; + VisibilityTypes getVisibility() const { + return cast(Val)->getVisibility(); + } + bool hasDefaultVisibility() const { + return cast(Val)->hasDefaultVisibility(); + } + bool hasHiddenVisibility() const { + return cast(Val)->hasHiddenVisibility(); + } + bool hasProtectedVisibility() const { + return cast(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(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(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(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(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(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(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(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(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 +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(this->Val)->getParent(); + return this->Ctx.getModule(LLVMM); + } + + using iterator = mapped_iterator< + decltype(static_cast(nullptr)->getIterator()), LLVMGVToGV>; + using reverse_iterator = mapped_iterator< + decltype(static_cast(nullptr)->getReverseIterator()), + LLVMGVToGV>; + iterator getIterator() const { + auto *LLVMGV = cast(this->Val); + LLVMGVToGV ToGV(this->Ctx); + return map_iterator(LLVMGV->getIterator(), ToGV); + } + reverse_iterator getReverseIterator() const { + auto *LLVMGV = cast(this->Val); + LLVMGVToGV ToGV(this->Ctx); + return map_iterator(LLVMGV->getReverseIterator(), ToGV); + } +}; + +class GlobalIFunc final + : public GlobalWithNodeAPI { + 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(this)->getResolverFunction(); + } + + static bool isValidLinkage(LinkageTypes L) { + return llvm::GlobalIFunc::isValidLinkage(L); + } + + // TODO: Missing applyAlongResolverPath(). + +#ifndef NDEBUG + void verify() const override { + assert(isa(Val) && "Expected a GlobalIFunc!"); + } + void dumpOS(raw_ostream &OS) const override { + dumpCommonPrefix(OS); + dumpCommonSuffix(OS); + } +#endif +}; + +class GlobalVariable final + : public GlobalWithNodeAPI { + 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(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(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(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(Val)->isConstant(); + } + void setConstant(bool V); + + bool isExternallyInitialized() const { + return cast(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(Val)->hasAttribute(Kind); + } + + /// Return true if the attribute exists. + bool hasAttribute(StringRef Kind) const { + return cast(Val)->hasAttribute(Kind); + } + + /// Return true if any attributes exist. + bool hasAttributes() const { + return cast(Val)->hasAttributes(); + } + + /// Return the attribute object. + Attribute getAttribute(Attribute::AttrKind Kind) const { + return cast(Val)->getAttribute(Kind); + } + + /// Return the attribute object. + Attribute getAttribute(StringRef Kind) const { + return cast(Val)->getAttribute(Kind); + } + + /// Return the attribute set for this global + AttributeSet getAttributes() const { + return cast(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(Val)->getAttributesAsList(Index); + } + + /// Check if section name is present + bool hasImplicitSection() const { + return cast(Val)->hasImplicitSection(); + } + + /// Get the custom code model raw value of this global. + /// + unsigned getCodeModelRaw() const { + return cast(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 getCodeModel() const { + return cast(Val)->getCodeModel(); + } + + // TODO: Missing setCodeModel(). Requires custom tracker. + +#ifndef NDEBUG + void verify() const override { + assert(isa(Val) && "Expected a GlobalVariable!"); + } + void dumpOS(raw_ostream &OS) const override { + dumpCommonPrefix(OS); + dumpCommonSuffix(OS); + } +#endif +}; + +class GlobalAlias final + : public GlobalWithNodeAPI { + 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( + static_cast(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(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(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(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(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(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(Val) && + "Expected a ConstantTokenNone!"); + } + void dumpOS(raw_ostream &OS) const override { + dumpCommonPrefix(OS); + dumpCommonSuffix(OS); + } +#endif +}; + +class Function : public GlobalWithNodeAPI { + /// Helper for mapped_iterator. + struct LLVMBBToBB { + Context &Ctx; + LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {} + BasicBlock &operator()(llvm::BasicBlock &LLVMBB) const { + return *cast(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(Val)->getParent()); + } + + Argument *getArg(unsigned Idx) const { + llvm::Argument *Arg = cast(Val)->getArg(Idx); + return cast(Ctx.getValue(Arg)); + } + + size_t arg_size() const { return cast(Val)->arg_size(); } + bool arg_empty() const { return cast(Val)->arg_empty(); } + + using iterator = mapped_iterator; + iterator begin() const { + LLVMBBToBB BBGetter(Ctx); + return iterator(cast(Val)->begin(), BBGetter); + } + iterator end() const { + LLVMBBToBB BBGetter(Ctx); + return iterator(cast(Val)->end(), BBGetter); + } + FunctionType *getFunctionType() const; + +#ifndef NDEBUG + void verify() const final { + assert(isa(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 66de9ee078d61..02246c303ab61 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(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(Val)->getValue(); - } - - /// getBitWidth - Return the scalar bitwidth of this constant. - unsigned getBitWidth() const { - return cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(Val)->getValueAPF(); - } - inline const APFloat &getValue() const { - return cast(Val)->getValue(); - } - - /// Return true if the value is positive or negative zero. - bool isZero() const { return cast(Val)->isZero(); } - - /// Return true if the sign bit is set. - bool isNegative() const { return cast(Val)->isNegative(); } - - /// Return true if the value is infinity - bool isInfinity() const { return cast(Val)->isInfinity(); } - - /// Return true if the value is a NaN. - bool isNaN() const { return cast(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(Val)->isExactlyValue(V); - } - - bool isExactlyValue(double V) const { - return cast(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(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 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 V); - - template - static std::enable_if_t::value, Constant *> - get(StructType *T, Csts *...Vs) { - return get(T, ArrayRef({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 V, bool Packed = false) { - return get(getTypeForElements(V, Packed), V); - } - static Constant *getAnon(Context &Ctx, ArrayRef 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 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 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(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(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(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(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(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(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(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(Val)->getAddressSpace(); - } - bool hasGlobalUnnamedAddr() const { - return cast(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(Val)->hasAtLeastLocalUnnamedAddr(); - } - - using UnnamedAddr = llvm::GlobalValue::UnnamedAddr; - - UnnamedAddr getUnnamedAddr() const { - return cast(Val)->getUnnamedAddr(); - } - void setUnnamedAddr(UnnamedAddr V); - - static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) { - return llvm::GlobalValue::getMinUnnamedAddr(A, B); - } - - bool hasComdat() const { return cast(Val)->hasComdat(); } - - // TODO: We need a SandboxIR Comdat if we want to implement getComdat(). - using VisibilityTypes = llvm::GlobalValue::VisibilityTypes; - VisibilityTypes getVisibility() const { - return cast(Val)->getVisibility(); - } - bool hasDefaultVisibility() const { - return cast(Val)->hasDefaultVisibility(); - } - bool hasHiddenVisibility() const { - return cast(Val)->hasHiddenVisibility(); - } - bool hasProtectedVisibility() const { - return cast(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(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(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(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(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(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(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(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(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 -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(this->Val)->getParent(); - return this->Ctx.getModule(LLVMM); - } - - using iterator = mapped_iterator< - decltype(static_cast(nullptr)->getIterator()), LLVMGVToGV>; - using reverse_iterator = mapped_iterator< - decltype(static_cast(nullptr)->getReverseIterator()), - LLVMGVToGV>; - iterator getIterator() const { - auto *LLVMGV = cast(this->Val); - LLVMGVToGV ToGV(this->Ctx); - return map_iterator(LLVMGV->getIterator(), ToGV); - } - reverse_iterator getReverseIterator() const { - auto *LLVMGV = cast(this->Val); - LLVMGVToGV ToGV(this->Ctx); - return map_iterator(LLVMGV->getReverseIterator(), ToGV); - } -}; - -class GlobalIFunc final - : public GlobalWithNodeAPI { - 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(this)->getResolverFunction(); - } - - static bool isValidLinkage(LinkageTypes L) { - return llvm::GlobalIFunc::isValidLinkage(L); - } - - // TODO: Missing applyAlongResolverPath(). - -#ifndef NDEBUG - void verify() const override { - assert(isa(Val) && "Expected a GlobalIFunc!"); - } - void dumpOS(raw_ostream &OS) const override { - dumpCommonPrefix(OS); - dumpCommonSuffix(OS); - } -#endif -}; - -class GlobalVariable final - : public GlobalWithNodeAPI { - 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(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(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(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(Val)->isConstant(); - } - void setConstant(bool V); - - bool isExternallyInitialized() const { - return cast(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(Val)->hasAttribute(Kind); - } - - /// Return true if the attribute exists. - bool hasAttribute(StringRef Kind) const { - return cast(Val)->hasAttribute(Kind); - } - - /// Return true if any attributes exist. - bool hasAttributes() const { - return cast(Val)->hasAttributes(); - } - - /// Return the attribute object. - Attribute getAttribute(Attribute::AttrKind Kind) const { - return cast(Val)->getAttribute(Kind); - } - - /// Return the attribute object. - Attribute getAttribute(StringRef Kind) const { - return cast(Val)->getAttribute(Kind); - } - - /// Return the attribute set for this global - AttributeSet getAttributes() const { - return cast(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(Val)->getAttributesAsList(Index); - } - - /// Check if section name is present - bool hasImplicitSection() const { - return cast(Val)->hasImplicitSection(); - } - - /// Get the custom code model raw value of this global. - /// - unsigned getCodeModelRaw() const { - return cast(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 getCodeModel() const { - return cast(Val)->getCodeModel(); - } - - // TODO: Missing setCodeModel(). Requires custom tracker. - -#ifndef NDEBUG - void verify() const override { - assert(isa(Val) && "Expected a GlobalVariable!"); - } - void dumpOS(raw_ostream &OS) const override { - dumpCommonPrefix(OS); - dumpCommonSuffix(OS); - } -#endif -}; - -class GlobalAlias final - : public GlobalWithNodeAPI { - 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( - static_cast(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(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(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(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(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(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(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 { } }; -class Function : public GlobalWithNodeAPI { - /// Helper for mapped_iterator. - struct LLVMBBToBB { - Context &Ctx; - LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {} - BasicBlock &operator()(llvm::BasicBlock &LLVMBB) const { - return *cast(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(Val)->getParent()); - } - - Argument *getArg(unsigned Idx) const { - llvm::Argument *Arg = cast(Val)->getArg(Idx); - return cast(Ctx.getValue(Arg)); - } - - size_t arg_size() const { return cast(Val)->arg_size(); } - bool arg_empty() const { return cast(Val)->arg_empty(); } - - using iterator = mapped_iterator; - iterator begin() const { - LLVMBBToBB BBGetter(Ctx); - return iterator(cast(Val)->begin(), BBGetter); - } - iterator end() const { - LLVMBBToBB BBGetter(Ctx); - return iterator(cast(Val)->end(), BBGetter); - } - FunctionType *getFunctionType() const; - -#ifndef NDEBUG - void verify() const final { - assert(isa(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 d9259db970da5..52afeb395a9a0 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 0000000000000..83b33f72f19d4 --- /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(Ctx.getOrCreateConstant(LLVMC)); +} +ConstantInt *ConstantInt::getFalse(Context &Ctx) { + auto *LLVMC = llvm::ConstantInt::getFalse(Ctx.LLVMCtx); + return cast(Ctx.getOrCreateConstant(LLVMC)); +} +ConstantInt *ConstantInt::getBool(Context &Ctx, bool V) { + auto *LLVMC = llvm::ConstantInt::getBool(Ctx.LLVMCtx, V); + return cast(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(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(Ty->getContext().getOrCreateConstant(LLVMC)); +} +ConstantInt *ConstantInt::getSigned(IntegerType *Ty, int64_t V) { + auto *LLVMC = + llvm::ConstantInt::getSigned(cast(Ty->LLVMTy), V); + return cast(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(Ctx.getOrCreateConstant(LLVMC)); +} +ConstantInt *ConstantInt::get(IntegerType *Ty, StringRef Str, uint8_t Radix) { + auto *LLVMC = + llvm::ConstantInt::get(cast(Ty->LLVMTy), Str, Radix); + return cast(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(Val)->getIntegerType(); + return cast(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(Ctx.getOrCreateConstant(LLVMC)); +} + +Constant *ConstantFP::getNaN(Type *Ty, bool Negative, uint64_t Payload) { + auto *LLVMC = llvm::ConstantFP::getNaN(Ty->LLVMTy, Negative, Payload); + return cast(Ty->getContext().getOrCreateConstant(LLVMC)); +} +Constant *ConstantFP::getQNaN(Type *Ty, bool Negative, APInt *Payload) { + auto *LLVMC = llvm::ConstantFP::getQNaN(Ty->LLVMTy, Negative, Payload); + return cast(Ty->getContext().getOrCreateConstant(LLVMC)); +} +Constant *ConstantFP::getSNaN(Type *Ty, bool Negative, APInt *Payload) { + auto *LLVMC = llvm::ConstantFP::getSNaN(Ty->LLVMTy, Negative, Payload); + return cast(Ty->getContext().getOrCreateConstant(LLVMC)); +} +Constant *ConstantFP::getZero(Type *Ty, bool Negative) { + auto *LLVMC = llvm::ConstantFP::getZero(Ty->LLVMTy, Negative); + return cast(Ty->getContext().getOrCreateConstant(LLVMC)); +} +Constant *ConstantFP::getNegativeZero(Type *Ty) { + auto *LLVMC = llvm::ConstantFP::getNegativeZero(Ty->LLVMTy); + return cast(Ty->getContext().getOrCreateConstant(LLVMC)); +} +Constant *ConstantFP::getInfinity(Type *Ty, bool Negative) { + auto *LLVMC = llvm::ConstantFP::getInfinity(Ty->LLVMTy, Negative); + return cast(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 V) { + auto &Ctx = T->getContext(); + SmallVector LLVMValues; + LLVMValues.reserve(V.size()); + for (auto *Elm : V) + LLVMValues.push_back(cast(Elm->Val)); + auto *LLVMC = + llvm::ConstantArray::get(cast(T->LLVMTy), LLVMValues); + return cast(Ctx.getOrCreateConstant(LLVMC)); +} + +ArrayType *ConstantArray::getType() const { + return cast( + Ctx.getType(cast(Val)->getType())); +} + +Constant *ConstantStruct::get(StructType *T, ArrayRef V) { + auto &Ctx = T->getContext(); + SmallVector LLVMValues; + LLVMValues.reserve(V.size()); + for (auto *Elm : V) + LLVMValues.push_back(cast(Elm->Val)); + auto *LLVMC = + llvm::ConstantStruct::get(cast(T->LLVMTy), LLVMValues); + return cast(Ctx.getOrCreateConstant(LLVMC)); +} + +StructType *ConstantStruct::getTypeForElements(Context &Ctx, + ArrayRef V, + bool Packed) { + unsigned VecSize = V.size(); + SmallVector 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( + Ty->getContext().getOrCreateConstant(LLVMC)); +} + +Constant *ConstantAggregateZero::getSequentialElement() const { + return cast(Ctx.getValue( + cast(Val)->getSequentialElement())); +} +Constant *ConstantAggregateZero::getStructElement(unsigned Elt) const { + return cast(Ctx.getValue( + cast(Val)->getStructElement(Elt))); +} +Constant *ConstantAggregateZero::getElementValue(Constant *C) const { + return cast( + Ctx.getValue(cast(Val)->getElementValue( + cast(C->Val)))); +} +Constant *ConstantAggregateZero::getElementValue(unsigned Idx) const { + return cast(Ctx.getValue( + cast(Val)->getElementValue(Idx))); +} + +ConstantPointerNull *ConstantPointerNull::get(PointerType *Ty) { + auto *LLVMC = + llvm::ConstantPointerNull::get(cast(Ty->LLVMTy)); + return cast(Ty->getContext().getOrCreateConstant(LLVMC)); +} + +PointerType *ConstantPointerNull::getType() const { + return cast( + Ctx.getType(cast(Val)->getType())); +} + +UndefValue *UndefValue::get(Type *T) { + auto *LLVMC = llvm::UndefValue::get(T->LLVMTy); + return cast(T->getContext().getOrCreateConstant(LLVMC)); +} + +UndefValue *UndefValue::getSequentialElement() const { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getSequentialElement())); +} + +UndefValue *UndefValue::getStructElement(unsigned Elt) const { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getStructElement(Elt))); +} + +UndefValue *UndefValue::getElementValue(Constant *C) const { + return cast( + Ctx.getOrCreateConstant(cast(Val)->getElementValue( + cast(C->Val)))); +} + +UndefValue *UndefValue::getElementValue(unsigned Idx) const { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getElementValue(Idx))); +} + +PoisonValue *PoisonValue::get(Type *T) { + auto *LLVMC = llvm::PoisonValue::get(T->LLVMTy); + return cast(T->getContext().getOrCreateConstant(LLVMC)); +} + +PoisonValue *PoisonValue::getSequentialElement() const { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getSequentialElement())); +} + +PoisonValue *PoisonValue::getStructElement(unsigned Elt) const { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getStructElement(Elt))); +} + +PoisonValue *PoisonValue::getElementValue(Constant *C) const { + return cast( + Ctx.getOrCreateConstant(cast(Val)->getElementValue( + cast(C->Val)))); +} + +PoisonValue *PoisonValue::getElementValue(unsigned Idx) const { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getElementValue(Idx))); +} + +void GlobalObject::setAlignment(MaybeAlign Align) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getAlign, &GlobalObject::setAlignment>>( + this); + cast(Val)->setAlignment(Align); +} + +void GlobalObject::setGlobalObjectSubClassData(unsigned V) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getGlobalObjectSubClassData, + &GlobalObject::setGlobalObjectSubClassData>>(this); + cast(Val)->setGlobalObjectSubClassData(V); +} + +void GlobalObject::setSection(StringRef S) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getSection, &GlobalObject::setSection>>( + this); + cast(Val)->setSection(S); +} + +template +GlobalT &GlobalWithNodeAPI:: + LLVMGVToGV::operator()(LLVMGlobalT &LLVMGV) const { + return cast(*Ctx.getValue(&LLVMGV)); +} + +// Explicit instantiations. +template class GlobalWithNodeAPI; +template class GlobalWithNodeAPI; +template class GlobalWithNodeAPI; +template class GlobalWithNodeAPI; + +void GlobalIFunc::setResolver(Constant *Resolver) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalIFunc::getResolver, &GlobalIFunc::setResolver>>( + this); + cast(Val)->setResolver( + cast(Resolver->Val)); +} + +Constant *GlobalIFunc::getResolver() const { + return Ctx.getOrCreateConstant(cast(Val)->getResolver()); +} + +Function *GlobalIFunc::getResolverFunction() { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getResolverFunction())); +} + +GlobalVariable & +GlobalVariable::LLVMGVToGV::operator()(llvm::GlobalVariable &LLVMGV) const { + return cast(*Ctx.getValue(&LLVMGV)); +} + +Constant *GlobalVariable::getInitializer() const { + return Ctx.getOrCreateConstant( + cast(Val)->getInitializer()); +} + +void GlobalVariable::setInitializer(Constant *InitVal) { + Ctx.getTracker() + .emplaceIfTracking>(this); + cast(Val)->setInitializer( + cast(InitVal->Val)); +} + +void GlobalVariable::setConstant(bool V) { + Ctx.getTracker() + .emplaceIfTracking>(this); + cast(Val)->setConstant(V); +} + +void GlobalVariable::setExternallyInitialized(bool V) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalVariable::isExternallyInitialized, + &GlobalVariable::setExternallyInitialized>>(this); + cast(Val)->setExternallyInitialized(V); +} + +void GlobalAlias::setAliasee(Constant *Aliasee) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalAlias::getAliasee, &GlobalAlias::setAliasee>>( + this); + cast(Val)->setAliasee(cast(Aliasee->Val)); +} + +Constant *GlobalAlias::getAliasee() const { + return cast( + Ctx.getOrCreateConstant(cast(Val)->getAliasee())); +} + +const GlobalObject *GlobalAlias::getAliaseeObject() const { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getAliaseeObject())); +} + +void GlobalValue::setUnnamedAddr(UnnamedAddr V) { + Ctx.getTracker() + .emplaceIfTracking>(this); + cast(Val)->setUnnamedAddr(V); +} + +void GlobalValue::setVisibility(VisibilityTypes V) { + Ctx.getTracker() + .emplaceIfTracking>(this); + cast(Val)->setVisibility(V); +} + +NoCFIValue *NoCFIValue::get(GlobalValue *GV) { + auto *LLVMC = llvm::NoCFIValue::get(cast(GV->Val)); + return cast(GV->getContext().getOrCreateConstant(LLVMC)); +} + +GlobalValue *NoCFIValue::getGlobalValue() const { + auto *LLVMC = cast(Val)->getGlobalValue(); + return cast(Ctx.getOrCreateConstant(LLVMC)); +} + +PointerType *NoCFIValue::getType() const { + return cast(Ctx.getType(cast(Val)->getType())); +} + +ConstantPtrAuth *ConstantPtrAuth::get(Constant *Ptr, ConstantInt *Key, + ConstantInt *Disc, Constant *AddrDisc) { + auto *LLVMC = llvm::ConstantPtrAuth::get( + cast(Ptr->Val), cast(Key->Val), + cast(Disc->Val), cast(AddrDisc->Val)); + return cast(Ptr->getContext().getOrCreateConstant(LLVMC)); +} + +Constant *ConstantPtrAuth::getPointer() const { + return Ctx.getOrCreateConstant( + cast(Val)->getPointer()); +} + +ConstantInt *ConstantPtrAuth::getKey() const { + return cast( + Ctx.getOrCreateConstant(cast(Val)->getKey())); +} + +ConstantInt *ConstantPtrAuth::getDiscriminator() const { + return cast(Ctx.getOrCreateConstant( + cast(Val)->getDiscriminator())); +} + +Constant *ConstantPtrAuth::getAddrDiscriminator() const { + return Ctx.getOrCreateConstant( + cast(Val)->getAddrDiscriminator()); +} + +ConstantPtrAuth *ConstantPtrAuth::getWithSameSchema(Constant *Pointer) const { + auto *LLVMC = cast(Val)->getWithSameSchema( + cast(Pointer->Val)); + return cast(Ctx.getOrCreateConstant(LLVMC)); +} + +BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) { + auto *LLVMC = llvm::BlockAddress::get(cast(F->Val), + cast(BB->Val)); + return cast(F->getContext().getOrCreateConstant(LLVMC)); +} + +BlockAddress *BlockAddress::get(BasicBlock *BB) { + auto *LLVMC = llvm::BlockAddress::get(cast(BB->Val)); + return cast(BB->getContext().getOrCreateConstant(LLVMC)); +} + +BlockAddress *BlockAddress::lookup(const BasicBlock *BB) { + auto *LLVMC = llvm::BlockAddress::lookup(cast(BB->Val)); + return cast_or_null(BB->getContext().getValue(LLVMC)); +} + +Function *BlockAddress::getFunction() const { + return cast( + Ctx.getValue(cast(Val)->getFunction())); +} + +BasicBlock *BlockAddress::getBasicBlock() const { + return cast( + Ctx.getValue(cast(Val)->getBasicBlock())); +} + +DSOLocalEquivalent *DSOLocalEquivalent::get(GlobalValue *GV) { + auto *LLVMC = llvm::DSOLocalEquivalent::get(cast(GV->Val)); + return cast(GV->getContext().getValue(LLVMC)); +} + +GlobalValue *DSOLocalEquivalent::getGlobalValue() const { + return cast( + Ctx.getValue(cast(Val)->getGlobalValue())); +} + +FunctionType *Function::getFunctionType() const { + return cast( + Ctx.getType(cast(Val)->getFunctionType())); +} + +#ifndef NDEBUG +void Function::dumpNameAndArgs(raw_ostream &OS) const { + auto *F = cast(Val); + OS << *F->getReturnType() << " @" << F->getName() << "("; + interleave( + F->args(), + [this, &OS](const llvm::Argument &LLVMArg) { + auto *SBArg = cast_or_null(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(Val); + interleave( + *LLVMF, + [this, &OS](const llvm::BasicBlock &LLVMBB) { + auto *BB = cast_or_null(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 12cac66480b0c..42df9df811973 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 Idxs, return Ctx.getOrCreateConstant(cast(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(Ctx.getOrCreateConstant(LLVMC)); -} -ConstantInt *ConstantInt::getFalse(Context &Ctx) { - auto *LLVMC = llvm::ConstantInt::getFalse(Ctx.LLVMCtx); - return cast(Ctx.getOrCreateConstant(LLVMC)); -} -ConstantInt *ConstantInt::getBool(Context &Ctx, bool V) { - auto *LLVMC = llvm::ConstantInt::getBool(Ctx.LLVMCtx, V); - return cast(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(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(Ty->getContext().getOrCreateConstant(LLVMC)); -} -ConstantInt *ConstantInt::getSigned(IntegerType *Ty, int64_t V) { - auto *LLVMC = - llvm::ConstantInt::getSigned(cast(Ty->LLVMTy), V); - return cast(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(Ctx.getOrCreateConstant(LLVMC)); -} -ConstantInt *ConstantInt::get(IntegerType *Ty, StringRef Str, uint8_t Radix) { - auto *LLVMC = - llvm::ConstantInt::get(cast(Ty->LLVMTy), Str, Radix); - return cast(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(Val)->getIntegerType(); - return cast(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(Ctx.getOrCreateConstant(LLVMC)); -} - -Constant *ConstantFP::getNaN(Type *Ty, bool Negative, uint64_t Payload) { - auto *LLVMC = llvm::ConstantFP::getNaN(Ty->LLVMTy, Negative, Payload); - return cast(Ty->getContext().getOrCreateConstant(LLVMC)); -} -Constant *ConstantFP::getQNaN(Type *Ty, bool Negative, APInt *Payload) { - auto *LLVMC = llvm::ConstantFP::getQNaN(Ty->LLVMTy, Negative, Payload); - return cast(Ty->getContext().getOrCreateConstant(LLVMC)); -} -Constant *ConstantFP::getSNaN(Type *Ty, bool Negative, APInt *Payload) { - auto *LLVMC = llvm::ConstantFP::getSNaN(Ty->LLVMTy, Negative, Payload); - return cast(Ty->getContext().getOrCreateConstant(LLVMC)); -} -Constant *ConstantFP::getZero(Type *Ty, bool Negative) { - auto *LLVMC = llvm::ConstantFP::getZero(Ty->LLVMTy, Negative); - return cast(Ty->getContext().getOrCreateConstant(LLVMC)); -} -Constant *ConstantFP::getNegativeZero(Type *Ty) { - auto *LLVMC = llvm::ConstantFP::getNegativeZero(Ty->LLVMTy); - return cast(Ty->getContext().getOrCreateConstant(LLVMC)); -} -Constant *ConstantFP::getInfinity(Type *Ty, bool Negative) { - auto *LLVMC = llvm::ConstantFP::getInfinity(Ty->LLVMTy, Negative); - return cast(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 V) { - auto &Ctx = T->getContext(); - SmallVector LLVMValues; - LLVMValues.reserve(V.size()); - for (auto *Elm : V) - LLVMValues.push_back(cast(Elm->Val)); - auto *LLVMC = - llvm::ConstantArray::get(cast(T->LLVMTy), LLVMValues); - return cast(Ctx.getOrCreateConstant(LLVMC)); -} - -ArrayType *ConstantArray::getType() const { - return cast( - Ctx.getType(cast(Val)->getType())); -} - -Constant *ConstantStruct::get(StructType *T, ArrayRef V) { - auto &Ctx = T->getContext(); - SmallVector LLVMValues; - LLVMValues.reserve(V.size()); - for (auto *Elm : V) - LLVMValues.push_back(cast(Elm->Val)); - auto *LLVMC = - llvm::ConstantStruct::get(cast(T->LLVMTy), LLVMValues); - return cast(Ctx.getOrCreateConstant(LLVMC)); -} - -StructType *ConstantStruct::getTypeForElements(Context &Ctx, - ArrayRef V, - bool Packed) { - unsigned VecSize = V.size(); - SmallVector 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( - Ty->getContext().getOrCreateConstant(LLVMC)); -} - -Constant *ConstantAggregateZero::getSequentialElement() const { - return cast(Ctx.getValue( - cast(Val)->getSequentialElement())); -} -Constant *ConstantAggregateZero::getStructElement(unsigned Elt) const { - return cast(Ctx.getValue( - cast(Val)->getStructElement(Elt))); -} -Constant *ConstantAggregateZero::getElementValue(Constant *C) const { - return cast( - Ctx.getValue(cast(Val)->getElementValue( - cast(C->Val)))); -} -Constant *ConstantAggregateZero::getElementValue(unsigned Idx) const { - return cast(Ctx.getValue( - cast(Val)->getElementValue(Idx))); -} - -ConstantPointerNull *ConstantPointerNull::get(PointerType *Ty) { - auto *LLVMC = - llvm::ConstantPointerNull::get(cast(Ty->LLVMTy)); - return cast(Ty->getContext().getOrCreateConstant(LLVMC)); -} - -PointerType *ConstantPointerNull::getType() const { - return cast( - Ctx.getType(cast(Val)->getType())); -} - -UndefValue *UndefValue::get(Type *T) { - auto *LLVMC = llvm::UndefValue::get(T->LLVMTy); - return cast(T->getContext().getOrCreateConstant(LLVMC)); -} - -UndefValue *UndefValue::getSequentialElement() const { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getSequentialElement())); -} - -UndefValue *UndefValue::getStructElement(unsigned Elt) const { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getStructElement(Elt))); -} - -UndefValue *UndefValue::getElementValue(Constant *C) const { - return cast( - Ctx.getOrCreateConstant(cast(Val)->getElementValue( - cast(C->Val)))); -} - -UndefValue *UndefValue::getElementValue(unsigned Idx) const { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getElementValue(Idx))); -} - -PoisonValue *PoisonValue::get(Type *T) { - auto *LLVMC = llvm::PoisonValue::get(T->LLVMTy); - return cast(T->getContext().getOrCreateConstant(LLVMC)); -} - -PoisonValue *PoisonValue::getSequentialElement() const { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getSequentialElement())); -} - -PoisonValue *PoisonValue::getStructElement(unsigned Elt) const { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getStructElement(Elt))); -} - -PoisonValue *PoisonValue::getElementValue(Constant *C) const { - return cast( - Ctx.getOrCreateConstant(cast(Val)->getElementValue( - cast(C->Val)))); -} - -PoisonValue *PoisonValue::getElementValue(unsigned Idx) const { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getElementValue(Idx))); -} - -void GlobalObject::setAlignment(MaybeAlign Align) { - Ctx.getTracker() - .emplaceIfTracking< - GenericSetter<&GlobalObject::getAlign, &GlobalObject::setAlignment>>( - this); - cast(Val)->setAlignment(Align); -} - -void GlobalObject::setGlobalObjectSubClassData(unsigned V) { - Ctx.getTracker() - .emplaceIfTracking< - GenericSetter<&GlobalObject::getGlobalObjectSubClassData, - &GlobalObject::setGlobalObjectSubClassData>>(this); - cast(Val)->setGlobalObjectSubClassData(V); -} - -void GlobalObject::setSection(StringRef S) { - Ctx.getTracker() - .emplaceIfTracking< - GenericSetter<&GlobalObject::getSection, &GlobalObject::setSection>>( - this); - cast(Val)->setSection(S); -} - -template -GlobalT &GlobalWithNodeAPI:: - LLVMGVToGV::operator()(LLVMGlobalT &LLVMGV) const { - return cast(*Ctx.getValue(&LLVMGV)); -} - -namespace llvm::sandboxir { -// Explicit instantiations. -template class GlobalWithNodeAPI; -template class GlobalWithNodeAPI; -template class GlobalWithNodeAPI; -template class GlobalWithNodeAPI; -} // namespace llvm::sandboxir - -void GlobalIFunc::setResolver(Constant *Resolver) { - Ctx.getTracker() - .emplaceIfTracking< - GenericSetter<&GlobalIFunc::getResolver, &GlobalIFunc::setResolver>>( - this); - cast(Val)->setResolver( - cast(Resolver->Val)); -} - -Constant *GlobalIFunc::getResolver() const { - return Ctx.getOrCreateConstant(cast(Val)->getResolver()); -} - -Function *GlobalIFunc::getResolverFunction() { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getResolverFunction())); -} - -GlobalVariable & -GlobalVariable::LLVMGVToGV::operator()(llvm::GlobalVariable &LLVMGV) const { - return cast(*Ctx.getValue(&LLVMGV)); -} - -Constant *GlobalVariable::getInitializer() const { - return Ctx.getOrCreateConstant( - cast(Val)->getInitializer()); -} - -void GlobalVariable::setInitializer(Constant *InitVal) { - Ctx.getTracker() - .emplaceIfTracking>(this); - cast(Val)->setInitializer( - cast(InitVal->Val)); -} - -void GlobalVariable::setConstant(bool V) { - Ctx.getTracker() - .emplaceIfTracking>(this); - cast(Val)->setConstant(V); -} - -void GlobalVariable::setExternallyInitialized(bool V) { - Ctx.getTracker() - .emplaceIfTracking< - GenericSetter<&GlobalVariable::isExternallyInitialized, - &GlobalVariable::setExternallyInitialized>>(this); - cast(Val)->setExternallyInitialized(V); -} - -void GlobalAlias::setAliasee(Constant *Aliasee) { - Ctx.getTracker() - .emplaceIfTracking< - GenericSetter<&GlobalAlias::getAliasee, &GlobalAlias::setAliasee>>( - this); - cast(Val)->setAliasee(cast(Aliasee->Val)); -} - -Constant *GlobalAlias::getAliasee() const { - return cast( - Ctx.getOrCreateConstant(cast(Val)->getAliasee())); -} - -const GlobalObject *GlobalAlias::getAliaseeObject() const { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getAliaseeObject())); -} - -void GlobalValue::setUnnamedAddr(UnnamedAddr V) { - Ctx.getTracker() - .emplaceIfTracking>(this); - cast(Val)->setUnnamedAddr(V); -} - -void GlobalValue::setVisibility(VisibilityTypes V) { - Ctx.getTracker() - .emplaceIfTracking>(this); - cast(Val)->setVisibility(V); -} - -NoCFIValue *NoCFIValue::get(GlobalValue *GV) { - auto *LLVMC = llvm::NoCFIValue::get(cast(GV->Val)); - return cast(GV->getContext().getOrCreateConstant(LLVMC)); -} - -GlobalValue *NoCFIValue::getGlobalValue() const { - auto *LLVMC = cast(Val)->getGlobalValue(); - return cast(Ctx.getOrCreateConstant(LLVMC)); -} - -PointerType *NoCFIValue::getType() const { - return cast(Ctx.getType(cast(Val)->getType())); -} - -ConstantPtrAuth *ConstantPtrAuth::get(Constant *Ptr, ConstantInt *Key, - ConstantInt *Disc, Constant *AddrDisc) { - auto *LLVMC = llvm::ConstantPtrAuth::get( - cast(Ptr->Val), cast(Key->Val), - cast(Disc->Val), cast(AddrDisc->Val)); - return cast(Ptr->getContext().getOrCreateConstant(LLVMC)); -} - -Constant *ConstantPtrAuth::getPointer() const { - return Ctx.getOrCreateConstant( - cast(Val)->getPointer()); -} - -ConstantInt *ConstantPtrAuth::getKey() const { - return cast( - Ctx.getOrCreateConstant(cast(Val)->getKey())); -} - -ConstantInt *ConstantPtrAuth::getDiscriminator() const { - return cast(Ctx.getOrCreateConstant( - cast(Val)->getDiscriminator())); -} - -Constant *ConstantPtrAuth::getAddrDiscriminator() const { - return Ctx.getOrCreateConstant( - cast(Val)->getAddrDiscriminator()); -} - -ConstantPtrAuth *ConstantPtrAuth::getWithSameSchema(Constant *Pointer) const { - auto *LLVMC = cast(Val)->getWithSameSchema( - cast(Pointer->Val)); - return cast(Ctx.getOrCreateConstant(LLVMC)); -} - -BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) { - auto *LLVMC = llvm::BlockAddress::get(cast(F->Val), - cast(BB->Val)); - return cast(F->getContext().getOrCreateConstant(LLVMC)); -} - -BlockAddress *BlockAddress::get(BasicBlock *BB) { - auto *LLVMC = llvm::BlockAddress::get(cast(BB->Val)); - return cast(BB->getContext().getOrCreateConstant(LLVMC)); -} - -BlockAddress *BlockAddress::lookup(const BasicBlock *BB) { - auto *LLVMC = llvm::BlockAddress::lookup(cast(BB->Val)); - return cast_or_null(BB->getContext().getValue(LLVMC)); -} - -Function *BlockAddress::getFunction() const { - return cast( - Ctx.getValue(cast(Val)->getFunction())); -} - -BasicBlock *BlockAddress::getBasicBlock() const { - return cast( - Ctx.getValue(cast(Val)->getBasicBlock())); -} - -DSOLocalEquivalent *DSOLocalEquivalent::get(GlobalValue *GV) { - auto *LLVMC = llvm::DSOLocalEquivalent::get(cast(GV->Val)); - return cast(GV->getContext().getValue(LLVMC)); -} - -GlobalValue *DSOLocalEquivalent::getGlobalValue() const { - return cast( - Ctx.getValue(cast(Val)->getGlobalValue())); -} - ConstantTokenNone *ConstantTokenNone::get(Context &Ctx) { auto *LLVMC = llvm::ConstantTokenNone::get(Ctx.LLVMCtx); return cast(Ctx.getOrCreateConstant(LLVMC)); } -FunctionType *Function::getFunctionType() const { - return cast( - Ctx.getType(cast(Val)->getFunctionType())); -} - -#ifndef NDEBUG -void Function::dumpNameAndArgs(raw_ostream &OS) const { - auto *F = cast(Val); - OS << *F->getReturnType() << " @" << F->getName() << "("; - interleave( - F->args(), - [this, &OS](const llvm::Argument &LLVMArg) { - auto *SBArg = cast_or_null(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(Val); - interleave( - *LLVMF, - [this, &OS](const llvm::BasicBlock &LLVMBB) { - auto *BB = cast_or_null(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(Ctx->getValue(&*It));