[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