[llvm] [IR] Add initial support for the byte type (PR #178666)
Pedro Lobo via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 14 09:33:00 PST 2026
https://github.com/pedroclobo updated https://github.com/llvm/llvm-project/pull/178666
>From b144d04beda91d51675c438a7fa59d6de3857c7f 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/4] [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 | 357 +++++++++++++++++-
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, 1585 insertions(+), 151 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 2bd971983e287..23f94408b86b5 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -169,6 +169,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 {
@@ -278,6 +279,7 @@ typedef enum {
LLVMConstantDataArrayValueKind,
LLVMConstantDataVectorValueKind,
LLVMConstantIntValueKind,
+ LLVMConstantByteValueKind,
LLVMConstantFPValueKind,
LLVMConstantPointerNullValueKind,
LLVMConstantTokenNoneValueKind,
@@ -1311,6 +1313,7 @@ LLVM_C_ABI void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm);
*
* types:
* integer type
+ * byte type
* real type
* function type
* sequence types:
@@ -1362,6 +1365,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
*
@@ -1978,6 +2015,7 @@ LLVM_C_ABI unsigned LLVMGetTargetExtTypeIntParam(LLVMTypeRef TargetExtTy,
macro(ConstantExpr) \
macro(ConstantFP) \
macro(ConstantInt) \
+ macro(ConstantByte) \
macro(ConstantPointerNull) \
macro(ConstantStruct) \
macro(ConstantTokenNone) \
@@ -2389,6 +2427,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.
*/
@@ -2433,6 +2512,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 fdaed0f0901a9..e795e3b86f20f 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -286,6 +286,7 @@ class Vocabulary {
VectorTy,
TokenTy,
IntegerTy,
+ ByteTy,
FunctionTy,
PointerTy,
StructTy,
@@ -459,9 +460,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");
@@ -489,6 +490,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 20d19f21a64ce..592bdf3a34949 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 f35b249e9686d..e754ffb580359 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 4d695e1e5c566..bc54269e5e762 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -637,6 +637,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,
@@ -646,6 +651,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,
@@ -784,6 +801,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 2d6bafdec2c16..ddf0538e0a30e 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -543,6 +543,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);
@@ -606,6 +624,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 4e7e31da09a52..9cbb5d3c8c8e6 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 068b52fcf0995..1965efd37b968 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4041,12 +4041,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)
@@ -4093,15 +4094,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
@@ -6552,10 +6554,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 036f3c2964997..550972a252e90 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2621,6 +2621,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");
@@ -3319,6 +3330,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");
@@ -3381,8 +3406,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]
@@ -3418,6 +3444,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 8bc98c92bc698..1e9058b9939b7 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,
@@ -1169,6 +1170,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;
@@ -2863,6 +2869,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();
@@ -2912,10 +2928,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 {
@@ -3959,6 +3975,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 420f09c514d63..4be7c59ce67f4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -3708,6 +3708,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);
@@ -3963,7 +3966,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())
@@ -4127,6 +4131,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();
@@ -4330,6 +4394,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 7eacdc0bd7bc4..d71ed4d4cb4ca 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 63c9d193421ea..2cbf2ae8105b7 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 82e4de6d07441..6a90f6748161a 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 726a3d8dd906f..265d7eed21a6c 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -2451,8 +2451,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 76152fe91a532..256b8cadfc210 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."));
@@ -92,6 +98,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
@@ -109,6 +119,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();
@@ -126,6 +140,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();
@@ -143,6 +161,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();
@@ -389,6 +411,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:
@@ -427,6 +451,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);
@@ -444,6 +472,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()));
@@ -468,6 +500,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()
@@ -548,6 +587,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;
@@ -752,7 +794,7 @@ static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) {
ReplaceableMetadataImpl::SalvageDebugInfo(*C);
const_cast<Constant *>(C)->destroyConstant();
}
-
+
return true;
}
@@ -999,6 +1041,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
//===----------------------------------------------------------------------===//
@@ -1269,6 +1436,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.");
@@ -1297,6 +1477,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);
@@ -1362,8 +1551,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);
@@ -1460,11 +1650,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;
}
}
@@ -1481,6 +1673,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.
@@ -1499,6 +1694,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());
@@ -1506,7 +1704,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);
@@ -1519,6 +1717,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());
@@ -1634,6 +1835,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);
@@ -1739,6 +1944,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))
@@ -1798,6 +2005,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();
@@ -1821,6 +2030,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)
@@ -1837,7 +2050,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());
}
@@ -2884,6 +3098,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;
}
@@ -3016,17 +3241,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
@@ -3063,6 +3325,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
@@ -3114,6 +3410,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(
@@ -3140,13 +3454,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);
@@ -3160,13 +3475,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);
@@ -3229,11 +3545,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 d31322a3013b6..0fd832ac5c99e 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -605,6 +605,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:
@@ -656,6 +658,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) {
@@ -1556,6 +1602,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));
}
@@ -1585,6 +1655,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 05aa6c29c0e50..f7361f337af0d 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -872,6 +872,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:
@@ -983,6 +986,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 be307cf08ccc5..8fcdd6e4e2d47 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -3237,7 +3237,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
@@ -3369,7 +3378,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 f46d3e5063e43..49a0816eeb345 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -147,6 +147,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 3d44d1317ecc7..a9962aed295b0 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4619,9 +4619,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);
@@ -4647,9 +4648,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 48a9085820471..7feaf5a7bb68e 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();
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 d62b0dd157b0b..12d1567466b1b 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
@@ -73,6 +73,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 e443adb17ac78..cb775622dc722 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
@@ -73,6 +73,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 7fb6043552f7b..cafc8eb1b7e23 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
@@ -73,6 +73,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 53cbe2d6ffd37..1510d6275c56f 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -1270,6 +1270,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 8dbce57302f6f..58c2d74036783 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: 110
+CHECK: 111
CHECK-NEXT: Ret 0
CHECK-NEXT: Br 1
CHECK-NEXT: Switch 2
@@ -76,38 +76,39 @@ CHECK-NEXT: MetadataTy 71
CHECK-NEXT: VectorTy 72
CHECK-NEXT: TokenTy 73
CHECK-NEXT: IntegerTy 74
-CHECK-NEXT: FunctionTy 75
-CHECK-NEXT: PointerTy 76
-CHECK-NEXT: StructTy 77
-CHECK-NEXT: ArrayTy 78
-CHECK-NEXT: UnknownTy 79
-CHECK-NEXT: Function 80
-CHECK-NEXT: Pointer 81
-CHECK-NEXT: Constant 82
-CHECK-NEXT: Variable 83
-CHECK-NEXT: FCMP_false 84
-CHECK-NEXT: FCMP_oeq 85
-CHECK-NEXT: FCMP_ogt 86
-CHECK-NEXT: FCMP_oge 87
-CHECK-NEXT: FCMP_olt 88
-CHECK-NEXT: FCMP_ole 89
-CHECK-NEXT: FCMP_one 90
-CHECK-NEXT: FCMP_ord 91
-CHECK-NEXT: FCMP_uno 92
-CHECK-NEXT: FCMP_ueq 93
-CHECK-NEXT: FCMP_ugt 94
-CHECK-NEXT: FCMP_uge 95
-CHECK-NEXT: FCMP_ult 96
-CHECK-NEXT: FCMP_ule 97
-CHECK-NEXT: FCMP_une 98
-CHECK-NEXT: FCMP_true 99
-CHECK-NEXT: ICMP_eq 100
-CHECK-NEXT: ICMP_ne 101
-CHECK-NEXT: ICMP_ugt 102
-CHECK-NEXT: ICMP_uge 103
-CHECK-NEXT: ICMP_ult 104
-CHECK-NEXT: ICMP_ule 105
-CHECK-NEXT: ICMP_sgt 106
-CHECK-NEXT: ICMP_sge 107
-CHECK-NEXT: ICMP_slt 108
-CHECK-NEXT: ICMP_sle 109
+CHECK-NEXT: ByteTy 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
diff --git a/llvm/test/tools/llvm-ir2vec/triplets.ll b/llvm/test/tools/llvm-ir2vec/triplets.ll
index 7b476f60a07b3..1a7220cc9c3c5 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: 12 74 0
-; TRIPLETS-NEXT: 12 83 2
-; TRIPLETS-NEXT: 12 83 3
+; TRIPLETS-NEXT: 12 84 2
+; TRIPLETS-NEXT: 12 84 3
; TRIPLETS-NEXT: 12 0 1
; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 83 2
+; TRIPLETS-NEXT: 0 84 2
; TRIPLETS-NEXT: 16 74 0
-; TRIPLETS-NEXT: 16 83 2
-; TRIPLETS-NEXT: 16 83 3
+; TRIPLETS-NEXT: 16 84 2
+; TRIPLETS-NEXT: 16 84 3
; TRIPLETS-NEXT: 16 0 1
; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 83 2
-; TRIPLETS-NEXT: 30 76 0
-; TRIPLETS-NEXT: 30 82 2
+; TRIPLETS-NEXT: 0 84 2
+; TRIPLETS-NEXT: 30 77 0
+; TRIPLETS-NEXT: 30 83 2
; TRIPLETS-NEXT: 30 30 1
-; TRIPLETS-NEXT: 30 76 0
-; TRIPLETS-NEXT: 30 82 2
+; TRIPLETS-NEXT: 30 77 0
+; TRIPLETS-NEXT: 30 83 2
; TRIPLETS-NEXT: 30 32 1
; TRIPLETS-NEXT: 32 69 0
-; TRIPLETS-NEXT: 32 83 2
-; TRIPLETS-NEXT: 32 81 3
+; TRIPLETS-NEXT: 32 84 2
+; TRIPLETS-NEXT: 32 82 3
; TRIPLETS-NEXT: 32 32 1
; TRIPLETS-NEXT: 32 69 0
-; TRIPLETS-NEXT: 32 83 2
-; TRIPLETS-NEXT: 32 81 3
+; TRIPLETS-NEXT: 32 84 2
+; TRIPLETS-NEXT: 32 82 3
; TRIPLETS-NEXT: 32 31 1
; TRIPLETS-NEXT: 31 74 0
-; TRIPLETS-NEXT: 31 81 2
+; TRIPLETS-NEXT: 31 82 2
; TRIPLETS-NEXT: 31 31 1
; TRIPLETS-NEXT: 31 74 0
-; TRIPLETS-NEXT: 31 81 2
+; TRIPLETS-NEXT: 31 82 2
; TRIPLETS-NEXT: 31 12 1
; TRIPLETS-NEXT: 12 74 0
-; TRIPLETS-NEXT: 12 83 2
-; TRIPLETS-NEXT: 12 83 3
+; TRIPLETS-NEXT: 12 84 2
+; TRIPLETS-NEXT: 12 84 3
; TRIPLETS-NEXT: 12 0 1
; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 83 2
\ No newline at end of file
+; TRIPLETS-NEXT: 0 84 2
\ No newline at end of file
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index bd640cd8d85ec..e5add4430e5a5 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 e085568a135fe..a095761bc246a 100644
--- a/llvm/unittests/Analysis/IR2VecTest.cpp
+++ b/llvm/unittests/Analysis/IR2VecTest.cpp
@@ -333,8 +333,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_Symbolic) {
EXPECT_EQ(AddEmb.size(), 2u);
EXPECT_EQ(RetEmb.size(), 2u);
- EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.5)));
- EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.5)));
+ EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.7)));
+ EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.6)));
}
TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
@@ -346,8 +346,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
EXPECT_EQ(AddEmb.size(), 2u);
EXPECT_EQ(RetEmb.size(), 2u);
- EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.5)));
- EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 32.6)));
+ EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.7)));
+ EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 32.8)));
}
TEST_F(IR2VecTestFixture, GetBBVector_Symbolic) {
@@ -357,9 +357,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.5, 25.5} + {15.5, 15.5} =
- // {41.0, 41.0}
- EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.0)));
+ // BB vector should be sum of add and ret: {25.7, 25.7} + {15.6, 15.6} =
+ // {41.3, 41.3}
+ EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.3)));
}
TEST_F(IR2VecTestFixture, GetBBVector_FlowAware) {
@@ -369,9 +369,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.5, 25.5} + {32.6, 32.6} =
- // {58.1, 58.1}
- EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 58.1)));
+ // BB vector should be sum of add and ret: {25.7, 25.7} + {32.8, 32.8} =
+ // {58.5, 58.5}
+ EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 58.5)));
}
TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
@@ -382,8 +382,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
EXPECT_EQ(FuncVec.size(), 2u);
- // Function vector should match BB vector (only one BB): {41.0, 41.0}
- EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.0)));
+ // Function vector should match BB vector (only one BB): {41.3, 41.3}
+ EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.3)));
}
TEST_F(IR2VecTestFixture, GetFunctionVector_FlowAware) {
@@ -393,8 +393,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): {58.1, 58.1}
- EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 58.1)));
+ // Function vector should match BB vector (only one BB): {58.5, 58.5}
+ EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 58.5)));
}
TEST_F(IR2VecTestFixture, MultipleComputeEmbeddingsConsistency_Symbolic) {
@@ -450,6 +450,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 cfad6d59c5ab11397a5279325c53f5d5beb8dd9a 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/4] [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 38f2ad8c166fd..bee9e88a64324 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:
@@ -4432,6 +4432,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
@@ -4865,6 +4913,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
@@ -12998,15 +13050,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:
""""""""
@@ -13017,6 +13089,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
@@ -13448,6 +13529,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.
@@ -13476,6 +13558,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 edabd49dafb4ac28888622c3ae3ce51823196b22 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/4] 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 bee9e88a64324..4699553faa6a5 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -13062,20 +13062,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 f0dd5350794eb2849e1ea0f4ef5a803e667fa976 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/4] 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 4699553faa6a5..9e40655606d27 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -13037,10 +13037,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:
""""""""""
@@ -13062,7 +13062,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:
@@ -13072,7 +13079,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>`
@@ -13099,6 +13107,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 23f94408b86b5..cf64668fbbbdd 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -1380,24 +1380,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
@@ -2437,36 +2422,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 e754ffb580359..ddb00b35c20ba 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 bc54269e5e762..4b63233025c3c 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -637,8 +637,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;
@@ -651,18 +651,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 1965efd37b968..3f9c389f3bc2a 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4096,7 +4096,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 265d7eed21a6c..6045a80d762c7 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -2451,10 +2451,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 256b8cadfc210..80d5664702de4 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."));
@@ -1052,44 +1046,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
@@ -1650,7 +1606,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)
@@ -1694,7 +1650,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))
@@ -1717,7 +1673,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))
@@ -1835,10 +1791,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 f7361f337af0d..c15eaca3b868c 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -986,15 +986,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));
@@ -1010,16 +1001,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
More information about the llvm-commits
mailing list