[clang] [CIR] Upstream initial support for complete record types (PR #135844)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 15 13:00:11 PDT 2025
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
More information about the cfe-commits
mailing list