================
@@ -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; };
----------------
erichkeane wrote:

What value is there in differentiating between 'class' and 'struct' ?  From a 
language perspective, they are effectively synonyms.

https://github.com/llvm/llvm-project/pull/135105
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to