llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Andy Kaylor (andykaylor)

<details>
<summary>Changes</summary>

This adds basic support for populating record types. In order to keep the 
change small, everything non-essential was deferred to a later change set. Only 
non-recursive structures are handled. Structures padding is not yet 
implemented. Bitfields are not supported. No attempt is made to handle ABI 
requirements for passing structure arguments.

---

Patch is 21.64 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/135844.diff


12 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+2) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIRTypes.td (+3) 
- (modified) clang/include/clang/CIR/MissingFeatures.h (+7) 
- (added) clang/lib/CIR/CodeGen/CIRGenRecordLayout.h (+54) 
- (added) clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp (+212) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+46-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+21-1) 
- (modified) clang/lib/CIR/CodeGen/CMakeLists.txt (+1) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+1-1) 
- (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+6) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+29) 
- (modified) clang/test/CIR/CodeGen/struct.c (+27) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 68a4505ca7a5a..6b2c938b8275d 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -95,6 +95,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
       return getZeroAttr(arrTy);
     if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
       return getConstNullPtrAttr(ptrTy);
+    if (auto RecordTy = mlir::dyn_cast<cir::RecordType>(ty))
+      return getZeroAttr(RecordTy);
     if (mlir::isa<cir::BoolType>(ty)) {
       return getCIRBoolAttr(false);
     }
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index c60af47f09def..23e20755dca95 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -499,6 +499,9 @@ def CIR_RecordType : CIR_Type<"Record", "record",
     std::string getPrefixedName() {
       return getKindAsStr() + "." + getName().getValue().str();
     }
+
+    void complete(llvm::ArrayRef<mlir::Type> members, bool packed,
+                  bool isPadded);
   }];
 
   let hasCustomAssemblyFormat = 1;
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 6f2fd2cb2b3ad..cdc56edd5e409 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -103,6 +103,13 @@ struct MissingFeatures {
 
   // RecordType
   static bool recordTypeLayoutInfo() { return false; }
+  static bool recursiveRecordLayout() { return false; }
+  static bool skippedLayout() { return false; }
+  static bool astRecordDeclAttr() { return false; }
+  static bool cxxSupport() { return false; }
+  static bool packedRecords() { return false; }
+  static bool recordPadding() { return false; }
+  static bool recordZeroInit() { return false; }
 
   // Misc
   static bool cxxABI() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayout.h 
b/clang/lib/CIR/CodeGen/CIRGenRecordLayout.h
new file mode 100644
index 0000000000000..a51e0460d1074
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayout.h
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CIR_CIRGENRECORDLAYOUT_H
+#define LLVM_CLANG_LIB_CIR_CIRGENRECORDLAYOUT_H
+
+#include "clang/AST/Decl.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+
+namespace clang::CIRGen {
+
+/// This class handles record and union layout info while lowering AST types
+/// to CIR types.
+///
+/// These layout objects are only created on demand as CIR generation requires.
+class CIRGenRecordLayout {
+  friend class CIRGenTypes;
+
+  CIRGenRecordLayout(const CIRGenRecordLayout &) = delete;
+  void operator=(const CIRGenRecordLayout &) = delete;
+
+private:
+  /// The CIR type corresponding to this record layout; used when laying it out
+  /// as a complete object.
+  cir::RecordType completeObjectType;
+
+  /// Map from (non-bit-field) record field to the corresponding cir record 
type
+  /// field no. This info is populated by the record builder.
+  llvm::DenseMap<const clang::FieldDecl *, unsigned> fieldInfo;
+
+public:
+  CIRGenRecordLayout(cir::RecordType completeObjectType)
+      : completeObjectType(completeObjectType) {}
+
+  /// Return the "complete object" LLVM type associated with
+  /// this record.
+  cir::RecordType getCIRType() const { return completeObjectType; }
+
+  /// Return cir::RecordType element number that corresponds to the field FD.
+  unsigned getCIRFieldNo(const clang::FieldDecl *FD) const {
+    FD = FD->getCanonicalDecl();
+    assert(fieldInfo.count(FD) && "Invalid field for record!");
+    return fieldInfo.lookup(FD);
+  }
+};
+
+} // namespace clang::CIRGen
+
+#endif
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp 
b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
new file mode 100644
index 0000000000000..d14eb2f3e2f51
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -0,0 +1,212 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to compute the layout of a record.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenBuilder.h"
+#include "CIRGenModule.h"
+#include "CIRGenTypes.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
+#include "llvm/Support/Casting.h"
+
+#include <memory>
+
+using namespace llvm;
+using namespace clang;
+using namespace clang::CIRGen;
+
+namespace {
+/// The CIRRecordLowering is responsible for lowering an ASTRecordLayout to an
+/// mlir::Type. Some of the lowering is straightforward, some is not.
+// TODO: Detail some of the complexities and weirdnesses?
+// (See CGRecordLayoutBuilder.cpp)
+struct CIRRecordLowering final {
+
+  // MemberInfo is a helper structure that contains information about a record
+  // member. In addition to the standard member types, there exists a sentinel
+  // member type that ensures correct rounding.
+  struct MemberInfo final {
+    CharUnits offset;
+    enum class InfoKind { Field } kind;
+    mlir::Type data;
+    union {
+      const FieldDecl *fieldDecl;
+      // CXXRecordDecl will be used here when supported.
+    };
+    MemberInfo(CharUnits offset, InfoKind kind, mlir::Type data,
+               const FieldDecl *fieldDecl = nullptr)
+        : offset(offset), kind(kind), data(data), fieldDecl(fieldDecl) {};
+    // MemberInfos are sorted so we define a < operator.
+    bool operator<(const MemberInfo &other) const {
+      return offset < other.offset;
+    }
+  };
+  // The constructor.
+  CIRRecordLowering(CIRGenTypes &cirGenTypes, const RecordDecl *recordDecl,
+                    bool isPacked);
+
+  void lower();
+
+  void accumulateFields();
+
+  CharUnits bitsToCharUnits(uint64_t bitOffset) {
+    return astContext.toCharUnitsFromBits(bitOffset);
+  }
+
+  CharUnits getSize(mlir::Type Ty) {
+    assert(!cir::MissingFeatures::recordTypeLayoutInfo());
+    return CharUnits::One();
+  }
+  CharUnits getAlignment(mlir::Type Ty) {
+    assert(!cir::MissingFeatures::recordTypeLayoutInfo());
+    return CharUnits::One();
+  }
+
+  mlir::Type getStorageType(const FieldDecl *fieldDecl) {
+    mlir::Type type = cirGenTypes.convertTypeForMem(fieldDecl->getType());
+    if (fieldDecl->isBitField()) {
+      cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+                                         "getStorageType for bitfields");
+    }
+    return type;
+  }
+
+  uint64_t getFieldBitOffset(const FieldDecl *fieldDecl) {
+    return astRecordLayout.getFieldOffset(fieldDecl->getFieldIndex());
+  }
+
+  /// Fills out the structures that are ultimately consumed.
+  void fillOutputFields();
+
+  CIRGenTypes &cirGenTypes;
+  CIRGenBuilderTy &builder;
+  const ASTContext &astContext;
+  const RecordDecl *recordDecl;
+  const ASTRecordLayout &astRecordLayout;
+  // Helpful intermediate data-structures
+  std::vector<MemberInfo> members;
+  // Output fields, consumed by CIRGenTypes::computeRecordLayout
+  llvm::SmallVector<mlir::Type, 16> fieldTypes;
+  llvm::DenseMap<const FieldDecl *, unsigned> fields;
+  bool zeroInitializable : 1;
+  bool packed : 1;
+  bool padded : 1;
+
+private:
+  CIRRecordLowering(const CIRRecordLowering &) = delete;
+  void operator=(const CIRRecordLowering &) = delete;
+}; // CIRRecordLowering
+} // namespace
+
+CIRRecordLowering::CIRRecordLowering(CIRGenTypes &cirGenTypes,
+                                     const RecordDecl *recordDecl,
+                                     bool isPacked)
+    : cirGenTypes(cirGenTypes), builder(cirGenTypes.getBuilder()),
+      astContext(cirGenTypes.getASTContext()), recordDecl(recordDecl),
+      astRecordLayout(
+          cirGenTypes.getASTContext().getASTRecordLayout(recordDecl)),
+      zeroInitializable(true), packed(isPacked), padded(false) {}
+
+void CIRRecordLowering::lower() {
+  if (recordDecl->isUnion()) {
+    cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+                                       "lower: union");
+    return;
+  }
+
+  assert(!cir::MissingFeatures::cxxSupport());
+
+  accumulateFields();
+
+  llvm::stable_sort(members);
+  // TODO: implement clipTailPadding once bitfields are implemented
+  assert(!cir::MissingFeatures::bitfields());
+  // TODO: implemented packed records
+  assert(!cir::MissingFeatures::packedRecords());
+  // TODO: implement padding
+  assert(!cir::MissingFeatures::recordPadding());
+  // TODO: support zeroInit
+  assert(!cir::MissingFeatures::recordZeroInit());
+
+  fillOutputFields();
+}
+
+void CIRRecordLowering::fillOutputFields() {
+  for (const MemberInfo &member : members) {
+    if (member.data)
+      fieldTypes.push_back(member.data);
+    if (member.kind == MemberInfo::InfoKind::Field) {
+      if (member.fieldDecl)
+        fields[member.fieldDecl->getCanonicalDecl()] = fieldTypes.size() - 1;
+      // A field without storage must be a bitfield.
+      assert(!cir::MissingFeatures::bitfields());
+    }
+    assert(!cir::MissingFeatures::cxxSupport());
+  }
+}
+
+void CIRRecordLowering::accumulateFields() {
+  for (const FieldDecl *field : recordDecl->fields()) {
+    if (field->isBitField()) {
+      cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+                                         "accumulate bitfields");
+      ++field;
+    } else if (!field->isZeroSize(astContext)) {
+      members.push_back(MemberInfo(bitsToCharUnits(getFieldBitOffset(field)),
+                                   MemberInfo::InfoKind::Field,
+                                   getStorageType(field), field));
+      ++field;
+    } else {
+      // TODO(cir): do we want to do anything special about zero size members?
+      ++field;
+    }
+  }
+}
+
+std::unique_ptr<CIRGenRecordLayout>
+CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) {
+  CIRRecordLowering lowering(*this, rd, /*packed=*/false);
+  assert(ty->isIncomplete() && "recomputing record layout?");
+  lowering.lower();
+
+  // If we're in C++, compute the base subobject type.
+  if (llvm::isa<CXXRecordDecl>(rd) && !rd->isUnion() &&
+      !rd->hasAttr<FinalAttr>()) {
+    cgm.errorNYI(rd->getSourceRange(), "computeRecordLayout: CXXRecordDecl");
+  }
+
+  // Fill in the record *after* computing the base type.  Filling in the body
+  // signifies that the type is no longer opaque and record layout is complete,
+  // but we may need to recursively layout rd while laying D out as a base 
type.
+  assert(!cir::MissingFeatures::astRecordDeclAttr());
+  ty->complete(lowering.fieldTypes, lowering.packed, lowering.padded);
+
+  auto rl = std::make_unique<CIRGenRecordLayout>(ty ? *ty : cir::RecordType());
+
+  assert(!cir::MissingFeatures::recordZeroInit());
+  assert(!cir::MissingFeatures::cxxSupport());
+  assert(!cir::MissingFeatures::bitfields());
+
+  // Add all the field numbers.
+  rl->fieldInfo.swap(lowering.fields);
+
+  // Dump the layout, if requested.
+  if (getASTContext().getLangOpts().DumpRecordLayouts) {
+    cgm.errorNYI(rd->getSourceRange(), "computeRecordLayout: dump layout");
+  }
+
+  // TODO: implement verification
+  return rl;
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index f625f83257859..ec77c4428d43b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -112,6 +112,18 @@ std::string CIRGenTypes::getRecordTypeName(const 
clang::RecordDecl *recordDecl,
   return builder.getUniqueRecordName(std::string(typeName));
 }
 
+// Return true if it is safe to convert the specified record decl to CIR and 
lay
+// it out, false if doing so would cause us to get into a recursive compilation
+// mess.
+static bool isSafeToConvert(const RecordDecl *RD, CIRGenTypes &CGT) {
+  // If no records are being laid out, we can certainly do this one.
+  if (CGT.noRecordsBeingLaidOut())
+    return true;
+
+  assert(!cir::MissingFeatures::recursiveRecordLayout());
+  return false;
+}
+
 /// Lay out a tagged decl type like struct or union.
 mlir::Type CIRGenTypes::convertRecordDeclType(const clang::RecordDecl *rd) {
   // TagDecl's are not necessarily unique, instead use the (clang) type
@@ -132,7 +144,40 @@ mlir::Type CIRGenTypes::convertRecordDeclType(const 
clang::RecordDecl *rd) {
   if (!rd || !rd->isCompleteDefinition() || entry.isComplete())
     return entry;
 
-  cgm.errorNYI(rd->getSourceRange(), "Complete record type");
+  // If converting this type would cause us to infinitely loop, don't do it!
+  if (!isSafeToConvert(rd, *this)) {
+    cgm.errorNYI(rd->getSourceRange(), "recursive record layout");
+    return entry;
+  }
+
+  // Okay, this is a definition of a type. Compile the implementation now.
+  bool insertResult = recordsBeingLaidOut.insert(key).second;
+  (void)insertResult;
+  assert(insertResult && "isSafeToCovert() should have caught this.");
+
+  // Force conversion of non-virtual base classes recursively.
+  if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
+    cgm.errorNYI(rd->getSourceRange(), "CXXRecordDecl");
+  }
+
+  // Layout fields.
+  std::unique_ptr<CIRGenRecordLayout> layout = computeRecordLayout(rd, &entry);
+  recordDeclTypes[key] = entry;
+  cirGenRecordLayouts[key] = std::move(layout);
+
+  // We're done laying out this record.
+  bool eraseResult = recordsBeingLaidOut.erase(key);
+  (void)eraseResult;
+  assert(eraseResult && "record not in RecordsBeingLaidOut set?");
+
+  // If this record blocked a FunctionType conversion, then recompute whatever
+  // was derived from that.
+  assert(!cir::MissingFeatures::skippedLayout());
+
+  // If we're done converting the outer-most record, then convert any deferred
+  // records as well.
+  assert(!cir::MissingFeatures::recursiveRecordLayout());
+
   return entry;
 }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h 
b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index fd855bf958ccb..38e4bb2f688ab 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -14,9 +14,10 @@
 #define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H
 
 #include "CIRGenFunctionInfo.h"
-#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "CIRGenRecordLayout.h"
 
 #include "clang/AST/Type.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
 
 #include "llvm/ADT/SmallPtrSet.h"
 
@@ -45,12 +46,22 @@ class CIRGenTypes {
   clang::ASTContext &astContext;
   CIRGenBuilderTy &builder;
 
+  /// Contains the CIR type for any converted RecordDecl.
+  llvm::DenseMap<const clang::Type *, std::unique_ptr<CIRGenRecordLayout>>
+      cirGenRecordLayouts;
+
   /// Contains the CIR type for any converted RecordDecl
   llvm::DenseMap<const clang::Type *, cir::RecordType> recordDeclTypes;
 
   /// Hold memoized CIRGenFunctionInfo results
   llvm::FoldingSet<CIRGenFunctionInfo> functionInfos;
 
+  /// This set keeps track of records that we're currently converting to a CIR
+  /// type. For example, when converting:
+  /// struct A { struct B { int x; } } when processing 'x', the 'A' and 'B'
+  /// types will be in this set.
+  llvm::SmallPtrSet<const clang::Type *, 4> recordsBeingLaidOut;
+
   llvm::SmallPtrSet<const CIRGenFunctionInfo *, 4> functionsBeingProcessed;
   /// Heper for convertType.
   mlir::Type convertFunctionTypeInternal(clang::QualType ft);
@@ -59,6 +70,9 @@ class CIRGenTypes {
   CIRGenTypes(CIRGenModule &cgm);
   ~CIRGenTypes();
 
+  CIRGenBuilderTy &getBuilder() const { return builder; }
+  CIRGenModule &getCGModule() const { return cgm; }
+
   /// Utility to check whether a function type can be converted to a CIR type
   /// (i.e. doesn't depend on an incomplete tag type).
   bool isFuncTypeConvertible(const clang::FunctionType *ft);
@@ -70,12 +84,18 @@ class CIRGenTypes {
   TypeCacheTy typeCache;
 
   mlir::MLIRContext &getMLIRContext() const;
+  clang::ASTContext &getASTContext() const { return astContext; }
+
+  bool noRecordsBeingLaidOut() const { return recordsBeingLaidOut.empty(); }
 
   /// Convert a Clang type into a mlir::Type.
   mlir::Type convertType(clang::QualType type);
 
   mlir::Type convertRecordDeclType(const clang::RecordDecl *recordDecl);
 
+  std::unique_ptr<CIRGenRecordLayout>
+  computeRecordLayout(const clang::RecordDecl *rd, cir::RecordType *ty);
+
   std::string getRecordTypeName(const clang::RecordDecl *,
                                 llvm::StringRef suffix);
 
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt 
b/clang/lib/CIR/CodeGen/CMakeLists.txt
index dc18f7f2af160..418bc2db408cb 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -18,6 +18,7 @@ add_clang_library(clangCIR
   CIRGenExprScalar.cpp
   CIRGenFunction.cpp
   CIRGenModule.cpp
+  CIRGenRecordLayoutBuilder.cpp
   CIRGenStmt.cpp
   CIRGenStmtOpenACC.cpp
   CIRGenTypes.cpp
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index f3e5e572653da..1f4232b9e29ec 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -212,7 +212,7 @@ static LogicalResult checkConstantTypes(mlir::Operation 
*op, mlir::Type opType,
   }
 
   if (isa<cir::ZeroAttr>(attrType)) {
-    if (::mlir::isa<cir::ArrayType>(opType))
+    if (isa<cir::RecordType, cir::ArrayType>(opType))
       return success();
     return op->emitOpError("zero expects struct or array type");
   }
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp 
b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 9b0177f159084..160732d9c3610 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -214,6 +214,12 @@ cir::RecordType::RecordKind RecordType::getKind() const {
   return getImpl()->kind;
 }
 
+void RecordType::complete(ArrayRef<Type> members, bool packed, bool padded) {
+  assert(!cir::MissingFeatures::astRecordDeclAttr());
+  if (mutate(members, packed, padded).failed())
+    llvm_unreachable("failed to complete record");
+}
+
 
//===----------------------------------------------------------------------===//
 // Data Layout information for types
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 7159f89c93a53..cb318c88c09c5 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1337,6 +1337,35 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
   converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
     return mlir::BFloat16Type::get(type.getContext());
   });
+  converter.addConversion([&](cir::RecordType type) -> mlir::Type {
+    // Convert struct members.
+    llvm::SmallVector<mlir::Type> llvmMembers;
+    switch (type.getKind()) {
+    case cir::RecordType::Struct:
+      for (mlir::Type ty : type.getMembers())
+        llvmMembers.push_back(convertTypeForMemory(converter, dataLayout, ty));
+      break;
+    // Unions are lowered as only the largest member.
+    case cir::RecordType::Union:
+      llvm_unreachable("Lowering of unions is NYI");
+      break;
+    }
+
+    // Record has a name: lower as an identified record.
+    mlir::LLVM::LLVMStructType llvmStruct;
+    if (type.getName()) {
+      llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
+          type.getContext(), type.getPrefixedName());
+      assert(!cir::MissingFeatures::packedRecords());
+      if (llvmStruct.setBody(llvmMembers, /*isPacked=*/true).failed())
+        llvm_unreacha...
[truncated]

``````````

</details>


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

Reply via email to