https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223424
>From 5bd4452ce11e3d6940e2dac7fe1fe3f638325a30 Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Tue, 29 Sep 2026 09:56:08 +0000 Subject: [PATCH] [CIR][CodeGen][NFC] Share isEmptyFieldForLayout and isEmptyRecordForLayout Deduplicates `isEmptyFieldForLayout` and `isEmptyRecordForLayout` between CIR and classic CodeGen into a new `RecordLayoutUtils.h`. `ABIInfoImpl.h` and CIR's `TargetInfo.h` re-export them with using-declarations, so the ~30 unqualified callers are untouched. --- .../clang/CodeGenUtils/RecordLayoutUtils.h | 34 ++++++++++++++ clang/lib/CIR/CodeGen/TargetInfo.cpp | 34 -------------- clang/lib/CIR/CodeGen/TargetInfo.h | 12 ++--- clang/lib/CodeGen/ABIInfoImpl.cpp | 33 -------------- clang/lib/CodeGen/ABIInfoImpl.h | 12 ++--- clang/lib/CodeGenUtils/CMakeLists.txt | 1 + clang/lib/CodeGenUtils/RecordLayoutUtils.cpp | 45 +++++++++++++++++++ 7 files changed, 86 insertions(+), 85 deletions(-) create mode 100644 clang/include/clang/CodeGenUtils/RecordLayoutUtils.h create mode 100644 clang/lib/CodeGenUtils/RecordLayoutUtils.cpp diff --git a/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h b/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h new file mode 100644 index 0000000000000..77f14fee5a3b4 --- /dev/null +++ b/clang/include/clang/CodeGenUtils/RecordLayoutUtils.h @@ -0,0 +1,34 @@ +//===--- RecordLayoutUtils.h - Shared record layout queries -----*- C++ -*-===// +// +// 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 file holds the AST queries about record layout that both classic +// CodeGen and CIR CodeGen need while lowering a record to its target type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGENUTILS_RECORDLAYOUTUTILS_H +#define LLVM_CLANG_CODEGENUTILS_RECORDLAYOUTUTILS_H + +#include "clang/AST/ASTContext.h" + +namespace clang::CodeGenUtils { + +/// 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); + +/// Return true iff a structure contains only empty base classes (per \ref +/// isEmptyRecordForLayout) and fields (per \ref isEmptyFieldForLayout). Note, +/// C++ record fields are considered empty if the [[no_unique_address]] +/// attribute would have made them empty, so this is not the same as \ref +/// isEmptyRecord. +bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T); + +} // namespace clang::CodeGenUtils + +#endif // LLVM_CLANG_CODEGENUTILS_RECORDLAYOUTUTILS_H diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp index cede4941b4473..57bc5f167e460 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.cpp +++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp @@ -11,40 +11,6 @@ using namespace clang; using namespace clang::CIRGen; -bool clang::CIRGen::isEmptyRecordForLayout(const ASTContext &context, - QualType t) { - const auto *rd = t->getAsRecordDecl(); - if (!rd) - return false; - - // If this is a C++ record, check the bases first. - if (const CXXRecordDecl *cxxrd = dyn_cast<CXXRecordDecl>(rd)) { - if (cxxrd->isDynamicClass()) - return false; - - for (const auto &i : cxxrd->bases()) - if (!isEmptyRecordForLayout(context, i.getType())) - return false; - } - - for (const auto *i : rd->fields()) - if (!isEmptyFieldForLayout(context, i)) - return false; - - return true; -} - -bool clang::CIRGen::isEmptyFieldForLayout(const ASTContext &context, - const FieldDecl *fd) { - if (fd->isZeroLengthBitField()) - return true; - - if (fd->isUnnamedBitField()) - return false; - - return isEmptyRecordForLayout(context, fd->getType()); -} - bool clang::CIRGen::isEmptyRecordForABI(const ASTContext &context, QualType t) { const auto *rd = t->getAsRecordDecl(); if (!rd) diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h index 5f380026e025d..e094fa53561f5 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.h +++ b/clang/lib/CIR/CodeGen/TargetInfo.h @@ -21,21 +21,15 @@ #include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/IR/CIROpsEnums.h" +#include "clang/CodeGenUtils/RecordLayoutUtils.h" #include <memory> #include <utility> namespace clang::CIRGen { -/// isEmptyFieldForLayout - Return true if the field is "empty", that is, -/// either a zero-width bit-field or an isEmptyRecordForLayout. -bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd); - -/// isEmptyRecordForLayout - Return true if a structure contains only empty -/// base classes (per isEmptyRecordForLayout) and fields (per -/// isEmptyFieldForLayout). Note, C++ record fields are considered empty -/// if the [[no_unique_address]] attribute would have made them empty. -bool isEmptyRecordForLayout(const ASTContext &context, QualType t); +using CodeGenUtils::isEmptyFieldForLayout; +using CodeGenUtils::isEmptyRecordForLayout; /// isEmptyFieldForABI - Return true if the field is "empty", that is, it is a /// zero-width bit-field or an (array of) empty record(s). An unnamed diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 887a645a4783a..23b6b7e8200da 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -302,39 +302,6 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, return true; } -bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context, - const FieldDecl *FD) { - if (FD->isZeroLengthBitField()) - return true; - - if (FD->isUnnamedBitField()) - return false; - - return isEmptyRecordForLayout(Context, FD->getType()); -} - -bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) { - const auto *RD = T->getAsRecordDecl(); - if (!RD) - return false; - - // If this is a C++ record, check the bases first. - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { - if (CXXRD->isDynamicClass()) - return false; - - for (const auto &I : CXXRD->bases()) - if (!isEmptyRecordForLayout(Context, I.getType())) - return false; - } - - for (const auto *I : RD->fields()) - if (!isEmptyFieldForLayout(Context, I)) - return false; - - return true; -} - const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { const auto *RD = T->getAsRecordDecl(); if (!RD) diff --git a/clang/lib/CodeGen/ABIInfoImpl.h b/clang/lib/CodeGen/ABIInfoImpl.h index d9d79c6a55ddb..89ea2219096a2 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.h +++ b/clang/lib/CodeGen/ABIInfoImpl.h @@ -11,6 +11,7 @@ #include "ABIInfo.h" #include "CGCXXABI.h" +#include "clang/CodeGenUtils/RecordLayoutUtils.h" namespace clang::CodeGen { @@ -120,15 +121,8 @@ bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays, bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr = false); -/// isEmptyFieldForLayout - Return true iff the field is "empty", that is, -/// either a zero-width bit-field or an \ref isEmptyRecordForLayout. -bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD); - -/// isEmptyRecordForLayout - Return true iff a structure contains only empty -/// base classes (per \ref isEmptyRecordForLayout) and fields (per -/// \ref isEmptyFieldForLayout). Note, C++ record fields are considered empty -/// if the [[no_unique_address]] attribute would have made them empty. -bool isEmptyRecordForLayout(const ASTContext &Context, QualType T); +using CodeGenUtils::isEmptyFieldForLayout; +using CodeGenUtils::isEmptyRecordForLayout; /// isSingleElementStruct - Determine if a structure is a "single /// element struct", i.e. it has exactly one non-empty field or diff --git a/clang/lib/CodeGenUtils/CMakeLists.txt b/clang/lib/CodeGenUtils/CMakeLists.txt index 5839e8f2e1fe5..f46ac572a0ce9 100644 --- a/clang/lib/CodeGenUtils/CMakeLists.txt +++ b/clang/lib/CodeGenUtils/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_library(clangCodeGenUtils FunctionUtils.cpp ItaniumCXXABIUtils.cpp ModuleUtils.cpp + RecordLayoutUtils.cpp LINK_LIBS clangAST diff --git a/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp b/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp new file mode 100644 index 0000000000000..3b8d433dc8759 --- /dev/null +++ b/clang/lib/CodeGenUtils/RecordLayoutUtils.cpp @@ -0,0 +1,45 @@ +//===--- RecordLayoutUtils.cpp - Shared record layout queries -------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "clang/CodeGenUtils/RecordLayoutUtils.h" + +namespace clang::CodeGenUtils { + +bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD) { + if (FD->isZeroLengthBitField()) + return true; + + if (FD->isUnnamedBitField()) + return false; + + return isEmptyRecordForLayout(Ctx, FD->getType()); +} + +bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T) { + const auto *RD = T->getAsRecordDecl(); + if (!RD) + return false; + + // If this is a C++ record, check the bases first. + if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { + if (CXXRD->isDynamicClass()) + return false; + + for (const auto &I : CXXRD->bases()) + if (!isEmptyRecordForLayout(Ctx, I.getType())) + return false; + } + + for (const auto *I : RD->fields()) + if (!isEmptyFieldForLayout(Ctx, I)) + return false; + + return true; +} + +} // namespace clang::CodeGenUtils _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
