[Reland][IR] Add initial support for the byte type (#186888)
This patch relands https://github.com/llvm/llvm-project/pull/178666. The original version caused CI failures due to the missing target triple in `llvm/test/CodeGen/X86/byte-constants.ll`. CI should be green now.
This commit is contained in:
parent
1c4e03cf78
commit
57568c288d
@ -95,6 +95,19 @@ For example, when working with boolean values, store them by zero-extending
|
||||
If you do use loads/stores on non-byte-sized types, make sure that you *always*
|
||||
use those types. For example, do not first store ``i8`` and then load ``i1``.
|
||||
|
||||
Use byte types when manipulating raw memory
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The byte type represents raw memory values in SSA registers. Loads and stores of
|
||||
byte types should be used when performing raw memory copies (such as ``memmove``
|
||||
and ``memcpy``). Using integer types to represent raw memory introduces type
|
||||
punning, which discards the provenance of pointers being copied.
|
||||
|
||||
Use a byte type if a value may hold either a pointer or any other type at run
|
||||
time (and you don't know which one), or if the value may contain uninitialized
|
||||
data. For instance, if a union may hold a pointer or another type, use byte
|
||||
types to load and store the value. Otherwise, use the specific type.
|
||||
|
||||
Prefer zext over sext when legal
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@ -787,8 +787,8 @@ be performed as loads and stores of the correct type since stores of other
|
||||
types may not propagate the external data.
|
||||
Therefore it is not legal to convert an existing load/store (or a
|
||||
``llvm.memcpy`` / ``llvm.memmove`` intrinsic) of pointer types with external
|
||||
state to a load/store of an integer type with the same bitwidth, as that may drop
|
||||
the external state.
|
||||
state to a load/store of an integer or byte type with the same bitwidth, as that
|
||||
may drop the external state.
|
||||
|
||||
|
||||
.. _globalvars:
|
||||
@ -4471,6 +4471,53 @@ Examples:
|
||||
| ``i1942652`` | a really big integer of over 1 million bits. |
|
||||
+----------------+------------------------------------------------+
|
||||
|
||||
.. _t_byte:
|
||||
|
||||
Byte Type
|
||||
"""""""""
|
||||
|
||||
:Overview:
|
||||
|
||||
The byte type represents raw memory data in SSA registers. It should be used
|
||||
when it cannot be determined whether a value holds a pointer or another type at
|
||||
run time, or if the value contains uninitialized or poison data. Frontends are
|
||||
expected to use a byte type when:
|
||||
|
||||
#. Lowering memory operations like `memcpy` and `memmove` to load/store pairs
|
||||
without knowing the underlying type being copied.
|
||||
|
||||
#. Working with union types that can hold a pointer alongside a non-pointer
|
||||
type.
|
||||
|
||||
#. Working with possibly uninitialized data.
|
||||
|
||||
Otherwise, when known, the specific type should be used. Each bit can be:
|
||||
|
||||
* An integer bit (0 or 1)
|
||||
* Part of a pointer value
|
||||
* ``poison``
|
||||
|
||||
Any bit width from 1 bit to 2\ :sup:`23`\ (about 8 million) can be specified.
|
||||
|
||||
:Syntax:
|
||||
|
||||
::
|
||||
|
||||
bN
|
||||
|
||||
The number of bits the byte occupies is specified by the ``N`` value.
|
||||
|
||||
Examples:
|
||||
*********
|
||||
|
||||
+----------------+------------------------------------------------+
|
||||
| ``b1`` | a single-bit byte value. |
|
||||
+----------------+------------------------------------------------+
|
||||
| ``b32`` | a 32-bit byte value. |
|
||||
+----------------+------------------------------------------------+
|
||||
| ``b128`` | a 128-bit byte value. |
|
||||
+----------------+------------------------------------------------+
|
||||
|
||||
.. _t_floating:
|
||||
|
||||
Floating-Point Types
|
||||
@ -4904,6 +4951,10 @@ Simple Constants
|
||||
Note that hexadecimal integers are sign extended from the number
|
||||
of active bits, i.e., the bit width minus the number of leading
|
||||
zeros. So '``s0x0001``' of type '``i16``' will be -1, not 1.
|
||||
**Byte constants**
|
||||
Byte constants are used to initialize global variables of the :ref:`byte
|
||||
<t_byte>` type. These are strictly equivalent to integer constants:
|
||||
``store b8 42, ptr %p`` is equivalent to ``store i8 42, ptr %p``.
|
||||
**Floating-point constants**
|
||||
Floating-point constants use standard decimal notation (e.g.
|
||||
123.421), exponential notation (e.g., 1.23421e+2), or a more precise
|
||||
@ -11774,6 +11825,8 @@ If the value being loaded is of aggregate type, the bytes that correspond to
|
||||
padding may be accessed but are ignored, because it is impossible to observe
|
||||
padding from the loaded aggregate value.
|
||||
If ``<pointer>`` is not a well-defined value, the behavior is undefined.
|
||||
The behavior of loading a value of a type that differs from the type used to
|
||||
store it is described in the :ref:`bitcast <i_bitcast>` section.
|
||||
|
||||
Examples:
|
||||
"""""""""
|
||||
@ -13032,10 +13085,10 @@ The '``bitcast``' instruction takes a value to cast, which must be a
|
||||
non-aggregate first class value, and a type to cast it to, which must
|
||||
also be a non-aggregate :ref:`first class <t_firstclass>` type. The
|
||||
bit sizes of ``value`` and the destination type, ``ty2``, must be
|
||||
identical. If the source type is a pointer, the destination type must
|
||||
also be a pointer of the same size. This instruction supports bitwise
|
||||
conversion of vectors to integers and to vectors of other types (as
|
||||
long as they have the same size).
|
||||
identical. If the source type is a pointer, the destination type must also be a
|
||||
pointer or a byte (vector of bytes) of the same size. This instruction supports
|
||||
bitwise conversion of vectors to integers and to vectors of other types (as long
|
||||
as they have the same size).
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
@ -13045,15 +13098,44 @@ is always a *no-op cast* because no bits change with this
|
||||
conversion. The conversion is done as if the ``value`` had been stored
|
||||
to memory and read back as type ``ty2``. Pointer (or vector of
|
||||
pointers) types may only be converted to other pointer (or vector of
|
||||
pointers) types with the same address space through this instruction.
|
||||
To convert pointers to other types, use the :ref:`inttoptr <i_inttoptr>`
|
||||
or :ref:`ptrtoint <i_ptrtoint>` instructions first.
|
||||
pointers) types with the same address space or byte (or vector of bytes) types
|
||||
through this instruction. To convert pointers to other types, use the
|
||||
:ref:`inttoptr <i_inttoptr>` or :ref:`ptrtoint <i_ptrtoint>` instructions first.
|
||||
|
||||
There is a caveat for bitcasts involving vector types in relation to
|
||||
endianness. For example ``bitcast <2 x i8> <value> to i16`` puts element zero
|
||||
of the vector in the least significant bits of the i16 for little-endian while
|
||||
element zero ends up in the most significant bits for big-endian.
|
||||
|
||||
If ``value`` is of the :ref:`byte type <t_byte>`:
|
||||
|
||||
* If ``ty2`` is a scalar type:
|
||||
|
||||
* If ``ty2`` is a byte type, the original bits are unchanged.
|
||||
|
||||
* If ``ty2`` is a pointer type:
|
||||
|
||||
* If at least one bit of ``value`` is ``poison``, the result is
|
||||
``poison``.
|
||||
|
||||
* If all bits of ``value`` are from the same pointer and are correctly
|
||||
ordered (there were no pointer bit swaps), the result is that pointer.
|
||||
|
||||
* Otherwise, the result is a pointer with the address given by the
|
||||
integer value of the input, and without provenance.
|
||||
|
||||
* If ``ty2`` is an integer or floating-point type:
|
||||
|
||||
* If at least one bit of ``value`` is ``poison``, the result is
|
||||
``poison``.
|
||||
|
||||
* Otherwise, the result is the value encoded by the input bits with
|
||||
their provenance stripped without being exposed.
|
||||
|
||||
* If ``ty2`` is a vector type, the input bits get sliced into chunks
|
||||
corresponding to lanes of the output. Each lane is then converted using the
|
||||
rules for scalar types above.
|
||||
|
||||
Example:
|
||||
""""""""
|
||||
|
||||
@ -13064,6 +13146,17 @@ Example:
|
||||
%Z = bitcast <2 x i32> %V to i64; ; yields i64: %V (depends on endianness)
|
||||
%Z = bitcast <2 x i32*> %V to <2 x i64*> ; yields <2 x i64*>
|
||||
|
||||
; considering %bi to hold an integer and %bp to hold a pointer,
|
||||
%a = bitcast b64 %bi to i64 ; returns an integer, no-op cast
|
||||
%b = bitcast b64 %bp to i64 ; reinterprets the pointer as an integer, returning its address without exposing provenance
|
||||
%c = bitcast b64 %bp to ptr ; returns a pointer, no-op cast
|
||||
%d = bitcast b64 %bi to ptr ; reinterprets the integer as a pointer, returning a pointer with no provenance
|
||||
|
||||
%e = bitcast <2 x b32> %v to i64 ; reinterprets the raw bytes as an integer
|
||||
%f = bitcast <2 x b32> %v to ptr ; reinterprets the raw bytes as a pointer
|
||||
|
||||
%g = bitcast <2 x b32> %v to <4 x i16> ; reinterprets the raw bytes as integers
|
||||
|
||||
.. _i_addrspacecast:
|
||||
|
||||
'``addrspacecast .. to``' Instruction
|
||||
@ -13495,6 +13588,7 @@ instructions may yield different values.
|
||||
While ``undef`` and ``poison`` pointers can be frozen, the result is a
|
||||
non-dereferenceable pointer. See the
|
||||
:ref:`Pointer Aliasing Rules <pointeraliasing>` section for more information.
|
||||
Values of the :ref:`byte type <t_byte>` are frozen on a per-bit basis.
|
||||
If an aggregate value or vector is frozen, the operand is frozen element-wise.
|
||||
The padding of an aggregate isn't considered, since it isn't visible
|
||||
without storing it into memory and loading it with a different type.
|
||||
@ -13523,6 +13617,9 @@ Example:
|
||||
%d = extractelement <2 x i32> %v.fr, i32 0 ; not undef
|
||||
%add.f = add i32 %d, %d ; even number
|
||||
|
||||
%l = load b32, ptr %p ; may be uninitialized
|
||||
%f = freeze b32 %l ; freezes on a per-bit basis
|
||||
|
||||
; branching on frozen value
|
||||
%poison = add nsw i1 %k, undef ; poison
|
||||
%c = freeze i1 %poison
|
||||
|
||||
@ -171,6 +171,7 @@ typedef enum {
|
||||
LLVMBFloatTypeKind = 18, /**< 16 bit brain floating point type */
|
||||
LLVMX86_AMXTypeKind = 19, /**< X86 AMX */
|
||||
LLVMTargetExtTypeKind = 20, /**< Target extension type */
|
||||
LLVMByteTypeKind = 21, /**< Arbitrary bit width bytes */
|
||||
} LLVMTypeKind;
|
||||
|
||||
typedef enum {
|
||||
@ -280,6 +281,7 @@ typedef enum {
|
||||
LLVMConstantDataArrayValueKind,
|
||||
LLVMConstantDataVectorValueKind,
|
||||
LLVMConstantIntValueKind,
|
||||
LLVMConstantByteValueKind,
|
||||
LLVMConstantFPValueKind,
|
||||
LLVMConstantPointerNullValueKind,
|
||||
LLVMConstantTokenNoneValueKind,
|
||||
@ -1347,6 +1349,7 @@ LLVM_C_ABI void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm);
|
||||
*
|
||||
* types:
|
||||
* integer type
|
||||
* byte type
|
||||
* real type
|
||||
* function type
|
||||
* sequence types:
|
||||
@ -1398,6 +1401,25 @@ LLVM_C_ABI void LLVMDumpType(LLVMTypeRef Val);
|
||||
*/
|
||||
LLVM_C_ABI char *LLVMPrintTypeToString(LLVMTypeRef Val);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCCoreTypeByte Byte Types
|
||||
*
|
||||
* Functions in this section operate on byte types.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtain a byte type from a context with specified bit width.
|
||||
*/
|
||||
LLVM_C_ABI LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C,
|
||||
unsigned NumBits);
|
||||
LLVM_C_ABI unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy);
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCCoreTypeInt Integer Types
|
||||
*
|
||||
@ -2014,6 +2036,7 @@ LLVM_C_ABI unsigned LLVMGetTargetExtTypeIntParam(LLVMTypeRef TargetExtTy,
|
||||
macro(ConstantExpr) \
|
||||
macro(ConstantFP) \
|
||||
macro(ConstantInt) \
|
||||
macro(ConstantByte) \
|
||||
macro(ConstantPointerNull) \
|
||||
macro(ConstantStruct) \
|
||||
macro(ConstantTokenNone) \
|
||||
@ -2427,6 +2450,36 @@ LLVM_C_ABI LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy,
|
||||
unsigned SLen,
|
||||
uint8_t Radix);
|
||||
|
||||
/**
|
||||
* Obtain a constant value for a byte type.
|
||||
*
|
||||
* The returned value corresponds to a llvm::ConstantByte.
|
||||
*
|
||||
* @see llvm::ConstantByte::get()
|
||||
*
|
||||
* @param ByteTy Byte type to obtain value of.
|
||||
* @param N The value the returned instance should refer to.
|
||||
*/
|
||||
LLVM_C_ABI LLVMValueRef LLVMConstByte(LLVMTypeRef ByteTy, unsigned long long N);
|
||||
|
||||
/**
|
||||
* Obtain a constant value for a byte of arbitrary precision.
|
||||
*
|
||||
* @see llvm::ConstantByte::get()
|
||||
*/
|
||||
LLVM_C_ABI LLVMValueRef LLVMConstByteOfArbitraryPrecision(
|
||||
LLVMTypeRef ByteTy, unsigned NumWords, const uint64_t Words[]);
|
||||
|
||||
/**
|
||||
* Obtain a constant value for a byte parsed from a string with specified
|
||||
* length.
|
||||
* @see llvm::ConstantByte::get()
|
||||
*/
|
||||
LLVM_C_ABI LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy,
|
||||
const char *Text,
|
||||
size_t SLen,
|
||||
uint8_t Radix);
|
||||
|
||||
/**
|
||||
* Obtain a constant value referring to a double floating point value.
|
||||
*/
|
||||
@ -2471,6 +2524,21 @@ LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal);
|
||||
*/
|
||||
LLVM_C_ABI long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal);
|
||||
|
||||
/**
|
||||
* Obtain the zero extended value for a byte constant value.
|
||||
*
|
||||
* @see llvm::ConstantByte::getZExtValue()
|
||||
*/
|
||||
LLVM_C_ABI unsigned long long
|
||||
LLVMConstByteGetZExtValue(LLVMValueRef ConstantVal);
|
||||
|
||||
/**
|
||||
* Obtain the sign extended value for a byte constant value.
|
||||
*
|
||||
* @see llvm::ConstantByte::getSExtValue()
|
||||
*/
|
||||
LLVM_C_ABI long long LLVMConstByteGetSExtValue(LLVMValueRef ConstantVal);
|
||||
|
||||
/**
|
||||
* Obtain the double value for an floating point constant value.
|
||||
* losesInfo indicates if some precision was lost in the conversion.
|
||||
|
||||
@ -292,6 +292,7 @@ public:
|
||||
VectorTy,
|
||||
TokenTy,
|
||||
IntegerTy,
|
||||
ByteTy,
|
||||
FunctionTy,
|
||||
PointerTy,
|
||||
StructTy,
|
||||
@ -465,9 +466,9 @@ private:
|
||||
|
||||
/// String mappings for CanonicalTypeID values
|
||||
static constexpr StringLiteral CanonicalTypeNames[] = {
|
||||
"FloatTy", "VoidTy", "LabelTy", "MetadataTy",
|
||||
"VectorTy", "TokenTy", "IntegerTy", "FunctionTy",
|
||||
"PointerTy", "StructTy", "ArrayTy", "UnknownTy"};
|
||||
"FloatTy", "VoidTy", "LabelTy", "MetadataTy", "VectorTy",
|
||||
"TokenTy", "IntegerTy", "ByteTy", "FunctionTy", "PointerTy",
|
||||
"StructTy", "ArrayTy", "UnknownTy"};
|
||||
static_assert(std::size(CanonicalTypeNames) ==
|
||||
static_cast<unsigned>(CanonicalTypeID::MaxCanonicalType),
|
||||
"CanonicalTypeNames array size must match MaxCanonicalType");
|
||||
@ -495,6 +496,7 @@ private:
|
||||
CanonicalTypeID::VectorTy, // X86_AMXTyID
|
||||
CanonicalTypeID::TokenTy, // TokenTyID
|
||||
CanonicalTypeID::IntegerTy, // IntegerTyID
|
||||
CanonicalTypeID::ByteTy, // ByteTyID
|
||||
CanonicalTypeID::FunctionTy, // FunctionTyID
|
||||
CanonicalTypeID::PointerTy, // PointerTyID
|
||||
CanonicalTypeID::StructTy, // StructTyID
|
||||
|
||||
@ -177,6 +177,8 @@ enum TypeCodes {
|
||||
TYPE_CODE_OPAQUE_POINTER = 25, // OPAQUE_POINTER: [addrspace]
|
||||
|
||||
TYPE_CODE_TARGET_TYPE = 26, // TARGET_TYPE
|
||||
|
||||
TYPE_CODE_BYTE = 27, // BYTE: [width]
|
||||
};
|
||||
|
||||
enum OperandBundleTagCode {
|
||||
@ -440,6 +442,8 @@ enum ConstantsCodes {
|
||||
CST_CODE_PTRAUTH = 33, // [ptr, key, disc, addrdisc]
|
||||
CST_CODE_PTRAUTH2 = 34, // [ptr, key, disc, addrdisc,
|
||||
// deactivation_symbol]
|
||||
CST_CODE_BYTE = 35, // BYTE: [intval]
|
||||
CST_CODE_WIDE_BYTE = 36, // WIDE_BYTE: [n x intval]
|
||||
};
|
||||
|
||||
/// CastOpcodes - These are values used in the bitcode files to encode which
|
||||
|
||||
@ -276,6 +276,144 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// Class for constant bytes.
|
||||
class ConstantByte final : public ConstantData {
|
||||
friend class Constant;
|
||||
friend class ConstantVector;
|
||||
|
||||
APInt Val;
|
||||
|
||||
ConstantByte(Type *Ty, const APInt &V);
|
||||
|
||||
void destroyConstantImpl();
|
||||
|
||||
/// Return a ConstantByte with the specified value and an implied Type. The
|
||||
/// type is the vector type whose byte element type corresponds to the bit
|
||||
/// width of the value.
|
||||
static ConstantByte *get(LLVMContext &Context, ElementCount EC,
|
||||
const APInt &V);
|
||||
|
||||
public:
|
||||
ConstantByte(const ConstantByte &) = delete;
|
||||
|
||||
/// If Ty is a vector type, return a Constant with a splat of the given
|
||||
/// value. Otherwise return a ConstantByte for the given value.
|
||||
/// \param ImplicitTrunc Whether to allow implicit truncation of the value.
|
||||
LLVM_ABI static Constant *get(Type *Ty, uint64_t V, bool isSigned = false,
|
||||
bool ImplicitTrunc = false);
|
||||
|
||||
/// Return a ConstantByte with the specified byte 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 byte and sign-extended to fit
|
||||
/// the type.
|
||||
/// \param ImplicitTrunc Whether to allow implicit truncation of the value.
|
||||
LLVM_ABI static ConstantByte *get(ByteType *Ty, uint64_t V,
|
||||
bool isSigned = false,
|
||||
bool ImplicitTrunc = false);
|
||||
|
||||
/// Return a ConstantByte with the specified value for the specified type. The
|
||||
/// value V will be canonicalized to an unsigned APInt. Accessing it with
|
||||
/// either getSExtValue() or getZExtValue() will yield a correctly sized and
|
||||
/// signed value for the type Ty.
|
||||
/// Get a ConstantByte for a specific signed value.
|
||||
/// \param ImplicitTrunc Whether to allow implicit truncation of the value.
|
||||
static ConstantByte *getSigned(ByteType *Ty, int64_t V,
|
||||
bool ImplicitTrunc = false) {
|
||||
return get(Ty, V, /*IsSigned=*/true, ImplicitTrunc);
|
||||
}
|
||||
static Constant *getSigned(Type *Ty, int64_t V, bool ImplicitTrunc = false) {
|
||||
return get(Ty, V, /*IsSigned=*/true, ImplicitTrunc);
|
||||
}
|
||||
|
||||
/// Return a ConstantByte with the specified value and an implied Type. The
|
||||
/// type is the byte type that corresponds to the bit width of the value.
|
||||
LLVM_ABI static ConstantByte *get(LLVMContext &Context, const APInt &V);
|
||||
|
||||
/// Return a ConstantByte constructed from the string strStart with the given
|
||||
/// radix.
|
||||
LLVM_ABI static ConstantByte *get(ByteType *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 ConstantByte 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 Val; }
|
||||
|
||||
/// getBitWidth - Return the scalar bitwidth of this constant.
|
||||
unsigned getBitWidth() const { return Val.getBitWidth(); }
|
||||
|
||||
/// Return the constant as a 64-bit byte 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 Val.getZExtValue(); }
|
||||
|
||||
/// Return the constant as a 64-bit byte 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 Val.getSExtValue(); }
|
||||
|
||||
/// Variant of the getType() method to always return a ByteType, which
|
||||
/// reduces the amount of casting needed in parts of the compiler.
|
||||
inline ByteType *getByteType() const {
|
||||
return cast<ByteType>(Value::getType());
|
||||
}
|
||||
|
||||
bool isNegative() const { return 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 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 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 Val.isAllOnes(); }
|
||||
|
||||
/// 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 {
|
||||
if (IsSigned)
|
||||
return Val.isMaxSignedValue();
|
||||
else
|
||||
return Val.isMaxValue();
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
if (IsSigned)
|
||||
return Val.isMinSignedValue();
|
||||
else
|
||||
return Val.isMinValue();
|
||||
}
|
||||
|
||||
/// Methods to support type inquiry through isa, cast, and dyn_cast.
|
||||
static bool classof(const Value *V) {
|
||||
return V->getValueID() == ConstantByteVal;
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// ConstantFP - Floating Point Values [float, double]
|
||||
///
|
||||
@ -588,10 +726,10 @@ public:
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// 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.
|
||||
/// simple 1/2/4/8-byte integer/byte or half/bfloat/float/double, and whose
|
||||
/// elements are just simple data values (i.e. ConstantInt/ConstantByte/
|
||||
/// 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.
|
||||
///
|
||||
@ -661,7 +799,8 @@ public:
|
||||
/// The size of the elements is known to be a multiple of one byte.
|
||||
LLVM_ABI uint64_t getElementByteSize() const;
|
||||
|
||||
/// This method returns true if this is an array of \p CharSize integers.
|
||||
/// This method returns true if this is an array of \p CharSize integers or
|
||||
/// bytes.
|
||||
LLVM_ABI bool isString(unsigned CharSize = 8) const;
|
||||
|
||||
/// This method returns true if the array "isString", ends with a null byte,
|
||||
@ -699,8 +838,8 @@ private:
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// An array constant whose element type is a simple 1/2/4/8-byte integer or
|
||||
/// float/double, and whose elements are just simple data values
|
||||
/// An array constant whose element type is a simple 1/2/4/8-byte integer, bytes
|
||||
/// 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.
|
||||
@ -733,9 +872,9 @@ public:
|
||||
/// 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.
|
||||
/// ElementTy must be one of i8/i16/i32/i64/b8/b16/b32/b64/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) {
|
||||
Type *Ty = ArrayType::get(ElementTy, NumElements);
|
||||
@ -752,13 +891,25 @@ public:
|
||||
LLVM_ABI static Constant *getFP(Type *ElementType, ArrayRef<uint32_t> Elts);
|
||||
LLVM_ABI static Constant *getFP(Type *ElementType, ArrayRef<uint64_t> Elts);
|
||||
|
||||
/// getByte() constructors - Return a constant of array type with a byte
|
||||
/// 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.
|
||||
/// Note that this can return a ConstantAggregateZero object.
|
||||
LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint8_t> Elts);
|
||||
LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint16_t> Elts);
|
||||
LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint32_t> Elts);
|
||||
LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint64_t> Elts);
|
||||
|
||||
/// 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.
|
||||
LLVM_ABI static Constant *
|
||||
getString(LLVMContext &Context, StringRef Initializer, bool AddNull = true);
|
||||
LLVM_ABI static Constant *getString(LLVMContext &Context,
|
||||
StringRef Initializer,
|
||||
bool AddNull = true,
|
||||
bool ByteString = false);
|
||||
|
||||
/// Specialize the getType() method to always return an ArrayType,
|
||||
/// which reduces the amount of casting needed in parts of the compiler.
|
||||
@ -805,15 +956,24 @@ public:
|
||||
/// 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.
|
||||
/// ElementTy must be one of i8/i16/i32/i64/b8/b16/b32/b64/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) {
|
||||
Type *Ty = VectorType::get(ElementTy, ElementCount::getFixed(NumElements));
|
||||
return getImpl(Data, Ty);
|
||||
}
|
||||
|
||||
/// getByte() constructors - Return a constant of vector type with a byte
|
||||
/// 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.
|
||||
LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint8_t> Elts);
|
||||
LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint16_t> Elts);
|
||||
LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint32_t> Elts);
|
||||
LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint64_t> Elts);
|
||||
|
||||
/// 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
|
||||
@ -826,7 +986,8 @@ public:
|
||||
|
||||
/// 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.
|
||||
/// i32/i64/b8/b16/b32/b64/half/bfloat/float/double) and must be a ConstantFP,
|
||||
/// ConstantByte or ConstantInt.
|
||||
LLVM_ABI static Constant *getSplat(unsigned NumElts, Constant *Elt);
|
||||
|
||||
/// Returns true if this is a splat constant, meaning that all elements have
|
||||
|
||||
@ -641,6 +641,11 @@ public:
|
||||
/// This is always at least as good as the ABI alignment.
|
||||
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const;
|
||||
|
||||
/// Returns a byte type with the same size of a pointer in the given address
|
||||
/// space.
|
||||
LLVM_ABI ByteType *getBytePtrType(LLVMContext &C,
|
||||
unsigned AddressSpace = 0) const;
|
||||
|
||||
/// Returns an integer type with size at least as big as that of a
|
||||
/// pointer in the given address space.
|
||||
LLVM_ABI IntegerType *getIntPtrType(LLVMContext &C,
|
||||
@ -650,6 +655,10 @@ public:
|
||||
/// big as that of a pointer of the given pointer (vector of pointer) type.
|
||||
LLVM_ABI Type *getIntPtrType(Type *) const;
|
||||
|
||||
/// Returns a byte (vector of byte) type with the same size of a pointer of
|
||||
/// the given pointer (vector of pointer) type.
|
||||
LLVM_ABI Type *getBytePtrType(Type *) const;
|
||||
|
||||
/// Returns the smallest integer type with size at least as big as
|
||||
/// Width bits.
|
||||
LLVM_ABI Type *getSmallestLegalIntType(LLVMContext &C,
|
||||
@ -788,6 +797,8 @@ inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const {
|
||||
case Type::StructTyID:
|
||||
// Get the layout annotation... which is lazily created on demand.
|
||||
return getStructLayout(cast<StructType>(Ty))->getSizeInBits();
|
||||
case Type::ByteTyID:
|
||||
return TypeSize::getFixed(Ty->getByteBitWidth());
|
||||
case Type::IntegerTyID:
|
||||
return TypeSize::getFixed(Ty->getIntegerBitWidth());
|
||||
case Type::HalfTyID:
|
||||
|
||||
@ -100,6 +100,50 @@ unsigned Type::getIntegerBitWidth() const {
|
||||
return cast<IntegerType>(this)->getBitWidth();
|
||||
}
|
||||
|
||||
/// Class to represent byte types.
|
||||
class ByteType : public Type {
|
||||
friend class LLVMContextImpl;
|
||||
|
||||
protected:
|
||||
explicit ByteType(LLVMContext &C, unsigned NumBits) : Type(C, ByteTyID) {
|
||||
setSubclassData(NumBits);
|
||||
}
|
||||
|
||||
public:
|
||||
/// This enum is just used to hold constants we need for ByteType.
|
||||
enum {
|
||||
MIN_BYTE_BITS = 1, ///< Minimum number of bits that can be specified
|
||||
MAX_BYTE_BITS =
|
||||
(1 << 23) ///< Maximum number of bits that can be specified
|
||||
///< Note that bit width is stored in the Type classes
|
||||
///< SubclassData field which has 24 bits. SelectionDAG type
|
||||
///< legalization can require a power of 2 ByteType, so limit
|
||||
///< to the largest representable power of 2, 8388608.
|
||||
};
|
||||
|
||||
/// This static method is the primary way of constructing a ByteType.
|
||||
/// If a ByteType with the same NumBits value was previously instantiated,
|
||||
/// that instance will be returned. Otherwise a new one will be created. Only
|
||||
/// one instance with a given NumBits value is ever created.
|
||||
/// Get or create a ByteType instance.
|
||||
LLVM_ABI static ByteType *get(LLVMContext &C, unsigned NumBits);
|
||||
|
||||
/// Get the number of bits in this ByteType
|
||||
unsigned getBitWidth() const { return getSubclassData(); }
|
||||
|
||||
/// For example, this is 0xFF for an 8 bit byte, 0xFFFF for b16, etc.
|
||||
/// @returns a bit mask with ones set for all the bits of this type.
|
||||
/// Get a bit mask for this type.
|
||||
LLVM_ABI APInt getMask() const;
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast.
|
||||
static bool classof(const Type *T) { return T->getTypeID() == ByteTyID; }
|
||||
};
|
||||
|
||||
unsigned Type::getByteBitWidth() const {
|
||||
return cast<ByteType>(this)->getBitWidth();
|
||||
}
|
||||
|
||||
/// Class to represent function types
|
||||
///
|
||||
class FunctionType : public Type {
|
||||
|
||||
@ -542,6 +542,24 @@ public:
|
||||
// Type creation methods
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// Fetch the type representing an 8-bit byte.
|
||||
ByteType *getByte8Ty() { return Type::getByte8Ty(Context); }
|
||||
|
||||
/// Fetch the type representing a 16-bit byte.
|
||||
ByteType *getByte16Ty() { return Type::getByte16Ty(Context); }
|
||||
|
||||
/// Fetch the type representing a 32-bit byte.
|
||||
ByteType *getByte32Ty() { return Type::getByte32Ty(Context); }
|
||||
|
||||
/// Fetch the type representing a 64-bit byte.
|
||||
ByteType *getByte64Ty() { return Type::getByte64Ty(Context); }
|
||||
|
||||
/// Fetch the type representing a 128-bit byte.
|
||||
ByteType *getByte128Ty() { return Type::getByte128Ty(Context); }
|
||||
|
||||
/// Fetch the type representing an N-bit byte.
|
||||
ByteType *getByteNTy(unsigned N) { return Type::getByteNTy(Context, N); }
|
||||
|
||||
/// Fetch the type representing a single bit
|
||||
IntegerType *getInt1Ty() {
|
||||
return Type::getInt1Ty(Context);
|
||||
@ -605,6 +623,12 @@ public:
|
||||
return PointerType::get(Context, AddrSpace);
|
||||
}
|
||||
|
||||
/// Fetch the type of a byte with size at least as big as that of a
|
||||
/// pointer in the given address space.
|
||||
ByteType *getBytePtrTy(const DataLayout &DL, unsigned AddrSpace = 0) {
|
||||
return DL.getBytePtrType(Context, AddrSpace);
|
||||
}
|
||||
|
||||
/// Fetch the type of an integer with size at least as big as that of a
|
||||
/// pointer in the given address space.
|
||||
IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) {
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ByteType;
|
||||
class IntegerType;
|
||||
struct fltSemantics;
|
||||
class LLVMContext;
|
||||
@ -68,6 +69,7 @@ public:
|
||||
|
||||
// Derived types... see DerivedTypes.h file.
|
||||
IntegerTyID, ///< Arbitrary bit width integers
|
||||
ByteTyID, ///< Arbitrary bit width bytes
|
||||
FunctionTyID, ///< Functions
|
||||
PointerTyID, ///< Pointers
|
||||
StructTyID, ///< Structures
|
||||
@ -236,6 +238,21 @@ public:
|
||||
/// Returns true if this is 'token' or a token-like target type.s
|
||||
LLVM_ABI bool isTokenLikeTy() const;
|
||||
|
||||
/// True if this is an instance of ByteType.
|
||||
bool isByteTy() const { return getTypeID() == ByteTyID; }
|
||||
|
||||
/// Return true if this is a ByteType of the given width.
|
||||
LLVM_ABI bool isByteTy(unsigned BitWidth) const;
|
||||
|
||||
/// Return true if this is a byte type or a vector of byte types.
|
||||
bool isByteOrByteVectorTy() const { return getScalarType()->isByteTy(); }
|
||||
|
||||
/// Return true if this is a byte type or a vector of byte types of
|
||||
/// the given width.
|
||||
bool isByteOrByteVectorTy(unsigned BitWidth) const {
|
||||
return getScalarType()->isByteTy(BitWidth);
|
||||
}
|
||||
|
||||
/// True if this is an instance of IntegerType.
|
||||
bool isIntegerTy() const { return getTypeID() == IntegerTyID; }
|
||||
|
||||
@ -295,7 +312,7 @@ public:
|
||||
/// includes all first-class types except struct and array types.
|
||||
bool isSingleValueType() const {
|
||||
return isFloatingPointTy() || isIntegerTy() || isPointerTy() ||
|
||||
isVectorTy() || isX86_AMXTy() || isTargetExtTy();
|
||||
isVectorTy() || isX86_AMXTy() || isTargetExtTy() || isByteTy();
|
||||
}
|
||||
|
||||
/// Return true if the type is an aggregate type. This means it is valid as
|
||||
@ -311,7 +328,8 @@ public:
|
||||
bool isSized(SmallPtrSetImpl<Type*> *Visited = nullptr) const {
|
||||
// If it's a primitive, it is always sized.
|
||||
if (getTypeID() == IntegerTyID || isFloatingPointTy() ||
|
||||
getTypeID() == PointerTyID || getTypeID() == X86_AMXTyID)
|
||||
getTypeID() == PointerTyID || getTypeID() == X86_AMXTyID ||
|
||||
getTypeID() == ByteTyID)
|
||||
return true;
|
||||
// If it is not something that can have a size (e.g. a function or label),
|
||||
// it doesn't have a size.
|
||||
@ -394,6 +412,7 @@ public:
|
||||
// methods should not be added here.
|
||||
|
||||
LLVM_ABI inline unsigned getIntegerBitWidth() const;
|
||||
LLVM_ABI inline unsigned getByteBitWidth() const;
|
||||
|
||||
LLVM_ABI inline Type *getFunctionParamType(unsigned i) const;
|
||||
LLVM_ABI inline unsigned getFunctionNumParams() const;
|
||||
@ -451,6 +470,13 @@ public:
|
||||
LLVM_ABI static Type *getPPC_FP128Ty(LLVMContext &C);
|
||||
LLVM_ABI static Type *getX86_AMXTy(LLVMContext &C);
|
||||
LLVM_ABI static Type *getTokenTy(LLVMContext &C);
|
||||
LLVM_ABI static ByteType *getByteNTy(LLVMContext &C, unsigned N);
|
||||
LLVM_ABI static ByteType *getByte1Ty(LLVMContext &C);
|
||||
LLVM_ABI static ByteType *getByte8Ty(LLVMContext &C);
|
||||
LLVM_ABI static ByteType *getByte16Ty(LLVMContext &C);
|
||||
LLVM_ABI static ByteType *getByte32Ty(LLVMContext &C);
|
||||
LLVM_ABI static ByteType *getByte64Ty(LLVMContext &C);
|
||||
LLVM_ABI static ByteType *getByte128Ty(LLVMContext &C);
|
||||
LLVM_ABI static IntegerType *getIntNTy(LLVMContext &C, unsigned N);
|
||||
LLVM_ABI static IntegerType *getInt1Ty(LLVMContext &C);
|
||||
LLVM_ABI static IntegerType *getInt8Ty(LLVMContext &C);
|
||||
@ -475,6 +501,17 @@ public:
|
||||
LLVM_ABI static Type *getFloatingPointTy(LLVMContext &C,
|
||||
const fltSemantics &S);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Convenience methods for getting byte/integer types.
|
||||
//
|
||||
/// Returns an integer (vector of integer) type with the same size of a byte
|
||||
/// of the given byte (vector of byte) type.
|
||||
LLVM_ABI static Type *getIntFromByteType(Type *);
|
||||
|
||||
/// Returns a byte (vector of byte) type with the same size of an integer of
|
||||
/// the given integer (vector of integer) type.
|
||||
LLVM_ABI static Type *getByteFromIntType(Type *);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Convenience methods for getting pointer types.
|
||||
//
|
||||
|
||||
@ -82,6 +82,7 @@ HANDLE_CONSTANT(ConstantAggregateZero)
|
||||
HANDLE_CONSTANT(ConstantDataArray)
|
||||
HANDLE_CONSTANT(ConstantDataVector)
|
||||
HANDLE_CONSTANT(ConstantInt)
|
||||
HANDLE_CONSTANT(ConstantByte)
|
||||
HANDLE_CONSTANT(ConstantFP)
|
||||
HANDLE_CONSTANT(ConstantTargetNone)
|
||||
HANDLE_CONSTANT(ConstantPointerNull)
|
||||
|
||||
@ -487,20 +487,26 @@ lltok::Kind LLLexer::LexHash() {
|
||||
return lltok::hash;
|
||||
}
|
||||
|
||||
/// Lex a label, integer type, keyword, or hexadecimal integer constant.
|
||||
/// Lex a label, integer or byte types, keyword, or hexadecimal integer
|
||||
/// constant.
|
||||
/// Label [-a-zA-Z$._0-9]+:
|
||||
/// ByteType b[0-9]+
|
||||
/// IntegerType i[0-9]+
|
||||
/// Keyword sdiv, float, ...
|
||||
/// HexIntConstant [us]0x[0-9A-Fa-f]+
|
||||
lltok::Kind LLLexer::LexIdentifier() {
|
||||
const char *StartChar = CurPtr;
|
||||
const char *IntEnd = CurPtr[-1] == 'i' ? nullptr : StartChar;
|
||||
const char IntOrByteIdentifier = CurPtr[-1];
|
||||
const char *IntOrByteEnd =
|
||||
(IntOrByteIdentifier == 'i' || IntOrByteIdentifier == 'b') ? nullptr
|
||||
: StartChar;
|
||||
const char *KeywordEnd = nullptr;
|
||||
|
||||
for (; isLabelChar(*CurPtr); ++CurPtr) {
|
||||
// If we decide this is an integer, remember the end of the sequence.
|
||||
if (!IntEnd && !isdigit(static_cast<unsigned char>(*CurPtr)))
|
||||
IntEnd = CurPtr;
|
||||
// If we decide this is a byte or an integer, remember the end of the
|
||||
// sequence.
|
||||
if (!IntOrByteEnd && !isdigit(static_cast<unsigned char>(*CurPtr)))
|
||||
IntOrByteEnd = CurPtr;
|
||||
if (!KeywordEnd && !isalnum(static_cast<unsigned char>(*CurPtr)) &&
|
||||
*CurPtr != '_')
|
||||
KeywordEnd = CurPtr;
|
||||
@ -513,18 +519,23 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
return lltok::LabelStr;
|
||||
}
|
||||
|
||||
// Otherwise, this wasn't a label. If this was valid as an integer type,
|
||||
// return it.
|
||||
if (!IntEnd) IntEnd = CurPtr;
|
||||
if (IntEnd != StartChar) {
|
||||
CurPtr = IntEnd;
|
||||
// Otherwise, this wasn't a label. If this was valid as a byte or an integer
|
||||
// type, return it.
|
||||
if (!IntOrByteEnd)
|
||||
IntOrByteEnd = CurPtr;
|
||||
if (IntOrByteEnd != StartChar) {
|
||||
CurPtr = IntOrByteEnd;
|
||||
uint64_t NumBits = atoull(StartChar, CurPtr);
|
||||
if (NumBits < IntegerType::MIN_INT_BITS ||
|
||||
NumBits > IntegerType::MAX_INT_BITS) {
|
||||
LexError("bitwidth for integer type out of range");
|
||||
LexError("bitwidth for integer or byte type out of range");
|
||||
return lltok::Error;
|
||||
}
|
||||
TyVal = IntegerType::get(Context, NumBits);
|
||||
if (IntOrByteIdentifier == 'i')
|
||||
TyVal = IntegerType::get(Context, NumBits);
|
||||
else
|
||||
TyVal = ByteType::get(Context, NumBits);
|
||||
|
||||
return lltok::Type;
|
||||
}
|
||||
|
||||
|
||||
@ -4189,12 +4189,13 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
|
||||
if (Elts.empty())
|
||||
return error(ID.Loc, "constant vector must not be empty");
|
||||
|
||||
if (!Elts[0]->getType()->isIntegerTy() &&
|
||||
if (!Elts[0]->getType()->isIntegerTy() && !Elts[0]->getType()->isByteTy() &&
|
||||
!Elts[0]->getType()->isFloatingPointTy() &&
|
||||
!Elts[0]->getType()->isPointerTy())
|
||||
return error(
|
||||
FirstEltLoc,
|
||||
"vector elements must have integer, pointer or floating point type");
|
||||
"vector elements must have integer, byte, pointer or floating point "
|
||||
"type");
|
||||
|
||||
// Verify that all the vector elements have the same type.
|
||||
for (unsigned i = 1, e = Elts.size(); i != e; ++i)
|
||||
@ -4241,15 +4242,16 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
|
||||
ID.Kind = ValID::t_Constant;
|
||||
return false;
|
||||
}
|
||||
case lltok::kw_c: // c "foo"
|
||||
case lltok::kw_c: { // c "foo"
|
||||
Lex.Lex();
|
||||
ID.ConstantVal = ConstantDataArray::getString(Context, Lex.getStrVal(),
|
||||
false);
|
||||
ArrayType *ATy = cast<ArrayType>(ExpectedTy);
|
||||
ID.ConstantVal = ConstantDataArray::getString(
|
||||
Context, Lex.getStrVal(), false, ATy->getElementType()->isByteTy());
|
||||
if (parseToken(lltok::StringConstant, "expected string"))
|
||||
return true;
|
||||
ID.Kind = ValID::t_Constant;
|
||||
return false;
|
||||
|
||||
}
|
||||
case lltok::kw_asm: {
|
||||
// ValID ::= 'asm' SideEffect? AlignStack? IntelDialect? STRINGCONSTANT ','
|
||||
// STRINGCONSTANT
|
||||
@ -6704,10 +6706,11 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V,
|
||||
V = NoCFIValue::get(cast<GlobalValue>(V));
|
||||
return V == nullptr;
|
||||
case ValID::t_APSInt:
|
||||
if (!Ty->isIntegerTy())
|
||||
return error(ID.Loc, "integer constant must have integer type");
|
||||
if (!Ty->isIntegerTy() && !Ty->isByteTy())
|
||||
return error(ID.Loc, "integer/byte constant must have integer/byte type");
|
||||
ID.APSIntVal = ID.APSIntVal.extOrTrunc(Ty->getPrimitiveSizeInBits());
|
||||
V = ConstantInt::get(Context, ID.APSIntVal);
|
||||
Ty->isIntegerTy() ? V = ConstantInt::get(Context, ID.APSIntVal)
|
||||
: V = ConstantByte::get(Context, ID.APSIntVal);
|
||||
return false;
|
||||
case ValID::t_APFloat:
|
||||
if (!Ty->isFloatingPointTy() ||
|
||||
|
||||
@ -2649,6 +2649,17 @@ Error BitcodeReader::parseTypeTableBody() {
|
||||
case bitc::TYPE_CODE_TOKEN: // TOKEN
|
||||
ResultTy = Type::getTokenTy(Context);
|
||||
break;
|
||||
case bitc::TYPE_CODE_BYTE: { // BYTE: [width]
|
||||
if (Record.empty())
|
||||
return error("Invalid record");
|
||||
|
||||
uint64_t NumBits = Record[0];
|
||||
if (NumBits < ByteType::MIN_BYTE_BITS ||
|
||||
NumBits > ByteType::MAX_BYTE_BITS)
|
||||
return error("Bitwidth for byte type out of range");
|
||||
ResultTy = ByteType::get(Context, NumBits);
|
||||
break;
|
||||
}
|
||||
case bitc::TYPE_CODE_INTEGER: { // INTEGER: [width]
|
||||
if (Record.empty())
|
||||
return error("Invalid integer record");
|
||||
@ -3347,6 +3358,20 @@ Error BitcodeReader::parseConstants() {
|
||||
V = ConstantInt::get(CurTy, VInt);
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_BYTE: // BYTE: [byteval]
|
||||
if (!CurTy->isByteOrByteVectorTy() || Record.empty())
|
||||
return error("Invalid byte const record");
|
||||
V = ConstantByte::get(CurTy, decodeSignRotatedValue(Record[0]));
|
||||
break;
|
||||
case bitc::CST_CODE_WIDE_BYTE: { // WIDE_BYTE: [n x byteval]
|
||||
if (!CurTy->isByteOrByteVectorTy() || Record.empty())
|
||||
return error("Invalid wide byte const record");
|
||||
|
||||
auto *ScalarTy = cast<ByteType>(CurTy->getScalarType());
|
||||
APInt VByte = readWideAPInt(Record, ScalarTy->getBitWidth());
|
||||
V = ConstantByte::get(CurTy, VByte);
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval]
|
||||
if (Record.empty())
|
||||
return error("Invalid float const record");
|
||||
@ -3409,8 +3434,9 @@ Error BitcodeReader::parseConstants() {
|
||||
return error("Invalid string record");
|
||||
|
||||
SmallString<16> Elts(Record.begin(), Record.end());
|
||||
V = ConstantDataArray::getString(Context, Elts,
|
||||
BitCode == bitc::CST_CODE_CSTRING);
|
||||
V = ConstantDataArray::getString(
|
||||
Context, Elts, BitCode == bitc::CST_CODE_CSTRING,
|
||||
cast<ArrayType>(CurTy)->getElementType()->isByteTy());
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_DATA: {// DATA: [n x value]
|
||||
@ -3446,6 +3472,30 @@ Error BitcodeReader::parseConstants() {
|
||||
V = ConstantDataVector::get(Context, Elts);
|
||||
else
|
||||
V = ConstantDataArray::get(Context, Elts);
|
||||
} else if (EltTy->isByteTy(8)) {
|
||||
SmallVector<uint8_t, 16> Elts(Record.begin(), Record.end());
|
||||
if (isa<VectorType>(CurTy))
|
||||
V = ConstantDataVector::getByte(EltTy, Elts);
|
||||
else
|
||||
V = ConstantDataArray::getByte(EltTy, Elts);
|
||||
} else if (EltTy->isByteTy(16)) {
|
||||
SmallVector<uint16_t, 16> Elts(Record.begin(), Record.end());
|
||||
if (isa<VectorType>(CurTy))
|
||||
V = ConstantDataVector::getByte(EltTy, Elts);
|
||||
else
|
||||
V = ConstantDataArray::getByte(EltTy, Elts);
|
||||
} else if (EltTy->isByteTy(32)) {
|
||||
SmallVector<uint32_t, 16> Elts(Record.begin(), Record.end());
|
||||
if (isa<VectorType>(CurTy))
|
||||
V = ConstantDataVector::getByte(EltTy, Elts);
|
||||
else
|
||||
V = ConstantDataArray::getByte(EltTy, Elts);
|
||||
} else if (EltTy->isByteTy(64)) {
|
||||
SmallVector<uint64_t, 16> Elts(Record.begin(), Record.end());
|
||||
if (isa<VectorType>(CurTy))
|
||||
V = ConstantDataVector::getByte(EltTy, Elts);
|
||||
else
|
||||
V = ConstantDataArray::getByte(EltTy, Elts);
|
||||
} else if (EltTy->isHalfTy()) {
|
||||
SmallVector<uint16_t, 16> Elts(Record.begin(), Record.end());
|
||||
if (isa<VectorType>(CurTy))
|
||||
|
||||
@ -136,6 +136,7 @@ enum {
|
||||
// CONSTANTS_BLOCK abbrev id's.
|
||||
CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV,
|
||||
CONSTANTS_INTEGER_ABBREV,
|
||||
CONSTANTS_BYTE_ABBREV,
|
||||
CONSTANTS_CE_CAST_Abbrev,
|
||||
CONSTANTS_NULL_Abbrev,
|
||||
|
||||
@ -1173,6 +1174,11 @@ void ModuleBitcodeWriter::writeTypeTable() {
|
||||
break;
|
||||
case Type::X86_AMXTyID: Code = bitc::TYPE_CODE_X86_AMX; break;
|
||||
case Type::TokenTyID: Code = bitc::TYPE_CODE_TOKEN; break;
|
||||
case Type::ByteTyID:
|
||||
// BYTE: [width]
|
||||
Code = bitc::TYPE_CODE_BYTE;
|
||||
TypeVals.push_back(T->getByteBitWidth());
|
||||
break;
|
||||
case Type::IntegerTyID:
|
||||
// INTEGER: [width]
|
||||
Code = bitc::TYPE_CODE_INTEGER;
|
||||
@ -2871,6 +2877,16 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
|
||||
emitWideAPInt(Record, IV->getValue());
|
||||
Code = bitc::CST_CODE_WIDE_INTEGER;
|
||||
}
|
||||
} else if (const ConstantByte *BV = dyn_cast<ConstantByte>(C)) {
|
||||
if (BV->getBitWidth() <= 64) {
|
||||
uint64_t V = BV->getSExtValue();
|
||||
emitSignedInt64(Record, V);
|
||||
Code = bitc::CST_CODE_BYTE;
|
||||
AbbrevToUse = CONSTANTS_BYTE_ABBREV;
|
||||
} else { // Wide bytes, > 64 bits in size.
|
||||
emitWideAPInt(Record, BV->getValue());
|
||||
Code = bitc::CST_CODE_WIDE_BYTE;
|
||||
}
|
||||
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
|
||||
Code = bitc::CST_CODE_FLOAT;
|
||||
Type *Ty = CFP->getType()->getScalarType();
|
||||
@ -2920,10 +2936,10 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
|
||||
else if (isCStr7)
|
||||
AbbrevToUse = CString7Abbrev;
|
||||
} else if (const ConstantDataSequential *CDS =
|
||||
dyn_cast<ConstantDataSequential>(C)) {
|
||||
dyn_cast<ConstantDataSequential>(C)) {
|
||||
Code = bitc::CST_CODE_DATA;
|
||||
Type *EltTy = CDS->getElementType();
|
||||
if (isa<IntegerType>(EltTy)) {
|
||||
if (isa<IntegerType>(EltTy) || isa<ByteType>(EltTy)) {
|
||||
for (uint64_t i = 0, e = CDS->getNumElements(); i != e; ++i)
|
||||
Record.push_back(CDS->getElementAsInteger(i));
|
||||
} else {
|
||||
@ -3968,6 +3984,15 @@ void ModuleBitcodeWriter::writeBlockInfo() {
|
||||
llvm_unreachable("Unexpected abbrev ordering!");
|
||||
}
|
||||
|
||||
{ // BYTE abbrev for CONSTANTS_BLOCK.
|
||||
auto Abbv = std::make_shared<BitCodeAbbrev>();
|
||||
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_BYTE));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
|
||||
if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) !=
|
||||
CONSTANTS_BYTE_ABBREV)
|
||||
llvm_unreachable("Unexpected abbrev ordering!");
|
||||
}
|
||||
|
||||
{ // CE_CAST abbrev for CONSTANTS_BLOCK.
|
||||
auto Abbv = std::make_shared<BitCodeAbbrev>();
|
||||
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST));
|
||||
|
||||
@ -3802,6 +3802,9 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV,
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
|
||||
return MCConstantExpr::create(CI->getZExtValue(), Ctx);
|
||||
|
||||
if (const ConstantByte *CB = dyn_cast<ConstantByte>(CV))
|
||||
return MCConstantExpr::create(CB->getZExtValue(), Ctx);
|
||||
|
||||
if (const ConstantPtrAuth *CPA = dyn_cast<ConstantPtrAuth>(CV))
|
||||
return lowerConstantPtrAuth(*CPA);
|
||||
|
||||
@ -4057,7 +4060,8 @@ static void emitGlobalConstantDataSequential(
|
||||
|
||||
// Otherwise, emit the values in successive locations.
|
||||
uint64_t ElementByteSize = CDS->getElementByteSize();
|
||||
if (isa<IntegerType>(CDS->getElementType())) {
|
||||
if (isa<IntegerType>(CDS->getElementType()) ||
|
||||
isa<ByteType>(CDS->getElementType())) {
|
||||
for (uint64_t I = 0, E = CDS->getNumElements(); I != E; ++I) {
|
||||
emitGlobalAliasInline(AP, ElementByteSize * I, AliasList);
|
||||
if (AP.isVerbose())
|
||||
@ -4221,13 +4225,15 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
|
||||
emitGlobalConstantFP(CFP->getValueAPF(), CFP->getType(), AP);
|
||||
}
|
||||
|
||||
static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
|
||||
static void emitGlobalConstantLargeAPInt(const APInt &Val,
|
||||
uint64_t TypeStoreSize,
|
||||
AsmPrinter &AP) {
|
||||
const DataLayout &DL = AP.getDataLayout();
|
||||
unsigned BitWidth = CI->getBitWidth();
|
||||
unsigned BitWidth = Val.getBitWidth();
|
||||
|
||||
// Copy the value as we may massage the layout for constants whose bit width
|
||||
// is not a multiple of 64-bits.
|
||||
APInt Realigned(CI->getValue());
|
||||
APInt Realigned(Val);
|
||||
uint64_t ExtraBits = 0;
|
||||
unsigned ExtraBitsSize = BitWidth & 63;
|
||||
|
||||
@ -4249,36 +4255,47 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
|
||||
// ExtraBits 0 1 (BitWidth / 64) - 1
|
||||
// chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN]
|
||||
ExtraBitsSize = alignTo(ExtraBitsSize, 8);
|
||||
ExtraBits = Realigned.getRawData()[0] &
|
||||
(((uint64_t)-1) >> (64 - ExtraBitsSize));
|
||||
ExtraBits =
|
||||
Realigned.getRawData()[0] & (((uint64_t)-1) >> (64 - ExtraBitsSize));
|
||||
if (BitWidth >= 64)
|
||||
Realigned.lshrInPlace(ExtraBitsSize);
|
||||
} else
|
||||
ExtraBits = Realigned.getRawData()[BitWidth / 64];
|
||||
}
|
||||
|
||||
// We don't expect assemblers to support integer data directives
|
||||
// We don't expect assemblers to support data directives
|
||||
// for more than 64 bits, so we emit the data in at most 64-bit
|
||||
// quantities at a time.
|
||||
const uint64_t *RawData = Realigned.getRawData();
|
||||
for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
|
||||
uint64_t Val = DL.isBigEndian() ? RawData[e - i - 1] : RawData[i];
|
||||
AP.OutStreamer->emitIntValue(Val, 8);
|
||||
uint64_t ChunkVal = DL.isBigEndian() ? RawData[e - i - 1] : RawData[i];
|
||||
AP.OutStreamer->emitIntValue(ChunkVal, 8);
|
||||
}
|
||||
|
||||
if (ExtraBitsSize) {
|
||||
// Emit the extra bits after the 64-bits chunks.
|
||||
|
||||
// Emit a directive that fills the expected size.
|
||||
uint64_t Size = AP.getDataLayout().getTypeStoreSize(CI->getType());
|
||||
Size -= (BitWidth / 64) * 8;
|
||||
uint64_t Size = TypeStoreSize - (BitWidth / 64) * 8;
|
||||
assert(Size && Size * 8 >= ExtraBitsSize &&
|
||||
(ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize)))
|
||||
== ExtraBits && "Directive too small for extra bits.");
|
||||
(ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) ==
|
||||
ExtraBits &&
|
||||
"Directive too small for extra bits.");
|
||||
AP.OutStreamer->emitIntValue(ExtraBits, Size);
|
||||
}
|
||||
}
|
||||
|
||||
static void emitGlobalConstantLargeByte(const ConstantByte *CB,
|
||||
AsmPrinter &AP) {
|
||||
emitGlobalConstantLargeAPInt(
|
||||
CB->getValue(), AP.getDataLayout().getTypeStoreSize(CB->getType()), AP);
|
||||
}
|
||||
|
||||
static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
|
||||
emitGlobalConstantLargeAPInt(
|
||||
CI->getValue(), AP.getDataLayout().getTypeStoreSize(CI->getType()), AP);
|
||||
}
|
||||
|
||||
/// Transform a not absolute MCExpr containing a reference to a GOT
|
||||
/// equivalent global, by a target specific GOT pc relative access to the
|
||||
/// final symbol.
|
||||
@ -4424,6 +4441,27 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
|
||||
return;
|
||||
}
|
||||
|
||||
if (const ConstantByte *CB = dyn_cast<ConstantByte>(CV)) {
|
||||
if (isa<VectorType>(CV->getType()))
|
||||
return emitGlobalConstantVector(DL, CV, AP, AliasList);
|
||||
|
||||
const uint64_t StoreSize = DL.getTypeStoreSize(CV->getType());
|
||||
if (StoreSize <= 8) {
|
||||
if (AP.isVerbose())
|
||||
AP.OutStreamer->getCommentOS()
|
||||
<< format("0x%" PRIx64 "\n", CB->getZExtValue());
|
||||
AP.OutStreamer->emitIntValue(CB->getZExtValue(), StoreSize);
|
||||
} else {
|
||||
emitGlobalConstantLargeByte(CB, AP);
|
||||
}
|
||||
|
||||
// Emit tail padding if needed
|
||||
if (Size != StoreSize)
|
||||
AP.OutStreamer->emitZeros(Size - StoreSize);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
|
||||
if (isa<VectorType>(CV->getType()))
|
||||
return emitGlobalConstantVector(DL, CV, AP, AliasList);
|
||||
|
||||
@ -1865,6 +1865,9 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
|
||||
return DAG.getConstant(*CI, DL, VT);
|
||||
}
|
||||
|
||||
if (const ConstantByte *CB = dyn_cast<ConstantByte>(C))
|
||||
return DAG.getConstant(CB->getValue(), getCurSDLoc(), VT);
|
||||
|
||||
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
|
||||
return DAG.getGlobalAddress(GV, getCurSDLoc(), VT);
|
||||
|
||||
|
||||
@ -254,6 +254,8 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){
|
||||
llvm_unreachable("Unknown type!");
|
||||
case Type::VoidTyID:
|
||||
return MVT::isVoid;
|
||||
case Type::ByteTyID:
|
||||
return getIntegerVT(cast<ByteType>(Ty)->getBitWidth());
|
||||
case Type::IntegerTyID:
|
||||
return getIntegerVT(cast<IntegerType>(Ty)->getBitWidth());
|
||||
case Type::HalfTyID: return MVT(MVT::f16);
|
||||
@ -304,6 +306,8 @@ EVT EVT::getEVT(Type *Ty, bool HandleUnknown){
|
||||
return MVT::getVT(Ty, HandleUnknown);
|
||||
case Type::TokenTyID:
|
||||
return MVT::Untyped;
|
||||
case Type::ByteTyID:
|
||||
return getIntegerVT(Ty->getContext(), cast<ByteType>(Ty)->getBitWidth());
|
||||
case Type::IntegerTyID:
|
||||
return getIntegerVT(Ty->getContext(), cast<IntegerType>(Ty)->getBitWidth());
|
||||
case Type::FixedVectorTyID:
|
||||
|
||||
@ -669,6 +669,9 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
|
||||
return;
|
||||
case Type::X86_AMXTyID: OS << "x86_amx"; return;
|
||||
case Type::TokenTyID: OS << "token"; return;
|
||||
case Type::ByteTyID:
|
||||
OS << 'b' << Ty->getByteBitWidth();
|
||||
return;
|
||||
case Type::IntegerTyID:
|
||||
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
|
||||
return;
|
||||
@ -1648,6 +1651,23 @@ static void writeConstantInternal(raw_ostream &Out, const Constant *CV,
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto *CB = dyn_cast<ConstantByte>(CV)) {
|
||||
Type *Ty = CB->getType();
|
||||
|
||||
if (Ty->isVectorTy()) {
|
||||
Out << "splat (";
|
||||
WriterCtx.TypePrinter->print(Ty->getScalarType(), Out);
|
||||
Out << " ";
|
||||
}
|
||||
|
||||
Out << CB->getValue();
|
||||
|
||||
if (Ty->isVectorTy())
|
||||
Out << ")";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto *CFP = dyn_cast<ConstantFP>(CV)) {
|
||||
Type *Ty = CFP->getType();
|
||||
|
||||
@ -1773,7 +1793,8 @@ static void writeConstantInternal(raw_ostream &Out, const Constant *CV,
|
||||
// TODO: Remove this block when the UseConstant{Int,FP}ForFixedLengthSplat
|
||||
// options are removed.
|
||||
if (auto *SplatVal = CV->getSplatValue()) {
|
||||
if (isa<ConstantInt>(SplatVal) || isa<ConstantFP>(SplatVal)) {
|
||||
if (isa<ConstantInt>(SplatVal) || isa<ConstantFP>(SplatVal) ||
|
||||
isa<ConstantByte>(SplatVal)) {
|
||||
Out << "splat (";
|
||||
writeAsOperandInternal(Out, SplatVal, WriterCtx, /*PrintType=*/true);
|
||||
Out << ')';
|
||||
@ -1820,7 +1841,8 @@ static void writeConstantInternal(raw_ostream &Out, const Constant *CV,
|
||||
// options are removed.
|
||||
if (CE->getOpcode() == Instruction::ShuffleVector) {
|
||||
if (auto *SplatVal = CE->getSplatValue()) {
|
||||
if (isa<ConstantInt>(SplatVal) || isa<ConstantFP>(SplatVal)) {
|
||||
if (isa<ConstantInt>(SplatVal) || isa<ConstantFP>(SplatVal) ||
|
||||
isa<ConstantByte>(SplatVal)) {
|
||||
Out << "splat (";
|
||||
writeAsOperandInternal(Out, SplatVal, WriterCtx, /*PrintType=*/true);
|
||||
Out << ')';
|
||||
|
||||
@ -2474,6 +2474,10 @@ AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
|
||||
// Attributes that only apply to integers.
|
||||
if (ASK & ASK_SAFE_TO_DROP)
|
||||
Incompatible.addAttribute(Attribute::AllocAlign);
|
||||
}
|
||||
|
||||
if (!Ty->isIntegerTy() && !Ty->isByteTy()) {
|
||||
// Attributes that only apply to integers and bytes.
|
||||
if (ASK & ASK_UNSAFE_TO_DROP)
|
||||
Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
|
||||
}
|
||||
|
||||
@ -76,6 +76,10 @@ bool Constant::isNullValue() const {
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
|
||||
return CI->isZero();
|
||||
|
||||
// 0 is null.
|
||||
if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
|
||||
return CB->isZero();
|
||||
|
||||
// +0.0 is null.
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
|
||||
// ppc_fp128 determine isZero using high order double only
|
||||
@ -93,6 +97,10 @@ bool Constant::isAllOnesValue() const {
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
|
||||
return CI->isMinusOne();
|
||||
|
||||
// Check for MaxValue bytes
|
||||
if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
|
||||
return CB->isMinusOne();
|
||||
|
||||
// Check for FP which are bitcasted from -1 integers
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
|
||||
return CFP->getValueAPF().bitcastToAPInt().isAllOnes();
|
||||
@ -110,6 +118,10 @@ bool Constant::isOneValue() const {
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
|
||||
return CI->isOne();
|
||||
|
||||
// Check for 1 bytes
|
||||
if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
|
||||
return CB->isOne();
|
||||
|
||||
// Check for FP which are bitcasted from 1 integers
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
|
||||
return CFP->getValueAPF().bitcastToAPInt().isOne();
|
||||
@ -127,6 +139,10 @@ bool Constant::isNotOneValue() const {
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
|
||||
return !CI->isOneValue();
|
||||
|
||||
// Check for 1 bytes
|
||||
if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
|
||||
return !CB->isOneValue();
|
||||
|
||||
// Check for FP which are bitcasted from 1 integers
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
|
||||
return !CFP->getValueAPF().bitcastToAPInt().isOne();
|
||||
@ -373,6 +389,8 @@ bool Constant::containsConstantExpression() const {
|
||||
/// Constructor to create a '0' constant of arbitrary type.
|
||||
Constant *Constant::getNullValue(Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::ByteTyID:
|
||||
return ConstantByte::get(Ty, 0);
|
||||
case Type::IntegerTyID:
|
||||
return ConstantInt::get(Ty, 0);
|
||||
case Type::HalfTyID:
|
||||
@ -411,6 +429,10 @@ Constant *Constant::getIntegerValue(Type *Ty, const APInt &V) {
|
||||
if (PointerType *PTy = dyn_cast<PointerType>(ScalarTy))
|
||||
C = ConstantExpr::getIntToPtr(C, PTy);
|
||||
|
||||
// Convert an integer to a byte, if necessary.
|
||||
if (ByteType *BTy = dyn_cast<ByteType>(ScalarTy))
|
||||
C = ConstantExpr::getBitCast(C, BTy);
|
||||
|
||||
// Broadcast a scalar to a vector, if necessary.
|
||||
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
|
||||
C = ConstantVector::getSplat(VTy->getElementCount(), C);
|
||||
@ -428,6 +450,10 @@ Constant *Constant::getAllOnesValue(Type *Ty) {
|
||||
return ConstantFP::get(Ty->getContext(), FL);
|
||||
}
|
||||
|
||||
if (ByteType *BTy = dyn_cast<ByteType>(Ty))
|
||||
return ConstantByte::get(Ty->getContext(),
|
||||
APInt::getAllOnes(BTy->getBitWidth()));
|
||||
|
||||
VectorType *VTy = cast<VectorType>(Ty);
|
||||
return ConstantVector::getSplat(VTy->getElementCount(),
|
||||
getAllOnesValue(VTy->getElementType()));
|
||||
@ -452,6 +478,13 @@ Constant *Constant::getAggregateElement(unsigned Elt) const {
|
||||
? ConstantInt::get(getContext(), CI->getValue())
|
||||
: nullptr;
|
||||
|
||||
if (const auto *CB = dyn_cast<ConstantByte>(this))
|
||||
return Elt < cast<VectorType>(getType())
|
||||
->getElementCount()
|
||||
.getKnownMinValue()
|
||||
? ConstantByte::get(getContext(), CB->getValue())
|
||||
: nullptr;
|
||||
|
||||
if (const auto *CFP = dyn_cast<ConstantFP>(this))
|
||||
return Elt < cast<VectorType>(getType())
|
||||
->getElementCount()
|
||||
@ -532,6 +565,9 @@ void llvm::deleteConstant(Constant *C) {
|
||||
case Constant::ConstantIntVal:
|
||||
delete static_cast<ConstantInt *>(C);
|
||||
break;
|
||||
case Constant::ConstantByteVal:
|
||||
delete static_cast<ConstantByte *>(C);
|
||||
break;
|
||||
case Constant::ConstantFPVal:
|
||||
delete static_cast<ConstantFP *>(C);
|
||||
break;
|
||||
@ -983,6 +1019,93 @@ void ConstantInt::destroyConstantImpl() {
|
||||
llvm_unreachable("You can't ConstantInt->destroyConstantImpl()!");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConstantByte
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ConstantByte::ConstantByte(Type *Ty, const APInt &V)
|
||||
: ConstantData(Ty, ConstantByteVal), Val(V) {
|
||||
assert(V.getBitWidth() ==
|
||||
cast<ByteType>(Ty->getScalarType())->getBitWidth() &&
|
||||
"Invalid constant for type");
|
||||
}
|
||||
|
||||
// Get a ConstantByte from an APInt.
|
||||
ConstantByte *ConstantByte::get(LLVMContext &Context, const APInt &V) {
|
||||
// get an existing value or the insertion position
|
||||
LLVMContextImpl *pImpl = Context.pImpl;
|
||||
std::unique_ptr<ConstantByte> &Slot =
|
||||
V.isZero() ? pImpl->ByteZeroConstants[V.getBitWidth()]
|
||||
: V.isOne() ? pImpl->ByteOneConstants[V.getBitWidth()]
|
||||
: pImpl->ByteConstants[V];
|
||||
if (!Slot) {
|
||||
// Get the corresponding byte type for the bit width of the value.
|
||||
ByteType *BTy = ByteType::get(Context, V.getBitWidth());
|
||||
Slot.reset(new ConstantByte(BTy, V));
|
||||
}
|
||||
assert(Slot->getType() == ByteType::get(Context, V.getBitWidth()));
|
||||
return Slot.get();
|
||||
}
|
||||
|
||||
// Get a ConstantByte vector with each lane set to the same APInt.
|
||||
ConstantByte *ConstantByte::get(LLVMContext &Context, ElementCount EC,
|
||||
const APInt &V) {
|
||||
// Get an existing value or the insertion position.
|
||||
std::unique_ptr<ConstantByte> &Slot =
|
||||
Context.pImpl->ByteSplatConstants[std::make_pair(EC, V)];
|
||||
if (!Slot) {
|
||||
ByteType *BTy = ByteType::get(Context, V.getBitWidth());
|
||||
VectorType *VTy = VectorType::get(BTy, EC);
|
||||
Slot.reset(new ConstantByte(VTy, V));
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
ByteType *BTy = ByteType::get(Context, V.getBitWidth());
|
||||
VectorType *VTy = VectorType::get(BTy, EC);
|
||||
assert(Slot->getType() == VTy);
|
||||
#endif
|
||||
return Slot.get();
|
||||
}
|
||||
|
||||
Constant *ConstantByte::get(Type *Ty, uint64_t V, bool isSigned,
|
||||
bool ImplicitTrunc) {
|
||||
Constant *C =
|
||||
get(cast<ByteType>(Ty->getScalarType()), V, isSigned, ImplicitTrunc);
|
||||
|
||||
// For vectors, broadcast the value.
|
||||
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
|
||||
return ConstantVector::getSplat(VTy->getElementCount(), C);
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
ConstantByte *ConstantByte::get(ByteType *Ty, uint64_t V, bool isSigned,
|
||||
bool ImplicitTrunc) {
|
||||
return get(Ty->getContext(),
|
||||
APInt(Ty->getBitWidth(), V, isSigned, ImplicitTrunc));
|
||||
}
|
||||
|
||||
Constant *ConstantByte::get(Type *Ty, const APInt &V) {
|
||||
ConstantByte *C = get(Ty->getContext(), V);
|
||||
assert(C->getType() == Ty->getScalarType() &&
|
||||
"ConstantByte type doesn't match the type implied by its value!");
|
||||
|
||||
// For vectors, broadcast the value.
|
||||
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
|
||||
return ConstantVector::getSplat(VTy->getElementCount(), C);
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
ConstantByte *ConstantByte::get(ByteType *Ty, StringRef Str, uint8_t radix) {
|
||||
return get(Ty->getContext(), APInt(Ty->getBitWidth(), Str, radix));
|
||||
}
|
||||
|
||||
/// Remove the constant from the constant table.
|
||||
void ConstantByte::destroyConstantImpl() {
|
||||
llvm_unreachable("You can't ConstantByte->destroyConstantImpl()!");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConstantFP
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1253,6 +1376,19 @@ static Constant *getIntSequenceIfElementsMatch(ArrayRef<Constant *> V) {
|
||||
return SequentialTy::get(V[0]->getContext(), Elts);
|
||||
}
|
||||
|
||||
template <typename SequentialTy, typename ElementTy>
|
||||
static Constant *getByteSequenceIfElementsMatch(ArrayRef<Constant *> V) {
|
||||
assert(!V.empty() && "Cannot get empty byte sequence.");
|
||||
|
||||
SmallVector<ElementTy, 16> Elts;
|
||||
for (Constant *C : V)
|
||||
if (auto *CI = dyn_cast<ConstantByte>(C))
|
||||
Elts.push_back(CI->getZExtValue());
|
||||
else
|
||||
return nullptr;
|
||||
return SequentialTy::getByte(V[0]->getType(), Elts);
|
||||
}
|
||||
|
||||
template <typename SequentialTy, typename ElementTy>
|
||||
static Constant *getFPSequenceIfElementsMatch(ArrayRef<Constant *> V) {
|
||||
assert(!V.empty() && "Cannot get empty FP sequence.");
|
||||
@ -1281,6 +1417,15 @@ static Constant *getSequenceIfElementsMatch(Constant *C,
|
||||
return getIntSequenceIfElementsMatch<SequenceTy, uint32_t>(V);
|
||||
else if (CI->getType()->isIntegerTy(64))
|
||||
return getIntSequenceIfElementsMatch<SequenceTy, uint64_t>(V);
|
||||
} else if (ConstantByte *CB = dyn_cast<ConstantByte>(C)) {
|
||||
if (CB->getType()->isByteTy(8))
|
||||
return getByteSequenceIfElementsMatch<SequenceTy, uint8_t>(V);
|
||||
else if (CB->getType()->isByteTy(16))
|
||||
return getByteSequenceIfElementsMatch<SequenceTy, uint16_t>(V);
|
||||
else if (CB->getType()->isByteTy(32))
|
||||
return getByteSequenceIfElementsMatch<SequenceTy, uint32_t>(V);
|
||||
else if (CB->getType()->isByteTy(64))
|
||||
return getByteSequenceIfElementsMatch<SequenceTy, uint64_t>(V);
|
||||
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
|
||||
if (CFP->getType()->isHalfTy() || CFP->getType()->isBFloatTy())
|
||||
return getFPSequenceIfElementsMatch<SequenceTy, uint16_t>(V);
|
||||
@ -1346,8 +1491,9 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) {
|
||||
if (C->isNullValue() && rangeOnlyContains(V.begin(), V.end(), C))
|
||||
return ConstantAggregateZero::get(Ty);
|
||||
|
||||
// Check to see if all of the elements are ConstantFP or ConstantInt and if
|
||||
// the element type is compatible with ConstantDataVector. If so, use it.
|
||||
// Check to see if all of the elements are ConstantFP or ConstantInt or
|
||||
// ConstantByte and if the element type is compatible with ConstantDataVector.
|
||||
// If so, use it.
|
||||
if (ConstantDataSequential::isElementTypeCompatible(C->getType()))
|
||||
return getSequenceIfElementsMatch<ConstantDataArray>(C, V);
|
||||
|
||||
@ -1444,11 +1590,13 @@ Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
|
||||
bool isPoison = isa<PoisonValue>(C);
|
||||
bool isSplatFP = UseConstantFPForFixedLengthSplat && isa<ConstantFP>(C);
|
||||
bool isSplatInt = UseConstantIntForFixedLengthSplat && isa<ConstantInt>(C);
|
||||
bool isSplatByte = isa<ConstantByte>(C);
|
||||
|
||||
if (isZero || isUndef || isSplatFP || isSplatInt) {
|
||||
if (isZero || isUndef || isSplatFP || isSplatInt || isSplatByte) {
|
||||
for (unsigned i = 1, e = V.size(); i != e; ++i)
|
||||
if (V[i] != C) {
|
||||
isZero = isUndef = isPoison = isSplatFP = isSplatInt = false;
|
||||
isZero = isUndef = isPoison = isSplatFP = isSplatInt = isSplatByte =
|
||||
false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1465,6 +1613,9 @@ Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
|
||||
if (isSplatInt)
|
||||
return ConstantInt::get(C->getContext(), T->getElementCount(),
|
||||
cast<ConstantInt>(C)->getValue());
|
||||
if (isSplatByte)
|
||||
return ConstantByte::get(C->getContext(), T->getElementCount(),
|
||||
cast<ConstantByte>(C)->getValue());
|
||||
|
||||
// Check to see if all of the elements are ConstantFP or ConstantInt and if
|
||||
// the element type is compatible with ConstantDataVector. If so, use it.
|
||||
@ -1483,6 +1634,9 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
|
||||
if (UseConstantIntForFixedLengthSplat && isa<ConstantInt>(V))
|
||||
return ConstantInt::get(V->getContext(), EC,
|
||||
cast<ConstantInt>(V)->getValue());
|
||||
if (isa<ConstantByte>(V))
|
||||
return ConstantByte::get(V->getContext(), EC,
|
||||
cast<ConstantByte>(V)->getValue());
|
||||
if (UseConstantFPForFixedLengthSplat && isa<ConstantFP>(V))
|
||||
return ConstantFP::get(V->getContext(), EC,
|
||||
cast<ConstantFP>(V)->getValue());
|
||||
@ -1490,7 +1644,7 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
|
||||
|
||||
// If this splat is compatible with ConstantDataVector, use it instead of
|
||||
// ConstantVector.
|
||||
if ((isa<ConstantFP>(V) || isa<ConstantInt>(V)) &&
|
||||
if ((isa<ConstantFP>(V) || isa<ConstantInt>(V) || isa<ConstantByte>(V)) &&
|
||||
ConstantDataSequential::isElementTypeCompatible(V->getType()))
|
||||
return ConstantDataVector::getSplat(EC.getKnownMinValue(), V);
|
||||
|
||||
@ -1503,6 +1657,9 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
|
||||
if (UseConstantIntForScalableSplat && isa<ConstantInt>(V))
|
||||
return ConstantInt::get(V->getContext(), EC,
|
||||
cast<ConstantInt>(V)->getValue());
|
||||
if (isa<ConstantByte>(V))
|
||||
return ConstantByte::get(V->getContext(), EC,
|
||||
cast<ConstantByte>(V)->getValue());
|
||||
if (UseConstantFPForScalableSplat && isa<ConstantFP>(V))
|
||||
return ConstantFP::get(V->getContext(), EC,
|
||||
cast<ConstantFP>(V)->getValue());
|
||||
@ -1723,6 +1880,8 @@ Constant *Constant::getSplatValue(bool AllowPoison) const {
|
||||
return getNullValue(cast<VectorType>(getType())->getElementType());
|
||||
if (auto *CI = dyn_cast<ConstantInt>(this))
|
||||
return ConstantInt::get(getContext(), CI->getValue());
|
||||
if (auto *CB = dyn_cast<ConstantByte>(this))
|
||||
return ConstantByte::get(getContext(), CB->getValue());
|
||||
if (auto *CFP = dyn_cast<ConstantFP>(this))
|
||||
return ConstantFP::get(getContext(), CFP->getValue());
|
||||
if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this))
|
||||
@ -1782,6 +1941,8 @@ Constant *ConstantVector::getSplatValue(bool AllowPoison) const {
|
||||
const APInt &Constant::getUniqueInteger() const {
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
|
||||
return CI->getValue();
|
||||
if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
|
||||
return CB->getValue();
|
||||
// Scalable vectors can use a ConstantExpr to build a splat.
|
||||
if (isa<ConstantExpr>(this))
|
||||
return cast<ConstantInt>(this->getSplatValue())->getValue();
|
||||
@ -1805,6 +1966,10 @@ ConstantRange Constant::toConstantRange() const {
|
||||
getSplatValue(/*AllowPoison=*/true)))
|
||||
return ConstantRange(CI->getValue());
|
||||
|
||||
if (auto *CB =
|
||||
dyn_cast_or_null<ConstantByte>(getSplatValue(/*AllowPoison=*/true)))
|
||||
return ConstantRange(CB->getValue());
|
||||
|
||||
if (auto *CDV = dyn_cast<ConstantDataVector>(this)) {
|
||||
ConstantRange CR = ConstantRange::getEmpty(BitWidth);
|
||||
for (unsigned I = 0, E = CDV->getNumElements(); I < E; ++I)
|
||||
@ -1821,7 +1986,8 @@ ConstantRange Constant::toConstantRange() const {
|
||||
if (isa<PoisonValue>(Elem))
|
||||
continue;
|
||||
auto *CI = dyn_cast<ConstantInt>(Elem);
|
||||
if (!CI)
|
||||
auto *CB = dyn_cast<ConstantByte>(Elem);
|
||||
if (!CI && !CB)
|
||||
return ConstantRange::getFull(BitWidth);
|
||||
CR = CR.unionWith(CI->getValue());
|
||||
}
|
||||
@ -2868,6 +3034,17 @@ bool ConstantDataSequential::isElementTypeCompatible(Type *Ty) {
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (auto *IT = dyn_cast<ByteType>(Ty)) {
|
||||
switch (IT->getBitWidth()) {
|
||||
case 8:
|
||||
case 16:
|
||||
case 32:
|
||||
case 64:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3000,17 +3177,54 @@ Constant *ConstantDataArray::getFP(Type *ElementType, ArrayRef<uint64_t> Elts) {
|
||||
return getImpl(StringRef(Data, Elts.size() * 8), Ty);
|
||||
}
|
||||
|
||||
Constant *ConstantDataArray::getString(LLVMContext &Context,
|
||||
StringRef Str, bool AddNull) {
|
||||
/// getByte() constructors - Return a constant of array type with a byte
|
||||
/// 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.
|
||||
/// Note that this can return a ConstantAggregateZero object.
|
||||
Constant *ConstantDataArray::getByte(Type *ElementType,
|
||||
ArrayRef<uint8_t> Elts) {
|
||||
assert(ElementType->isByteTy(8) && "Element type is not a 8-bit byte type");
|
||||
Type *Ty = ArrayType::get(ElementType, Elts.size());
|
||||
const char *Data = reinterpret_cast<const char *>(Elts.data());
|
||||
return getImpl(StringRef(Data, Elts.size() * 1), Ty);
|
||||
}
|
||||
Constant *ConstantDataArray::getByte(Type *ElementType,
|
||||
ArrayRef<uint16_t> Elts) {
|
||||
assert(ElementType->isByteTy(16) && "Element type is not a 16-bit byte type");
|
||||
Type *Ty = ArrayType::get(ElementType, Elts.size());
|
||||
const char *Data = reinterpret_cast<const char *>(Elts.data());
|
||||
return getImpl(StringRef(Data, Elts.size() * 2), Ty);
|
||||
}
|
||||
Constant *ConstantDataArray::getByte(Type *ElementType,
|
||||
ArrayRef<uint32_t> Elts) {
|
||||
assert(ElementType->isByteTy(32) && "Element type is not a 32-bit byte type");
|
||||
Type *Ty = ArrayType::get(ElementType, Elts.size());
|
||||
const char *Data = reinterpret_cast<const char *>(Elts.data());
|
||||
return getImpl(StringRef(Data, Elts.size() * 4), Ty);
|
||||
}
|
||||
Constant *ConstantDataArray::getByte(Type *ElementType,
|
||||
ArrayRef<uint64_t> Elts) {
|
||||
assert(ElementType->isByteTy(64) && "Element type is not a 64-bit byte type");
|
||||
Type *Ty = ArrayType::get(ElementType, Elts.size());
|
||||
const char *Data = reinterpret_cast<const char *>(Elts.data());
|
||||
return getImpl(StringRef(Data, Elts.size() * 8), Ty);
|
||||
}
|
||||
|
||||
Constant *ConstantDataArray::getString(LLVMContext &Context, StringRef Str,
|
||||
bool AddNull, bool ByteString) {
|
||||
if (!AddNull) {
|
||||
const uint8_t *Data = Str.bytes_begin();
|
||||
return get(Context, ArrayRef(Data, Str.size()));
|
||||
return ByteString
|
||||
? getByte(Type::getByte8Ty(Context), ArrayRef(Data, Str.size()))
|
||||
: get(Context, ArrayRef(Data, Str.size()));
|
||||
}
|
||||
|
||||
SmallVector<uint8_t, 64> ElementVals;
|
||||
ElementVals.append(Str.begin(), Str.end());
|
||||
ElementVals.push_back(0);
|
||||
return get(Context, ElementVals);
|
||||
return ByteString ? getByte(Type::getByte8Ty(Context), ElementVals)
|
||||
: get(Context, ElementVals);
|
||||
}
|
||||
|
||||
/// get() constructors - Return a constant with vector type with an element
|
||||
@ -3047,6 +3261,40 @@ Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<double> Elts) {
|
||||
return getImpl(StringRef(Data, Elts.size() * 8), Ty);
|
||||
}
|
||||
|
||||
/// getByte() constructors - Return a constant of vector type with a byte
|
||||
/// 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.
|
||||
/// Note that this can return a ConstantAggregateZero object.
|
||||
Constant *ConstantDataVector::getByte(Type *ElementType,
|
||||
ArrayRef<uint8_t> Elts) {
|
||||
assert(ElementType->isByteTy(8) && "Element type is not a 8-bit byte");
|
||||
auto *Ty = FixedVectorType::get(ElementType, Elts.size());
|
||||
const char *Data = reinterpret_cast<const char *>(Elts.data());
|
||||
return getImpl(StringRef(Data, Elts.size() * 1), Ty);
|
||||
}
|
||||
Constant *ConstantDataVector::getByte(Type *ElementType,
|
||||
ArrayRef<uint16_t> Elts) {
|
||||
assert(ElementType->isByteTy(16) && "Element type is not a 16-bit byte");
|
||||
auto *Ty = FixedVectorType::get(ElementType, Elts.size());
|
||||
const char *Data = reinterpret_cast<const char *>(Elts.data());
|
||||
return getImpl(StringRef(Data, Elts.size() * 2), Ty);
|
||||
}
|
||||
Constant *ConstantDataVector::getByte(Type *ElementType,
|
||||
ArrayRef<uint32_t> Elts) {
|
||||
assert(ElementType->isByteTy(32) && "Element type is not a 32-bit byte");
|
||||
auto *Ty = FixedVectorType::get(ElementType, Elts.size());
|
||||
const char *Data = reinterpret_cast<const char *>(Elts.data());
|
||||
return getImpl(StringRef(Data, Elts.size() * 4), Ty);
|
||||
}
|
||||
Constant *ConstantDataVector::getByte(Type *ElementType,
|
||||
ArrayRef<uint64_t> Elts) {
|
||||
assert(ElementType->isByteTy(64) && "Element type is not a 64-bit byte");
|
||||
auto *Ty = FixedVectorType::get(ElementType, Elts.size());
|
||||
const char *Data = reinterpret_cast<const char *>(Elts.data());
|
||||
return getImpl(StringRef(Data, Elts.size() * 8), Ty);
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -3098,6 +3346,24 @@ Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) {
|
||||
return get(V->getContext(), Elts);
|
||||
}
|
||||
|
||||
if (ConstantByte *CB = dyn_cast<ConstantByte>(V)) {
|
||||
if (CB->getType()->isByteTy(8)) {
|
||||
SmallVector<uint8_t, 16> Elts(NumElts, CB->getZExtValue());
|
||||
return getByte(V->getType(), Elts);
|
||||
}
|
||||
if (CB->getType()->isByteTy(16)) {
|
||||
SmallVector<uint16_t, 16> Elts(NumElts, CB->getZExtValue());
|
||||
return getByte(V->getType(), Elts);
|
||||
}
|
||||
if (CB->getType()->isByteTy(32)) {
|
||||
SmallVector<uint32_t, 16> Elts(NumElts, CB->getZExtValue());
|
||||
return getByte(V->getType(), Elts);
|
||||
}
|
||||
assert(CB->getType()->isByteTy(64) && "Unsupported ConstantData type");
|
||||
SmallVector<uint64_t, 16> Elts(NumElts, CB->getZExtValue());
|
||||
return getByte(V->getType(), Elts);
|
||||
}
|
||||
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
|
||||
if (CFP->getType()->isHalfTy()) {
|
||||
SmallVector<uint16_t, 16> Elts(
|
||||
@ -3124,13 +3390,14 @@ Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) {
|
||||
}
|
||||
|
||||
uint64_t ConstantDataSequential::getElementAsInteger(uint64_t Elt) const {
|
||||
assert(isa<IntegerType>(getElementType()) &&
|
||||
"Accessor can only be used when element is an integer");
|
||||
assert(
|
||||
(isa<IntegerType>(getElementType()) || isa<ByteType>(getElementType())) &&
|
||||
"Accessor can only be used when element is an integer or byte");
|
||||
const char *EltPtr = getElementPointer(Elt);
|
||||
|
||||
// The data is stored in host byte order, make sure to cast back to the right
|
||||
// type to load with the right endianness.
|
||||
switch (getElementType()->getIntegerBitWidth()) {
|
||||
switch (getElementType()->getScalarSizeInBits()) {
|
||||
default: llvm_unreachable("Invalid bitwidth for CDS");
|
||||
case 8:
|
||||
return *reinterpret_cast<const uint8_t *>(EltPtr);
|
||||
@ -3144,13 +3411,14 @@ uint64_t ConstantDataSequential::getElementAsInteger(uint64_t Elt) const {
|
||||
}
|
||||
|
||||
APInt ConstantDataSequential::getElementAsAPInt(uint64_t Elt) const {
|
||||
assert(isa<IntegerType>(getElementType()) &&
|
||||
"Accessor can only be used when element is an integer");
|
||||
assert(
|
||||
(isa<IntegerType>(getElementType()) || isa<ByteType>(getElementType())) &&
|
||||
"Accessor can only be used when element is an integer or byte");
|
||||
const char *EltPtr = getElementPointer(Elt);
|
||||
|
||||
// The data is stored in host byte order, make sure to cast back to the right
|
||||
// type to load with the right endianness.
|
||||
switch (getElementType()->getIntegerBitWidth()) {
|
||||
switch (getElementType()->getScalarSizeInBits()) {
|
||||
default: llvm_unreachable("Invalid bitwidth for CDS");
|
||||
case 8: {
|
||||
auto EltVal = *reinterpret_cast<const uint8_t *>(EltPtr);
|
||||
@ -3213,11 +3481,16 @@ Constant *ConstantDataSequential::getElementAsConstant(uint64_t Elt) const {
|
||||
getElementType()->isFloatTy() || getElementType()->isDoubleTy())
|
||||
return ConstantFP::get(getContext(), getElementAsAPFloat(Elt));
|
||||
|
||||
if (getElementType()->isByteTy())
|
||||
return ConstantByte::get(getElementType(), getElementAsInteger(Elt));
|
||||
|
||||
return ConstantInt::get(getElementType(), getElementAsInteger(Elt));
|
||||
}
|
||||
|
||||
bool ConstantDataSequential::isString(unsigned CharSize) const {
|
||||
return isa<ArrayType>(getType()) && getElementType()->isIntegerTy(CharSize);
|
||||
return isa<ArrayType>(getType()) &&
|
||||
(getElementType()->isIntegerTy(CharSize) ||
|
||||
getElementType()->isByteTy(CharSize));
|
||||
}
|
||||
|
||||
bool ConstantDataSequential::isCString() const {
|
||||
|
||||
@ -621,6 +621,8 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
|
||||
return LLVMLabelTypeKind;
|
||||
case Type::MetadataTyID:
|
||||
return LLVMMetadataTypeKind;
|
||||
case Type::ByteTyID:
|
||||
return LLVMByteTypeKind;
|
||||
case Type::IntegerTyID:
|
||||
return LLVMIntegerTypeKind;
|
||||
case Type::FunctionTyID:
|
||||
@ -672,6 +674,16 @@ char *LLVMPrintTypeToString(LLVMTypeRef Ty) {
|
||||
return strdup(buf.c_str());
|
||||
}
|
||||
|
||||
/*--.. Operations on byte types ............................................--*/
|
||||
|
||||
LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C, unsigned NumBits) {
|
||||
return wrap(ByteType::get(*unwrap(C), NumBits));
|
||||
}
|
||||
|
||||
unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy) {
|
||||
return unwrap<ByteType>(ByteTy)->getBitWidth();
|
||||
}
|
||||
|
||||
/*--.. Operations on integer types .........................................--*/
|
||||
|
||||
LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C) {
|
||||
@ -1572,6 +1584,30 @@ LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy, const char Str[],
|
||||
Radix));
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMConstByte(LLVMTypeRef ByteTy, unsigned long long N) {
|
||||
return wrap(ConstantByte::get(unwrap<ByteType>(ByteTy), N));
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMConstByteOfArbitraryPrecision(LLVMTypeRef ByteTy,
|
||||
unsigned NumWords,
|
||||
const uint64_t Words[]) {
|
||||
ByteType *Ty = unwrap<ByteType>(ByteTy);
|
||||
return wrap(ConstantByte::get(
|
||||
Ty->getContext(), APInt(Ty->getBitWidth(), ArrayRef(Words, NumWords))));
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMConstByteOfString(LLVMTypeRef ByteTy, const char Str[],
|
||||
uint8_t Radix) {
|
||||
return wrap(
|
||||
ConstantByte::get(unwrap<ByteType>(ByteTy), StringRef(Str), Radix));
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy, const char Str[],
|
||||
size_t SLen, uint8_t Radix) {
|
||||
return wrap(
|
||||
ConstantByte::get(unwrap<ByteType>(ByteTy), StringRef(Str, SLen), Radix));
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N) {
|
||||
return wrap(ConstantFP::get(unwrap(RealTy), N));
|
||||
}
|
||||
@ -1601,6 +1637,14 @@ long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal) {
|
||||
return unwrap<ConstantInt>(ConstantVal)->getSExtValue();
|
||||
}
|
||||
|
||||
unsigned long long LLVMConstByteGetZExtValue(LLVMValueRef ConstantVal) {
|
||||
return unwrap<ConstantByte>(ConstantVal)->getZExtValue();
|
||||
}
|
||||
|
||||
long long LLVMConstByteGetSExtValue(LLVMValueRef ConstantVal) {
|
||||
return unwrap<ConstantByte>(ConstantVal)->getSExtValue();
|
||||
}
|
||||
|
||||
double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *LosesInfo) {
|
||||
ConstantFP *cFP = unwrap<ConstantFP>(ConstantVal) ;
|
||||
Type *Ty = cFP->getType();
|
||||
|
||||
@ -874,6 +874,9 @@ Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
|
||||
const Align Align = abi_or_pref ? StructABIAlignment : StructPrefAlignment;
|
||||
return std::max(Align, Layout->getAlignment());
|
||||
}
|
||||
case Type::ByteTyID:
|
||||
// The byte type has the same alignment as the equally sized integer type.
|
||||
return getIntegerAlignment(Ty->getByteBitWidth(), abi_or_pref);
|
||||
case Type::IntegerTyID:
|
||||
return getIntegerAlignment(Ty->getIntegerBitWidth(), abi_or_pref);
|
||||
case Type::HalfTyID:
|
||||
@ -988,6 +991,21 @@ Type *DataLayout::getIntPtrType(Type *Ty) const {
|
||||
return IntTy;
|
||||
}
|
||||
|
||||
ByteType *DataLayout::getBytePtrType(LLVMContext &C,
|
||||
unsigned AddressSpace) const {
|
||||
return ByteType::get(C, getPointerSizeInBits(AddressSpace));
|
||||
}
|
||||
|
||||
Type *DataLayout::getBytePtrType(Type *Ty) const {
|
||||
assert(Ty->isPtrOrPtrVectorTy() &&
|
||||
"Expected a pointer or pointer vector type.");
|
||||
unsigned NumBits = getPointerTypeSizeInBits(Ty);
|
||||
ByteType *ByteTy = ByteType::get(Ty->getContext(), NumBits);
|
||||
if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
|
||||
return VectorType::get(ByteTy, VecTy);
|
||||
return ByteTy;
|
||||
}
|
||||
|
||||
Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const {
|
||||
for (unsigned LegalIntWidth : LegalIntWidths)
|
||||
if (Width <= LegalIntWidth)
|
||||
|
||||
@ -3242,7 +3242,16 @@ CastInst::getCastOpcode(
|
||||
DestTy->getPrimitiveSizeInBits().getFixedValue(); // 0 for ptr
|
||||
|
||||
// Run through the possibilities ...
|
||||
if (DestTy->isIntegerTy()) { // Casting to integral
|
||||
if (DestTy->isByteTy()) { // Casting to byte
|
||||
if (SrcTy->isIntegerTy()) { // Casting from integral
|
||||
assert(DestBits == SrcBits && "Illegal cast from integer to byte type");
|
||||
return BitCast;
|
||||
} else if (SrcTy->isPointerTy()) { // Casting from pointer
|
||||
assert(DestBits == SrcBits && "Illegal cast from pointer to byte type");
|
||||
return BitCast;
|
||||
}
|
||||
llvm_unreachable("Illegal cast to byte type");
|
||||
} else if (DestTy->isIntegerTy()) { // Casting to integral
|
||||
if (SrcTy->isIntegerTy()) { // Casting from integral
|
||||
if (DestBits < SrcBits)
|
||||
return Trunc; // int -> smaller int
|
||||
@ -3374,7 +3383,10 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
|
||||
PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
|
||||
|
||||
// BitCast implies a no-op cast of type only. No bits change.
|
||||
// However, you can't cast pointers to anything but pointers.
|
||||
// However, you can't cast pointers to anything but pointers/bytes.
|
||||
if ((SrcPtrTy && DstTy->isByteOrByteVectorTy()) ||
|
||||
(SrcTy->isByteOrByteVectorTy() && DstPtrTy))
|
||||
return true;
|
||||
if (!SrcPtrTy != !DstPtrTy)
|
||||
return false;
|
||||
|
||||
|
||||
@ -146,6 +146,9 @@ static std::string getMangledTypeStr(Type *Ty, bool &HasUnnamedType) {
|
||||
case Type::IntegerTyID:
|
||||
Result += "i" + utostr(cast<IntegerType>(Ty)->getBitWidth());
|
||||
break;
|
||||
case Type::ByteTyID:
|
||||
Result += "b" + utostr(cast<ByteType>(Ty)->getBitWidth());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
|
||||
@ -37,7 +37,8 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
|
||||
X86_FP80Ty(C, Type::X86_FP80TyID), FP128Ty(C, Type::FP128TyID),
|
||||
PPC_FP128Ty(C, Type::PPC_FP128TyID), X86_AMXTy(C, Type::X86_AMXTyID),
|
||||
Int1Ty(C, 1), Int8Ty(C, 8), Int16Ty(C, 16), Int32Ty(C, 32),
|
||||
Int64Ty(C, 64), Int128Ty(C, 128) {}
|
||||
Int64Ty(C, 64), Int128Ty(C, 128), Byte1Ty(C, 1), Byte8Ty(C, 8),
|
||||
Byte16Ty(C, 16), Byte32Ty(C, 32), Byte64Ty(C, 64), Byte128Ty(C, 128) {}
|
||||
|
||||
LLVMContextImpl::~LLVMContextImpl() {
|
||||
#ifndef NDEBUG
|
||||
@ -119,6 +120,10 @@ LLVMContextImpl::~LLVMContextImpl() {
|
||||
IntOneConstants.clear();
|
||||
IntConstants.clear();
|
||||
IntSplatConstants.clear();
|
||||
ByteZeroConstants.clear();
|
||||
ByteOneConstants.clear();
|
||||
ByteConstants.clear();
|
||||
ByteSplatConstants.clear();
|
||||
FPConstants.clear();
|
||||
FPSplatConstants.clear();
|
||||
CDSConstants.clear();
|
||||
|
||||
@ -1674,6 +1674,12 @@ public:
|
||||
DenseMap<std::pair<ElementCount, APInt>, std::unique_ptr<ConstantInt>>
|
||||
IntSplatConstants;
|
||||
|
||||
DenseMap<unsigned, std::unique_ptr<ConstantByte>> ByteZeroConstants;
|
||||
DenseMap<unsigned, std::unique_ptr<ConstantByte>> ByteOneConstants;
|
||||
DenseMap<APInt, std::unique_ptr<ConstantByte>> ByteConstants;
|
||||
DenseMap<std::pair<ElementCount, APInt>, std::unique_ptr<ConstantByte>>
|
||||
ByteSplatConstants;
|
||||
|
||||
DenseMap<APFloat, std::unique_ptr<ConstantFP>> FPConstants;
|
||||
DenseMap<std::pair<ElementCount, APFloat>, std::unique_ptr<ConstantFP>>
|
||||
FPSplatConstants;
|
||||
@ -1743,11 +1749,15 @@ public:
|
||||
ConstantInt *TheTrueVal = nullptr;
|
||||
ConstantInt *TheFalseVal = nullptr;
|
||||
|
||||
ConstantByte *TheTrueByteVal = nullptr;
|
||||
ConstantByte *TheFalseByteVal = nullptr;
|
||||
|
||||
// Basic type instances.
|
||||
Type VoidTy, LabelTy, HalfTy, BFloatTy, FloatTy, DoubleTy, MetadataTy,
|
||||
TokenTy;
|
||||
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_AMXTy;
|
||||
IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty;
|
||||
ByteType Byte1Ty, Byte8Ty, Byte16Ty, Byte32Ty, Byte64Ty, Byte128Ty;
|
||||
|
||||
std::unique_ptr<ConstantTokenNone> TheNoneToken;
|
||||
|
||||
@ -1756,6 +1766,7 @@ public:
|
||||
SpecificBumpPtrAllocator<ConstantRangeAttributeImpl>
|
||||
ConstantRangeAttributeAlloc;
|
||||
|
||||
DenseMap<unsigned, ByteType *> ByteTypes;
|
||||
DenseMap<unsigned, IntegerType *> IntegerTypes;
|
||||
|
||||
using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>;
|
||||
|
||||
@ -54,6 +54,10 @@ Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Type::isByteTy(unsigned BitWidth) const {
|
||||
return isByteTy() && cast<ByteType>(this)->getBitWidth() == BitWidth;
|
||||
}
|
||||
|
||||
bool Type::isIntegerTy(unsigned Bitwidth) const {
|
||||
return isIntegerTy() && cast<IntegerType>(this)->getBitWidth() == Bitwidth;
|
||||
}
|
||||
@ -212,6 +216,8 @@ TypeSize Type::getPrimitiveSizeInBits() const {
|
||||
return TypeSize::getFixed(128);
|
||||
case Type::X86_AMXTyID:
|
||||
return TypeSize::getFixed(8192);
|
||||
case Type::ByteTyID:
|
||||
return TypeSize::getFixed(cast<ByteType>(this)->getBitWidth());
|
||||
case Type::IntegerTyID:
|
||||
return TypeSize::getFixed(cast<IntegerType>(this)->getBitWidth());
|
||||
case Type::FixedVectorTyID:
|
||||
@ -290,6 +296,17 @@ Type *Type::getFP128Ty(LLVMContext &C) { return &C.pImpl->FP128Ty; }
|
||||
Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; }
|
||||
Type *Type::getX86_AMXTy(LLVMContext &C) { return &C.pImpl->X86_AMXTy; }
|
||||
|
||||
ByteType *Type::getByte1Ty(LLVMContext &C) { return &C.pImpl->Byte1Ty; }
|
||||
ByteType *Type::getByte8Ty(LLVMContext &C) { return &C.pImpl->Byte8Ty; }
|
||||
ByteType *Type::getByte16Ty(LLVMContext &C) { return &C.pImpl->Byte16Ty; }
|
||||
ByteType *Type::getByte32Ty(LLVMContext &C) { return &C.pImpl->Byte32Ty; }
|
||||
ByteType *Type::getByte64Ty(LLVMContext &C) { return &C.pImpl->Byte64Ty; }
|
||||
ByteType *Type::getByte128Ty(LLVMContext &C) { return &C.pImpl->Byte128Ty; }
|
||||
|
||||
ByteType *Type::getByteNTy(LLVMContext &C, unsigned N) {
|
||||
return ByteType::get(C, N);
|
||||
}
|
||||
|
||||
IntegerType *Type::getInt1Ty(LLVMContext &C) { return &C.pImpl->Int1Ty; }
|
||||
IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; }
|
||||
IntegerType *Type::getInt16Ty(LLVMContext &C) { return &C.pImpl->Int16Ty; }
|
||||
@ -301,6 +318,25 @@ IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) {
|
||||
return IntegerType::get(C, N);
|
||||
}
|
||||
|
||||
Type *Type::getIntFromByteType(Type *Ty) {
|
||||
assert(Ty->isByteOrByteVectorTy() && "Expected a byte or byte vector type.");
|
||||
unsigned NumBits = Ty->getScalarSizeInBits();
|
||||
IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
|
||||
if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
|
||||
return VectorType::get(IntTy, VecTy);
|
||||
return IntTy;
|
||||
}
|
||||
|
||||
Type *Type::getByteFromIntType(Type *Ty) {
|
||||
assert(!Ty->isPtrOrPtrVectorTy() &&
|
||||
"Expected a non-pointer or non-pointer vector type.");
|
||||
unsigned NumBits = Ty->getScalarSizeInBits();
|
||||
ByteType *ByteTy = ByteType::get(Ty->getContext(), NumBits);
|
||||
if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
|
||||
return VectorType::get(ByteTy, VecTy);
|
||||
return ByteTy;
|
||||
}
|
||||
|
||||
Type *Type::getWasm_ExternrefTy(LLVMContext &C) {
|
||||
// opaque pointer in addrspace(10)
|
||||
return PointerType::get(C, 10);
|
||||
@ -341,6 +377,40 @@ IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) {
|
||||
|
||||
APInt IntegerType::getMask() const { return APInt::getAllOnes(getBitWidth()); }
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ByteType Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ByteType *ByteType::get(LLVMContext &C, unsigned NumBits) {
|
||||
assert(NumBits >= MIN_BYTE_BITS && "bitwidth too small");
|
||||
assert(NumBits <= MAX_BYTE_BITS && "bitwidth too large");
|
||||
|
||||
// Check for the built-in byte types
|
||||
switch (NumBits) {
|
||||
case 8:
|
||||
return Type::getByte8Ty(C);
|
||||
case 16:
|
||||
return Type::getByte16Ty(C);
|
||||
case 32:
|
||||
return Type::getByte32Ty(C);
|
||||
case 64:
|
||||
return Type::getByte64Ty(C);
|
||||
case 128:
|
||||
return Type::getByte128Ty(C);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ByteType *&Entry = C.pImpl->ByteTypes[NumBits];
|
||||
|
||||
if (!Entry)
|
||||
Entry = new (C.pImpl->Alloc) ByteType(C, NumBits);
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
APInt ByteType::getMask() const { return APInt::getAllOnes(getBitWidth()); }
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FunctionType Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -788,7 +858,8 @@ VectorType *VectorType::get(Type *ElementType, ElementCount EC) {
|
||||
|
||||
bool VectorType::isValidElementType(Type *ElemTy) {
|
||||
if (ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() ||
|
||||
ElemTy->isPointerTy() || ElemTy->getTypeID() == TypedPointerTyID)
|
||||
ElemTy->isPointerTy() || ElemTy->getTypeID() == TypedPointerTyID ||
|
||||
ElemTy->isByteTy())
|
||||
return true;
|
||||
if (auto *TTy = dyn_cast<TargetExtType>(ElemTy))
|
||||
return TTy->hasProperty(TargetExtType::CanBeVectorElement);
|
||||
|
||||
@ -4640,9 +4640,10 @@ void Verifier::visitLoadInst(LoadInst &LI) {
|
||||
LI.getOrdering() != AtomicOrdering::AcquireRelease,
|
||||
"Load cannot have Release ordering", &LI);
|
||||
Check(ElTy->getScalarType()->isIntOrPtrTy() ||
|
||||
ElTy->getScalarType()->isByteTy() ||
|
||||
ElTy->getScalarType()->isFloatingPointTy(),
|
||||
"atomic load operand must have integer, pointer, floating point, "
|
||||
"or vector type!",
|
||||
"atomic load operand must have integer, byte, pointer, floating "
|
||||
"point, or vector type!",
|
||||
ElTy, &LI);
|
||||
|
||||
checkAtomicMemAccessSize(ElTy, &LI);
|
||||
@ -4668,9 +4669,10 @@ void Verifier::visitStoreInst(StoreInst &SI) {
|
||||
SI.getOrdering() != AtomicOrdering::AcquireRelease,
|
||||
"Store cannot have Acquire ordering", &SI);
|
||||
Check(ElTy->getScalarType()->isIntOrPtrTy() ||
|
||||
ElTy->getScalarType()->isByteTy() ||
|
||||
ElTy->getScalarType()->isFloatingPointTy(),
|
||||
"atomic store operand must have integer, pointer, floating point, "
|
||||
"or vector type!",
|
||||
"atomic store operand must have integer, byte, pointer, floating "
|
||||
"point, or vector type!",
|
||||
ElTy, &SI);
|
||||
checkAtomicMemAccessSize(ElTy, &SI);
|
||||
} else {
|
||||
|
||||
@ -316,6 +316,7 @@ unsigned HexagonTargetObjectFile::getSmallestAddressableSize(const Type *Ty,
|
||||
case Type::HalfTyID:
|
||||
case Type::FloatTyID:
|
||||
case Type::DoubleTyID:
|
||||
case Type::ByteTyID:
|
||||
case Type::IntegerTyID: {
|
||||
const DataLayout &DL = GV->getDataLayout();
|
||||
// It is unfortunate that DL's function take non-const Type*.
|
||||
|
||||
@ -74,6 +74,7 @@ Key: MetadataTy: [ 3.50 4.00 ]
|
||||
Key: VectorTy: [ 11.50 12.00 ]
|
||||
Key: TokenTy: [ 5.50 6.00 ]
|
||||
Key: IntegerTy: [ 6.50 7.00 ]
|
||||
Key: ByteTy: [ 0.00 0.00 ]
|
||||
Key: FunctionTy: [ 7.50 8.00 ]
|
||||
Key: PointerTy: [ 8.50 9.00 ]
|
||||
Key: StructTy: [ 9.50 10.00 ]
|
||||
|
||||
@ -74,6 +74,7 @@ Key: MetadataTy: [ 3.50 4.00 ]
|
||||
Key: VectorTy: [ 11.50 12.00 ]
|
||||
Key: TokenTy: [ 5.50 6.00 ]
|
||||
Key: IntegerTy: [ 6.50 7.00 ]
|
||||
Key: ByteTy: [ 0.00 0.00 ]
|
||||
Key: FunctionTy: [ 7.50 8.00 ]
|
||||
Key: PointerTy: [ 8.50 9.00 ]
|
||||
Key: StructTy: [ 9.50 10.00 ]
|
||||
|
||||
@ -74,6 +74,7 @@ Key: MetadataTy: [ 0.00 0.00 ]
|
||||
Key: VectorTy: [ 0.00 0.00 ]
|
||||
Key: TokenTy: [ 0.00 0.00 ]
|
||||
Key: IntegerTy: [ 0.00 0.00 ]
|
||||
Key: ByteTy: [ 0.00 0.00 ]
|
||||
Key: FunctionTy: [ 0.00 0.00 ]
|
||||
Key: PointerTy: [ 0.00 0.00 ]
|
||||
Key: StructTy: [ 0.00 0.00 ]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
; RUN: not llvm-as %s 2>&1 | FileCheck %s
|
||||
; PR2060
|
||||
|
||||
; CHECK: integer constant must have integer type
|
||||
; CHECK: integer/byte constant must have integer/byte type
|
||||
|
||||
define ptr @foo() {
|
||||
ret ptr 0
|
||||
|
||||
73
llvm/test/Assembler/byte-invalid.ll
Normal file
73
llvm/test/Assembler/byte-invalid.ll
Normal file
@ -0,0 +1,73 @@
|
||||
; RUN: split-file %s %t
|
||||
; RUN: not llvm-as -disable-output %t/zext-byte-to-int.ll 2>&1 | FileCheck %t/zext-byte-to-int.ll
|
||||
; RUN: not llvm-as -disable-output %t/sext-byte-to-int.ll 2>&1 | FileCheck %t/sext-byte-to-int.ll
|
||||
; RUN: not llvm-as -disable-output %t/trunc-byte-to-byte.ll 2>&1 | FileCheck %t/trunc-byte-to-byte.ll
|
||||
; RUN: not llvm-as -disable-output %t/zext-int-to-byte.ll 2>&1 | FileCheck %t/zext-int-to-byte.ll
|
||||
; RUN: not llvm-as -disable-output %t/sext-int-to-byte.ll 2>&1 | FileCheck %t/sext-int-to-byte.ll
|
||||
; RUN: not llvm-as -disable-output %t/trunc-int-to-byte.ll 2>&1 | FileCheck %t/trunc-int-to-byte.ll
|
||||
; RUN: not llvm-as -disable-output %t/trunc-byte-to-int.ll 2>&1 | FileCheck %t/trunc-byte-to-int.ll
|
||||
; RUN: not llvm-as -disable-output %t/lshr-byte.ll 2>&1 | FileCheck %t/lshr-byte.ll
|
||||
; RUN: not llvm-as -disable-output %t/icmp-byte.ll 2>&1 | FileCheck %t/icmp-byte.ll
|
||||
|
||||
;--- zext-byte-to-int.ll
|
||||
; CHECK: invalid cast opcode for cast from 'b8' to 'i32'
|
||||
define void @test(b8 %b) {
|
||||
%t = zext b8 %b to i32
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- sext-byte-to-int.ll
|
||||
; CHECK: invalid cast opcode for cast from 'b8' to 'i32'
|
||||
define void @test(b8 %b) {
|
||||
%t = sext b8 %b to i32
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- trunc-byte-to-byte.ll
|
||||
; CHECK: invalid cast opcode for cast from 'b32' to 'b8'
|
||||
define void @test(b32 %b) {
|
||||
%t = trunc b32 %b to b8
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- zext-int-to-byte.ll
|
||||
; CHECK: invalid cast opcode for cast from 'i8' to 'b32'
|
||||
define void @test(i8 %v) {
|
||||
%t = zext i8 %v to b32
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- sext-int-to-byte.ll
|
||||
; CHECK: invalid cast opcode for cast from 'i8' to 'b32'
|
||||
define void @test(i8 %v) {
|
||||
%t = sext i8 %v to b32
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- trunc-int-to-byte.ll
|
||||
; CHECK: invalid cast opcode for cast from 'i32' to 'b8'
|
||||
define void @test(i32 %v) {
|
||||
%t = trunc i32 %v to b8
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- trunc-byte-to-int.ll
|
||||
; CHECK: invalid cast opcode for cast from 'b32' to 'i8'
|
||||
define void @test(b32 %b) {
|
||||
%t = trunc b32 %b to i8
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- lshr-byte.ll
|
||||
; CHECK: invalid operand type for instruction
|
||||
define void @test(b32 %b) {
|
||||
%t = lshr b32 %b, 8
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- icmp-byte.ll
|
||||
; CHECK: icmp requires integer operands
|
||||
define void @test(b8 %b1, b8 %b2) {
|
||||
%cmp = icmp eq b8 %b1, %b2
|
||||
ret void
|
||||
}
|
||||
101
llvm/test/Assembler/byte.ll
Normal file
101
llvm/test/Assembler/byte.ll
Normal file
@ -0,0 +1,101 @@
|
||||
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
|
||||
|
||||
; CHECK: common global [32 x b8] zeroinitializer
|
||||
; CHECK: constant [1 x b8] zeroinitializer
|
||||
; CHECK: constant [15 x b8] c"Hello, World!\0A\00"
|
||||
; CHECK: constant [15 x b8] c"Hello, World!\0A\00"
|
||||
@a = common global [32 x b8] zeroinitializer, align 1
|
||||
@b = constant [1 x b8] zeroinitializer
|
||||
@c = constant [15 x b8] [b8 72, b8 101, b8 108, b8 108, b8 111, b8 44, b8 32, b8 87, b8 111, b8 114, b8 108, b8 100, b8 33, b8 10, b8 0]
|
||||
@d = constant [15 x b8] c"Hello, World!\0A\00"
|
||||
|
||||
define void @bytes(b1 %a, b3 %b, b5 %c, b8 %d, b16 %e, b32 %f, b64 %g, b128 %h, <8 x b5> %i, <2 x b64> %j) {
|
||||
; CHECK-LABEL: define void @bytes(
|
||||
; CHECK-SAME: b1 [[A:%.*]], b3 [[B:%.*]], b5 [[C:%.*]], b8 [[D:%.*]], b16 [[E:%.*]], b32 [[F:%.*]], b64 [[G:%.*]], b128 [[H:%.*]], <8 x b5> [[I:%.*]], <2 x b64> [[J:%.*]]) {
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @byte_alloca() {
|
||||
; CHECK-LABEL: define void @byte_alloca() {
|
||||
; CHECK-NEXT: [[B1:%.*]] = alloca b8, align 1
|
||||
; CHECK-NEXT: [[B8:%.*]] = alloca b64, align 8
|
||||
; CHECK-NEXT: [[V:%.*]] = alloca <4 x b64>, align 32
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca [4 x b64], align 8
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%b1 = alloca b8
|
||||
%b8 = alloca b64
|
||||
%v = alloca <4 x b64>
|
||||
%a = alloca [4 x b64]
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @byte_load_store(ptr %ptr) {
|
||||
; CHECK-LABEL: define void @byte_load_store(
|
||||
; CHECK-SAME: ptr [[PTR:%.*]]) {
|
||||
; CHECK-NEXT: [[B:%.*]] = load b8, ptr [[PTR]], align 1
|
||||
; CHECK-NEXT: store b8 [[B]], ptr [[PTR]], align 1
|
||||
; CHECK-NEXT: store b8 0, ptr [[PTR]], align 1
|
||||
; CHECK-NEXT: [[V:%.*]] = load <4 x b64>, ptr [[PTR]], align 32
|
||||
; CHECK-NEXT: store <4 x b64> [[V]], ptr [[PTR]], align 32
|
||||
; CHECK-NEXT: store <4 x b64> <b64 0, b64 1, b64 2, b64 3>, ptr [[PTR]], align 32
|
||||
; CHECK-NEXT: [[A:%.*]] = load [4 x b8], ptr [[PTR]], align 1
|
||||
; CHECK-NEXT: store [4 x b8] [[A]], ptr [[PTR]], align 1
|
||||
; CHECK-NEXT: store [4 x b8] c"\00\01\02\03", ptr [[PTR]], align 1
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%b = load b8, ptr %ptr
|
||||
store b8 %b, ptr %ptr
|
||||
store b8 0, ptr %ptr
|
||||
%v = load <4 x b64>, ptr %ptr
|
||||
store <4 x b64> %v, ptr %ptr
|
||||
store <4 x b64> <b64 0, b64 1, b64 2, b64 3>, ptr %ptr
|
||||
%a = load [4 x b8], ptr %ptr
|
||||
store [4 x b8] %a, ptr %ptr
|
||||
store [4 x b8] [b8 0, b8 1, b8 2, b8 3], ptr %ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @bitcasts(i64 %i, b64 %b, ptr %p) {
|
||||
; CHECK-LABEL: define void @bitcasts(
|
||||
; CHECK-SAME: i64 [[I:%.*]], b64 [[B:%.*]], ptr [[P:%.*]]) {
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast ptr [[P]] to b64
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[I]] to b64
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = bitcast b64 [[B]] to <8 x b8>
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = bitcast b64 [[B]] to i64
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = bitcast b64 [[B]] to ptr
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = bitcast <8 x b8> [[TMP3]] to <2 x b32>
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = bitcast <2 x b32> [[TMP6]] to b64
|
||||
; CHECK-NEXT: [[TMP8:%.*]] = bitcast <2 x b32> splat (b32 1) to b64
|
||||
; CHECK-NEXT: [[TMP9:%.*]] = bitcast <8 x b8> [[TMP3]] to <4 x i16>
|
||||
; CHECK-NEXT: [[TMP10:%.*]] = bitcast <2 x b32> [[TMP6]] to ptr
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%1 = bitcast ptr %p to b64
|
||||
%2 = bitcast i64 %i to b64
|
||||
%3 = bitcast b64 %b to <8 x b8>
|
||||
%4 = bitcast b64 %b to i64
|
||||
%5 = bitcast b64 %b to ptr
|
||||
%6 = bitcast <8 x b8> %3 to <2 x b32>
|
||||
%7 = bitcast <2 x b32> %6 to b64
|
||||
%8 = bitcast <2 x b32> <b32 1, b32 1> to b64
|
||||
%9 = bitcast <8 x b8> %3 to <4 x i16>
|
||||
%10 = bitcast <2 x b32> %6 to ptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @freeze(b3 %t, b64 %b, <4 x b64> %v) {
|
||||
; CHECK-LABEL: define void @freeze(
|
||||
; CHECK-SAME: b3 [[T:%.*]], b64 [[B:%.*]], <4 x b64> [[V:%.*]]) {
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = freeze b3 [[T]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = freeze b64 [[B]]
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = freeze <4 x b64> [[V]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%1 = freeze b3 %t
|
||||
%2 = freeze b64 %b
|
||||
%3 = freeze <4 x b64> %v
|
||||
ret void
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
; RUN: not llvm-as --disable-output %s 2>&1 | FileCheck -DFILE=%s %s
|
||||
|
||||
; i8388609 is the smallest integer type that can't be represented in LLVM IR
|
||||
; CHECK: [[FILE]]:[[@LINE+1]]:21: error: bitwidth for integer type out of range
|
||||
; CHECK: [[FILE]]:[[@LINE+1]]:21: error: bitwidth for integer or byte type out of range
|
||||
@i2 = common global i8388609 0, align 4
|
||||
|
||||
11
llvm/test/Bindings/llvm-c/byte.ll
Normal file
11
llvm/test/Bindings/llvm-c/byte.ll
Normal file
@ -0,0 +1,11 @@
|
||||
; RUN: llvm-as < %s | llvm-dis > %t.orig
|
||||
; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo
|
||||
; RUN: diff -w %t.orig %t.echo
|
||||
|
||||
define void @foo(b8 %a, b16 %b, b64 %c) {
|
||||
%1 = alloca b16, align 2
|
||||
store b16 %b, ptr %1, align 2
|
||||
%2 = load b16, ptr %1, align 2
|
||||
%3 = bitcast b16 %2 to <2 x b8>
|
||||
ret void
|
||||
}
|
||||
@ -72,6 +72,7 @@ define void @types() {
|
||||
%10 = alloca ptr addrspace(5), align 8
|
||||
%11 = alloca <5 x ptr>, align 64
|
||||
%12 = alloca <1 x i64>, align 8
|
||||
%13 = alloca b8, align 1
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -1288,6 +1288,8 @@ define void @typesystem() {
|
||||
; CHECK: %t9 = alloca <4 x i32>
|
||||
%t10 = alloca <vscale x 4 x i32>
|
||||
; CHECK: %t10 = alloca <vscale x 4 x i32>
|
||||
%t11 = alloca b8
|
||||
; CHECK: %t11 = alloca b8
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
63
llvm/test/CodeGen/X86/byte-constants.ll
Normal file
63
llvm/test/CodeGen/X86/byte-constants.ll
Normal file
@ -0,0 +1,63 @@
|
||||
; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s
|
||||
|
||||
; CHECK: .globl x
|
||||
; CHECK: x:
|
||||
; CHECK: .quad 10
|
||||
|
||||
@x = global b64 bitcast (i64 10 to b64)
|
||||
|
||||
; CHECK: .globl b
|
||||
; CHECK: b:
|
||||
; CHECK: .byte 1
|
||||
|
||||
@b = global b1 1
|
||||
|
||||
; CHECK: .globl f
|
||||
; CHECK: f:
|
||||
; CHECK: .byte 31
|
||||
|
||||
@f = global b5 31
|
||||
|
||||
; CHECK: .globl r
|
||||
; CHECK: r:
|
||||
; CHECK: .long 42
|
||||
|
||||
@r = global b32 42
|
||||
|
||||
; CHECK: .globl w
|
||||
; CHECK: w:
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
|
||||
@w = global b128 -1
|
||||
|
||||
; CHECK: .globl uw
|
||||
; CHECK: uw:
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
|
||||
@uw = global b256 -1
|
||||
|
||||
; CHECK: .globl v
|
||||
; CHECK: v:
|
||||
; CHECK: .byte 1
|
||||
; CHECK: .byte 2
|
||||
; CHECK: .byte 3
|
||||
; CHECK: .byte 4
|
||||
|
||||
@v = global <4 x b8> <b8 1, b8 2, b8 3, b8 4>
|
||||
|
||||
; CHECK: .globl uv
|
||||
; CHECK: uv:
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
; CHECK: .quad -1
|
||||
|
||||
@uv = global <4 x b128> <b128 -1, b128 -1, b128 -1, b128 -1>
|
||||
@ -1,6 +1,6 @@
|
||||
; RUN: not opt -passes=verify < %s 2>&1 | FileCheck %s
|
||||
; CHECK: atomic store operand must have integer, pointer, floating point, or vector type!
|
||||
; CHECK: atomic load operand must have integer, pointer, floating point, or vector type!
|
||||
; CHECK: atomic store operand must have integer, byte, pointer, floating point, or vector type!
|
||||
; CHECK: atomic load operand must have integer, byte, pointer, floating point, or vector type!
|
||||
|
||||
%ty = type { i32 };
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
; RUN: llvm-ir2vec entities | FileCheck %s
|
||||
|
||||
CHECK: 111
|
||||
CHECK: 112
|
||||
CHECK-NEXT: Ret 0
|
||||
CHECK-NEXT: UncondBr 1
|
||||
CHECK-NEXT: CondBr 2
|
||||
@ -77,38 +77,39 @@ CHECK-NEXT: MetadataTy 72
|
||||
CHECK-NEXT: VectorTy 73
|
||||
CHECK-NEXT: TokenTy 74
|
||||
CHECK-NEXT: IntegerTy 75
|
||||
CHECK-NEXT: FunctionTy 76
|
||||
CHECK-NEXT: PointerTy 77
|
||||
CHECK-NEXT: StructTy 78
|
||||
CHECK-NEXT: ArrayTy 79
|
||||
CHECK-NEXT: UnknownTy 80
|
||||
CHECK-NEXT: Function 81
|
||||
CHECK-NEXT: Pointer 82
|
||||
CHECK-NEXT: Constant 83
|
||||
CHECK-NEXT: Variable 84
|
||||
CHECK-NEXT: FCMP_false 85
|
||||
CHECK-NEXT: FCMP_oeq 86
|
||||
CHECK-NEXT: FCMP_ogt 87
|
||||
CHECK-NEXT: FCMP_oge 88
|
||||
CHECK-NEXT: FCMP_olt 89
|
||||
CHECK-NEXT: FCMP_ole 90
|
||||
CHECK-NEXT: FCMP_one 91
|
||||
CHECK-NEXT: FCMP_ord 92
|
||||
CHECK-NEXT: FCMP_uno 93
|
||||
CHECK-NEXT: FCMP_ueq 94
|
||||
CHECK-NEXT: FCMP_ugt 95
|
||||
CHECK-NEXT: FCMP_uge 96
|
||||
CHECK-NEXT: FCMP_ult 97
|
||||
CHECK-NEXT: FCMP_ule 98
|
||||
CHECK-NEXT: FCMP_une 99
|
||||
CHECK-NEXT: FCMP_true 100
|
||||
CHECK-NEXT: ICMP_eq 101
|
||||
CHECK-NEXT: ICMP_ne 102
|
||||
CHECK-NEXT: ICMP_ugt 103
|
||||
CHECK-NEXT: ICMP_uge 104
|
||||
CHECK-NEXT: ICMP_ult 105
|
||||
CHECK-NEXT: ICMP_ule 106
|
||||
CHECK-NEXT: ICMP_sgt 107
|
||||
CHECK-NEXT: ICMP_sge 108
|
||||
CHECK-NEXT: ICMP_slt 109
|
||||
CHECK-NEXT: ICMP_sle 110
|
||||
CHECK-NEXT: ByteTy 76
|
||||
CHECK-NEXT: FunctionTy 77
|
||||
CHECK-NEXT: PointerTy 78
|
||||
CHECK-NEXT: StructTy 79
|
||||
CHECK-NEXT: ArrayTy 80
|
||||
CHECK-NEXT: UnknownTy 81
|
||||
CHECK-NEXT: Function 82
|
||||
CHECK-NEXT: Pointer 83
|
||||
CHECK-NEXT: Constant 84
|
||||
CHECK-NEXT: Variable 85
|
||||
CHECK-NEXT: FCMP_false 86
|
||||
CHECK-NEXT: FCMP_oeq 87
|
||||
CHECK-NEXT: FCMP_ogt 88
|
||||
CHECK-NEXT: FCMP_oge 89
|
||||
CHECK-NEXT: FCMP_olt 90
|
||||
CHECK-NEXT: FCMP_ole 91
|
||||
CHECK-NEXT: FCMP_one 92
|
||||
CHECK-NEXT: FCMP_ord 93
|
||||
CHECK-NEXT: FCMP_uno 94
|
||||
CHECK-NEXT: FCMP_ueq 95
|
||||
CHECK-NEXT: FCMP_ugt 96
|
||||
CHECK-NEXT: FCMP_uge 97
|
||||
CHECK-NEXT: FCMP_ult 98
|
||||
CHECK-NEXT: FCMP_ule 99
|
||||
CHECK-NEXT: FCMP_une 100
|
||||
CHECK-NEXT: FCMP_true 101
|
||||
CHECK-NEXT: ICMP_eq 102
|
||||
CHECK-NEXT: ICMP_ne 103
|
||||
CHECK-NEXT: ICMP_ugt 104
|
||||
CHECK-NEXT: ICMP_uge 105
|
||||
CHECK-NEXT: ICMP_ult 106
|
||||
CHECK-NEXT: ICMP_ule 107
|
||||
CHECK-NEXT: ICMP_sgt 108
|
||||
CHECK-NEXT: ICMP_sge 109
|
||||
CHECK-NEXT: ICMP_slt 110
|
||||
CHECK-NEXT: ICMP_sle 111
|
||||
|
||||
@ -26,40 +26,40 @@ entry:
|
||||
|
||||
; TRIPLETS: MAX_RELATION=3
|
||||
; TRIPLETS-NEXT: 13 75 0
|
||||
; TRIPLETS-NEXT: 13 84 2
|
||||
; TRIPLETS-NEXT: 13 84 3
|
||||
; TRIPLETS-NEXT: 13 85 2
|
||||
; TRIPLETS-NEXT: 13 85 3
|
||||
; TRIPLETS-NEXT: 13 0 1
|
||||
; TRIPLETS-NEXT: 0 70 0
|
||||
; TRIPLETS-NEXT: 0 84 2
|
||||
; TRIPLETS-NEXT: 0 85 2
|
||||
; TRIPLETS-NEXT: 17 75 0
|
||||
; TRIPLETS-NEXT: 17 84 2
|
||||
; TRIPLETS-NEXT: 17 84 3
|
||||
; TRIPLETS-NEXT: 17 85 2
|
||||
; TRIPLETS-NEXT: 17 85 3
|
||||
; TRIPLETS-NEXT: 17 0 1
|
||||
; TRIPLETS-NEXT: 0 70 0
|
||||
; TRIPLETS-NEXT: 0 84 2
|
||||
; TRIPLETS-NEXT: 31 77 0
|
||||
; TRIPLETS-NEXT: 31 83 2
|
||||
; TRIPLETS-NEXT: 0 85 2
|
||||
; TRIPLETS-NEXT: 31 78 0
|
||||
; TRIPLETS-NEXT: 31 84 2
|
||||
; TRIPLETS-NEXT: 31 31 1
|
||||
; TRIPLETS-NEXT: 31 77 0
|
||||
; TRIPLETS-NEXT: 31 83 2
|
||||
; TRIPLETS-NEXT: 31 78 0
|
||||
; TRIPLETS-NEXT: 31 84 2
|
||||
; TRIPLETS-NEXT: 31 33 1
|
||||
; TRIPLETS-NEXT: 33 70 0
|
||||
; TRIPLETS-NEXT: 33 84 2
|
||||
; TRIPLETS-NEXT: 33 82 3
|
||||
; TRIPLETS-NEXT: 33 85 2
|
||||
; TRIPLETS-NEXT: 33 83 3
|
||||
; TRIPLETS-NEXT: 33 33 1
|
||||
; TRIPLETS-NEXT: 33 70 0
|
||||
; TRIPLETS-NEXT: 33 84 2
|
||||
; TRIPLETS-NEXT: 33 82 3
|
||||
; TRIPLETS-NEXT: 33 85 2
|
||||
; TRIPLETS-NEXT: 33 83 3
|
||||
; TRIPLETS-NEXT: 33 32 1
|
||||
; TRIPLETS-NEXT: 32 75 0
|
||||
; TRIPLETS-NEXT: 32 82 2
|
||||
; TRIPLETS-NEXT: 32 83 2
|
||||
; TRIPLETS-NEXT: 32 32 1
|
||||
; TRIPLETS-NEXT: 32 75 0
|
||||
; TRIPLETS-NEXT: 32 82 2
|
||||
; TRIPLETS-NEXT: 32 83 2
|
||||
; TRIPLETS-NEXT: 32 13 1
|
||||
; TRIPLETS-NEXT: 13 75 0
|
||||
; TRIPLETS-NEXT: 13 84 2
|
||||
; TRIPLETS-NEXT: 13 84 3
|
||||
; TRIPLETS-NEXT: 13 85 2
|
||||
; TRIPLETS-NEXT: 13 85 3
|
||||
; TRIPLETS-NEXT: 13 0 1
|
||||
; TRIPLETS-NEXT: 0 70 0
|
||||
; TRIPLETS-NEXT: 0 84 2
|
||||
; TRIPLETS-NEXT: 0 85 2
|
||||
|
||||
@ -89,6 +89,8 @@ struct TypeCloner {
|
||||
return LLVMPPCFP128TypeInContext(Ctx);
|
||||
case LLVMLabelTypeKind:
|
||||
return LLVMLabelTypeInContext(Ctx);
|
||||
case LLVMByteTypeKind:
|
||||
return LLVMByteTypeInContext(Ctx, LLVMGetByteTypeWidth(Src));
|
||||
case LLVMIntegerTypeKind:
|
||||
return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));
|
||||
case LLVMFunctionTypeKind: {
|
||||
|
||||
@ -363,8 +363,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_Symbolic) {
|
||||
EXPECT_EQ(AddEmb.size(), 2u);
|
||||
EXPECT_EQ(RetEmb.size(), 2u);
|
||||
|
||||
EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.9)));
|
||||
EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.7)));
|
||||
EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 26.1)));
|
||||
EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.8)));
|
||||
}
|
||||
|
||||
TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
|
||||
@ -376,8 +376,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
|
||||
EXPECT_EQ(AddEmb.size(), 2u);
|
||||
EXPECT_EQ(RetEmb.size(), 2u);
|
||||
|
||||
EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.9)));
|
||||
EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 33.1)));
|
||||
EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 26.1)));
|
||||
EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 33.3)));
|
||||
}
|
||||
|
||||
TEST_F(IR2VecTestFixture, GetBBVector_Symbolic) {
|
||||
@ -387,9 +387,9 @@ TEST_F(IR2VecTestFixture, GetBBVector_Symbolic) {
|
||||
const auto &BBVec = Emb->getBBVector(*BB);
|
||||
|
||||
EXPECT_EQ(BBVec.size(), 2u);
|
||||
// BB vector should be sum of add and ret: {25.9, 25.9} + {15.7, 15.7} =
|
||||
// {41.6, 41.6}
|
||||
EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.6)));
|
||||
// BB vector should be sum of add and ret: {26.1, 26.1} + {15.8, 15.8} =
|
||||
// {41.9, 41.9}
|
||||
EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.9)));
|
||||
}
|
||||
|
||||
TEST_F(IR2VecTestFixture, GetBBVector_FlowAware) {
|
||||
@ -399,9 +399,9 @@ TEST_F(IR2VecTestFixture, GetBBVector_FlowAware) {
|
||||
const auto &BBVec = Emb->getBBVector(*BB);
|
||||
|
||||
EXPECT_EQ(BBVec.size(), 2u);
|
||||
// BB vector should be sum of add and ret: {25.9, 25.9} + {33.1, 33.1} =
|
||||
// {59.0, 59.0}
|
||||
EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 59.0)));
|
||||
// BB vector should be sum of add and ret: {26.1, 26.1} + {33.3, 33.3} =
|
||||
// {59.4, 59.4}
|
||||
EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 59.4)));
|
||||
}
|
||||
|
||||
TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
|
||||
@ -412,8 +412,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
|
||||
|
||||
EXPECT_EQ(FuncVec.size(), 2u);
|
||||
|
||||
// Function vector should match BB vector (only one BB): {41.6, 41.6}
|
||||
EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.6)));
|
||||
// Function vector should match BB vector (only one BB): {41.9, 41.9}
|
||||
EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.9)));
|
||||
}
|
||||
|
||||
TEST_F(IR2VecTestFixture, GetFunctionVector_FlowAware) {
|
||||
@ -423,8 +423,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector_FlowAware) {
|
||||
const auto &FuncVec = Emb->getFunctionVector();
|
||||
|
||||
EXPECT_EQ(FuncVec.size(), 2u);
|
||||
// Function vector should match BB vector (only one BB): {59.0, 59.0}
|
||||
EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 59.0)));
|
||||
// Function vector should match BB vector (only one BB): {59.4, 59.4}
|
||||
EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 59.4)));
|
||||
}
|
||||
|
||||
TEST_F(IR2VecTestFixture, MultipleComputeEmbeddingsConsistency_Symbolic) {
|
||||
@ -480,6 +480,7 @@ static constexpr unsigned MaxPredicateKinds = Vocabulary::MaxPredicateKinds;
|
||||
// names and their canonical string keys.
|
||||
#define IR2VEC_HANDLE_TYPE_BIMAP(X) \
|
||||
X(VoidTyID, VoidTy, "VoidTy") \
|
||||
X(ByteTyID, ByteTy, "ByteTy") \
|
||||
X(IntegerTyID, IntegerTy, "IntegerTy") \
|
||||
X(FloatTyID, FloatTy, "FloatTy") \
|
||||
X(PointerTyID, PointerTy, "PointerTy") \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user