[llvm] [IR] Add initial support for the byte type (PR #178666)
Pedro Lobo via llvm-commits
llvm-commits at lists.llvm.org
Sun Mar 15 14:01:40 PDT 2026
https://github.com/pedroclobo updated https://github.com/llvm/llvm-project/pull/178666
>From e6649bb1affd4db11a058e463c4ebf98adceda7b Mon Sep 17 00:00:00 2001
From: George Mitenkov <georgemitenk0v at gmail.com>
Date: Thu, 22 Jul 2021 14:29:05 +0300
Subject: [PATCH 1/6] [IR] Introduce the byte type
- Adds the byte type
- Extends the `bitcast` instruction to accept byte operands
- Fixes `IR2Vec` tests
---
llvm/include/llvm-c/Core.h | 93 +++++
llvm/include/llvm/Analysis/IR2Vec.h | 8 +-
llvm/include/llvm/Bitcode/LLVMBitCodes.h | 4 +
llvm/include/llvm/IR/Constants.h | 248 +++++++++++-
llvm/include/llvm/IR/DataLayout.h | 19 +
llvm/include/llvm/IR/DerivedTypes.h | 56 +++
llvm/include/llvm/IR/IRBuilder.h | 24 ++
llvm/include/llvm/IR/Type.h | 30 +-
llvm/include/llvm/IR/Value.def | 1 +
llvm/lib/AsmParser/LLLexer.cpp | 35 +-
llvm/lib/AsmParser/LLParser.cpp | 21 +-
llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 54 ++-
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 29 +-
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 87 ++++-
.../SelectionDAG/FunctionLoweringInfo.cpp | 2 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 3 +
llvm/lib/CodeGen/ValueTypes.cpp | 4 +
llvm/lib/IR/AsmWriter.cpp | 26 +-
llvm/lib/IR/Attributes.cpp | 4 +-
llvm/lib/IR/Constants.cpp | 355 +++++++++++++++++-
llvm/lib/IR/Core.cpp | 78 ++++
llvm/lib/IR/DataLayout.cpp | 37 ++
llvm/lib/IR/Instructions.cpp | 16 +-
llvm/lib/IR/Intrinsics.cpp | 3 +
llvm/lib/IR/LLVMContextImpl.cpp | 7 +-
llvm/lib/IR/LLVMContextImpl.h | 11 +
llvm/lib/IR/Type.cpp | 54 ++-
llvm/lib/IR/Verifier.cpp | 10 +-
.../DirectX/DXILWriter/DXILBitcodeWriter.cpp | 19 +
.../Hexagon/HexagonTargetObjectFile.cpp | 1 +
.../Inputs/reference_default_vocab_print.txt | 1 +
.../Inputs/reference_wtd1_vocab_print.txt | 1 +
.../Inputs/reference_wtd2_vocab_print.txt | 1 +
.../Assembler/2008-02-18-IntPointerCrash.ll | 2 +-
llvm/test/Assembler/byte-invalid-cast-1.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-2.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-3.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-4.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-5.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-6.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-7.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-8.ll | 7 +
llvm/test/Assembler/byte-invalid-cmp.ll | 7 +
llvm/test/Assembler/byte.ll | 102 +++++
llvm/test/Assembler/invalid-inttype.ll | 2 +-
llvm/test/Bindings/llvm-c/byte.ll | 11 +
llvm/test/Bindings/llvm-c/echo.ll | 1 +
llvm/test/Bitcode/compatibility.ll | 2 +
llvm/test/CodeGen/X86/byte-constants.ll | 63 ++++
llvm/test/Verifier/atomics.ll | 4 +-
llvm/test/tools/llvm-ir2vec/entities.ll | 73 ++--
llvm/test/tools/llvm-ir2vec/triplets.ll | 38 +-
llvm/tools/llvm-c-test/echo.cpp | 2 +
llvm/unittests/Analysis/IR2VecTest.cpp | 29 +-
54 files changed, 1584 insertions(+), 150 deletions(-)
create mode 100644 llvm/test/Assembler/byte-invalid-cast-1.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-2.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-3.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-4.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-5.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-6.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-7.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-8.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cmp.ll
create mode 100644 llvm/test/Assembler/byte.ll
create mode 100644 llvm/test/Bindings/llvm-c/byte.ll
create mode 100644 llvm/test/CodeGen/X86/byte-constants.ll
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 869031d9e1c73..4abad7d6bfab7 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -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,40 @@ 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.
+ */
+LLVMTypeRef LLVMByte8TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByte16TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByte32TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByte64TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByte128TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C, unsigned NumBits);
+
+/**
+ * Obtain a byte type from the global context with a specified bit
+ * width.
+ */
+LLVMTypeRef LLVMByte8Type(void);
+LLVMTypeRef LLVMByte16Type(void);
+LLVMTypeRef LLVMByte32Type(void);
+LLVMTypeRef LLVMByte64Type(void);
+LLVMTypeRef LLVMByte128Type(void);
+LLVMTypeRef LLVMByteType(unsigned NumBits);
+unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy);
+
/**
* @defgroup LLVMCCoreTypeInt Integer Types
*
@@ -2014,6 +2051,7 @@ LLVM_C_ABI unsigned LLVMGetTargetExtTypeIntParam(LLVMTypeRef TargetExtTy,
macro(ConstantExpr) \
macro(ConstantFP) \
macro(ConstantInt) \
+ macro(ConstantByte) \
macro(ConstantPointerNull) \
macro(ConstantStruct) \
macro(ConstantTokenNone) \
@@ -2427,6 +2465,47 @@ 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.
+ */
+LLVMValueRef LLVMConstByte(LLVMTypeRef ByteTy, unsigned long long N);
+
+/**
+ * Obtain a constant value for a byte of arbitrary precision.
+ *
+ * @see llvm::ConstantByte::get()
+ */
+LLVMValueRef LLVMConstByteOfArbitraryPrecision(LLVMTypeRef ByteTy,
+ unsigned NumWords,
+ const uint64_t Words[]);
+
+/**
+ * Obtain a constant value for a byte parsed from a string.
+ *
+ * A similar API, LLVMConstByteOfStringAndSize is also available. If the
+ * string's length is available, it is preferred to call that function
+ * instead.
+ *
+ * @see llvm::ConstantByte::get()
+ */
+LLVMValueRef LLVMConstByteOfString(LLVMTypeRef ByteTy, const char *Text,
+ uint8_t Radix);
+
+/**
+ * Obtain a constant value for a byte parsed from a string with specified
+ * length.
+ * @see llvm::ConstantByte::get()
+ */
+LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy, const char *Text,
+ unsigned SLen, uint8_t Radix);
+
/**
* Obtain a constant value referring to a double floating point value.
*/
@@ -2471,6 +2550,20 @@ 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()
+ */
+unsigned long long LLVMConstByteGetZExtValue(LLVMValueRef ConstantVal);
+
+/**
+ * Obtain the sign extended value for a byte constant value.
+ *
+ * @see llvm::ConstantByte::getSExtValue()
+ */
+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.
diff --git a/llvm/include/llvm/Analysis/IR2Vec.h b/llvm/include/llvm/Analysis/IR2Vec.h
index 922c65d5c8340..968873c918393 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -292,6 +292,7 @@ class Vocabulary {
VectorTy,
TokenTy,
IntegerTy,
+ ByteTy,
FunctionTy,
PointerTy,
StructTy,
@@ -465,9 +466,9 @@ class Vocabulary {
/// 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 @@ class Vocabulary {
CanonicalTypeID::VectorTy, // X86_AMXTyID
CanonicalTypeID::TokenTy, // TokenTyID
CanonicalTypeID::IntegerTy, // IntegerTyID
+ CanonicalTypeID::ByteTy, // ByteTyID
CanonicalTypeID::FunctionTy, // FunctionTyID
CanonicalTypeID::PointerTy, // PointerTyID
CanonicalTypeID::StructTy, // StructTyID
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index bcf596a0d79b2..4ac3029175d0d 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -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
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index a1f667353b26e..9d13798da13a3 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -276,6 +276,199 @@ class ConstantInt final : public ConstantData {
}
};
+//===----------------------------------------------------------------------===//
+/// 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;
+
+ LLVM_ABI static ConstantByte *getTrue(LLVMContext &Context);
+ LLVM_ABI static ConstantByte *getFalse(LLVMContext &Context);
+ LLVM_ABI static ConstantByte *getBool(LLVMContext &Context, bool V);
+ LLVM_ABI static Constant *getTrue(Type *Ty);
+ LLVM_ABI static Constant *getFalse(Type *Ty);
+ LLVM_ABI static Constant *getBool(Type *Ty, bool V);
+
+ /// If Ty is a vector type, return a Constant with a splat of the given
+ /// value. Otherwise return a 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(); }
+
+ /// Return the constant as an llvm::MaybeAlign.
+ /// Note that this method can assert if the value does not fit in 64 bits or
+ /// is not a power of two.
+ inline MaybeAlign getMaybeAlignValue() const {
+ return MaybeAlign(getZExtValue());
+ }
+
+ /// Return the constant as an llvm::Align, interpreting `0` as `Align(1)`.
+ /// Note that this method can assert if the value does not fit in 64 bits or
+ /// is not a power of two.
+ inline Align getAlignValue() const {
+ return getMaybeAlignValue().valueOrOne();
+ }
+
+ /// A helper method that can be used to determine if the constant contained
+ /// within is equal to a constant. This only works for very small values,
+ /// because this is all that can be represented with all types.
+ /// Determine if this constant's value is same as an unsigned char.
+ bool equalsByte(uint64_t V) const { return Val == V; }
+
+ /// 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());
+ }
+
+ /// This static method returns true if the type Ty is big enough to
+ /// represent the value V. This can be used to avoid having the get method
+ /// assert when V is larger than Ty can represent. Note that there are two
+ /// versions of this method, one for unsigned and one for signed integers.
+ /// Although ConstantByte canonicalizes everything to an unsigned integer,
+ /// the signed version avoids callers having to convert a signed quantity
+ /// to the appropriate unsigned type before calling the method.
+ /// @returns true if V is a valid value for type Ty
+ /// Determine if the value is in range for the given type.
+ LLVM_ABI static bool isValueValidForType(Type *Ty, uint64_t V);
+ LLVM_ABI static bool isValueValidForType(Type *Ty, int64_t V);
+
+ bool isNegative() const { return 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();
+ }
+
+ /// This function will return true iff this constant represents a value with
+ /// active bits bigger than 64 bits or a value greater than the given uint64_t
+ /// value.
+ /// @returns true iff this constant is greater or equal to the given number.
+ /// Determine if the value is greater or equal to the given number.
+ bool uge(uint64_t Num) const { return Val.uge(Num); }
+
+ /// getLimitedValue - If the value is smaller than the specified limit,
+ /// return it, otherwise return the limit value. This causes the value
+ /// to saturate to the limit.
+ /// @returns the min of the value of the constant and the specified value
+ /// Get the constant's value with a saturation limit
+ uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
+ return Val.getLimitedValue(Limit);
+ }
+
+ /// 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 +781,10 @@ class ConstantPointerNull final : public ConstantData {
//===----------------------------------------------------------------------===//
/// 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 +854,8 @@ class ConstantDataSequential : public ConstantData {
/// 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 +893,8 @@ class ConstantDataSequential : public ConstantData {
};
//===----------------------------------------------------------------------===//
-/// 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 +927,9 @@ class ConstantDataArray final : public ConstantDataSequential {
/// 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 +946,25 @@ class ConstantDataArray final : public ConstantDataSequential {
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 +1011,24 @@ class ConstantDataVector final : public ConstantDataSequential {
/// 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 +1041,8 @@ class ConstantDataVector final : public ConstantDataSequential {
/// 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
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index 583963ab12e26..ad55c1ceed634 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -641,6 +641,11 @@ class DataLayout {
/// This is always at least as good as the ABI alignment.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const;
+ /// Returns a byte type with size at least as big as that 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,18 @@ class DataLayout {
/// big as that of a pointer of the given pointer (vector of pointer) type.
LLVM_ABI Type *getIntPtrType(Type *) const;
+ /// Returns an integer (vector of integer) type with size at least as
+ /// big as that of a byte of the given byte (vector of byte) type.
+ LLVM_ABI Type *getIntByteType(Type *) const;
+
+ /// Returns a byte (vector of byte) type with size at least as big as that of
+ /// a pointer of the given pointer (vector of pointer) type.
+ LLVM_ABI Type *getBytePtrType(Type *) const;
+
+ /// Returns a byte (vector of byte) type with size at least as big as that of
+ /// an integer of the given integer (vector of integer) type.
+ LLVM_ABI Type *getByteIntType(Type *) const;
+
/// Returns the smallest integer type with size at least as big as
/// Width bits.
LLVM_ABI Type *getSmallestLegalIntType(LLVMContext &C,
@@ -788,6 +805,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:
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index b22177c9e6c2d..876c4c8c871ce 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -100,6 +100,62 @@ unsigned Type::getIntegerBitWidth() const {
return cast<IntegerType>(this)->getBitWidth();
}
+/// Class to represent byte types. Note that this class is also used to
+/// represent the built-in byte types: Byte8Ty, Byte16Ty, Byte32Ty and
+/// Byte64Ty.
+/// Byte representation type
+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);
+
+ /// Returns type twice as wide the input type.
+ ByteType *getExtendedType() const {
+ return Type::getByteNTy(getContext(), 2 * getScalarSizeInBits());
+ }
+
+ /// Get the number of bits in this ByteType
+ unsigned getBitWidth() const { return getSubclassData(); }
+
+ /// Return a bitmask with ones set for all of the bits. This is 0xFF for i8,
+ /// 0xFFFF for i16, etc.
+ uint64_t getBitMask() const { return ~uint64_t(0UL) >> (64 - getBitWidth()); }
+
+ /// 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 {
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 028d1e26b730c..4ed3d73c4a057 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -542,6 +542,24 @@ class IRBuilderBase {
// 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 @@ class IRBuilderBase {
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) {
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 44db4ef163a64..56417ee14796f 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -26,6 +26,7 @@
namespace llvm {
+class ByteType;
class IntegerType;
struct fltSemantics;
class LLVMContext;
@@ -68,6 +69,7 @@ class Type {
// 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 @@ class Type {
/// 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 @@ class Type {
/// 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 @@ class Type {
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 @@ class Type {
// 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 @@ class Type {
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);
diff --git a/llvm/include/llvm/IR/Value.def b/llvm/include/llvm/IR/Value.def
index 34b8d4967b28a..96160fbe3bcb4 100644
--- a/llvm/include/llvm/IR/Value.def
+++ b/llvm/include/llvm/IR/Value.def
@@ -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)
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index b3c7bf94fa69c..bfc5f64a78838 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -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;
}
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index b7832cafc27c8..d8d224cfab376 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -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 = static_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() ||
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 5dbab67900dc0..d6d28ca7b5ae7 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -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))
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 568874b145c8d..ce7449354ba8e 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -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));
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 40a80576ba86b..7d8ddd1849330 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -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,6 +4225,66 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
emitGlobalConstantFP(CFP->getValueAPF(), CFP->getType(), AP);
}
+static void emitGlobalConstantLargeByte(const ConstantByte *CB,
+ AsmPrinter &AP) {
+ const DataLayout &DL = AP.getDataLayout();
+ unsigned BitWidth = CB->getBitWidth();
+
+ // Copy the value as we may massage the layout for constants whose bit width
+ // is not a multiple of 64-bits.
+ APInt Realigned(CB->getValue());
+ uint64_t ExtraBits = 0;
+ unsigned ExtraBitsSize = BitWidth & 63;
+
+ if (ExtraBitsSize) {
+ // The bit width of the data is not a multiple of 64-bits.
+ // The extra bits are expected to be at the end of the chunk of the memory.
+ // Little endian:
+ // * Nothing to be done, just record the extra bits to emit.
+ // Big endian:
+ // * Record the extra bits to emit.
+ // * Realign the raw data to emit the chunks of 64-bits.
+ if (DL.isBigEndian()) {
+ // Basically the structure of the raw data is a chunk of 64-bits cells:
+ // 0 1 BitWidth / 64
+ // [chunk1][chunk2] ... [chunkN].
+ // The most significant chunk is chunkN and it should be emitted first.
+ // However, due to the alignment issue chunkN contains useless bits.
+ // Realign the chunks so that they contain only useful information:
+ // 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));
+ if (BitWidth >= 64)
+ Realigned.lshrInPlace(ExtraBitsSize);
+ } else
+ ExtraBits = Realigned.getRawData()[BitWidth / 64];
+ }
+
+ // We don't expect assemblers to support byte 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);
+ }
+
+ 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(CB->getType());
+ Size -= (BitWidth / 64) * 8;
+ assert(Size && Size * 8 >= ExtraBitsSize &&
+ (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) ==
+ ExtraBits &&
+ "Directive too small for extra bits.");
+ AP.OutStreamer->emitIntValue(ExtraBits, Size);
+ }
+}
+
static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
const DataLayout &DL = AP.getDataLayout();
unsigned BitWidth = CI->getBitWidth();
@@ -4424,6 +4488,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);
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index b0e7ae4f9e845..88824c878a760 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -479,7 +479,7 @@ void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) {
LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg];
Value *V = PN->getIncomingValue(0);
- if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
+ if (isa<UndefValue>(V) || isa<ConstantExpr>(V) || isa<ConstantByte>(V)) {
DestLOI.NumSignBits = 1;
DestLOI.Known = KnownBits(BitWidth);
continue;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 0a1fb2aed6ca3..b7bd05329d8ef 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -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);
diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp
index 0743c92c5b95b..e74068e22f4cd 100644
--- a/llvm/lib/CodeGen/ValueTypes.cpp
+++ b/llvm/lib/CodeGen/ValueTypes.cpp
@@ -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:
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 2147488d381f4..7bff1e307237c 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -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 << ')';
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 696bc6fffc035..b47d99aa21289 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -2470,8 +2470,8 @@ AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
AttributeSafetyKind ASK) {
AttributeMask Incompatible;
- if (!Ty->isIntegerTy()) {
- // Attributes that only apply to integers.
+ if (!Ty->isIntegerTy() && !Ty->isByteTy()) {
+ // Attributes that only apply to integers and bytes.
if (ASK & ASK_SAFE_TO_DROP)
Incompatible.addAttribute(Attribute::AllocAlign);
if (ASK & ASK_UNSAFE_TO_DROP)
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 78ac276f4f3da..9cd2237c0774e 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -39,12 +39,18 @@ using namespace PatternMatch;
static cl::opt<bool> UseConstantIntForFixedLengthSplat(
"use-constant-int-for-fixed-length-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantInt's native fixed-length vector splat support."));
+static cl::opt<bool> UseConstantByteForFixedLengthSplat(
+ "use-constant-byte-for-fixed-length-splat", cl::init(false), cl::Hidden,
+ cl::desc("Use ConstantByte's native fixed-length vector splat support."));
static cl::opt<bool> UseConstantFPForFixedLengthSplat(
"use-constant-fp-for-fixed-length-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantFP's native fixed-length vector splat support."));
static cl::opt<bool> UseConstantIntForScalableSplat(
"use-constant-int-for-scalable-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantInt's native scalable vector splat support."));
+static cl::opt<bool> UseConstantByteForScalableSplat(
+ "use-constant-byte-for-scalable-splat", cl::init(false), cl::Hidden,
+ cl::desc("Use ConstantByte's native scalable vector splat support."));
static cl::opt<bool> UseConstantFPForScalableSplat(
"use-constant-fp-for-scalable-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantFP's native scalable vector splat support."));
@@ -76,6 +82,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 +103,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 +124,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 +145,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 +395,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 +435,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 +456,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 +484,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 +571,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 +1025,131 @@ 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");
+}
+
+ConstantByte *ConstantByte::getTrue(LLVMContext &Context) {
+ LLVMContextImpl *pImpl = Context.pImpl;
+ if (!pImpl->TheTrueByteVal)
+ pImpl->TheTrueByteVal = ConstantByte::get(Type::getByte1Ty(Context), 1);
+ return pImpl->TheTrueByteVal;
+}
+
+ConstantByte *ConstantByte::getFalse(LLVMContext &Context) {
+ LLVMContextImpl *pImpl = Context.pImpl;
+ if (!pImpl->TheFalseByteVal)
+ pImpl->TheFalseByteVal = ConstantByte::get(Type::getByte1Ty(Context), 0);
+ return pImpl->TheFalseByteVal;
+}
+
+ConstantByte *ConstantByte::getBool(LLVMContext &Context, bool V) {
+ return V ? getTrue(Context) : getFalse(Context);
+}
+
+Constant *ConstantByte::getTrue(Type *Ty) {
+ assert(Ty->isByteOrByteVectorTy(1) && "Type not i1 or vector of i1.");
+ ConstantByte *TrueC = ConstantByte::getTrue(Ty->getContext());
+ if (auto *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getElementCount(), TrueC);
+ return TrueC;
+}
+
+Constant *ConstantByte::getFalse(Type *Ty) {
+ assert(Ty->isByteOrByteVectorTy(1) && "Type not i1 or vector of i1.");
+ ConstantByte *FalseC = ConstantByte::getFalse(Ty->getContext());
+ if (auto *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getElementCount(), FalseC);
+ return FalseC;
+}
+
+Constant *ConstantByte::getBool(Type *Ty, bool V) {
+ return V ? getTrue(Ty) : getFalse(Ty);
+}
+
+// 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 +1420,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 +1461,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 +1535,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 +1634,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 = UseConstantByteForFixedLengthSplat && 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 +1657,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 +1678,9 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
if (UseConstantIntForFixedLengthSplat && isa<ConstantInt>(V))
return ConstantInt::get(V->getContext(), EC,
cast<ConstantInt>(V)->getValue());
+ if (UseConstantByteForFixedLengthSplat && 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 +1688,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 +1701,9 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
if (UseConstantIntForScalableSplat && isa<ConstantInt>(V))
return ConstantInt::get(V->getContext(), EC,
cast<ConstantInt>(V)->getValue());
+ if (UseConstantByteForScalableSplat && 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());
@@ -1618,6 +1819,10 @@ bool ConstantInt::isValueValidForType(Type *Ty, int64_t Val) {
return isIntN(NumBits, Val);
}
+bool ConstantByte::isValueValidForType(Type *Ty, uint64_t Val) {
+ return isUIntN(Ty->getByteBitWidth(), Val);
+}
+
bool ConstantFP::isValueValidForType(Type *Ty, const APFloat& Val) {
// convert modifies in place, so make a copy.
APFloat Val2 = APFloat(Val);
@@ -1723,6 +1928,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 +1989,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 +2014,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 +2034,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 +3082,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 +3225,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 +3309,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 +3394,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 +3438,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 +3459,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 +3529,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 {
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index f54e885968fcb..c38fd15ffe00d 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -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,50 @@ char *LLVMPrintTypeToString(LLVMTypeRef Ty) {
return strdup(buf.c_str());
}
+/*--.. Operations on byte types ............................................--*/
+
+LLVMTypeRef LLVMByte8TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte8Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByte16TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte16Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByte32TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte32Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByte64TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte64Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByte128TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte128Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C, unsigned NumBits) {
+ return wrap(ByteType::get(*unwrap(C), NumBits));
+}
+
+LLVMTypeRef LLVMByte8Type(void) {
+ return LLVMByte8TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByte16Type(void) {
+ return LLVMByte16TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByte32Type(void) {
+ return LLVMByte32TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByte64Type(void) {
+ return LLVMByte64TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByte128Type(void) {
+ return LLVMByte128TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByteType(unsigned NumBits) {
+ return LLVMByteTypeInContext(getGlobalContextForCAPI(), NumBits);
+}
+
+unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy) {
+ return unwrap<ByteType>(ByteTy)->getBitWidth();
+}
+
/*--.. Operations on integer types .........................................--*/
LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C) {
@@ -1572,6 +1618,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[],
+ unsigned 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 +1671,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();
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 22b489110d064..80756bcf2e56e 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -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,40 @@ Type *DataLayout::getIntPtrType(Type *Ty) const {
return IntTy;
}
+Type *DataLayout::getIntByteType(Type *Ty) const {
+ 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;
+}
+
+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::getByteIntType(Type *Ty) const {
+ 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 *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const {
for (unsigned LegalIntWidth : LegalIntWidths)
if (Width <= LegalIntWidth)
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 8423ff8a4c453..1da7e55bdc28a 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -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;
diff --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp
index 186bd1edb8c52..a955777b0e026 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -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<IntegerType>(Ty)->getBitWidth());
+ break;
}
}
return Result;
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index 8f79398b086eb..9bb14178234db 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -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();
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 2c9921df0422e..85aaecede4795 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1674,6 +1674,12 @@ class LLVMContextImpl {
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 @@ class LLVMContextImpl {
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 @@ class LLVMContextImpl {
SpecificBumpPtrAllocator<ConstantRangeAttributeImpl>
ConstantRangeAttributeAlloc;
+ DenseMap<unsigned, ByteType *> ByteTypes;
DenseMap<unsigned, IntegerType *> IntegerTypes;
using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>;
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 299d07b81837b..585c9c45c3524 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -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; }
@@ -341,6 +358,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 cast<ByteType>(Type::getByte8Ty(C));
+ case 16:
+ return cast<ByteType>(Type::getByte16Ty(C));
+ case 32:
+ return cast<ByteType>(Type::getByte32Ty(C));
+ case 64:
+ return cast<ByteType>(Type::getByte64Ty(C));
+ case 128:
+ return cast<ByteType>(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 +839,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);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 3cdc75ca9869e..176684915e929 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4637,9 +4637,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);
@@ -4665,9 +4666,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 {
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index 92341721c2b1a..dac63df0b90a6 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -77,6 +77,7 @@ class DXILBitcodeWriter {
// 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,
@@ -2014,6 +2015,24 @@ void DXILBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
}
Code = bitc::CST_CODE_WIDE_INTEGER;
}
+ } else if (const ConstantByte *BV = dyn_cast<ConstantByte>(C)) {
+ if (BV->getBitWidth() <= 64) {
+ uint64_t V = BV->getZExtValue();
+ emitSignedInt64(Record, V);
+ Code = bitc::CST_CODE_BYTE;
+ AbbrevToUse = CONSTANTS_BYTE_ABBREV;
+ } else { // Wide bytes, > 64 bits in size.
+ // We have an arbitrary precision byte value to write whose
+ // bit width is > 64. However, in canonical unsigned integer
+ // format it is likely that the high bits are going to be zero.
+ // So, we only write the number of active words.
+ unsigned NWords = BV->getValue().getActiveWords();
+ const uint64_t *RawWords = BV->getValue().getRawData();
+ for (unsigned i = 0; i != NWords; ++i) {
+ emitSignedInt64(Record, RawWords[i]);
+ }
+ 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();
diff --git a/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp b/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
index 0c1b0aea41f41..0212dffa38645 100644
--- a/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
@@ -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*.
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
index a5c1c8e209bf2..cc36415abb00b 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
@@ -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 ]
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
index ed761e6058210..8d837e9502739 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
@@ -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 ]
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
index 8fc27098c383b..3d31b9d9db315 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
@@ -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 ]
diff --git a/llvm/test/Assembler/2008-02-18-IntPointerCrash.ll b/llvm/test/Assembler/2008-02-18-IntPointerCrash.ll
index 0d8fbc08917a0..82818adfec309 100644
--- a/llvm/test/Assembler/2008-02-18-IntPointerCrash.ll
+++ b/llvm/test/Assembler/2008-02-18-IntPointerCrash.ll
@@ -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
diff --git a/llvm/test/Assembler/byte-invalid-cast-1.ll b/llvm/test/Assembler/byte-invalid-cast-1.ll
new file mode 100644
index 0000000000000..793a8c25ea3f1
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-1.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b8' to 'i32'
+define void @invalid_zext(b8 %b) {
+ %t = zext b8 %b to i32
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-2.ll b/llvm/test/Assembler/byte-invalid-cast-2.ll
new file mode 100644
index 0000000000000..fa2cee7f11005
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-2.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b8' to 'i32'
+define void @invalid_sext(b8 %b) {
+ %t = sext b8 %b to i32
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-3.ll b/llvm/test/Assembler/byte-invalid-cast-3.ll
new file mode 100644
index 0000000000000..ec78843d70862
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-3.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b32' to 'b8'
+define void @invalid_trunc(b32 %b) {
+ %t = trunc b32 %b to b8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-4.ll b/llvm/test/Assembler/byte-invalid-cast-4.ll
new file mode 100644
index 0000000000000..878cdd8e27425
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-4.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'i8' to 'b32'
+define void @invalid_zext(i8 %v) {
+ %t = zext i8 %v to b32
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-5.ll b/llvm/test/Assembler/byte-invalid-cast-5.ll
new file mode 100644
index 0000000000000..bb569ff9c6064
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-5.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'i8' to 'b32'
+define void @invalid_sext(i8 %v) {
+ %t = sext i8 %v to b32
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-6.ll b/llvm/test/Assembler/byte-invalid-cast-6.ll
new file mode 100644
index 0000000000000..fcfb00383ce3e
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-6.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'i32' to 'b8'
+define void @invalid_trunc(i32 %v) {
+ %t = trunc i32 %v to b8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-7.ll b/llvm/test/Assembler/byte-invalid-cast-7.ll
new file mode 100644
index 0000000000000..edad062e0cbcd
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-7.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b32' to 'i8'
+define void @invalid_trunc(b32 %b) {
+ %t = trunc b32 %b to i8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-8.ll b/llvm/test/Assembler/byte-invalid-cast-8.ll
new file mode 100644
index 0000000000000..2d92841c870ce
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-8.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid operand type for instruction
+define void @invalid_lshr(b32 %b) {
+ %t = lshr b32 %b, 8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cmp.ll b/llvm/test/Assembler/byte-invalid-cmp.ll
new file mode 100644
index 0000000000000..8206b037ea911
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cmp.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: icmp requires integer operands
+define void @byte_compare(b8 %b1, b8 %b2) {
+ %cmp = icmp eq b8 %b1, %b2
+ ret void
+}
diff --git a/llvm/test/Assembler/byte.ll b/llvm/test/Assembler/byte.ll
new file mode 100644
index 0000000000000..2a896337a3f02
--- /dev/null
+++ b/llvm/test/Assembler/byte.ll
@@ -0,0 +1,102 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -S | 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"
+ at a = common global [32 x b8] zeroinitializer, align 1
+ at b = constant [1 x b8] zeroinitializer
+ at 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]
+ at 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
+}
diff --git a/llvm/test/Assembler/invalid-inttype.ll b/llvm/test/Assembler/invalid-inttype.ll
index 9e3c31148af2d..ef050d599875e 100644
--- a/llvm/test/Assembler/invalid-inttype.ll
+++ b/llvm/test/Assembler/invalid-inttype.ll
@@ -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
diff --git a/llvm/test/Bindings/llvm-c/byte.ll b/llvm/test/Bindings/llvm-c/byte.ll
new file mode 100644
index 0000000000000..93b9819c3c9b9
--- /dev/null
+++ b/llvm/test/Bindings/llvm-c/byte.ll
@@ -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
+}
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index ab1771d1f879f..0202990018045 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -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
}
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index 6cce477e2af04..06e7fc0096a53 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -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
}
diff --git a/llvm/test/CodeGen/X86/byte-constants.ll b/llvm/test/CodeGen/X86/byte-constants.ll
new file mode 100644
index 0000000000000..77b77fc3e50e9
--- /dev/null
+++ b/llvm/test/CodeGen/X86/byte-constants.ll
@@ -0,0 +1,63 @@
+; RUN: llc < %s | FileCheck %s
+
+; CHECK: .globl x
+; CHECK: x:
+; CHECK: .quad 10
+
+ at x = global b64 bitcast (i64 10 to b64)
+
+; CHECK: .globl b
+; CHECK: b:
+; CHECK: .byte 1
+
+ at b = global b1 1
+
+; CHECK: .globl f
+; CHECK: f:
+; CHECK: .byte 31
+
+ at f = global b5 31
+
+; CHECK: .globl r
+; CHECK: r:
+; CHECK: .long 42
+
+ at r = global b32 42
+
+; CHECK: .globl w
+; CHECK: w:
+; CHECK: .quad -1
+; CHECK: .quad -1
+
+ at w = global b128 -1
+
+; CHECK: .globl uw
+; CHECK: uw:
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+
+ at uw = global b256 -1
+
+; CHECK: .globl v
+; CHECK: v:
+; CHECK: .byte 1
+; CHECK: .byte 2
+; CHECK: .byte 3
+; CHECK: .byte 4
+
+ at 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
+
+ at uv = global <4 x b128> <b128 -1, b128 -1, b128 -1, b128 -1>
diff --git a/llvm/test/Verifier/atomics.ll b/llvm/test/Verifier/atomics.ll
index 17bf5a0528d73..2b1f971e6e91f 100644
--- a/llvm/test/Verifier/atomics.ll
+++ b/llvm/test/Verifier/atomics.ll
@@ -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 };
diff --git a/llvm/test/tools/llvm-ir2vec/entities.ll b/llvm/test/tools/llvm-ir2vec/entities.ll
index 6b2e2e4db2ff6..002614164c128 100644
--- a/llvm/test/tools/llvm-ir2vec/entities.ll
+++ b/llvm/test/tools/llvm-ir2vec/entities.ll
@@ -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
diff --git a/llvm/test/tools/llvm-ir2vec/triplets.ll b/llvm/test/tools/llvm-ir2vec/triplets.ll
index 7632e236c4107..45a158c926900 100644
--- a/llvm/test/tools/llvm-ir2vec/triplets.ll
+++ b/llvm/test/tools/llvm-ir2vec/triplets.ll
@@ -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
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index 3df27998ec057..7b045314207b8 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -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: {
diff --git a/llvm/unittests/Analysis/IR2VecTest.cpp b/llvm/unittests/Analysis/IR2VecTest.cpp
index 694d04b22b720..f86eee2117e47 100644
--- a/llvm/unittests/Analysis/IR2VecTest.cpp
+++ b/llvm/unittests/Analysis/IR2VecTest.cpp
@@ -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") \
>From 9c0922ee34457d8b9b4fccfea9adec95324aab4e Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Wed, 28 Jan 2026 19:34:19 +0000
Subject: [PATCH 2/6] [LangRef] Add section on the byte type
---
llvm/docs/Frontend/PerformanceTips.rst | 13 ++++
llvm/docs/LangRef.rst | 95 ++++++++++++++++++++++++--
2 files changed, 103 insertions(+), 5 deletions(-)
diff --git a/llvm/docs/Frontend/PerformanceTips.rst b/llvm/docs/Frontend/PerformanceTips.rst
index b81df707a31a6..a11c8e3a16857 100644
--- a/llvm/docs/Frontend/PerformanceTips.rst
+++ b/llvm/docs/Frontend/PerformanceTips.rst
@@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8bf66c56f82fc..26f99693a52c5 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -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,54 @@ 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 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 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 +4952,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
@@ -13045,15 +13097,35 @@ 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 ``value`` contains at least one ``poison`` bit, the cast result is
+``poison``.
+
+* If ``value`` is any mix of (non-``poison``) pointer and non-pointer bits:
+
+ * If ``ty2`` is a non-pointer type, the provenance of the pointer bits is
+ stripped without being exposed, similarly to the
+ :ref:`ptrtoaddr <i_ptrtoaddr>` instruction.
+
+ * If ``ty2`` is a pointer type, then if all bits of ``value`` are from the
+ same pointer and are correctly ordered (there were no pointer bit swaps),
+ the cast result is that pointer. If ``value`` is a mix of bits from
+ different pointers or a mix of pointer and non-pointer bits, the result is a
+ pointer without provenance. This pointer cannot be dereferenced, but can be
+ used in comparisons or :ref:`getelementptr <i_getelementptr>` instructions.
+
+* Otherwise, the cast is a *no-op*.
+
Example:
""""""""
@@ -13064,6 +13136,15 @@ 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
+
.. _i_addrspacecast:
'``addrspacecast .. to``' Instruction
@@ -13495,6 +13576,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 +13605,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 unitialized
+ %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
>From 4b74a2ef846ad1f9337971e10f927257e2dd5ede Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Mon, 9 Feb 2026 23:28:09 +0000
Subject: [PATCH 3/6] fix docs
---
llvm/docs/LangRef.rst | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 26f99693a52c5..153e7cfe758b5 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -13109,20 +13109,21 @@ element zero ends up in the most significant bits for big-endian.
If ``value`` is of the :ref:`byte type <t_byte>`:
* If ``value`` contains at least one ``poison`` bit, the cast result is
-``poison``.
+ ``poison``.
* If ``value`` is any mix of (non-``poison``) pointer and non-pointer bits:
* If ``ty2`` is a non-pointer type, the provenance of the pointer bits is
- stripped without being exposed, similarly to the
- :ref:`ptrtoaddr <i_ptrtoaddr>` instruction.
+ stripped without being exposed, similarly to the
+ :ref:`ptrtoaddr <i_ptrtoaddr>` instruction.
* If ``ty2`` is a pointer type, then if all bits of ``value`` are from the
- same pointer and are correctly ordered (there were no pointer bit swaps),
- the cast result is that pointer. If ``value`` is a mix of bits from
- different pointers or a mix of pointer and non-pointer bits, the result is a
- pointer without provenance. This pointer cannot be dereferenced, but can be
- used in comparisons or :ref:`getelementptr <i_getelementptr>` instructions.
+ same pointer and are correctly ordered (there were no pointer bit swaps),
+ the cast result is that pointer. If ``value`` is a mix of bits from
+ different pointers or a mix of pointer and non-pointer bits, the result is
+ a pointer without provenance. This pointer cannot be dereferenced, but can
+ be used in comparisons or :ref:`getelementptr <i_getelementptr>`
+ instructions.
* Otherwise, the cast is a *no-op*.
>From 8bbf7fca646a4645a87f3e34b02b59c29b42c940 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Sat, 14 Feb 2026 17:30:03 +0000
Subject: [PATCH 4/6] address review comments
---
llvm/docs/LangRef.rst | 22 ++++++++----
llvm/include/llvm-c/Core.h | 46 ++++++------------------
llvm/include/llvm/IR/Constants.h | 42 ----------------------
llvm/include/llvm/IR/DataLayout.h | 16 +++------
llvm/include/llvm/IR/DerivedTypes.h | 5 +--
llvm/include/llvm/IR/Type.h | 11 ++++++
llvm/lib/AsmParser/LLParser.cpp | 2 +-
llvm/lib/IR/Attributes.cpp | 8 +++--
llvm/lib/IR/Constants.cpp | 54 ++---------------------------
llvm/lib/IR/DataLayout.cpp | 19 ----------
llvm/lib/IR/Type.cpp | 19 ++++++++++
llvm/test/Assembler/byte.ll | 3 +-
12 files changed, 72 insertions(+), 175 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 153e7cfe758b5..d211fbbe88f96 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -13084,10 +13084,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:
""""""""""
@@ -13109,7 +13109,14 @@ element zero ends up in the most significant bits for big-endian.
If ``value`` is of the :ref:`byte type <t_byte>`:
* If ``value`` contains at least one ``poison`` bit, the cast result is
- ``poison``.
+
+ * ``poison``, if ``ty2`` is a scalar type.
+
+ * a vector where only the lanes containing at least one ``poison`` bit are
+ ``poison``, if ``ty2`` is a vector type. The values of the remaining
+ non-``poison`` lanes are given by bitcasting the bits of ``value``
+ corresponding to each lane (according to the target's endianness) to the
+ lane element type.
* If ``value`` is any mix of (non-``poison``) pointer and non-pointer bits:
@@ -13119,7 +13126,8 @@ If ``value`` is of the :ref:`byte type <t_byte>`:
* If ``ty2`` is a pointer type, then if all bits of ``value`` are from the
same pointer and are correctly ordered (there were no pointer bit swaps),
- the cast result is that pointer. If ``value`` is a mix of bits from
+ the cast result is that pointer. If all the bits are from the same pointer
+ and these are not correctly ordered, or if ``value`` is a mix of bits from
different pointers or a mix of pointer and non-pointer bits, the result is
a pointer without provenance. This pointer cannot be dereferenced, but can
be used in comparisons or :ref:`getelementptr <i_getelementptr>`
@@ -13146,6 +13154,8 @@ Example:
%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
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 4abad7d6bfab7..4a2d5702dad28 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -1416,24 +1416,9 @@ LLVM_C_ABI char *LLVMPrintTypeToString(LLVMTypeRef Val);
/**
* Obtain a byte type from a context with specified bit width.
*/
-LLVMTypeRef LLVMByte8TypeInContext(LLVMContextRef C);
-LLVMTypeRef LLVMByte16TypeInContext(LLVMContextRef C);
-LLVMTypeRef LLVMByte32TypeInContext(LLVMContextRef C);
-LLVMTypeRef LLVMByte64TypeInContext(LLVMContextRef C);
-LLVMTypeRef LLVMByte128TypeInContext(LLVMContextRef C);
-LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C, unsigned NumBits);
-
-/**
- * Obtain a byte type from the global context with a specified bit
- * width.
- */
-LLVMTypeRef LLVMByte8Type(void);
-LLVMTypeRef LLVMByte16Type(void);
-LLVMTypeRef LLVMByte32Type(void);
-LLVMTypeRef LLVMByte64Type(void);
-LLVMTypeRef LLVMByte128Type(void);
-LLVMTypeRef LLVMByteType(unsigned NumBits);
-unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy);
+LLVM_C_ABI LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C,
+ unsigned NumBits);
+LLVM_C_ABI unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy);
/**
* @defgroup LLVMCCoreTypeInt Integer Types
@@ -2475,36 +2460,25 @@ LLVM_C_ABI LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy,
* @param ByteTy Byte type to obtain value of.
* @param N The value the returned instance should refer to.
*/
-LLVMValueRef LLVMConstByte(LLVMTypeRef ByteTy, unsigned long long N);
+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()
*/
-LLVMValueRef LLVMConstByteOfArbitraryPrecision(LLVMTypeRef ByteTy,
- unsigned NumWords,
- const uint64_t Words[]);
-
-/**
- * Obtain a constant value for a byte parsed from a string.
- *
- * A similar API, LLVMConstByteOfStringAndSize is also available. If the
- * string's length is available, it is preferred to call that function
- * instead.
- *
- * @see llvm::ConstantByte::get()
- */
-LLVMValueRef LLVMConstByteOfString(LLVMTypeRef ByteTy, const char *Text,
- uint8_t Radix);
+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()
*/
-LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy, const char *Text,
- unsigned SLen, uint8_t Radix);
+LLVM_C_ABI LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy,
+ const char *Text,
+ unsigned SLen,
+ uint8_t Radix);
/**
* Obtain a constant value referring to a double floating point value.
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 9d13798da13a3..e155585647732 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -297,13 +297,6 @@ class ConstantByte final : public ConstantData {
public:
ConstantByte(const ConstantByte &) = delete;
- LLVM_ABI static ConstantByte *getTrue(LLVMContext &Context);
- LLVM_ABI static ConstantByte *getFalse(LLVMContext &Context);
- LLVM_ABI static ConstantByte *getBool(LLVMContext &Context, bool V);
- LLVM_ABI static Constant *getTrue(Type *Ty);
- LLVM_ABI static Constant *getFalse(Type *Ty);
- LLVM_ABI static Constant *getBool(Type *Ty, bool V);
-
/// If Ty is a vector type, return a Constant with a splat of the given
/// value. Otherwise return a ConstantByte for the given value.
/// \param ImplicitTrunc Whether to allow implicit truncation of the value.
@@ -366,20 +359,6 @@ class ConstantByte final : public ConstantData {
/// Return the sign extended value.
inline int64_t getSExtValue() const { return Val.getSExtValue(); }
- /// Return the constant as an llvm::MaybeAlign.
- /// Note that this method can assert if the value does not fit in 64 bits or
- /// is not a power of two.
- inline MaybeAlign getMaybeAlignValue() const {
- return MaybeAlign(getZExtValue());
- }
-
- /// Return the constant as an llvm::Align, interpreting `0` as `Align(1)`.
- /// Note that this method can assert if the value does not fit in 64 bits or
- /// is not a power of two.
- inline Align getAlignValue() const {
- return getMaybeAlignValue().valueOrOne();
- }
-
/// A helper method that can be used to determine if the constant contained
/// within is equal to a constant. This only works for very small values,
/// because this is all that can be represented with all types.
@@ -392,18 +371,6 @@ class ConstantByte final : public ConstantData {
return cast<ByteType>(Value::getType());
}
- /// This static method returns true if the type Ty is big enough to
- /// represent the value V. This can be used to avoid having the get method
- /// assert when V is larger than Ty can represent. Note that there are two
- /// versions of this method, one for unsigned and one for signed integers.
- /// Although ConstantByte canonicalizes everything to an unsigned integer,
- /// the signed version avoids callers having to convert a signed quantity
- /// to the appropriate unsigned type before calling the method.
- /// @returns true if V is a valid value for type Ty
- /// Determine if the value is in range for the given type.
- LLVM_ABI static bool isValueValidForType(Type *Ty, uint64_t V);
- LLVM_ABI static bool isValueValidForType(Type *Ty, int64_t V);
-
bool isNegative() const { return Val.isNegative(); }
/// This is just a convenience method to make client code smaller for a
@@ -454,15 +421,6 @@ class ConstantByte final : public ConstantData {
/// Determine if the value is greater or equal to the given number.
bool uge(uint64_t Num) const { return Val.uge(Num); }
- /// getLimitedValue - If the value is smaller than the specified limit,
- /// return it, otherwise return the limit value. This causes the value
- /// to saturate to the limit.
- /// @returns the min of the value of the constant and the specified value
- /// Get the constant's value with a saturation limit
- uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
- return Val.getLimitedValue(Limit);
- }
-
/// Methods to support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Value *V) {
return V->getValueID() == ConstantByteVal;
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index ad55c1ceed634..9c0ee38635b8e 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -641,8 +641,8 @@ class DataLayout {
/// This is always at least as good as the ABI alignment.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const;
- /// Returns a byte type with size at least as big as that of a
- /// pointer in the given address space.
+ /// 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;
@@ -655,18 +655,10 @@ class DataLayout {
/// big as that of a pointer of the given pointer (vector of pointer) type.
LLVM_ABI Type *getIntPtrType(Type *) const;
- /// Returns an integer (vector of integer) type with size at least as
- /// big as that of a byte of the given byte (vector of byte) type.
- LLVM_ABI Type *getIntByteType(Type *) const;
-
- /// Returns a byte (vector of byte) type with size at least as big as that of
- /// a pointer of the given pointer (vector of pointer) type.
+ /// 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 a byte (vector of byte) type with size at least as big as that of
- /// an integer of the given integer (vector of integer) type.
- LLVM_ABI Type *getByteIntType(Type *) const;
-
/// Returns the smallest integer type with size at least as big as
/// Width bits.
LLVM_ABI Type *getSmallestLegalIntType(LLVMContext &C,
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 876c4c8c871ce..23ef199362f5a 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -100,10 +100,7 @@ unsigned Type::getIntegerBitWidth() const {
return cast<IntegerType>(this)->getBitWidth();
}
-/// Class to represent byte types. Note that this class is also used to
-/// represent the built-in byte types: Byte8Ty, Byte16Ty, Byte32Ty and
-/// Byte64Ty.
-/// Byte representation type
+/// Class to represent byte types.
class ByteType : public Type {
friend class LLVMContextImpl;
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 56417ee14796f..7a21d68e94e0a 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -501,6 +501,17 @@ class Type {
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 *getIntByteType(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 *getByteIntType(Type *);
+
//===--------------------------------------------------------------------===//
// Convenience methods for getting pointer types.
//
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index d8d224cfab376..09b893b33786d 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4244,7 +4244,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
}
case lltok::kw_c: { // c "foo"
Lex.Lex();
- ArrayType *ATy = static_cast<ArrayType *>(ExpectedTy);
+ ArrayType *ATy = cast<ArrayType>(ExpectedTy);
ID.ConstantVal = ConstantDataArray::getString(
Context, Lex.getStrVal(), false, ATy->getElementType()->isByteTy());
if (parseToken(lltok::StringConstant, "expected string"))
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index b47d99aa21289..4a073db5a589e 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -2470,10 +2470,14 @@ AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
AttributeSafetyKind ASK) {
AttributeMask Incompatible;
- if (!Ty->isIntegerTy() && !Ty->isByteTy()) {
- // Attributes that only apply to integers and bytes.
+ if (!Ty->isIntegerTy()) {
+ // 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);
}
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 9cd2237c0774e..c9ef44be0919c 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -39,18 +39,12 @@ using namespace PatternMatch;
static cl::opt<bool> UseConstantIntForFixedLengthSplat(
"use-constant-int-for-fixed-length-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantInt's native fixed-length vector splat support."));
-static cl::opt<bool> UseConstantByteForFixedLengthSplat(
- "use-constant-byte-for-fixed-length-splat", cl::init(false), cl::Hidden,
- cl::desc("Use ConstantByte's native fixed-length vector splat support."));
static cl::opt<bool> UseConstantFPForFixedLengthSplat(
"use-constant-fp-for-fixed-length-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantFP's native fixed-length vector splat support."));
static cl::opt<bool> UseConstantIntForScalableSplat(
"use-constant-int-for-scalable-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantInt's native scalable vector splat support."));
-static cl::opt<bool> UseConstantByteForScalableSplat(
- "use-constant-byte-for-scalable-splat", cl::init(false), cl::Hidden,
- cl::desc("Use ConstantByte's native scalable vector splat support."));
static cl::opt<bool> UseConstantFPForScalableSplat(
"use-constant-fp-for-scalable-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantFP's native scalable vector splat support."));
@@ -1036,44 +1030,6 @@ ConstantByte::ConstantByte(Type *Ty, const APInt &V)
"Invalid constant for type");
}
-ConstantByte *ConstantByte::getTrue(LLVMContext &Context) {
- LLVMContextImpl *pImpl = Context.pImpl;
- if (!pImpl->TheTrueByteVal)
- pImpl->TheTrueByteVal = ConstantByte::get(Type::getByte1Ty(Context), 1);
- return pImpl->TheTrueByteVal;
-}
-
-ConstantByte *ConstantByte::getFalse(LLVMContext &Context) {
- LLVMContextImpl *pImpl = Context.pImpl;
- if (!pImpl->TheFalseByteVal)
- pImpl->TheFalseByteVal = ConstantByte::get(Type::getByte1Ty(Context), 0);
- return pImpl->TheFalseByteVal;
-}
-
-ConstantByte *ConstantByte::getBool(LLVMContext &Context, bool V) {
- return V ? getTrue(Context) : getFalse(Context);
-}
-
-Constant *ConstantByte::getTrue(Type *Ty) {
- assert(Ty->isByteOrByteVectorTy(1) && "Type not i1 or vector of i1.");
- ConstantByte *TrueC = ConstantByte::getTrue(Ty->getContext());
- if (auto *VTy = dyn_cast<VectorType>(Ty))
- return ConstantVector::getSplat(VTy->getElementCount(), TrueC);
- return TrueC;
-}
-
-Constant *ConstantByte::getFalse(Type *Ty) {
- assert(Ty->isByteOrByteVectorTy(1) && "Type not i1 or vector of i1.");
- ConstantByte *FalseC = ConstantByte::getFalse(Ty->getContext());
- if (auto *VTy = dyn_cast<VectorType>(Ty))
- return ConstantVector::getSplat(VTy->getElementCount(), FalseC);
- return FalseC;
-}
-
-Constant *ConstantByte::getBool(Type *Ty, bool V) {
- return V ? getTrue(Ty) : getFalse(Ty);
-}
-
// Get a ConstantByte from an APInt.
ConstantByte *ConstantByte::get(LLVMContext &Context, const APInt &V) {
// get an existing value or the insertion position
@@ -1634,7 +1590,7 @@ 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 = UseConstantByteForFixedLengthSplat && isa<ConstantByte>(C);
+ bool isSplatByte = isa<ConstantByte>(C);
if (isZero || isUndef || isSplatFP || isSplatInt || isSplatByte) {
for (unsigned i = 1, e = V.size(); i != e; ++i)
@@ -1678,7 +1634,7 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
if (UseConstantIntForFixedLengthSplat && isa<ConstantInt>(V))
return ConstantInt::get(V->getContext(), EC,
cast<ConstantInt>(V)->getValue());
- if (UseConstantByteForFixedLengthSplat && isa<ConstantByte>(V))
+ if (isa<ConstantByte>(V))
return ConstantByte::get(V->getContext(), EC,
cast<ConstantByte>(V)->getValue());
if (UseConstantFPForFixedLengthSplat && isa<ConstantFP>(V))
@@ -1701,7 +1657,7 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
if (UseConstantIntForScalableSplat && isa<ConstantInt>(V))
return ConstantInt::get(V->getContext(), EC,
cast<ConstantInt>(V)->getValue());
- if (UseConstantByteForScalableSplat && isa<ConstantByte>(V))
+ if (isa<ConstantByte>(V))
return ConstantByte::get(V->getContext(), EC,
cast<ConstantByte>(V)->getValue());
if (UseConstantFPForScalableSplat && isa<ConstantFP>(V))
@@ -1819,10 +1775,6 @@ bool ConstantInt::isValueValidForType(Type *Ty, int64_t Val) {
return isIntN(NumBits, Val);
}
-bool ConstantByte::isValueValidForType(Type *Ty, uint64_t Val) {
- return isUIntN(Ty->getByteBitWidth(), Val);
-}
-
bool ConstantFP::isValueValidForType(Type *Ty, const APFloat& Val) {
// convert modifies in place, so make a copy.
APFloat Val2 = APFloat(Val);
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 80756bcf2e56e..758f49f60c3f1 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -991,15 +991,6 @@ Type *DataLayout::getIntPtrType(Type *Ty) const {
return IntTy;
}
-Type *DataLayout::getIntByteType(Type *Ty) const {
- 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;
-}
-
ByteType *DataLayout::getBytePtrType(LLVMContext &C,
unsigned AddressSpace) const {
return ByteType::get(C, getPointerSizeInBits(AddressSpace));
@@ -1015,16 +1006,6 @@ Type *DataLayout::getBytePtrType(Type *Ty) const {
return ByteTy;
}
-Type *DataLayout::getByteIntType(Type *Ty) const {
- 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 *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const {
for (unsigned LegalIntWidth : LegalIntWidths)
if (Width <= LegalIntWidth)
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 585c9c45c3524..5c4fe00581d0d 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -318,6 +318,25 @@ IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) {
return IntegerType::get(C, N);
}
+Type *Type::getIntByteType(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::getByteIntType(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);
diff --git a/llvm/test/Assembler/byte.ll b/llvm/test/Assembler/byte.ll
index 2a896337a3f02..1a02d0fab5df3 100644
--- a/llvm/test/Assembler/byte.ll
+++ b/llvm/test/Assembler/byte.ll
@@ -1,5 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt < %s -S | FileCheck %s
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
; CHECK: common global [32 x b8] zeroinitializer
; CHECK: constant [1 x b8] zeroinitializer
>From 85eb90ca4f0e4735143270b3c03f5993af1dcac4 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Sat, 21 Feb 2026 12:02:23 +0000
Subject: [PATCH 5/6] address review comments
---
llvm/docs/LangRef.rst | 6 +-
llvm/include/llvm-c/Core.h | 2 +-
llvm/include/llvm/IR/Constants.h | 13 ---
llvm/include/llvm/IR/DerivedTypes.h | 9 ---
llvm/include/llvm/IR/Type.h | 4 +-
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 81 ++++---------------
llvm/lib/IR/Core.cpp | 32 +-------
llvm/lib/IR/Intrinsics.cpp | 2 +-
llvm/lib/IR/Type.cpp | 14 ++--
.../DirectX/DXILWriter/DXILBitcodeWriter.cpp | 19 -----
llvm/test/Assembler/byte-invalid-cast-1.ll | 7 --
llvm/test/Assembler/byte-invalid-cast-2.ll | 7 --
llvm/test/Assembler/byte-invalid-cast-3.ll | 7 --
llvm/test/Assembler/byte-invalid-cast-4.ll | 7 --
llvm/test/Assembler/byte-invalid-cast-5.ll | 7 --
llvm/test/Assembler/byte-invalid-cast-6.ll | 7 --
llvm/test/Assembler/byte-invalid-cast-7.ll | 7 --
llvm/test/Assembler/byte-invalid-cast-8.ll | 7 --
llvm/test/Assembler/byte-invalid-cmp.ll | 7 --
llvm/test/Assembler/byte-invalid.ll | 73 +++++++++++++++++
20 files changed, 106 insertions(+), 212 deletions(-)
delete mode 100644 llvm/test/Assembler/byte-invalid-cast-1.ll
delete mode 100644 llvm/test/Assembler/byte-invalid-cast-2.ll
delete mode 100644 llvm/test/Assembler/byte-invalid-cast-3.ll
delete mode 100644 llvm/test/Assembler/byte-invalid-cast-4.ll
delete mode 100644 llvm/test/Assembler/byte-invalid-cast-5.ll
delete mode 100644 llvm/test/Assembler/byte-invalid-cast-6.ll
delete mode 100644 llvm/test/Assembler/byte-invalid-cast-7.ll
delete mode 100644 llvm/test/Assembler/byte-invalid-cast-8.ll
delete mode 100644 llvm/test/Assembler/byte-invalid-cmp.ll
create mode 100644 llvm/test/Assembler/byte-invalid.ll
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d211fbbe88f96..8dd12ccf101be 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -4480,8 +4480,8 @@ Byte Type
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 data. Frontends are expected to
-use a byte type when:
+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.
@@ -11826,6 +11826,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:
"""""""""
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 4a2d5702dad28..3a7500b52c5fd 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2477,7 +2477,7 @@ LLVM_C_ABI LLVMValueRef LLVMConstByteOfArbitraryPrecision(
*/
LLVM_C_ABI LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy,
const char *Text,
- unsigned SLen,
+ size_t SLen,
uint8_t Radix);
/**
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index e155585647732..49ba36bf2dd1a 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -359,12 +359,6 @@ class ConstantByte final : public ConstantData {
/// Return the sign extended value.
inline int64_t getSExtValue() const { return Val.getSExtValue(); }
- /// A helper method that can be used to determine if the constant contained
- /// within is equal to a constant. This only works for very small values,
- /// because this is all that can be represented with all types.
- /// Determine if this constant's value is same as an unsigned char.
- bool equalsByte(uint64_t V) const { return Val == V; }
-
/// 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 {
@@ -414,13 +408,6 @@ class ConstantByte final : public ConstantData {
return Val.isMinValue();
}
- /// This function will return true iff this constant represents a value with
- /// active bits bigger than 64 bits or a value greater than the given uint64_t
- /// value.
- /// @returns true iff this constant is greater or equal to the given number.
- /// Determine if the value is greater or equal to the given number.
- bool uge(uint64_t Num) const { return Val.uge(Num); }
-
/// Methods to support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Value *V) {
return V->getValueID() == ConstantByteVal;
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 23ef199362f5a..c272f091e31a4 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -128,18 +128,9 @@ class ByteType : public Type {
/// Get or create a ByteType instance.
LLVM_ABI static ByteType *get(LLVMContext &C, unsigned NumBits);
- /// Returns type twice as wide the input type.
- ByteType *getExtendedType() const {
- return Type::getByteNTy(getContext(), 2 * getScalarSizeInBits());
- }
-
/// Get the number of bits in this ByteType
unsigned getBitWidth() const { return getSubclassData(); }
- /// Return a bitmask with ones set for all of the bits. This is 0xFF for i8,
- /// 0xFFFF for i16, etc.
- uint64_t getBitMask() const { return ~uint64_t(0UL) >> (64 - getBitWidth()); }
-
/// 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.
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 7a21d68e94e0a..4217d797cdf28 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -506,11 +506,11 @@ class Type {
//
/// 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 *getIntByteType(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 *getByteIntType(Type *);
+ LLVM_ABI static Type *getByteFromIntType(Type *);
//===--------------------------------------------------------------------===//
// Convenience methods for getting pointer types.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 7d8ddd1849330..d3a9df4fd9817 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -4225,14 +4225,15 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
emitGlobalConstantFP(CFP->getValueAPF(), CFP->getType(), AP);
}
-static void emitGlobalConstantLargeByte(const ConstantByte *CB,
- AsmPrinter &AP) {
+static void emitGlobalConstantLargeAPInt(const APInt &Val,
+ uint64_t TypeStoreSize,
+ AsmPrinter &AP) {
const DataLayout &DL = AP.getDataLayout();
- unsigned BitWidth = CB->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(CB->getValue());
+ APInt Realigned(Val);
uint64_t ExtraBits = 0;
unsigned ExtraBitsSize = BitWidth & 63;
@@ -4262,21 +4263,20 @@ static void emitGlobalConstantLargeByte(const ConstantByte *CB,
ExtraBits = Realigned.getRawData()[BitWidth / 64];
}
- // We don't expect assemblers to support byte 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(CB->getType());
- Size -= (BitWidth / 64) * 8;
+ uint64_t Size = TypeStoreSize - (BitWidth / 64) * 8;
assert(Size && Size * 8 >= ExtraBitsSize &&
(ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) ==
ExtraBits &&
@@ -4285,62 +4285,15 @@ static void emitGlobalConstantLargeByte(const ConstantByte *CB,
}
}
-static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
- const DataLayout &DL = AP.getDataLayout();
- unsigned BitWidth = CI->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());
- uint64_t ExtraBits = 0;
- unsigned ExtraBitsSize = BitWidth & 63;
-
- if (ExtraBitsSize) {
- // The bit width of the data is not a multiple of 64-bits.
- // The extra bits are expected to be at the end of the chunk of the memory.
- // Little endian:
- // * Nothing to be done, just record the extra bits to emit.
- // Big endian:
- // * Record the extra bits to emit.
- // * Realign the raw data to emit the chunks of 64-bits.
- if (DL.isBigEndian()) {
- // Basically the structure of the raw data is a chunk of 64-bits cells:
- // 0 1 BitWidth / 64
- // [chunk1][chunk2] ... [chunkN].
- // The most significant chunk is chunkN and it should be emitted first.
- // However, due to the alignment issue chunkN contains useless bits.
- // Realign the chunks so that they contain only useful information:
- // 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));
- if (BitWidth >= 64)
- Realigned.lshrInPlace(ExtraBitsSize);
- } else
- ExtraBits = Realigned.getRawData()[BitWidth / 64];
- }
-
- // We don't expect assemblers to support integer 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);
- }
-
- if (ExtraBitsSize) {
- // Emit the extra bits after the 64-bits chunks.
+static void emitGlobalConstantLargeByte(const ConstantByte *CB,
+ AsmPrinter &AP) {
+ emitGlobalConstantLargeAPInt(
+ CB->getValue(), AP.getDataLayout().getTypeStoreSize(CB->getType()), AP);
+}
- // Emit a directive that fills the expected size.
- uint64_t Size = AP.getDataLayout().getTypeStoreSize(CI->getType());
- Size -= (BitWidth / 64) * 8;
- assert(Size && Size * 8 >= ExtraBitsSize &&
- (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize)))
- == ExtraBits && "Directive too small for extra bits.");
- AP.OutStreamer->emitIntValue(ExtraBits, Size);
- }
+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
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index c38fd15ffe00d..4456583e69b12 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -676,40 +676,10 @@ char *LLVMPrintTypeToString(LLVMTypeRef Ty) {
/*--.. Operations on byte types ............................................--*/
-LLVMTypeRef LLVMByte8TypeInContext(LLVMContextRef C) {
- return (LLVMTypeRef)Type::getByte8Ty(*unwrap(C));
-}
-LLVMTypeRef LLVMByte16TypeInContext(LLVMContextRef C) {
- return (LLVMTypeRef)Type::getByte16Ty(*unwrap(C));
-}
-LLVMTypeRef LLVMByte32TypeInContext(LLVMContextRef C) {
- return (LLVMTypeRef)Type::getByte32Ty(*unwrap(C));
-}
-LLVMTypeRef LLVMByte64TypeInContext(LLVMContextRef C) {
- return (LLVMTypeRef)Type::getByte64Ty(*unwrap(C));
-}
-LLVMTypeRef LLVMByte128TypeInContext(LLVMContextRef C) {
- return (LLVMTypeRef)Type::getByte128Ty(*unwrap(C));
-}
LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C, unsigned NumBits) {
return wrap(ByteType::get(*unwrap(C), NumBits));
}
-LLVMTypeRef LLVMByte8Type(void) {
- return LLVMByte8TypeInContext(getGlobalContextForCAPI());
-}
-LLVMTypeRef LLVMByte16Type(void) {
- return LLVMByte16TypeInContext(getGlobalContextForCAPI());
-}
-LLVMTypeRef LLVMByte32Type(void) {
- return LLVMByte32TypeInContext(getGlobalContextForCAPI());
-}
-LLVMTypeRef LLVMByte64Type(void) {
- return LLVMByte64TypeInContext(getGlobalContextForCAPI());
-}
-LLVMTypeRef LLVMByte128Type(void) {
- return LLVMByte128TypeInContext(getGlobalContextForCAPI());
-}
LLVMTypeRef LLVMByteType(unsigned NumBits) {
return LLVMByteTypeInContext(getGlobalContextForCAPI(), NumBits);
}
@@ -1637,7 +1607,7 @@ LLVMValueRef LLVMConstByteOfString(LLVMTypeRef ByteTy, const char Str[],
}
LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy, const char Str[],
- unsigned SLen, uint8_t Radix) {
+ size_t SLen, uint8_t Radix) {
return wrap(
ConstantByte::get(unwrap<ByteType>(ByteTy), StringRef(Str, SLen), Radix));
}
diff --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp
index a955777b0e026..f2c6921bbb7e0 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -147,7 +147,7 @@ static std::string getMangledTypeStr(Type *Ty, bool &HasUnnamedType) {
Result += "i" + utostr(cast<IntegerType>(Ty)->getBitWidth());
break;
case Type::ByteTyID:
- Result += "b" + utostr(cast<IntegerType>(Ty)->getBitWidth());
+ Result += "b" + utostr(cast<ByteType>(Ty)->getBitWidth());
break;
}
}
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 5c4fe00581d0d..498e78d4b0cc8 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -318,7 +318,7 @@ IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) {
return IntegerType::get(C, N);
}
-Type *Type::getIntByteType(Type *Ty) {
+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);
@@ -327,7 +327,7 @@ Type *Type::getIntByteType(Type *Ty) {
return IntTy;
}
-Type *Type::getByteIntType(Type *Ty) {
+Type *Type::getByteFromIntType(Type *Ty) {
assert(!Ty->isPtrOrPtrVectorTy() &&
"Expected a non-pointer or non-pointer vector type.");
unsigned NumBits = Ty->getScalarSizeInBits();
@@ -388,15 +388,15 @@ ByteType *ByteType::get(LLVMContext &C, unsigned NumBits) {
// Check for the built-in byte types
switch (NumBits) {
case 8:
- return cast<ByteType>(Type::getByte8Ty(C));
+ return Type::getByte8Ty(C);
case 16:
- return cast<ByteType>(Type::getByte16Ty(C));
+ return Type::getByte16Ty(C);
case 32:
- return cast<ByteType>(Type::getByte32Ty(C));
+ return Type::getByte32Ty(C);
case 64:
- return cast<ByteType>(Type::getByte64Ty(C));
+ return Type::getByte64Ty(C);
case 128:
- return cast<ByteType>(Type::getByte128Ty(C));
+ return Type::getByte128Ty(C);
default:
break;
}
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index dac63df0b90a6..92341721c2b1a 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -77,7 +77,6 @@ class DXILBitcodeWriter {
// 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,
@@ -2015,24 +2014,6 @@ void DXILBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
}
Code = bitc::CST_CODE_WIDE_INTEGER;
}
- } else if (const ConstantByte *BV = dyn_cast<ConstantByte>(C)) {
- if (BV->getBitWidth() <= 64) {
- uint64_t V = BV->getZExtValue();
- emitSignedInt64(Record, V);
- Code = bitc::CST_CODE_BYTE;
- AbbrevToUse = CONSTANTS_BYTE_ABBREV;
- } else { // Wide bytes, > 64 bits in size.
- // We have an arbitrary precision byte value to write whose
- // bit width is > 64. However, in canonical unsigned integer
- // format it is likely that the high bits are going to be zero.
- // So, we only write the number of active words.
- unsigned NWords = BV->getValue().getActiveWords();
- const uint64_t *RawWords = BV->getValue().getRawData();
- for (unsigned i = 0; i != NWords; ++i) {
- emitSignedInt64(Record, RawWords[i]);
- }
- 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();
diff --git a/llvm/test/Assembler/byte-invalid-cast-1.ll b/llvm/test/Assembler/byte-invalid-cast-1.ll
deleted file mode 100644
index 793a8c25ea3f1..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cast-1.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: invalid cast opcode for cast from 'b8' to 'i32'
-define void @invalid_zext(b8 %b) {
- %t = zext b8 %b to i32
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid-cast-2.ll b/llvm/test/Assembler/byte-invalid-cast-2.ll
deleted file mode 100644
index fa2cee7f11005..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cast-2.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: invalid cast opcode for cast from 'b8' to 'i32'
-define void @invalid_sext(b8 %b) {
- %t = sext b8 %b to i32
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid-cast-3.ll b/llvm/test/Assembler/byte-invalid-cast-3.ll
deleted file mode 100644
index ec78843d70862..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cast-3.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: invalid cast opcode for cast from 'b32' to 'b8'
-define void @invalid_trunc(b32 %b) {
- %t = trunc b32 %b to b8
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid-cast-4.ll b/llvm/test/Assembler/byte-invalid-cast-4.ll
deleted file mode 100644
index 878cdd8e27425..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cast-4.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: invalid cast opcode for cast from 'i8' to 'b32'
-define void @invalid_zext(i8 %v) {
- %t = zext i8 %v to b32
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid-cast-5.ll b/llvm/test/Assembler/byte-invalid-cast-5.ll
deleted file mode 100644
index bb569ff9c6064..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cast-5.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: invalid cast opcode for cast from 'i8' to 'b32'
-define void @invalid_sext(i8 %v) {
- %t = sext i8 %v to b32
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid-cast-6.ll b/llvm/test/Assembler/byte-invalid-cast-6.ll
deleted file mode 100644
index fcfb00383ce3e..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cast-6.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: invalid cast opcode for cast from 'i32' to 'b8'
-define void @invalid_trunc(i32 %v) {
- %t = trunc i32 %v to b8
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid-cast-7.ll b/llvm/test/Assembler/byte-invalid-cast-7.ll
deleted file mode 100644
index edad062e0cbcd..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cast-7.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: invalid cast opcode for cast from 'b32' to 'i8'
-define void @invalid_trunc(b32 %b) {
- %t = trunc b32 %b to i8
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid-cast-8.ll b/llvm/test/Assembler/byte-invalid-cast-8.ll
deleted file mode 100644
index 2d92841c870ce..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cast-8.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: invalid operand type for instruction
-define void @invalid_lshr(b32 %b) {
- %t = lshr b32 %b, 8
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid-cmp.ll b/llvm/test/Assembler/byte-invalid-cmp.ll
deleted file mode 100644
index 8206b037ea911..0000000000000
--- a/llvm/test/Assembler/byte-invalid-cmp.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: icmp requires integer operands
-define void @byte_compare(b8 %b1, b8 %b2) {
- %cmp = icmp eq b8 %b1, %b2
- ret void
-}
diff --git a/llvm/test/Assembler/byte-invalid.ll b/llvm/test/Assembler/byte-invalid.ll
new file mode 100644
index 0000000000000..3cbecf25abacb
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid.ll
@@ -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
+}
>From 95b8b223be3d766ddb970e994685e4f89bc19d22 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Sun, 8 Mar 2026 11:12:16 +0000
Subject: [PATCH 6/6] address review comments
---
llvm/docs/LangRef.rst | 45 +++++++++----------
llvm/include/llvm-c/Core.h | 5 ++-
llvm/include/llvm/IR/Constants.h | 2 +-
.../SelectionDAG/FunctionLoweringInfo.cpp | 2 +-
llvm/lib/IR/Core.cpp | 4 --
5 files changed, 27 insertions(+), 31 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8dd12ccf101be..b0d541061d2eb 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -4491,8 +4491,7 @@ expected to use a byte type when:
#. Working with possibly uninitialized data.
-Otherwise, when known, the specific specific type should be used. Each bit can
-be:
+Otherwise, when known, the specific type should be used. Each bit can be:
* An integer bit (0 or 1)
* Part of a pointer value
@@ -13110,32 +13109,32 @@ element zero ends up in the most significant bits for big-endian.
If ``value`` is of the :ref:`byte type <t_byte>`:
-* If ``value`` contains at least one ``poison`` bit, the cast result is
+* If ``ty2`` is a scalar type:
- * ``poison``, if ``ty2`` is a scalar type.
+ * If ``ty2`` is a byte type, the original bits are unchanged.
- * a vector where only the lanes containing at least one ``poison`` bit are
- ``poison``, if ``ty2`` is a vector type. The values of the remaining
- non-``poison`` lanes are given by bitcasting the bits of ``value``
- corresponding to each lane (according to the target's endianness) to the
- lane element type.
+ * If ``ty2`` is a pointer type:
-* If ``value`` is any mix of (non-``poison``) pointer and non-pointer bits:
+ * If at least one bit of ``value`` is ``poison``, the result is
+ ``poison``.
- * If ``ty2`` is a non-pointer type, the provenance of the pointer bits is
- stripped without being exposed, similarly to the
- :ref:`ptrtoaddr <i_ptrtoaddr>` instruction.
+ * 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.
- * If ``ty2`` is a pointer type, then if all bits of ``value`` are from the
- same pointer and are correctly ordered (there were no pointer bit swaps),
- the cast result is that pointer. If all the bits are from the same pointer
- and these are not correctly ordered, or if ``value`` is a mix of bits from
- different pointers or a mix of pointer and non-pointer bits, the result is
- a pointer without provenance. This pointer cannot be dereferenced, but can
- be used in comparisons or :ref:`getelementptr <i_getelementptr>`
- instructions.
+ * Otherwise, the result is a pointer with the address given by the
+ integer value of the input, and without provenance.
-* Otherwise, the cast is a *no-op*.
+ * 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:
""""""""
@@ -13618,7 +13617,7 @@ 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 unitialized
+ %l = load b32, ptr %p ; may be uninitialized
%f = freeze b32 %l ; freezes on a per-bit basis
; branching on frozen value
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 3a7500b52c5fd..9dba8a905753a 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2529,14 +2529,15 @@ LLVM_C_ABI long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal);
*
* @see llvm::ConstantByte::getZExtValue()
*/
-unsigned long long LLVMConstByteGetZExtValue(LLVMValueRef ConstantVal);
+LLVM_C_ABI unsigned long long
+LLVMConstByteGetZExtValue(LLVMValueRef ConstantVal);
/**
* Obtain the sign extended value for a byte constant value.
*
* @see llvm::ConstantByte::getSExtValue()
*/
-long long LLVMConstByteGetSExtValue(LLVMValueRef ConstantVal);
+LLVM_C_ABI long long LLVMConstByteGetSExtValue(LLVMValueRef ConstantVal);
/**
* Obtain the double value for an floating point constant value.
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 49ba36bf2dd1a..2b3f4119e50e2 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -839,7 +839,7 @@ class ConstantDataSequential : public ConstantData {
//===----------------------------------------------------------------------===//
/// 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
+/// 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.
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 88824c878a760..b0e7ae4f9e845 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -479,7 +479,7 @@ void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) {
LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg];
Value *V = PN->getIncomingValue(0);
- if (isa<UndefValue>(V) || isa<ConstantExpr>(V) || isa<ConstantByte>(V)) {
+ if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
DestLOI.NumSignBits = 1;
DestLOI.Known = KnownBits(BitWidth);
continue;
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 4456583e69b12..f91439f410eaa 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -680,10 +680,6 @@ LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C, unsigned NumBits) {
return wrap(ByteType::get(*unwrap(C), NumBits));
}
-LLVMTypeRef LLVMByteType(unsigned NumBits) {
- return LLVMByteTypeInContext(getGlobalContextForCAPI(), NumBits);
-}
-
unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy) {
return unwrap<ByteType>(ByteTy)->getBitWidth();
}
More information about the llvm-commits
mailing list