================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits