[clang] [CIR] Upstream minimal support for structure types (PR #135105)
Bruno Cardoso Lopes via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 11 13:45:25 PDT 2025
================
@@ -400,13 +400,126 @@ def VoidPtr : Type<
"cir::VoidType::get($_builder.getContext()))"> {
}
+//===----------------------------------------------------------------------===//
+// StructType
+//
+// The base type for all RecordDecls.
+//===----------------------------------------------------------------------===//
+
+def CIR_StructType : CIR_Type<"Struct", "struct",
+ [
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
+ MutableType,
+ ]> {
+ let summary = "CIR struct type";
+ let description = [{
+ Each unique clang::RecordDecl is mapped to a `cir.struct` and any object in
+ C/C++ that has a struct type will have a `cir.struct` in CIR.
+
+ There are three possible formats for this type:
+
+ - Identified and complete structs: unique name and a known body.
+ - Identified and incomplete structs: unique name and unknown body.
+ - Anonymous structs: no name and a known body.
+
+ Identified structs are uniqued by their name, and anonymous structs are
+ uniqued by their body. This means that two anonymous structs with the same
+ body will be the same type, and two identified structs with the same name
+ will be the same type. Attempting to build a struct with an existing name,
+ but a different body will result in an error.
+
+ A few examples:
+
+ ```mlir
+ !complete = !cir.struct<struct "complete" {!cir.int<u, 8>}>
+ !incomplete = !cir.struct<struct "incomplete" incomplete>
+ !anonymous = !cir.struct<struct {!cir.int<u, 8>}>
+ ```
+
+ Incomplete structs are mutable, meaning they can be later completed with a
+ body automatically updating in place every type in the code that uses the
+ incomplete struct. Mutability allows for recursive types to be represented,
+ meaning the struct can have members that refer to itself. This is useful for
+ representing recursive records and is implemented through a special syntax.
+ In the example below, the `Node` struct has a member that is a pointer to a
+ `Node` struct:
+
+ ```mlir
+ !struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct
+ "Node">>}>
+ ```
+ }];
+
+ let parameters = (ins
+ OptionalArrayRefParameter<"mlir::Type">:$members,
+ OptionalParameter<"mlir::StringAttr">:$name,
+ "bool":$incomplete,
+ "bool":$packed,
+ "bool":$padded,
+ "StructType::RecordKind":$kind
+ );
+
+ // StorageClass is defined in C++ for mutability.
+ let storageClass = "StructTypeStorage";
+ let genStorageClass = 0;
+
+ let skipDefaultBuilders = 1;
+ let genVerifyDecl = 1;
+
+ let builders = [
+ // Create an identified and incomplete struct type.
+ TypeBuilder<(ins
+ "mlir::StringAttr":$name,
+ "RecordKind":$kind
+ ), [{
+ return $_get($_ctxt, /*members=*/llvm::ArrayRef<Type>{}, name,
+ /*incomplete=*/true, /*packed=*/false,
+ /*padded=*/false, kind);
+ }]>];
+
+ let extraClassDeclaration = [{
+ using Base::verifyInvariants;
+
+ enum RecordKind : uint32_t { Class, Union, Struct };
+
+ bool isClass() const { return getKind() == RecordKind::Class; };
+ bool isStruct() const { return getKind() == RecordKind::Struct; };
----------------
bcardosolopes wrote:
some extra background: the distinction currently tracks some missing CodeGen support (as done by @sitio-couto a year go), but I'm in favor removing in favor of only one (to distinguish from unions) in the future if it's not used by anything else.
https://github.com/llvm/llvm-project/pull/135105
More information about the cfe-commits
mailing list