https://github.com/xlauko created https://github.com/llvm/llvm-project/pull/227258
isDiscreteBitFieldABI and isOverlappingVBaseABI were equivalent members of CGRecordLowering and CIRRecordLowering. Both only consult the target's C++ ABI and, for the bit-field rule, the record's ms_struct attribute, so they become free functions in RecordLayoutUtils.h taking the ASTContext and the RecordDecl. No functional change. >From 5213a374a2bc7ab126d5b33de2a2e9e961268476 Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Tue, 29 Sep 2026 09:56:12 +0000 Subject: [PATCH] [CIR][CodeGen][NFC] Share the bit-field and vbase layout ABI predicates isDiscreteBitFieldABI and isOverlappingVBaseABI were equivalent members of CGRecordLowering and CIRRecordLowering. Both only consult the target's C++ ABI and, for the bit-field rule, the record's ms_struct attribute, so they become free functions in RecordLayoutUtils.h taking the ASTContext and the RecordDecl. No functional change. --- .../clang/CodeGenUtils/RecordLayoutUtils.h | 12 +++++++ .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp | 23 +++----------- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 31 +++++-------------- clang/lib/CodeGenUtils/RecordLayoutUtils.cpp | 9 ++++++ 4 files changed, 32 insertions(+), 43 deletions(-) diff --git a/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h b/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h index 77f14fee5a3b4..2c1ee3c271a3d 100644 --- a/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h +++ b/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h @@ -18,6 +18,12 @@ namespace clang::CodeGenUtils { +/// The Microsoft bitfield layout rule allocates discrete storage units of the +/// field's formal type and only combines adjacent fields of the same formal +/// type. We want to emit a layout with these discrete storage units instead +/// of combining them into a continuous run. +bool isDiscreteBitFieldABI(const ASTContext &Ctx, const RecordDecl *RD); + /// Return true iff the field is "empty", that is, either a zero-width /// bit-field or an \ref isEmptyRecordForLayout. bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD); @@ -29,6 +35,12 @@ bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD); /// isEmptyRecord. bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T); +/// The Itanium base layout rule allows virtual bases to overlap other bases, +/// which complicates layout in specific ways. +/// +/// Note specifically that the ms_struct attribute doesn't change this. +bool isOverlappingVBaseABI(const ASTContext &Ctx); + } // namespace clang::CodeGenUtils #endif // LLVM_CLANG_CODEGENUTILS_RECORDLAYOUTUTILS_H diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp index c2075a245f05c..733cb208fd93e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp @@ -23,6 +23,7 @@ #include "clang/CIR/Dialect/IR/CIRDataLayout.h" #include "clang/CIR/MissingFeatures.h" #include "clang/CodeGenUtils/CodeGenUtils.h" +#include "clang/CodeGenUtils/RecordLayoutUtils.h" #include "llvm/Support/Casting.h" #include <memory> @@ -133,27 +134,10 @@ struct CIRRecordLowering final { /// Helper function to check if the target machine is BigEndian. bool isBigEndian() const { return astContext.getTargetInfo().isBigEndian(); } - // The Itanium base layout rule allows virtual bases to overlap - // other bases, which complicates layout in specific ways. - // - // Note specifically that the ms_struct attribute doesn't change this. - bool isOverlappingVBaseABI() { - return !astContext.getTargetInfo().getCXXABI().isMicrosoft(); - } // Recursively searches all of the bases to find out if a vbase is // not the primary vbase of some base class. bool hasOwnStorage(const CXXRecordDecl *decl, const CXXRecordDecl *query); - /// The Microsoft bitfield layout rule allocates discrete storage - /// units of the field's formal type and only combines adjacent - /// fields of the same formal type. We want to emit a layout with - /// these discrete storage units instead of combining them into a - /// continuous run. - bool isDiscreteBitFieldABI() { - return astContext.getTargetInfo().getCXXABI().isMicrosoft() || - recordDecl->isMsStruct(astContext); - } - CharUnits bitsToCharUnits(uint64_t bitOffset) { return astContext.toCharUnitsFromBits(bitOffset); } @@ -445,7 +429,7 @@ void CIRRecordLowering::fillOutputFields() { RecordDecl::field_iterator CIRRecordLowering::accumulateBitFields(RecordDecl::field_iterator field, RecordDecl::field_iterator fieldEnd) { - if (isDiscreteBitFieldABI()) { + if (CodeGenUtils::isDiscreteBitFieldABI(astContext, recordDecl)) { // run stores the first element of the current run of bitfields. fieldEnd is // used as a special value to note that we don't have a current run. A // bitfield run is a contiguous collection of bitfields that can be stored @@ -1292,7 +1276,8 @@ void CIRRecordLowering::accumulateVBases() { CharUnits offset = astRecordLayout.getVBaseClassOffset(baseDecl); // If the vbase is a primary virtual base of some base, then it doesn't // get its own storage location but instead lives inside of that base. - if (isOverlappingVBaseABI() && astContext.isNearlyEmpty(baseDecl) && + if (CodeGenUtils::isOverlappingVBaseABI(astContext) && + astContext.isNearlyEmpty(baseDecl) && !hasOwnStorage(cxxRecordDecl, baseDecl)) { members.push_back(MemberInfo(offset, MemberInfo::InfoKind::VBase, nullptr, cir::RecordMemberKind::Data, baseDecl)); diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index d98d7c0c96dc3..7b21b40ff26ed 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -22,6 +22,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/CodeGenUtils/CodeGenUtils.h" +#include "clang/CodeGenUtils/RecordLayoutUtils.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Type.h" @@ -100,27 +101,9 @@ struct CGRecordLowering { return MemberInfo(Offset, MemberInfo::Field, Data); } - /// The Microsoft bitfield layout rule allocates discrete storage - /// units of the field's formal type and only combines adjacent - /// fields of the same formal type. We want to emit a layout with - /// these discrete storage units instead of combining them into a - /// continuous run. - bool isDiscreteBitFieldABI() const { - return Context.getTargetInfo().getCXXABI().isMicrosoft() || - D->isMsStruct(Context); - } - /// Helper function to check if the target machine is BigEndian. bool isBE() const { return Context.getTargetInfo().isBigEndian(); } - /// The Itanium base layout rule allows virtual bases to overlap - /// other bases, which complicates layout in specific ways. - /// - /// Note specifically that the ms_struct attribute doesn't change this. - bool isOverlappingVBaseABI() const { - return !Context.getTargetInfo().getCXXABI().isMicrosoft(); - } - /// Wraps llvm::Type::getIntNTy with some implicit arguments. llvm::Type *getIntNType(uint64_t NumBits) const { unsigned AlignedBits = llvm::alignTo(NumBits, Context.getCharWidth()); @@ -143,7 +126,8 @@ struct CGRecordLowering { llvm::Type *getStorageType(const FieldDecl *FD) const { llvm::Type *Type = Types.ConvertTypeForMem(FD->getType()); if (!FD->isBitField()) return Type; - if (isDiscreteBitFieldABI()) return Type; + if (CodeGenUtils::isDiscreteBitFieldABI(Context, D)) + return Type; return getIntNType(std::min(FD->getBitWidthValue(), (unsigned)Context.toBits(getSize(Type)))); } @@ -406,7 +390,7 @@ RecordDecl::field_iterator CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, RecordDecl::field_iterator Field, RecordDecl::field_iterator FieldEnd) { - if (isDiscreteBitFieldABI()) { + if (CodeGenUtils::isDiscreteBitFieldABI(Context, D)) { // Run stores the first element of the current run of bitfields. FieldEnd is // used as a special value to note that we don't have a current run. A // bitfield run is a contiguous collection of bitfields that can be stored @@ -874,7 +858,7 @@ CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const { // smaller than the nvsize. Here we check to see if such a base is placed // before the nvsize and set the scissor offset to that, instead of the // nvsize. - if (!isNonVirtualBaseType && isOverlappingVBaseABI()) + if (!isNonVirtualBaseType && CodeGenUtils::isOverlappingVBaseABI(Context)) for (const auto &Base : RD->vbases()) { const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); if (isEmptyRecordForLayout(Context, Base.getType())) @@ -898,9 +882,8 @@ void CGRecordLowering::accumulateVBases() { CharUnits Offset = Layout.getVBaseClassOffset(BaseDecl); // If the vbase is a primary virtual base of some base, then it doesn't // get its own storage location but instead lives inside of that base. - if (isOverlappingVBaseABI() && - Context.isNearlyEmpty(BaseDecl) && - !hasOwnStorage(RD, BaseDecl)) { + if (CodeGenUtils::isOverlappingVBaseABI(Context) && + Context.isNearlyEmpty(BaseDecl) && !hasOwnStorage(RD, BaseDecl)) { Members.push_back(MemberInfo(Offset, MemberInfo::VBase, nullptr, BaseDecl)); continue; diff --git a/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp b/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp index 3b8d433dc8759..b41fb61491377 100644 --- a/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp +++ b/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp @@ -7,9 +7,14 @@ //===----------------------------------------------------------------------===// #include "clang/CodeGenUtils/RecordLayoutUtils.h" +#include "clang/Basic/TargetInfo.h" namespace clang::CodeGenUtils { +bool isDiscreteBitFieldABI(const ASTContext &Ctx, const RecordDecl *RD) { + return Ctx.getTargetInfo().getCXXABI().isMicrosoft() || RD->isMsStruct(Ctx); +} + bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD) { if (FD->isZeroLengthBitField()) return true; @@ -42,4 +47,8 @@ bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T) { return true; } +bool isOverlappingVBaseABI(const ASTContext &Ctx) { + return !Ctx.getTargetInfo().getCXXABI().isMicrosoft(); +} + } // namespace clang::CodeGenUtils _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
