From 5975f3b5da440792a0f210ca71dbce387914367f Mon Sep 17 00:00:00 2001 From: xlauko Date: Wed, 25 Jun 2025 21:25:56 +0200 Subject: [PATCH] [CIR] Implement SizedTypeInterface to make isSized hookable. This 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. --- clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 3 + .../include/clang/CIR/Dialect/IR/CIRTypes.td | 67 ++++++++++++------- .../clang/CIR/Interfaces/CIRTypeInterfaces.td | 28 ++++++++ clang/lib/CIR/CodeGen/CIRGenBuilder.h | 12 ---- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 4 +- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 12 ++++ 6 files changed, 89 insertions(+), 37 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h index e7fb3c9ef83a..4a0fe7f40ff5 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h @@ -27,6 +27,9 @@ struct RecordTypeStorage; bool isValidFundamentalIntWidth(unsigned width); +// Returns true if the type is a CIR sized type. +bool isSized(mlir::Type ty); + } // namespace cir mlir::ParseResult parseAddrSpaceAttribute(mlir::AsmParser &p, diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index cb3a0746909d..8bcbb08a0e28 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -35,8 +35,10 @@ class CIR_Type traits = [], // IntType //===----------------------------------------------------------------------===// -def CIR_IntType : CIR_Type<"Int", "int", - [DeclareTypeInterfaceMethods]> { +def CIR_IntType : CIR_Type<"Int", "int", [ + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods, +]> { let summary = "Integer type with arbitrary precision up to a fixed limit"; let description = [{ CIR type that represents integer types with arbitrary precision. @@ -81,8 +83,9 @@ def CIR_IntType : CIR_Type<"Int", "int", //===----------------------------------------------------------------------===// class CIR_FloatType : CIR_Type, - DeclareTypeInterfaceMethods + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods ]>; def CIR_Single : CIR_FloatType<"Single", "float"> { @@ -151,9 +154,10 @@ def CIR_LongDouble : CIR_FloatType<"LongDouble", "long_double"> { // ComplexType //===----------------------------------------------------------------------===// -def CIR_ComplexType : CIR_Type<"Complex", "complex", - [DeclareTypeInterfaceMethods]> { - +def CIR_ComplexType : CIR_Type<"Complex", "complex", [ + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods +]> { let summary = "CIR complex type"; let description = [{ CIR type that represents a C complex number. `cir.complex` models the C type @@ -194,9 +198,10 @@ def CIR_ComplexType : CIR_Type<"Complex", "complex", // PointerType //===----------------------------------------------------------------------===// -def CIR_PointerType : CIR_Type<"Pointer", "ptr", - [DeclareTypeInterfaceMethods]> { - +def CIR_PointerType : CIR_Type<"Pointer", "ptr", [ + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods +]> { let summary = "CIR pointer type"; let description = [{ `CIR.ptr` is a type returned by any op generating a pointer in C++. @@ -295,9 +300,10 @@ def CIR_DataMemberType : CIR_Type<"DataMember", "data_member", // BoolType //===----------------------------------------------------------------------===// -def CIR_BoolType : CIR_Type<"Bool", "bool", - [DeclareTypeInterfaceMethods]> { - +def CIR_BoolType : CIR_Type<"Bool", "bool", [ + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods +]> { let summary = "CIR bool type"; let description = [{ `cir.bool` represent's C++ bool type. @@ -308,9 +314,10 @@ def CIR_BoolType : CIR_Type<"Bool", "bool", // ArrayType //===----------------------------------------------------------------------===// -def CIR_ArrayType : CIR_Type<"Array", "array", - [DeclareTypeInterfaceMethods]> { - +def CIR_ArrayType : CIR_Type<"Array", "array", [ + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods, +]> { let summary = "CIR array type"; let description = [{ `CIR.array` represents C/C++ constant arrays. @@ -329,14 +336,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]> { +def CIR_VectorType : CIR_Type<"Vector", "vector", [ + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods, +]> { let summary = "CIR vector type"; let description = [{ @@ -378,6 +393,12 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", `<` $elementType `x` $size `>` }]; + let extraClassDefinition = [{ + bool $cppClass::isSized() const { + return ::cir::isSized(getElementType()); + } + }]; + let genVerifyDecl = 1; } @@ -524,11 +545,11 @@ def CIR_VoidType : CIR_Type<"Void", "void"> { // The base type for all RecordDecls. //===----------------------------------------------------------------------===// -def CIR_RecordType : CIR_Type<"Record", "record", - [ - DeclareTypeInterfaceMethods, - MutableType, - ]> { +def CIR_RecordType : CIR_Type<"Record", "record", [ + DeclareTypeInterfaceMethods, + DeclareTypeInterfaceMethods, + 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 84147478f803..fef77997f896 100644 --- a/clang/include/clang/CIR/Interfaces/CIRTypeInterfaces.td +++ b/clang/include/clang/CIR/Interfaces/CIRTypeInterfaces.td @@ -53,4 +53,32 @@ 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 255314a89465..9764a8ba14f4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -527,18 +527,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return getCompleteRecordTy(members, name, packed, padded, ast); } - bool isSized(mlir::Type ty) { - if (mlir::isa(ty)) - return true; - if (mlir::isa(ty)) { - return isSized(mlir::cast(ty).getElementType()); - } - assert(0 && "Unimplemented size for type"); - return false; - } - // // Constant creation helpers // ------------------------- diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 7a910c54e021..55f2891a550f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -646,7 +646,7 @@ mlir::Type CIRGenTypes::convertType(QualType T) { // 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]. ResultType = convertTypeForMem(A->getElementType()); - if (!Builder.isSized(ResultType)) { + if (!cir::isSized(ResultType)) { SkippedLayout = true; ResultType = Builder.getUInt8Ty(); } @@ -659,7 +659,7 @@ mlir::Type CIRGenTypes::convertType(QualType T) { // FIXME: In LLVM, "lower arrays of undefined struct type to arrays of // i8 just to have a concrete type". Not sure this makes sense in CIR yet. - assert(Builder.isSized(EltTy) && "not implemented"); + assert(cir::isSized(EltTy) && "not implemented"); ResultType = cir::ArrayType::get(EltTy, A->getSize().getZExtValue()); break; } diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 4f1b297412f9..4d35b4aebbf0 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -38,6 +38,18 @@ using cir::MissingFeatures; +//===----------------------------------------------------------------------===// +// CIR Helpers +//===----------------------------------------------------------------------===// + +bool cir::isSized(mlir::Type ty) { + if (auto sizedTy = mlir::dyn_cast(ty)) + return sizedTy.isSized(); + // TODO: Remove this once all sized types are annotated. + assert(0 && "Unimplemented size for type"); + return false; +} + //===----------------------------------------------------------------------===// // CIR Custom Parser/Printer Signatures //===----------------------------------------------------------------------===//