[llvm-branch-commits] [clang] [CIR] Implement SizedTypeInterface to make isSized hookable (PR #146045)
Henrich Lauko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Jun 27 02:27:20 PDT 2025
https://github.com/xlauko created https://github.com/llvm/llvm-project/pull/146045
Resolves issues pointed out in https://github.com/llvm/llvm-project/pull/143960/files#r2164047625 of needing to update sized list of types on each new type.
This mirrors incubator changes from https://github.com/llvm/clangir/pull/1714
>From 586f2cc7a2c0fa86d1c70e486cf169f5e82bcfd3 Mon Sep 17 00:00:00 2001
From: xlauko <xlauko at mail.muni.cz>
Date: Fri, 27 Jun 2025 11:24:23 +0200
Subject: [PATCH] [CIR] Implement SizedTypeInterface to make isSized hookable
Resolves issues pointed out in https://github.com/llvm/llvm-project/pull/143960/files#r2164047625 of needing to update sized list of types on each new type.
This mirrors incubator changes from https://github.com/llvm/clangir/pull/1714
---
clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 9 +++
.../include/clang/CIR/Dialect/IR/CIRTypes.td | 73 ++++++++++++-------
.../clang/CIR/Interfaces/CIRTypeInterfaces.td | 25 +++++++
clang/lib/CIR/CodeGen/CIRGenBuilder.h | 12 ---
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 4 +-
clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 10 +++
6 files changed, 92 insertions(+), 41 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
index 620c72ef9023e..7f9fb9ef388b3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
@@ -26,6 +26,15 @@ struct RecordTypeStorage;
bool isValidFundamentalIntWidth(unsigned width);
+/// Returns true if the type is a CIR sized type.
+///
+/// Types are sized if they implement SizedTypeInterface and
+/// return true from its method isSized.
+///
+/// Unsized types are those that do not have a size, such as
+/// void, or abstract types.
+bool isSized(mlir::Type ty);
+
} // namespace cir
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 75c42a08c185f..bfe42562abad7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -33,8 +33,10 @@ class CIR_Type<string name, string typeMnemonic, list<Trait> traits = [],
// IntType
//===----------------------------------------------------------------------===//
-def CIR_IntType : CIR_Type<"Int", "int",
- [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
+def CIR_IntType : CIR_Type<"Int", "int", [
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+ DeclareTypeInterfaceMethods<CIR_SizedTypeInterface>
+]> {
let summary = "Integer type with arbitrary precision up to a fixed limit";
let description = [{
CIR type that represents integer types with arbitrary precision, including
@@ -82,7 +84,8 @@ def CIR_IntType : CIR_Type<"Int", "int",
class CIR_FloatType<string name, string mnemonic> : CIR_Type<name, mnemonic, [
DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
- DeclareTypeInterfaceMethods<CIR_FPTypeInterface>
+ DeclareTypeInterfaceMethods<CIR_FPTypeInterface>,
+ DeclareTypeInterfaceMethods<CIR_SizedTypeInterface>
]>;
def CIR_Single : CIR_FloatType<"Single", "float"> {
@@ -165,9 +168,10 @@ def CIR_LongDouble : CIR_FloatType<"LongDouble", "long_double"> {
// ComplexType
//===----------------------------------------------------------------------===//
-def CIR_ComplexType : CIR_Type<"Complex", "complex",
- [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
-
+def CIR_ComplexType : CIR_Type<"Complex", "complex", [
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+ DeclareTypeInterfaceMethods<CIR_SizedTypeInterface>
+]> {
let summary = "CIR complex type";
let description = [{
CIR type that represents a C complex number. `cir.complex` models the C type
@@ -215,12 +219,13 @@ def CIR_ComplexType : CIR_Type<"Complex", "complex",
// PointerType
//===----------------------------------------------------------------------===//
-def CIR_PointerType : CIR_Type<"Pointer", "ptr",
- [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
-
+def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+ DeclareTypeInterfaceMethods<CIR_SizedTypeInterface>
+]> {
let summary = "CIR pointer type";
let description = [{
- The `cir.ptr` type represents C and C++ pointer types and C++ reference
+ The `!cir.ptr` type represents C and C++ pointer types and C++ reference
types, other than pointers-to-members. The `pointee` type is the type
pointed to.
@@ -279,13 +284,13 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr",
// BoolType
//===----------------------------------------------------------------------===//
-def CIR_BoolType :
- CIR_Type<"Bool", "bool",
- [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
-
+def CIR_BoolType : CIR_Type<"Bool", "bool", [
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+ DeclareTypeInterfaceMethods<CIR_SizedTypeInterface>
+]> {
let summary = "CIR bool type";
let description = [{
- `cir.bool` represents C++ bool type.
+ `!cir.bool` represents C++ bool type.
}];
}
@@ -293,12 +298,13 @@ def CIR_BoolType :
// ArrayType
//===----------------------------------------------------------------------===//
-def CIR_ArrayType : CIR_Type<"Array", "array",
- [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
-
+def CIR_ArrayType : CIR_Type<"Array", "array", [
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+ DeclareTypeInterfaceMethods<CIR_SizedTypeInterface, ["isSized"]>,
+]> {
let summary = "CIR array type";
let description = [{
- `CIR.array` represents C/C++ constant arrays.
+ `!cir.array` represents C/C++ constant arrays.
}];
let parameters = (ins "mlir::Type":$elementType, "uint64_t":$size);
@@ -314,15 +320,22 @@ def CIR_ArrayType : CIR_Type<"Array", "array",
let assemblyFormat = [{
`<` $elementType `x` $size `>`
}];
+
+ let extraClassDefinition = [{
+ bool $cppClass::isSized() const {
+ return ::cir::isSized(getElementType());
+ }
+ }];
}
//===----------------------------------------------------------------------===//
// VectorType (fixed size)
//===----------------------------------------------------------------------===//
-def CIR_VectorType : CIR_Type<"Vector", "vector",
- [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
-
+def CIR_VectorType : CIR_Type<"Vector", "vector", [
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+ DeclareTypeInterfaceMethods<CIR_SizedTypeInterface, ["isSized"]>,
+]> {
let summary = "CIR vector type";
let description = [{
The `!cir.vector` type represents a fixed-size, one-dimensional vector.
@@ -363,6 +376,12 @@ def CIR_VectorType : CIR_Type<"Vector", "vector",
}]>,
];
+ let extraClassDefinition = [{
+ bool $cppClass::isSized() const {
+ return ::cir::isSized(getElementType());
+ }
+ }];
+
let genVerifyDecl = 1;
}
@@ -459,11 +478,11 @@ def CIR_VoidType : CIR_Type<"Void", "void"> {
// The base type for all RecordDecls.
//===----------------------------------------------------------------------===//
-def CIR_RecordType : CIR_Type<"Record", "record",
- [
- DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
- MutableType,
- ]> {
+def CIR_RecordType : CIR_Type<"Record", "record", [
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+ DeclareTypeInterfaceMethods<CIR_SizedTypeInterface>,
+ MutableType,
+]> {
let summary = "CIR record type";
let description = [{
Each unique clang::RecordDecl is mapped to a `cir.record` and any object in
diff --git a/clang/include/clang/CIR/Interfaces/CIRTypeInterfaces.td b/clang/include/clang/CIR/Interfaces/CIRTypeInterfaces.td
index 84147478f8030..1b1acf749e773 100644
--- a/clang/include/clang/CIR/Interfaces/CIRTypeInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIRTypeInterfaces.td
@@ -53,4 +53,29 @@ def CIR_FPTypeInterface : TypeInterface<"FPTypeInterface"> {
];
}
+def CIR_SizedTypeInterface : TypeInterface<"SizedTypeInterface"> {
+ let description = [{
+ Annotates types that have known size. Types that don't have a size are
+ abstract types and void.
+ }];
+ let cppNamespace = "::cir";
+ let methods = [
+ InterfaceMethod<[{
+ Returns true if this is a sized type. This mirrors sizedness from the
+ clang AST, where a type is sized if it has a known size.
+ By default type defining this interface returns true,
+ but this can be overridden if sizedness depends on properties of the type.
+ For example, whether a struct is not sized if it is incomplete.
+ }],
+ /*retTy=*/"bool",
+ /*methodName=*/"isSized",
+ /*args=*/(ins),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ return true;
+ }]
+ >,
+ ];
+}
+
#endif // CLANG_CIR_INTERFACES_CIRTYPEINTERFACES_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index e316c39b98919..17b931a0693aa 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -139,18 +139,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return getType<cir::RecordType>(nameAttr, kind);
}
- bool isSized(mlir::Type ty) {
- if (mlir::isa<cir::PointerType, cir::ArrayType, cir::BoolType, cir::IntType,
- cir::FPTypeInterface, cir::ComplexType, cir::RecordType>(ty))
- return true;
-
- if (const auto vt = mlir::dyn_cast<cir::VectorType>(ty))
- return isSized(vt.getElementType());
-
- assert(!cir::MissingFeatures::unsizedTypes());
- return false;
- }
-
// Return true if the value is a null constant such as null pointer, (+0.0)
// for floating-point or zero initializer
bool isNullValue(mlir::Attribute attr) const {
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 621eb66962bfb..3e07f6d3e54cc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -424,7 +424,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
// int X[] -> [0 x int], unless the element type is not sized. If it is
// unsized (e.g. an incomplete record) just use [0 x i8].
- if (!builder.isSized(elemTy)) {
+ if (!cir::isSized(elemTy)) {
elemTy = cgm.SInt8Ty;
}
@@ -438,7 +438,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
// TODO(CIR): In LLVM, "lower arrays of undefined struct type to arrays of
// i8 just to have a concrete type"
- if (!builder.isSized(elemTy)) {
+ if (!cir::isSized(elemTy)) {
cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type);
resultType = cgm.UInt32Ty;
break;
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 1db5a9728fdb9..c6760cf1618cb 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -18,6 +18,16 @@
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/TypeSwitch.h"
+//===----------------------------------------------------------------------===//
+// CIR Helpers
+//===----------------------------------------------------------------------===//
+bool cir::isSized(mlir::Type ty) {
+ if (auto sizedTy = mlir::dyn_cast<cir::SizedTypeInterface>(ty))
+ return sizedTy.isSized();
+ assert(!cir::MissingFeatures::unsizedTypes());
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// CIR Custom Parser/Printer Signatures
//===----------------------------------------------------------------------===//
More information about the llvm-branch-commits
mailing list