[IR] Add initial support for the byte type (#178666)

Following the [byte type RFC](https://discourse.llvm.org/t/rfc-add-a-new-byte-type-to-llvm-ir/89522)
and the discussions within the [LLVM IR Formal Specification WG](https://discourse.llvm.org/t/rfc-forming-a-working-group-on-formal-specification-for-llvm/89056), this PR introduces initial support for the byte type in LLVM. This PR:
- Adds the byte type to LLVM's type system
- Extends the `bitcast` instruction to accept the byte operands
- Adds parsing tests for all new functionality
- Fixes failing regressions tests (IR2Vec and IRNormalizer)

---------

Co-authored-by: George Mitenkov <georgemitenk0v@gmail.com>
This commit is contained in:
Pedro Lobo 2026-03-15 21:56:06 +00:00 committed by GitHub
parent 36041192cf
commit 80f2ef70f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
46 changed files with 1488 additions and 168 deletions

View File

@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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 {

View File

@ -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) {

View File

@ -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.
//

View File

@ -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)

View File

@ -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;
}

View File

@ -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() ||

View File

@ -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))

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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 << ')';

View File

@ -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);
}

View File

@ -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 {

View File

@ -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();

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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>;

View File

@ -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);

View File

@ -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 {

View File

@ -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*.

View File

@ -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 ]

View File

@ -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 ]

View File

@ -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 ]

View File

@ -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

View 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
View 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
}

View File

@ -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

View 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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -0,0 +1,63 @@
; RUN: llc < %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>

View File

@ -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 };

View File

@ -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

View File

@ -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

View File

@ -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: {

View File

@ -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") \