================ @@ -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