[llvm] [IR][CodeGen] Add new SizedCapabilityType for use in CodeGen (PR #177192)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 21 08:19:09 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
@llvm/pr-subscribers-backend-hexagon
Author: Alexander Richardson (arichardson)
<details>
<summary>Changes</summary>
EVT::getTypeForEVT currently returns a PointerType for MVT::cN, but this
has a couple of issues. The first issue is we have to hard-code the
address space, though that's not such a big deal given we do that
elsewhere too. The bigger issue is that, when we later pass that to
MVT::getVT or EVT::getEVT, it doesn't know what the right size is, so
returns MVT::cPTR instead, which is not a true value type, and is
supposed to only be used by TableGen. This has been seen to confuse
TargetLoweringBase::getTypeConversion, as when presented with a vector
of capability pointers it can end up trying to recreate a smaller vector
of the same type, but this trips up various assertions for the MVT::cPTR
as both the IR methods and the code here are expecting to be dealing
with actual value types.
Borrowing the idea of TypedPointerType (DXILPointerTyID) a bit,
introduce a new IR type, SizedCapabilityType, to represent a fixed-size
capability during CodeGen, which allows lossless roundtripping from MVT
to Type and back.
Co-authored-by: Alexander Richardson <alexrichardson@<!-- -->google.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/177192.diff
13 Files Affected:
- (modified) llvm/include/llvm/CodeGenTypes/MachineValueType.h (+11)
- (modified) llvm/include/llvm/IR/DataLayout.h (+2)
- (modified) llvm/include/llvm/IR/DerivedTypes.h (+35)
- (modified) llvm/include/llvm/IR/Type.h (+17-10)
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+2)
- (modified) llvm/lib/CodeGen/ValueTypes.cpp (+6)
- (modified) llvm/lib/IR/AsmWriter.cpp (+3)
- (modified) llvm/lib/IR/Core.cpp (+2)
- (modified) llvm/lib/IR/DataLayout.cpp (+2)
- (modified) llvm/lib/IR/LLVMContextImpl.h (+1)
- (modified) llvm/lib/IR/Type.cpp (+26-5)
- (modified) llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp (+1)
- (modified) llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp (+1)
``````````diff
diff --git a/llvm/include/llvm/CodeGenTypes/MachineValueType.h b/llvm/include/llvm/CodeGenTypes/MachineValueType.h
index 08a9c85a213e0..a9a0970a67e7a 100644
--- a/llvm/include/llvm/CodeGenTypes/MachineValueType.h
+++ b/llvm/include/llvm/CodeGenTypes/MachineValueType.h
@@ -455,6 +455,17 @@ namespace llvm {
return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE);
}
+ static MVT getCheriCapabilityVT(unsigned BitWidth) {
+ switch (BitWidth) {
+ default:
+ return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE);
+ case 64:
+ return MVT::c64;
+ case 128:
+ return MVT::c128;
+ }
+ }
+
static MVT getVectorVT(MVT VT, unsigned NumElements) {
#define GET_VT_VECATTR(Ty, Sc, Tup, nElem, ElTy) \
if (!Sc && !Tup && VT.SimpleTy == ElTy && NumElements == nElem) \
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index 4d695e1e5c566..3532084cd8ad1 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -810,6 +810,8 @@ inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const {
getTypeSizeInBits(VTy->getElementType()).getFixedValue();
return TypeSize(MinBits, EltCnt.isScalable());
}
+ case Type::SizedCapabilityTyID:
+ return TypeSize::getFixed(cast<SizedCapabilityType>(Ty)->getBitWidth());
case Type::TargetExtTyID: {
Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType();
return getTypeSizeInBits(LayoutTy);
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index b22177c9e6c2d..073b114d0dd82 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -747,6 +747,41 @@ class PointerType : public Type {
}
};
+/// Class to represent fixed-size capability types during CodeGen.
+class SizedCapabilityType : public Type {
+ friend class LLVMContextImpl;
+
+protected:
+ explicit SizedCapabilityType(LLVMContext &C, unsigned NumBits)
+ : Type(C, SizedCapabilityTyID) {
+ setSubclassData(NumBits);
+ }
+
+public:
+ /// This enum is just used to hold constants we need for SizedCapabilityType.
+ enum {
+ MIN_CAP_BITS = 64, ///< Minimum number of bits that can be specified
+ MAX_CAP_BITS = 256 ///< Maximum number of bits that can be specified
+ ///< Note that bit width is stored in the Type classes
+ ///< SubclassData field which has 24 bits.
+ };
+
+ /// This static method is the primary way of constructing an IntegerType.
+ /// If an IntegerType 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 an IntegerType instance.
+ static SizedCapabilityType *get(LLVMContext &C, unsigned NumBits);
+
+ /// Get the number of bits in this IntegerType
+ unsigned getBitWidth() const { return getSubclassData(); }
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Type *T) {
+ return T->getTypeID() == SizedCapabilityTyID;
+ }
+};
+
Type *Type::getExtendedType() const {
assert(
isIntOrIntVectorTy() &&
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 44db4ef163a64..99d996b03f4d3 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -67,15 +67,16 @@ class Type {
TokenTyID, ///< Tokens
// Derived types... see DerivedTypes.h file.
- IntegerTyID, ///< Arbitrary bit width integers
- FunctionTyID, ///< Functions
- PointerTyID, ///< Pointers
- StructTyID, ///< Structures
- ArrayTyID, ///< Arrays
- FixedVectorTyID, ///< Fixed width SIMD vector type
- ScalableVectorTyID, ///< Scalable SIMD vector type
- TypedPointerTyID, ///< Typed pointer used by some GPU targets
- TargetExtTyID, ///< Target extension type
+ IntegerTyID, ///< Arbitrary bit width integers
+ FunctionTyID, ///< Functions
+ PointerTyID, ///< Pointers
+ StructTyID, ///< Structures
+ ArrayTyID, ///< Arrays
+ FixedVectorTyID, ///< Fixed width SIMD vector type
+ ScalableVectorTyID, ///< Scalable SIMD vector type
+ TypedPointerTyID, ///< Typed pointer used by some GPU targets
+ TargetExtTyID, ///< Target extension type
+ SizedCapabilityTyID, ///< Fixed-size CHERI capability type
};
private:
@@ -266,6 +267,11 @@ class Type {
/// True if this is an instance of PointerType.
bool isPointerTy() const { return getTypeID() == PointerTyID; }
+ /// True if this is an instance of PointerType.
+ bool isSizedCapabilityTy() const {
+ return getTypeID() == SizedCapabilityTyID;
+ }
+
/// Return true if this is a pointer type or a vector of pointer types.
bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); }
@@ -311,7 +317,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() == SizedCapabilityTyID)
return true;
// If it is not something that can have a size (e.g. a function or label),
// it doesn't have a size.
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 845ecb4672cf2..b2721351c751c 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1259,6 +1259,8 @@ void ModuleBitcodeWriter::writeTypeTable() {
}
case Type::TypedPointerTyID:
llvm_unreachable("Typed pointers cannot be added to IR modules");
+ case Type::SizedCapabilityTyID:
+ llvm_unreachable("Fixed-size capabilities cannot be added to IR modules");
}
// Emit the finished record.
diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp
index 0743c92c5b95b..b0622eca9ba22 100644
--- a/llvm/lib/CodeGen/ValueTypes.cpp
+++ b/llvm/lib/CodeGen/ValueTypes.cpp
@@ -234,6 +234,10 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const {
case MVT::externref: return Type::getWasm_ExternrefTy(Context);
case MVT::funcref: return Type::getWasm_FuncrefTy(Context);
case MVT::Metadata: return Type::getMetadataTy(Context);
+ case MVT::c64:
+ return SizedCapabilityType::get(Context, 64);
+ case MVT::c128:
+ return SizedCapabilityType::get(Context, 128);
#define GET_VT_EVT(Ty, EVT) case MVT::Ty: return EVT;
#include "llvm/CodeGen/GenVT.inc"
#undef GET_VT_EVT
@@ -256,6 +260,8 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){
return MVT::isVoid;
case Type::IntegerTyID:
return getIntegerVT(cast<IntegerType>(Ty)->getBitWidth());
+ case Type::SizedCapabilityTyID:
+ return getCheriCapabilityVT(cast<SizedCapabilityType>(Ty)->getBitWidth());
case Type::HalfTyID: return MVT(MVT::f16);
case Type::BFloatTyID: return MVT(MVT::bf16);
case Type::FloatTyID: return MVT(MVT::f32);
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index cbdd444f15d85..d595442e8e871 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -729,6 +729,9 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
OS << '>';
return;
}
+ case Type::SizedCapabilityTyID:
+ OS << 'c' << cast<SizedCapabilityType>(Ty)->getBitWidth();
+ return;
case Type::TypedPointerTyID: {
TypedPointerType *TPTy = cast<TypedPointerType>(Ty);
OS << "typedptr(" << *TPTy->getElementType() << ", "
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index d31322a3013b6..f3e259d4ca21b 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -627,6 +627,8 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
return LLVMTargetExtTypeKind;
case Type::TypedPointerTyID:
llvm_unreachable("Typed pointers are unsupported via the C API");
+ case Type::SizedCapabilityTyID:
+ llvm_unreachable("Fixed-size capabilities are unsupported via the C API");
}
llvm_unreachable("Unhandled TypeID.");
}
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 05aa6c29c0e50..80b96a64de033 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -917,6 +917,8 @@ Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType();
return getAlignment(LayoutTy, abi_or_pref);
}
+ case Type::SizedCapabilityTyID:
+ return Align(cast<SizedCapabilityType>(Ty)->getBitWidth() / 8);
default:
llvm_unreachable("Bad type for getAlignment!!!");
}
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 2c9921df0422e..ebc05714fc5c0 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1773,6 +1773,7 @@ class LLVMContextImpl {
PointerType *AS0PointerType = nullptr; // AddrSpace = 0
DenseMap<unsigned, PointerType *> PointerTypes;
DenseMap<std::pair<Type *, unsigned>, TypedPointerType *> ASTypedPointerTypes;
+ SmallDenseMap<unsigned, SizedCapabilityType *, 1> SizedCapabilityTypes;
/// ValueHandles - This map keeps track of all of the value handles that are
/// watching a Value*. The Value::HasValueHandle bit is used to know
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 299d07b81837b..3d5d21e999d71 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -222,6 +222,8 @@ TypeSize Type::getPrimitiveSizeInBits() const {
assert(!ETS.isScalable() && "Vector type should have fixed-width elements");
return {ETS.getFixedValue() * EC.getKnownMinValue(), EC.isScalable()};
}
+ case Type::SizedCapabilityTyID:
+ return TypeSize::getFixed(cast<SizedCapabilityType>(this)->getBitWidth());
default:
return TypeSize::getFixed(0);
}
@@ -788,7 +790,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->isSizedCapabilityTy())
return true;
if (auto *TTy = dyn_cast<TargetExtType>(ElemTy))
return TTy->hasProperty(TargetExtType::CanBeVectorElement);
@@ -803,8 +806,8 @@ FixedVectorType *FixedVectorType::get(Type *ElementType, unsigned NumElts) {
assert(NumElts > 0 && "#Elements of a VectorType must be greater than 0");
assert(isValidElementType(ElementType) && "Element type of a VectorType must "
"be an integer, floating point, "
- "pointer type, or a valid target "
- "extension type.");
+ "pointer type, sized capability or "
+ "a valid target extension type.");
auto EC = ElementCount::getFixed(NumElts);
@@ -825,8 +828,9 @@ ScalableVectorType *ScalableVectorType::get(Type *ElementType,
unsigned MinNumElts) {
assert(MinNumElts > 0 && "#Elements of a VectorType must be greater than 0");
assert(isValidElementType(ElementType) && "Element type of a VectorType must "
- "be an integer, floating point, or "
- "pointer type.");
+ "be an integer, floating point, "
+ "pointer, or sized capability "
+ "type.");
auto EC = ElementCount::getScalable(MinNumElts);
@@ -1078,3 +1082,20 @@ bool TargetExtType::hasProperty(Property Prop) const {
uint64_t Properties = getTargetTypeInfo(this).Properties;
return (Properties & Prop) == Prop;
}
+
+//===----------------------------------------------------------------------===//
+// SizedCapabilityType Implementation
+//===----------------------------------------------------------------------===//
+
+SizedCapabilityType *SizedCapabilityType::get(LLVMContext &C,
+ unsigned NumBits) {
+ assert(NumBits >= MIN_CAP_BITS && "bitwidth too small");
+ assert(NumBits <= MAX_CAP_BITS && "bitwidth too large");
+
+ SizedCapabilityType *&Entry = C.pImpl->SizedCapabilityTypes[NumBits];
+
+ if (!Entry)
+ Entry = new (C.pImpl->Alloc) SizedCapabilityType(C, NumBits);
+
+ return Entry;
+}
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index 48a9085820471..9a23947b6115a 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -1022,6 +1022,7 @@ void DXILBitcodeWriter::writeTypeTable() {
case Type::X86_AMXTyID:
case Type::TokenTyID:
case Type::TargetExtTyID:
+ case Type::SizedCapabilityTyID:
llvm_unreachable("These should never be used!!!");
break;
case Type::VoidTyID:
diff --git a/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp b/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
index 0c1b0aea41f41..b9a080b813481 100644
--- a/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
@@ -333,6 +333,7 @@ unsigned HexagonTargetObjectFile::getSmallestAddressableSize(const Type *Ty,
case Type::TokenTyID:
case Type::TypedPointerTyID:
case Type::TargetExtTyID:
+ case Type::SizedCapabilityTyID:
return 0;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/177192
More information about the llvm-commits
mailing list