1524 lines
57 KiB
C++
1524 lines
57 KiB
C++
//===- 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/Argument.h"
|
|
#include "llvm/SandboxIR/BasicBlock.h"
|
|
#include "llvm/SandboxIR/Context.h"
|
|
#include "llvm/SandboxIR/Type.h"
|
|
#include "llvm/SandboxIR/User.h"
|
|
#include "llvm/Support/Compiler.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/Values.def"
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
sandboxir::Context &getParent() const { return getContext(); }
|
|
unsigned getUseOperandNo(const Use &Use) const override {
|
|
return getUseOperandNoDefault(Use);
|
|
}
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::Constant>(Val) && "Expected Constant!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override;
|
|
#endif
|
|
};
|
|
|
|
// TODO: This should inherit from ConstantData.
|
|
class ConstantInt : public Constant {
|
|
ConstantInt(llvm::ConstantInt *C, Context &Ctx)
|
|
: Constant(ClassID::ConstantInt, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
|
|
llvm_unreachable("ConstantInt has no operands!");
|
|
}
|
|
|
|
public:
|
|
LLVM_ABI static ConstantInt *getTrue(Context &Ctx);
|
|
LLVM_ABI static ConstantInt *getFalse(Context &Ctx);
|
|
LLVM_ABI static ConstantInt *getBool(Context &Ctx, bool V);
|
|
LLVM_ABI static Constant *getTrue(Type *Ty);
|
|
LLVM_ABI static Constant *getFalse(Type *Ty);
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static Constant *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.
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static ConstantInt *getSigned(IntegerType *Ty, int64_t V);
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static ConstantInt *get(Context &Ctx, const APInt &V);
|
|
|
|
/// Return a ConstantInt constructed from the string strStart with the given
|
|
/// radix.
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static Constant *get(Type *Ty, const APInt &V);
|
|
|
|
/// Return the constant as an APInt value reference. This allows clients to
|
|
/// obtain a full-precision copy of the value.
|
|
/// Return the constant's value.
|
|
inline const APInt &getValue() const {
|
|
return cast<llvm::ConstantInt>(Val)->getValue();
|
|
}
|
|
|
|
/// getBitWidth - Return the scalar bitwidth of this constant.
|
|
unsigned getBitWidth() const {
|
|
return cast<llvm::ConstantInt>(Val)->getBitWidth();
|
|
}
|
|
/// Return the constant as a 64-bit unsigned integer value after it
|
|
/// has been zero extended as appropriate for the type of this constant. Note
|
|
/// that this method can assert if the value does not fit in 64 bits.
|
|
/// Return the zero extended value.
|
|
inline uint64_t getZExtValue() const {
|
|
return cast<llvm::ConstantInt>(Val)->getZExtValue();
|
|
}
|
|
|
|
/// Return the constant as a 64-bit integer value after it has been sign
|
|
/// extended as appropriate for the type of this constant. Note that
|
|
/// this method can assert if the value does not fit in 64 bits.
|
|
/// Return the sign extended value.
|
|
inline int64_t getSExtValue() const {
|
|
return cast<llvm::ConstantInt>(Val)->getSExtValue();
|
|
}
|
|
|
|
/// Return the constant as an llvm::MaybeAlign.
|
|
/// Note that this method can assert if the value does not fit in 64 bits or
|
|
/// is not a power of two.
|
|
inline MaybeAlign getMaybeAlignValue() const {
|
|
return cast<llvm::ConstantInt>(Val)->getMaybeAlignValue();
|
|
}
|
|
|
|
/// Return the constant as an llvm::Align, interpreting `0` as `Align(1)`.
|
|
/// Note that this method can assert if the value does not fit in 64 bits or
|
|
/// is not a power of two.
|
|
inline Align getAlignValue() const {
|
|
return cast<llvm::ConstantInt>(Val)->getAlignValue();
|
|
}
|
|
|
|
/// A helper method that can be used to determine if the constant contained
|
|
/// within is equal to a constant. This only works for very small values,
|
|
/// because this is all that can be represented with all types.
|
|
/// Determine if this constant's value is same as an unsigned char.
|
|
bool equalsInt(uint64_t V) const {
|
|
return cast<llvm::ConstantInt>(Val)->equalsInt(V);
|
|
}
|
|
|
|
/// Variant of the getType() method to always return an IntegerType, which
|
|
/// reduces the amount of casting needed in parts of the compiler.
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static bool isValueValidForType(Type *Ty, uint64_t V);
|
|
LLVM_ABI static bool isValueValidForType(Type *Ty, int64_t V);
|
|
|
|
bool isNegative() const { return cast<llvm::ConstantInt>(Val)->isNegative(); }
|
|
|
|
/// This is just a convenience method to make client code smaller for a
|
|
/// common code. It also correctly performs the comparison without the
|
|
/// potential for an assertion from getZExtValue().
|
|
bool isZero() const { return cast<llvm::ConstantInt>(Val)->isZero(); }
|
|
|
|
/// This is just a convenience method to make client code smaller for a
|
|
/// common case. It also correctly performs the comparison without the
|
|
/// potential for an assertion from getZExtValue().
|
|
/// Determine if the value is one.
|
|
bool isOne() const { return cast<llvm::ConstantInt>(Val)->isOne(); }
|
|
|
|
/// This function will return true iff every bit in this constant is set
|
|
/// to true.
|
|
/// @returns true iff this constant's bits are all set to true.
|
|
/// Determine if the value is all ones.
|
|
bool isMinusOne() const { return cast<llvm::ConstantInt>(Val)->isMinusOne(); }
|
|
|
|
/// This function will return true iff this constant represents the largest
|
|
/// value that may be represented by the constant's type.
|
|
/// @returns true iff this is the largest value that may be represented
|
|
/// by this type.
|
|
/// Determine if the value is maximal.
|
|
bool isMaxValue(bool IsSigned) const {
|
|
return cast<llvm::ConstantInt>(Val)->isMaxValue(IsSigned);
|
|
}
|
|
|
|
/// This function will return true iff this constant represents the smallest
|
|
/// value that may be represented by this constant's type.
|
|
/// @returns true if this is the smallest value that may be represented by
|
|
/// this type.
|
|
/// Determine if the value is minimal.
|
|
bool isMinValue(bool IsSigned) const {
|
|
return cast<llvm::ConstantInt>(Val)->isMinValue(IsSigned);
|
|
}
|
|
|
|
/// This function will return true iff this constant represents a value with
|
|
/// active bits bigger than 64 bits or a value greater than the given uint64_t
|
|
/// value.
|
|
/// @returns true iff this constant is greater or equal to the given number.
|
|
/// Determine if the value is greater or equal to the given number.
|
|
bool uge(uint64_t Num) const {
|
|
return cast<llvm::ConstantInt>(Val)->uge(Num);
|
|
}
|
|
|
|
/// getLimitedValue - If the value is smaller than the specified limit,
|
|
/// return it, otherwise return the limit value. This causes the value
|
|
/// to saturate to the limit.
|
|
/// @returns the min of the value of the constant and the specified value
|
|
/// Get the constant's value with a saturation limit
|
|
uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
|
|
return cast<llvm::ConstantInt>(Val)->getLimitedValue(Limit);
|
|
}
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantInt;
|
|
}
|
|
unsigned getUseOperandNo(const Use &Use) const override {
|
|
llvm_unreachable("ConstantInt has no operands!");
|
|
}
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::ConstantInt>(Val) && "Expected a ConstantInst!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
// TODO: This should inherit from ConstantData.
|
|
class ConstantFP final : public Constant {
|
|
ConstantFP(llvm::ConstantFP *C, Context &Ctx)
|
|
: Constant(ClassID::ConstantFP, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
/// This returns a ConstantFP, or a vector containing a splat of a ConstantFP,
|
|
/// for the specified value in the specified type. This should only be used
|
|
/// for simple constant values like 2.0/1.0 etc, that are known-valid both as
|
|
/// host double and as the target format.
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static Constant *get(Type *Ty, const APFloat &V);
|
|
|
|
LLVM_ABI static Constant *get(Type *Ty, StringRef Str);
|
|
|
|
LLVM_ABI static ConstantFP *get(const APFloat &V, Context &Ctx);
|
|
|
|
LLVM_ABI static Constant *getNaN(Type *Ty, bool Negative = false,
|
|
uint64_t Payload = 0);
|
|
LLVM_ABI static Constant *getQNaN(Type *Ty, bool Negative = false,
|
|
APInt *Payload = nullptr);
|
|
LLVM_ABI static Constant *getSNaN(Type *Ty, bool Negative = false,
|
|
APInt *Payload = nullptr);
|
|
LLVM_ABI static Constant *getZero(Type *Ty, bool Negative = false);
|
|
|
|
LLVM_ABI static Constant *getNegativeZero(Type *Ty);
|
|
LLVM_ABI static Constant *getInfinity(Type *Ty, bool Negative = false);
|
|
|
|
/// Return true if Ty is big enough to represent V.
|
|
LLVM_ABI static bool isValueValidForType(Type *Ty, const APFloat &V);
|
|
|
|
inline const APFloat &getValueAPF() const {
|
|
return cast<llvm::ConstantFP>(Val)->getValueAPF();
|
|
}
|
|
inline const APFloat &getValue() const {
|
|
return cast<llvm::ConstantFP>(Val)->getValue();
|
|
}
|
|
|
|
/// Return true if the value is positive or negative zero.
|
|
bool isZero() const { return cast<llvm::ConstantFP>(Val)->isZero(); }
|
|
|
|
/// Return true if the sign bit is set.
|
|
bool isNegative() const { return cast<llvm::ConstantFP>(Val)->isNegative(); }
|
|
|
|
/// Return true if the value is infinity
|
|
bool isInfinity() const { return cast<llvm::ConstantFP>(Val)->isInfinity(); }
|
|
|
|
/// Return true if the value is a NaN.
|
|
bool isNaN() const { return cast<llvm::ConstantFP>(Val)->isNaN(); }
|
|
|
|
/// We don't rely on operator== working on double values, as it returns true
|
|
/// for things that are clearly not equal, like -0.0 and 0.0.
|
|
/// As such, this method can be used to do an exact bit-for-bit comparison of
|
|
/// two floating point values. The version with a double operand is retained
|
|
/// because it's so convenient to write isExactlyValue(2.0), but please use
|
|
/// it only for simple constants.
|
|
bool isExactlyValue(const APFloat &V) const {
|
|
return cast<llvm::ConstantFP>(Val)->isExactlyValue(V);
|
|
}
|
|
|
|
bool isExactlyValue(double V) const {
|
|
return cast<llvm::ConstantFP>(Val)->isExactlyValue(V);
|
|
}
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantFP;
|
|
}
|
|
|
|
// TODO: Better name: getOperandNo(const Use&). Should be private.
|
|
unsigned getUseOperandNo(const Use &Use) const final {
|
|
llvm_unreachable("ConstantFP has no operands!");
|
|
}
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::ConstantFP>(Val) && "Expected a ConstantFP!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
/// Base class for aggregate constants (with operands).
|
|
class ConstantAggregate : public Constant {
|
|
protected:
|
|
ConstantAggregate(ClassID ID, llvm::Constant *C, Context &Ctx)
|
|
: Constant(ID, C, Ctx) {}
|
|
|
|
public:
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
auto ID = From->getSubclassID();
|
|
return ID == ClassID::ConstantVector || ID == ClassID::ConstantStruct ||
|
|
ID == ClassID::ConstantArray;
|
|
}
|
|
};
|
|
|
|
class ConstantArray final : public ConstantAggregate {
|
|
ConstantArray(llvm::ConstantArray *C, Context &Ctx)
|
|
: ConstantAggregate(ClassID::ConstantArray, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
LLVM_ABI static Constant *get(ArrayType *T, ArrayRef<Constant *> V);
|
|
LLVM_ABI 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:
|
|
LLVM_ABI static Constant *get(StructType *T, ArrayRef<Constant *> V);
|
|
|
|
template <typename... Csts>
|
|
static std::enable_if_t<are_base_of<Constant, Csts...>::value, Constant *>
|
|
get(StructType *T, Csts *...Vs) {
|
|
return get(T, ArrayRef<Constant *>({Vs...}));
|
|
}
|
|
/// Return an anonymous struct that has the specified elements.
|
|
/// If the struct is possibly empty, then you must specify a context.
|
|
static Constant *getAnon(ArrayRef<Constant *> V, bool Packed = false) {
|
|
return get(getTypeForElements(V, Packed), V);
|
|
}
|
|
static Constant *getAnon(Context &Ctx, ArrayRef<Constant *> V,
|
|
bool Packed = false) {
|
|
return get(getTypeForElements(Ctx, V, Packed), V);
|
|
}
|
|
/// This version of the method allows an empty list.
|
|
LLVM_ABI static StructType *
|
|
getTypeForElements(Context &Ctx, ArrayRef<Constant *> V, bool Packed = false);
|
|
/// Return an anonymous struct type to use for a constant with the specified
|
|
/// set of elements. The list must not be empty.
|
|
static StructType *getTypeForElements(ArrayRef<Constant *> V,
|
|
bool Packed = false) {
|
|
assert(!V.empty() &&
|
|
"ConstantStruct::getTypeForElements cannot be called on empty list");
|
|
return getTypeForElements(V[0]->getContext(), V, Packed);
|
|
}
|
|
|
|
/// Specialization - reduce amount of casting.
|
|
inline StructType *getType() const {
|
|
return cast<StructType>(Value::getType());
|
|
}
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantStruct;
|
|
}
|
|
};
|
|
|
|
class ConstantVector final : public ConstantAggregate {
|
|
ConstantVector(llvm::ConstantVector *C, Context &Ctx)
|
|
: ConstantAggregate(ClassID::ConstantVector, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
LLVM_ABI static Constant *get(ArrayRef<Constant *> V);
|
|
/// Return a ConstantVector with the specified constant in each element.
|
|
/// Note that this might not return an instance of ConstantVector
|
|
LLVM_ABI static Constant *getSplat(ElementCount EC, Constant *Elt);
|
|
/// Specialize the getType() method to always return a FixedVectorType,
|
|
/// which reduces the amount of casting needed in parts of the compiler.
|
|
inline FixedVectorType *getType() const {
|
|
return cast<FixedVectorType>(Value::getType());
|
|
}
|
|
/// If all elements of the vector constant have the same value, return that
|
|
/// value. Otherwise, return nullptr. Ignore poison elements by setting
|
|
/// AllowPoison to true.
|
|
LLVM_ABI Constant *getSplatValue(bool AllowPoison = false) const;
|
|
|
|
/// 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:
|
|
LLVM_ABI static ConstantAggregateZero *get(Type *Ty);
|
|
/// If this CAZ has array or vector type, return a zero with the right element
|
|
/// type.
|
|
LLVM_ABI Constant *getSequentialElement() const;
|
|
/// If this CAZ has struct type, return a zero with the right element type for
|
|
/// the specified element.
|
|
LLVM_ABI 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).
|
|
LLVM_ABI Constant *getElementValue(Constant *C) const;
|
|
/// Return a zero of the right value for the specified GEP index.
|
|
LLVM_ABI Constant *getElementValue(unsigned Idx) const;
|
|
/// Return the number of elements in the array, vector, or struct.
|
|
ElementCount getElementCount() const {
|
|
return cast<llvm::ConstantAggregateZero>(Val)->getElementCount();
|
|
}
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantAggregateZero;
|
|
}
|
|
unsigned getUseOperandNo(const Use &Use) const final {
|
|
llvm_unreachable("ConstantAggregateZero has no operands!");
|
|
}
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::ConstantAggregateZero>(Val) && "Expected a CAZ!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
/// ConstantDataSequential - A vector or array constant whose element type is a
|
|
/// simple 1/2/4/8-byte integer or half/bfloat/float/double, and whose elements
|
|
/// are just simple data values (i.e. ConstantInt/ConstantFP). This Constant
|
|
/// node has no operands because it stores all of the elements of the constant
|
|
/// as densely packed data, instead of as Value*'s.
|
|
///
|
|
/// This is the common base class of ConstantDataArray and ConstantDataVector.
|
|
class ConstantDataSequential : public Constant {
|
|
protected:
|
|
ConstantDataSequential(ClassID ID, llvm::ConstantDataSequential *C,
|
|
Context &Ctx)
|
|
: Constant(ID, C, Ctx) {}
|
|
|
|
public:
|
|
/// Return true if a ConstantDataSequential can be formed with a vector or
|
|
/// array of the specified element type.
|
|
/// ConstantDataArray only works with normal float and int types that are
|
|
/// stored densely in memory, not with things like i42 or x86_f80.
|
|
static bool isElementTypeCompatible(Type *Ty) {
|
|
return llvm::ConstantDataSequential::isElementTypeCompatible(Ty->LLVMTy);
|
|
}
|
|
/// If this is a sequential container of integers (of any size), return the
|
|
/// specified element in the low bits of a uint64_t.
|
|
uint64_t getElementAsInteger(unsigned ElmIdx) const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getElementAsInteger(ElmIdx);
|
|
}
|
|
/// If this is a sequential container of integers (of any size), return the
|
|
/// specified element as an APInt.
|
|
APInt getElementAsAPInt(unsigned ElmIdx) const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getElementAsAPInt(ElmIdx);
|
|
}
|
|
/// If this is a sequential container of floating point type, return the
|
|
/// specified element as an APFloat.
|
|
APFloat getElementAsAPFloat(unsigned ElmIdx) const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getElementAsAPFloat(ElmIdx);
|
|
}
|
|
/// If this is an sequential container of floats, return the specified element
|
|
/// as a float.
|
|
float getElementAsFloat(unsigned ElmIdx) const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getElementAsFloat(ElmIdx);
|
|
}
|
|
/// If this is an sequential container of doubles, return the specified
|
|
/// element as a double.
|
|
double getElementAsDouble(unsigned ElmIdx) const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getElementAsDouble(ElmIdx);
|
|
}
|
|
/// Return a Constant for a specified index's element.
|
|
/// Note that this has to compute a new constant to return, so it isn't as
|
|
/// efficient as getElementAsInteger/Float/Double.
|
|
Constant *getElementAsConstant(unsigned ElmIdx) const {
|
|
return Ctx.getOrCreateConstant(
|
|
cast<llvm::ConstantDataSequential>(Val)->getElementAsConstant(ElmIdx));
|
|
}
|
|
/// Return the element type of the array/vector.
|
|
Type *getElementType() const {
|
|
return Ctx.getType(
|
|
cast<llvm::ConstantDataSequential>(Val)->getElementType());
|
|
}
|
|
/// Return the number of elements in the array or vector.
|
|
unsigned getNumElements() const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getNumElements();
|
|
}
|
|
/// Return the size (in bytes) of each element in the array/vector.
|
|
/// The size of the elements is known to be a multiple of one byte.
|
|
uint64_t getElementByteSize() const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getElementByteSize();
|
|
}
|
|
/// This method returns true if this is an array of \p CharSize integers.
|
|
bool isString(unsigned CharSize = 8) const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->isString(CharSize);
|
|
}
|
|
/// This method returns true if the array "isString", ends with a null byte,
|
|
/// and does not contains any other null bytes.
|
|
bool isCString() const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->isCString();
|
|
}
|
|
/// If this array is isString(), then this method returns the array as a
|
|
/// StringRef. Otherwise, it asserts out.
|
|
StringRef getAsString() const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getAsString();
|
|
}
|
|
/// If this array is isCString(), then this method returns the array (without
|
|
/// the trailing null byte) as a StringRef. Otherwise, it asserts out.
|
|
StringRef getAsCString() const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getAsCString();
|
|
}
|
|
/// Return the raw, underlying, bytes of this data. Note that this is an
|
|
/// extremely tricky thing to work with, as it exposes the host endianness of
|
|
/// the data elements.
|
|
StringRef getRawDataValues() const {
|
|
return cast<llvm::ConstantDataSequential>(Val)->getRawDataValues();
|
|
}
|
|
|
|
static bool classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantDataArray ||
|
|
From->getSubclassID() == ClassID::ConstantDataVector;
|
|
}
|
|
};
|
|
|
|
class ConstantDataArray final : public ConstantDataSequential {
|
|
ConstantDataArray(llvm::ConstantDataArray *C, Context &Ctx)
|
|
: ConstantDataSequential(ClassID::ConstantDataArray, C, Ctx) {}
|
|
friend class Context;
|
|
|
|
public:
|
|
static bool classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantDataArray;
|
|
}
|
|
/// get() constructor - Return a constant with array type with an element
|
|
/// count and element type matching the ArrayRef passed in. Note that this
|
|
/// can return a ConstantAggregateZero object.
|
|
template <typename ElementTy>
|
|
static Constant *get(Context &Ctx, ArrayRef<ElementTy> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataArray::get(Ctx.LLVMCtx, Elts);
|
|
return Ctx.getOrCreateConstant(NewLLVMC);
|
|
}
|
|
|
|
/// get() constructor - ArrayTy needs to be compatible with
|
|
/// ArrayRef<ElementTy>.
|
|
template <typename ArrayTy>
|
|
static Constant *get(Context &Ctx, ArrayTy &Elts) {
|
|
return ConstantDataArray::get(Ctx, ArrayRef(Elts));
|
|
}
|
|
|
|
/// getRaw() constructor - Return a constant with array type with an element
|
|
/// count and element type matching the NumElements and ElementTy parameters
|
|
/// passed in. Note that this can return a ConstantAggregateZero object.
|
|
/// ElementTy must be one of i8/i16/i32/i64/half/bfloat/float/double. Data is
|
|
/// the buffer containing the elements. Be careful to make sure Data uses the
|
|
/// right endianness, the buffer will be used as-is.
|
|
static Constant *getRaw(StringRef Data, uint64_t NumElements,
|
|
Type *ElementTy) {
|
|
auto *LLVMC =
|
|
llvm::ConstantDataArray::getRaw(Data, NumElements, ElementTy->LLVMTy);
|
|
return ElementTy->getContext().getOrCreateConstant(LLVMC);
|
|
}
|
|
/// getFP() constructors - Return a constant of array type with a float
|
|
/// element type taken from argument `ElementType', and count taken from
|
|
/// argument `Elts'. The amount of bits of the contained type must match the
|
|
/// number of bits of the type contained in the passed in ArrayRef.
|
|
/// (i.e. half or bfloat for 16bits, float for 32bits, double for 64bits) Note
|
|
/// that this can return a ConstantAggregateZero object.
|
|
static Constant *getFP(Type *ElementType, ArrayRef<uint16_t> Elts) {
|
|
auto *LLVMC = llvm::ConstantDataArray::getFP(ElementType->LLVMTy, Elts);
|
|
return ElementType->getContext().getOrCreateConstant(LLVMC);
|
|
}
|
|
static Constant *getFP(Type *ElementType, ArrayRef<uint32_t> Elts) {
|
|
auto *LLVMC = llvm::ConstantDataArray::getFP(ElementType->LLVMTy, Elts);
|
|
return ElementType->getContext().getOrCreateConstant(LLVMC);
|
|
}
|
|
static Constant *getFP(Type *ElementType, ArrayRef<uint64_t> Elts) {
|
|
auto *LLVMC = llvm::ConstantDataArray::getFP(ElementType->LLVMTy, Elts);
|
|
return ElementType->getContext().getOrCreateConstant(LLVMC);
|
|
}
|
|
/// This method constructs a CDS and initializes it with a text string.
|
|
/// The default behavior (AddNull==true) causes a null terminator to
|
|
/// be placed at the end of the array (increasing the length of the string by
|
|
/// one more than the StringRef would normally indicate. Pass AddNull=false
|
|
/// to disable this behavior.
|
|
static Constant *getString(Context &Ctx, StringRef Initializer,
|
|
bool AddNull = true) {
|
|
auto *LLVMC =
|
|
llvm::ConstantDataArray::getString(Ctx.LLVMCtx, Initializer, AddNull);
|
|
return Ctx.getOrCreateConstant(LLVMC);
|
|
}
|
|
|
|
/// Specialize the getType() method to always return an ArrayType,
|
|
/// which reduces the amount of casting needed in parts of the compiler.
|
|
inline ArrayType *getType() const {
|
|
return cast<ArrayType>(Value::getType());
|
|
}
|
|
};
|
|
|
|
/// A vector constant whose element type is a simple 1/2/4/8-byte integer or
|
|
/// float/double, and whose elements are just simple data values
|
|
/// (i.e. ConstantInt/ConstantFP). This Constant node has no operands because it
|
|
/// stores all of the elements of the constant as densely packed data, instead
|
|
/// of as Value*'s.
|
|
class ConstantDataVector final : public ConstantDataSequential {
|
|
ConstantDataVector(llvm::ConstantDataVector *C, Context &Ctx)
|
|
: ConstantDataSequential(ClassID::ConstantDataVector, C, Ctx) {}
|
|
friend class Context;
|
|
|
|
public:
|
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
static bool classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantDataVector;
|
|
}
|
|
/// get() constructors - Return a constant with vector type with an element
|
|
/// count and element type matching the ArrayRef passed in. Note that this
|
|
/// can return a ConstantAggregateZero object.
|
|
static Constant *get(Context &Ctx, ArrayRef<uint8_t> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::get(Ctx.LLVMCtx, Elts);
|
|
return Ctx.getOrCreateConstant(NewLLVMC);
|
|
}
|
|
static Constant *get(Context &Ctx, ArrayRef<uint16_t> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::get(Ctx.LLVMCtx, Elts);
|
|
return Ctx.getOrCreateConstant(NewLLVMC);
|
|
}
|
|
static Constant *get(Context &Ctx, ArrayRef<uint32_t> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::get(Ctx.LLVMCtx, Elts);
|
|
return Ctx.getOrCreateConstant(NewLLVMC);
|
|
}
|
|
static Constant *get(Context &Ctx, ArrayRef<uint64_t> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::get(Ctx.LLVMCtx, Elts);
|
|
return Ctx.getOrCreateConstant(NewLLVMC);
|
|
}
|
|
static Constant *get(Context &Ctx, ArrayRef<float> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::get(Ctx.LLVMCtx, Elts);
|
|
return Ctx.getOrCreateConstant(NewLLVMC);
|
|
}
|
|
static Constant *get(Context &Ctx, ArrayRef<double> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::get(Ctx.LLVMCtx, Elts);
|
|
return Ctx.getOrCreateConstant(NewLLVMC);
|
|
}
|
|
|
|
/// getRaw() constructor - Return a constant with vector type with an element
|
|
/// count and element type matching the NumElements and ElementTy parameters
|
|
/// passed in. Note that this can return a ConstantAggregateZero object.
|
|
/// ElementTy must be one of i8/i16/i32/i64/half/bfloat/float/double. Data is
|
|
/// the buffer containing the elements. Be careful to make sure Data uses the
|
|
/// right endianness, the buffer will be used as-is.
|
|
static Constant *getRaw(StringRef Data, uint64_t NumElements,
|
|
Type *ElementTy) {
|
|
auto *NewLLVMC =
|
|
llvm::ConstantDataVector::getRaw(Data, NumElements, ElementTy->LLVMTy);
|
|
return ElementTy->getContext().getOrCreateConstant(NewLLVMC);
|
|
}
|
|
/// getFP() constructors - Return a constant of vector type with a float
|
|
/// element type taken from argument `ElementType', and count taken from
|
|
/// argument `Elts'. The amount of bits of the contained type must match the
|
|
/// number of bits of the type contained in the passed in ArrayRef.
|
|
/// (i.e. half or bfloat for 16bits, float for 32bits, double for 64bits) Note
|
|
/// that this can return a ConstantAggregateZero object.
|
|
static Constant *getFP(Type *ElementType, ArrayRef<uint16_t> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::getFP(ElementType->LLVMTy, Elts);
|
|
return ElementType->getContext().getOrCreateConstant(NewLLVMC);
|
|
}
|
|
static Constant *getFP(Type *ElementType, ArrayRef<uint32_t> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::getFP(ElementType->LLVMTy, Elts);
|
|
return ElementType->getContext().getOrCreateConstant(NewLLVMC);
|
|
}
|
|
static Constant *getFP(Type *ElementType, ArrayRef<uint64_t> Elts) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::getFP(ElementType->LLVMTy, Elts);
|
|
return ElementType->getContext().getOrCreateConstant(NewLLVMC);
|
|
}
|
|
|
|
/// Return a ConstantVector with the specified constant in each element.
|
|
/// The specified constant has to be a of a compatible type (i8/i16/
|
|
/// i32/i64/half/bfloat/float/double) and must be a ConstantFP or ConstantInt.
|
|
static Constant *getSplat(unsigned NumElts, Constant *Elt) {
|
|
auto *NewLLVMC = llvm::ConstantDataVector::getSplat(
|
|
NumElts, cast<llvm::Constant>(Elt->Val));
|
|
return Elt->getContext().getOrCreateConstant(NewLLVMC);
|
|
}
|
|
|
|
/// Returns true if this is a splat constant, meaning that all elements have
|
|
/// the same value.
|
|
bool isSplat() const {
|
|
return cast<llvm::ConstantDataVector>(Val)->isSplat();
|
|
}
|
|
|
|
/// If this is a splat constant, meaning that all of the elements have the
|
|
/// same value, return that value. Otherwise return NULL.
|
|
Constant *getSplatValue() const {
|
|
return Ctx.getOrCreateConstant(
|
|
cast<llvm::ConstantDataVector>(Val)->getSplatValue());
|
|
}
|
|
|
|
/// Specialize the getType() method to always return a FixedVectorType,
|
|
/// which reduces the amount of casting needed in parts of the compiler.
|
|
inline FixedVectorType *getType() const {
|
|
return cast<FixedVectorType>(Value::getType());
|
|
}
|
|
};
|
|
|
|
// 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:
|
|
LLVM_ABI static ConstantPointerNull *get(PointerType *Ty);
|
|
|
|
LLVM_ABI Type *getType() const;
|
|
LLVM_ABI PointerType *getPointerType() const;
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantPointerNull;
|
|
}
|
|
unsigned getUseOperandNo(const Use &Use) const final {
|
|
llvm_unreachable("ConstantPointerNull has no operands!");
|
|
}
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::ConstantPointerNull>(Val) && "Expected a CPNull!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
// TODO: Inherit from ConstantData.
|
|
class UndefValue : public Constant {
|
|
protected:
|
|
UndefValue(llvm::UndefValue *C, Context &Ctx)
|
|
: Constant(ClassID::UndefValue, C, Ctx) {}
|
|
UndefValue(ClassID ID, llvm::Constant *C, Context &Ctx)
|
|
: Constant(ID, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
/// Static factory methods - Return an 'undef' object of the specified type.
|
|
LLVM_ABI static UndefValue *get(Type *T);
|
|
|
|
/// If this Undef has array or vector type, return a undef with the right
|
|
/// element type.
|
|
LLVM_ABI UndefValue *getSequentialElement() const;
|
|
|
|
/// If this undef has struct type, return a undef with the right element type
|
|
/// for the specified element.
|
|
LLVM_ABI 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).
|
|
LLVM_ABI UndefValue *getElementValue(Constant *C) const;
|
|
|
|
/// Return an undef of the right value for the specified GEP index.
|
|
LLVM_ABI UndefValue *getElementValue(unsigned Idx) const;
|
|
|
|
/// Return the number of elements in the array, vector, or struct.
|
|
unsigned getNumElements() const {
|
|
return cast<llvm::UndefValue>(Val)->getNumElements();
|
|
}
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::UndefValue ||
|
|
From->getSubclassID() == ClassID::PoisonValue;
|
|
}
|
|
unsigned getUseOperandNo(const Use &Use) const final {
|
|
llvm_unreachable("UndefValue has no operands!");
|
|
}
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::UndefValue>(Val) && "Expected an UndefValue!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
class PoisonValue final : public UndefValue {
|
|
PoisonValue(llvm::PoisonValue *C, Context &Ctx)
|
|
: UndefValue(ClassID::PoisonValue, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
/// Static factory methods - Return an 'poison' object of the specified type.
|
|
LLVM_ABI static PoisonValue *get(Type *T);
|
|
|
|
/// If this poison has array or vector type, return a poison with the right
|
|
/// element type.
|
|
LLVM_ABI PoisonValue *getSequentialElement() const;
|
|
|
|
/// If this poison has struct type, return a poison with the right element
|
|
/// type for the specified element.
|
|
LLVM_ABI 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).
|
|
LLVM_ABI PoisonValue *getElementValue(Constant *C) const;
|
|
|
|
/// Return an poison of the right value for the specified GEP index.
|
|
LLVM_ABI PoisonValue *getElementValue(unsigned Idx) const;
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::PoisonValue;
|
|
}
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::PoisonValue>(Val) && "Expected a PoisonValue!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
class GlobalValue : public Constant {
|
|
protected:
|
|
GlobalValue(ClassID ID, llvm::GlobalValue *C, Context &Ctx)
|
|
: Constant(ID, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
using LinkageTypes = llvm::GlobalValue::LinkageTypes;
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
switch (From->getSubclassID()) {
|
|
case ClassID::Function:
|
|
case ClassID::GlobalVariable:
|
|
case ClassID::GlobalAlias:
|
|
case ClassID::GlobalIFunc:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
unsigned getAddressSpace() const {
|
|
return cast<llvm::GlobalValue>(Val)->getAddressSpace();
|
|
}
|
|
bool hasGlobalUnnamedAddr() const {
|
|
return cast<llvm::GlobalValue>(Val)->hasGlobalUnnamedAddr();
|
|
}
|
|
|
|
/// Returns true if this value's address is not significant in this module.
|
|
/// This attribute is intended to be used only by the code generator and LTO
|
|
/// to allow the linker to decide whether the global needs to be in the symbol
|
|
/// table. It should probably not be used in optimizations, as the value may
|
|
/// have uses outside the module; use hasGlobalUnnamedAddr() instead.
|
|
bool hasAtLeastLocalUnnamedAddr() const {
|
|
return cast<llvm::GlobalValue>(Val)->hasAtLeastLocalUnnamedAddr();
|
|
}
|
|
|
|
using UnnamedAddr = llvm::GlobalValue::UnnamedAddr;
|
|
|
|
UnnamedAddr getUnnamedAddr() const {
|
|
return cast<llvm::GlobalValue>(Val)->getUnnamedAddr();
|
|
}
|
|
LLVM_ABI void setUnnamedAddr(UnnamedAddr V);
|
|
|
|
static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) {
|
|
return llvm::GlobalValue::getMinUnnamedAddr(A, B);
|
|
}
|
|
|
|
bool hasComdat() const { return cast<llvm::GlobalValue>(Val)->hasComdat(); }
|
|
|
|
// TODO: We need a SandboxIR Comdat if we want to implement getComdat().
|
|
using VisibilityTypes = llvm::GlobalValue::VisibilityTypes;
|
|
VisibilityTypes getVisibility() const {
|
|
return cast<llvm::GlobalValue>(Val)->getVisibility();
|
|
}
|
|
bool hasDefaultVisibility() const {
|
|
return cast<llvm::GlobalValue>(Val)->hasDefaultVisibility();
|
|
}
|
|
bool hasHiddenVisibility() const {
|
|
return cast<llvm::GlobalValue>(Val)->hasHiddenVisibility();
|
|
}
|
|
bool hasProtectedVisibility() const {
|
|
return cast<llvm::GlobalValue>(Val)->hasProtectedVisibility();
|
|
}
|
|
LLVM_ABI 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;
|
|
}
|
|
}
|
|
|
|
/// Check if this global has a custom object file section.
|
|
///
|
|
/// This is more efficient than calling getSection() and checking for an empty
|
|
/// string.
|
|
bool hasSection() const {
|
|
return cast<llvm::GlobalObject>(Val)->hasSection();
|
|
}
|
|
|
|
/// Get the custom section of this global if it has one.
|
|
///
|
|
/// If this global does not have a custom section, this will be empty and the
|
|
/// default object file section (.text, .data, etc) will be used.
|
|
StringRef getSection() const {
|
|
return cast<llvm::GlobalObject>(Val)->getSection();
|
|
}
|
|
|
|
/// Change the section for this global.
|
|
///
|
|
/// Setting the section to the empty string tells LLVM to choose an
|
|
/// appropriate default object file section.
|
|
LLVM_ABI void setSection(StringRef S);
|
|
|
|
bool hasComdat() const { return cast<llvm::GlobalObject>(Val)->hasComdat(); }
|
|
|
|
// TODO: implement get/setComdat(), etc. once we have a sandboxir::Comdat.
|
|
|
|
// TODO: We currently don't support Metadata in sandboxir so all
|
|
// Metadata-related functions are missing.
|
|
|
|
using VCallVisibility = llvm::GlobalObject::VCallVisibility;
|
|
|
|
VCallVisibility getVCallVisibility() const {
|
|
return cast<llvm::GlobalObject>(Val)->getVCallVisibility();
|
|
}
|
|
|
|
/// Returns true if the alignment of the value can be unilaterally
|
|
/// increased.
|
|
///
|
|
/// Note that for functions this is the alignment of the code, not the
|
|
/// alignment of a function pointer.
|
|
bool canIncreaseAlignment() const {
|
|
return cast<llvm::GlobalObject>(Val)->canIncreaseAlignment();
|
|
}
|
|
};
|
|
|
|
/// Provides API functions, like getIterator() and getReverseIterator() to
|
|
/// GlobalIFunc, Function, GlobalVariable and GlobalAlias. In LLVM IR these are
|
|
/// provided by ilist_node.
|
|
template <typename GlobalT, typename LLVMGlobalT, typename ParentT,
|
|
typename LLVMParentT>
|
|
class GlobalWithNodeAPI : public ParentT {
|
|
/// Helper for mapped_iterator.
|
|
struct LLVMGVToGV {
|
|
Context &Ctx;
|
|
LLVMGVToGV(Context &Ctx) : Ctx(Ctx) {}
|
|
LLVM_ABI GlobalT &operator()(LLVMGlobalT &LLVMGV) const;
|
|
};
|
|
|
|
public:
|
|
GlobalWithNodeAPI(Value::ClassID ID, LLVMParentT *C, Context &Ctx)
|
|
: ParentT(ID, C, Ctx) {}
|
|
|
|
Module *getParent() const {
|
|
llvm::Module *LLVMM = cast<LLVMGlobalT>(this->Val)->getParent();
|
|
return this->Ctx.getModule(LLVMM);
|
|
}
|
|
|
|
using iterator = mapped_iterator<
|
|
decltype(static_cast<LLVMGlobalT *>(nullptr)->getIterator()), LLVMGVToGV>;
|
|
using reverse_iterator = mapped_iterator<
|
|
decltype(static_cast<LLVMGlobalT *>(nullptr)->getReverseIterator()),
|
|
LLVMGVToGV>;
|
|
iterator getIterator() const {
|
|
auto *LLVMGV = cast<LLVMGlobalT>(this->Val);
|
|
LLVMGVToGV ToGV(this->Ctx);
|
|
return map_iterator(LLVMGV->getIterator(), ToGV);
|
|
}
|
|
reverse_iterator getReverseIterator() const {
|
|
auto *LLVMGV = cast<LLVMGlobalT>(this->Val);
|
|
LLVMGVToGV ToGV(this->Ctx);
|
|
return map_iterator(LLVMGV->getReverseIterator(), ToGV);
|
|
}
|
|
};
|
|
|
|
// Explicit instantiations.
|
|
extern template class LLVM_TEMPLATE_ABI GlobalWithNodeAPI<
|
|
GlobalIFunc, llvm::GlobalIFunc, GlobalObject, llvm::GlobalObject>;
|
|
extern template class LLVM_TEMPLATE_ABI GlobalWithNodeAPI<
|
|
Function, llvm::Function, GlobalObject, llvm::GlobalObject>;
|
|
extern template class LLVM_TEMPLATE_ABI GlobalWithNodeAPI<
|
|
GlobalVariable, llvm::GlobalVariable, GlobalObject, llvm::GlobalObject>;
|
|
extern template class LLVM_TEMPLATE_ABI GlobalWithNodeAPI<
|
|
GlobalAlias, llvm::GlobalAlias, GlobalValue, llvm::GlobalValue>;
|
|
|
|
class GlobalIFunc final
|
|
: public GlobalWithNodeAPI<GlobalIFunc, llvm::GlobalIFunc, GlobalObject,
|
|
llvm::GlobalObject> {
|
|
GlobalIFunc(llvm::GlobalObject *C, Context &Ctx)
|
|
: GlobalWithNodeAPI(ClassID::GlobalIFunc, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::GlobalIFunc;
|
|
}
|
|
|
|
// TODO: Missing create() because we don't have a sandboxir::Module yet.
|
|
|
|
// TODO: Missing functions: copyAttributesFrom(), removeFromParent(),
|
|
// eraseFromParent()
|
|
|
|
LLVM_ABI void setResolver(Constant *Resolver);
|
|
|
|
LLVM_ABI Constant *getResolver() const;
|
|
|
|
// Return the resolver function after peeling off potential ConstantExpr
|
|
// indirection.
|
|
LLVM_ABI Function *getResolverFunction();
|
|
const Function *getResolverFunction() const {
|
|
return const_cast<GlobalIFunc *>(this)->getResolverFunction();
|
|
}
|
|
|
|
static bool isValidLinkage(LinkageTypes L) {
|
|
return llvm::GlobalIFunc::isValidLinkage(L);
|
|
}
|
|
|
|
// TODO: Missing applyAlongResolverPath().
|
|
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::GlobalIFunc>(Val) && "Expected a GlobalIFunc!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
class GlobalVariable final
|
|
: public GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
|
|
GlobalObject, llvm::GlobalObject> {
|
|
GlobalVariable(llvm::GlobalObject *C, Context &Ctx)
|
|
: GlobalWithNodeAPI(ClassID::GlobalVariable, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
/// Helper for mapped_iterator.
|
|
struct LLVMGVToGV {
|
|
Context &Ctx;
|
|
LLVMGVToGV(Context &Ctx) : Ctx(Ctx) {}
|
|
LLVM_ABI GlobalVariable &operator()(llvm::GlobalVariable &LLVMGV) const;
|
|
};
|
|
|
|
public:
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::GlobalVariable;
|
|
}
|
|
|
|
/// Definitions have initializers, declarations don't.
|
|
///
|
|
inline bool hasInitializer() const {
|
|
return cast<llvm::GlobalVariable>(Val)->hasInitializer();
|
|
}
|
|
|
|
/// hasDefinitiveInitializer - Whether the global variable has an initializer,
|
|
/// and any other instances of the global (this can happen due to weak
|
|
/// linkage) are guaranteed to have the same initializer.
|
|
///
|
|
/// Note that if you want to transform a global, you must use
|
|
/// hasUniqueInitializer() instead, because of the *_odr linkage type.
|
|
///
|
|
/// Example:
|
|
///
|
|
/// @a = global SomeType* null - Initializer is both definitive and unique.
|
|
///
|
|
/// @b = global weak SomeType* null - Initializer is neither definitive nor
|
|
/// unique.
|
|
///
|
|
/// @c = global weak_odr SomeType* null - Initializer is definitive, but not
|
|
/// unique.
|
|
inline bool hasDefinitiveInitializer() const {
|
|
return cast<llvm::GlobalVariable>(Val)->hasDefinitiveInitializer();
|
|
}
|
|
|
|
/// hasUniqueInitializer - Whether the global variable has an initializer, and
|
|
/// any changes made to the initializer will turn up in the final executable.
|
|
inline bool hasUniqueInitializer() const {
|
|
return cast<llvm::GlobalVariable>(Val)->hasUniqueInitializer();
|
|
}
|
|
|
|
/// getInitializer - Return the initializer for this global variable. It is
|
|
/// illegal to call this method if the global is external, because we cannot
|
|
/// tell what the value is initialized to!
|
|
///
|
|
LLVM_ABI 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().
|
|
LLVM_ABI void setInitializer(Constant *InitVal);
|
|
|
|
// TODO: Add missing replaceInitializer(). Requires special tracker
|
|
|
|
/// If the value is a global constant, its value is immutable throughout the
|
|
/// runtime execution of the program. Assigning a value into the constant
|
|
/// leads to undefined behavior.
|
|
///
|
|
bool isConstant() const {
|
|
return cast<llvm::GlobalVariable>(Val)->isConstant();
|
|
}
|
|
LLVM_ABI void setConstant(bool V);
|
|
|
|
bool isExternallyInitialized() const {
|
|
return cast<llvm::GlobalVariable>(Val)->isExternallyInitialized();
|
|
}
|
|
LLVM_ABI void setExternallyInitialized(bool Val);
|
|
|
|
// TODO: Missing copyAttributesFrom()
|
|
|
|
// TODO: Missing removeFromParent(), eraseFromParent(), dropAllReferences()
|
|
|
|
// TODO: Missing addDebugInfo(), getDebugInfo()
|
|
|
|
// TODO: Missing attribute setter functions: addAttribute(), setAttributes().
|
|
// There seems to be no removeAttribute() so we can't undo them.
|
|
|
|
/// Return true if the attribute exists.
|
|
bool hasAttribute(Attribute::AttrKind Kind) const {
|
|
return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
|
|
}
|
|
|
|
/// Return true if the attribute exists.
|
|
bool hasAttribute(StringRef Kind) const {
|
|
return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
|
|
}
|
|
|
|
/// Return true if any attributes exist.
|
|
bool hasAttributes() const {
|
|
return cast<llvm::GlobalVariable>(Val)->hasAttributes();
|
|
}
|
|
|
|
/// Return the attribute object.
|
|
Attribute getAttribute(Attribute::AttrKind Kind) const {
|
|
return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
|
|
}
|
|
|
|
/// Return the attribute object.
|
|
Attribute getAttribute(StringRef Kind) const {
|
|
return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
|
|
}
|
|
|
|
/// Return the attribute set for this global
|
|
AttributeSet getAttributes() const {
|
|
return cast<llvm::GlobalVariable>(Val)->getAttributes();
|
|
}
|
|
|
|
/// Return attribute set as list with index.
|
|
/// FIXME: This may not be required once ValueEnumerators
|
|
/// in bitcode-writer can enumerate attribute-set.
|
|
AttributeList getAttributesAsList(unsigned Index) const {
|
|
return cast<llvm::GlobalVariable>(Val)->getAttributesAsList(Index);
|
|
}
|
|
|
|
/// Check if section name is present
|
|
bool hasImplicitSection() const {
|
|
return cast<llvm::GlobalVariable>(Val)->hasImplicitSection();
|
|
}
|
|
|
|
/// Get the custom code model raw value of this global.
|
|
///
|
|
unsigned getCodeModelRaw() const {
|
|
return cast<llvm::GlobalVariable>(Val)->getCodeModelRaw();
|
|
}
|
|
|
|
/// Get the custom code model of this global if it has one.
|
|
///
|
|
/// If this global does not have a custom code model, the empty instance
|
|
/// will be returned.
|
|
std::optional<CodeModel::Model> getCodeModel() const {
|
|
return cast<llvm::GlobalVariable>(Val)->getCodeModel();
|
|
}
|
|
|
|
/// Returns the alignment of the given variable.
|
|
MaybeAlign getAlign() const {
|
|
return cast<llvm::GlobalVariable>(Val)->getAlign();
|
|
}
|
|
|
|
// TODO: Add missing: setAligment(Align)
|
|
|
|
/// Sets the alignment attribute of the GlobalVariable.
|
|
/// This method will be deprecated as the alignment property should always be
|
|
/// defined.
|
|
LLVM_ABI void setAlignment(MaybeAlign Align);
|
|
|
|
// TODO: Missing setCodeModel(). Requires custom tracker.
|
|
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::GlobalVariable>(Val) && "Expected a GlobalVariable!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
class GlobalAlias final
|
|
: public GlobalWithNodeAPI<GlobalAlias, llvm::GlobalAlias, GlobalValue,
|
|
llvm::GlobalValue> {
|
|
GlobalAlias(llvm::GlobalAlias *C, Context &Ctx)
|
|
: GlobalWithNodeAPI(ClassID::GlobalAlias, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::GlobalAlias;
|
|
}
|
|
|
|
// TODO: Missing create() due to unimplemented sandboxir::Module.
|
|
|
|
// TODO: Missing copyAttributresFrom().
|
|
// TODO: Missing removeFromParent(), eraseFromParent().
|
|
|
|
LLVM_ABI void setAliasee(Constant *Aliasee);
|
|
LLVM_ABI Constant *getAliasee() const;
|
|
|
|
LLVM_ABI const GlobalObject *getAliaseeObject() const;
|
|
GlobalObject *getAliaseeObject() {
|
|
return const_cast<GlobalObject *>(
|
|
static_cast<const GlobalAlias *>(this)->getAliaseeObject());
|
|
}
|
|
|
|
static bool isValidLinkage(LinkageTypes L) {
|
|
return llvm::GlobalAlias::isValidLinkage(L);
|
|
}
|
|
};
|
|
|
|
class NoCFIValue final : public Constant {
|
|
NoCFIValue(llvm::NoCFIValue *C, Context &Ctx)
|
|
: Constant(ClassID::NoCFIValue, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
|
|
return getOperandUseDefault(OpIdx, Verify);
|
|
}
|
|
|
|
public:
|
|
/// Return a NoCFIValue for the specified function.
|
|
LLVM_ABI static NoCFIValue *get(GlobalValue *GV);
|
|
|
|
LLVM_ABI GlobalValue *getGlobalValue() const;
|
|
|
|
/// NoCFIValue is always a pointer.
|
|
LLVM_ABI PointerType *getType() const;
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::NoCFIValue;
|
|
}
|
|
|
|
unsigned getUseOperandNo(const Use &Use) const final {
|
|
return getUseOperandNoDefault(Use);
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::NoCFIValue>(Val) && "Expected a NoCFIValue!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
class ConstantPtrAuth final : public Constant {
|
|
ConstantPtrAuth(llvm::ConstantPtrAuth *C, Context &Ctx)
|
|
: Constant(ClassID::ConstantPtrAuth, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
/// Return a pointer signed with the specified parameters.
|
|
LLVM_ABI static ConstantPtrAuth *get(Constant *Ptr, ConstantInt *Key,
|
|
ConstantInt *Disc, Constant *AddrDisc,
|
|
Constant *DeactivationSymbol);
|
|
/// The pointer that is signed in this ptrauth signed pointer.
|
|
LLVM_ABI Constant *getPointer() const;
|
|
|
|
/// The Key ID, an i32 constant.
|
|
LLVM_ABI ConstantInt *getKey() const;
|
|
|
|
/// The integer discriminator, an i64 constant, or 0.
|
|
LLVM_ABI 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.
|
|
LLVM_ABI Constant *getAddrDiscriminator() const;
|
|
|
|
LLVM_ABI Constant *getDeactivationSymbol() const;
|
|
|
|
/// Whether there is any non-null address discriminator.
|
|
bool hasAddressDiscriminator() const {
|
|
return cast<llvm::ConstantPtrAuth>(Val)->hasAddressDiscriminator();
|
|
}
|
|
|
|
/// Whether the address uses a special address discriminator.
|
|
/// These discriminators can't be used in real pointer-auth values; they
|
|
/// can only be used in "prototype" values that indicate how some real
|
|
/// schema is supposed to be produced.
|
|
bool hasSpecialAddressDiscriminator(uint64_t Value) const {
|
|
return cast<llvm::ConstantPtrAuth>(Val)->hasSpecialAddressDiscriminator(
|
|
Value);
|
|
}
|
|
|
|
/// Check whether an authentication operation with key \p Key and (possibly
|
|
/// blended) discriminator \p Discriminator is known to be compatible with
|
|
/// this ptrauth signed pointer.
|
|
bool isKnownCompatibleWith(const Value *Key, const Value *Discriminator,
|
|
const DataLayout &DL) const {
|
|
return cast<llvm::ConstantPtrAuth>(Val)->isKnownCompatibleWith(
|
|
Key->Val, Discriminator->Val, DL);
|
|
}
|
|
|
|
/// Produce a new ptrauth expression signing the given value using
|
|
/// the same schema as is stored in one.
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static BlockAddress *get(Function *F, BasicBlock *BB);
|
|
|
|
/// Return a BlockAddress for the specified basic block. The basic
|
|
/// block must be embedded into a function.
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static BlockAddress *lookup(const BasicBlock *BB);
|
|
|
|
LLVM_ABI Function *getFunction() const;
|
|
LLVM_ABI 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.
|
|
LLVM_ABI static DSOLocalEquivalent *get(GlobalValue *GV);
|
|
|
|
LLVM_ABI GlobalValue *getGlobalValue() const;
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::DSOLocalEquivalent;
|
|
}
|
|
|
|
unsigned getUseOperandNo(const Use &Use) const final {
|
|
llvm_unreachable("DSOLocalEquivalent has no operands!");
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::DSOLocalEquivalent>(Val) &&
|
|
"Expected a DSOLocalEquivalent!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
// TODO: This should inherit from ConstantData.
|
|
class ConstantTokenNone final : public Constant {
|
|
ConstantTokenNone(llvm::ConstantTokenNone *C, Context &Ctx)
|
|
: Constant(ClassID::ConstantTokenNone, C, Ctx) {}
|
|
friend class Context; // For constructor.
|
|
|
|
public:
|
|
/// Return the ConstantTokenNone.
|
|
LLVM_ABI static ConstantTokenNone *get(Context &Ctx);
|
|
|
|
/// For isa/dyn_cast.
|
|
static bool classof(const sandboxir::Value *From) {
|
|
return From->getSubclassID() == ClassID::ConstantTokenNone;
|
|
}
|
|
|
|
unsigned getUseOperandNo(const Use &Use) const final {
|
|
llvm_unreachable("ConstantTokenNone has no operands!");
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void verify() const override {
|
|
assert(isa<llvm::ConstantTokenNone>(Val) &&
|
|
"Expected a ConstantTokenNone!");
|
|
}
|
|
void dumpOS(raw_ostream &OS) const override {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
} // namespace llvm::sandboxir
|
|
|
|
#endif // LLVM_SANDBOXIR_CONSTANT_H
|