[clang] [CIR] Upstream initial support for complete record types (PR #135844)
Bruno Cardoso Lopes via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 15 17:58:21 PDT 2025
================
@@ -0,0 +1,222 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 base types are 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;
+
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned zeroInitializable : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned packed : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned 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;
+ }
+
+ if (isa<CXXRecordDecl>(recordDecl)) {
+ cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+ "lower: class");
+ 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?
----------------
bcardosolopes wrote:
maybe add a verify on missing feature here? this will lead to LLVM IR lowering differences so might be good to track.
https://github.com/llvm/llvm-project/pull/135844
More information about the cfe-commits
mailing list