[llvm-branch-commits] [clang] [CIR][CodeGen][NFC] Retire the CodeGenUtils.h catch-all header (PR #223451)
Henrich Lauko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Sep 29 04:23:38 PDT 2026
https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223451
>From 74cbb5d53a1acddf9a5484ce71ffb5d7dfdf18d0 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Mon, 14 Sep 2026 16:22:27 +0000
Subject: [PATCH] [CIR][CodeGen][NFC] Retire the CodeGenUtils.h catch-all
header
Moves the last helpers out of `CodeGenUtils.h` into `ClassUtils.h`,
`ModuleUtils.h`, `TargetUtils.h` and `FunctionUtils.h` (`checkTargetFeatures`,
since it came from CodeGenFunction.cpp) and deletes the header. Only moves code
already on main, so it can be dropped on its own.
---
clang/include/clang/CodeGenUtils/ClassUtils.h | 18 ++
.../include/clang/CodeGenUtils/CodeGenUtils.h | 65 -----
.../clang/CodeGenUtils/FunctionUtils.h | 26 +-
.../include/clang/CodeGenUtils/ModuleUtils.h | 7 +
.../include/clang/CodeGenUtils/TargetUtils.h | 4 +
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 2 +-
clang/lib/CIR/CodeGen/CIRGenClass.cpp | 1 -
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 2 +-
clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 2 +-
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 1 -
.../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp | 2 +-
clang/lib/CodeGen/CGClass.cpp | 1 -
clang/lib/CodeGen/CGExpr.cpp | 2 +-
clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 2 +-
clang/lib/CodeGen/CodeGenFunction.cpp | 1 -
clang/lib/CodeGen/CodeGenModule.cpp | 1 -
clang/lib/CodeGenUtils/CMakeLists.txt | 1 -
clang/lib/CodeGenUtils/ClassUtils.cpp | 78 ++++++
clang/lib/CodeGenUtils/CodeGenUtils.cpp | 233 ------------------
clang/lib/CodeGenUtils/FunctionUtils.cpp | 120 +++++++++
clang/lib/CodeGenUtils/ModuleUtils.cpp | 17 ++
clang/lib/CodeGenUtils/TargetUtils.cpp | 5 +
22 files changed, 279 insertions(+), 312 deletions(-)
delete mode 100644 clang/include/clang/CodeGenUtils/CodeGenUtils.h
delete mode 100644 clang/lib/CodeGenUtils/CodeGenUtils.cpp
diff --git a/clang/include/clang/CodeGenUtils/ClassUtils.h b/clang/include/clang/CodeGenUtils/ClassUtils.h
index 63664ed737933..570c67110e120 100644
--- a/clang/include/clang/CodeGenUtils/ClassUtils.h
+++ b/clang/include/clang/CodeGenUtils/ClassUtils.h
@@ -24,6 +24,24 @@ namespace clang::CodeGenUtils {
/// properly set.
bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init);
+/// Check whether we need to initialize any vtable pointers before calling this
+/// destructor.
+bool canSkipVTablePointerInitialization(ASTContext &Ctx,
+ const CXXDestructorDecl *Dtor);
+
+/// Check whether destructing \p Field has no observable behaviors, and thus can
+/// be skipped when creating a destructor body. So non-record types, anonymous
+/// structs/unions, or record types where the destructor doesnt DO anything are
+/// considered as this version of 'trivial'.
+/// Note: This is a more liberal definition of trivial destruction than the C++
+/// Standard's version, and thus cannot be used as a substitute for C++ Standard
+/// requirements.
+bool fieldHasTrivialDestructorBody(ASTContext &Ctx, const FieldDecl *Field);
+
+/// Return whether \p BaseInit initializes a base class that is dynamic, that
+/// is, one whose vtable pointer must be set before the initializer runs.
+bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit);
+
} // namespace clang::CodeGenUtils
#endif // LLVM_CLANG_CODEGENUTILS_CLASSUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/CodeGenUtils.h b/clang/include/clang/CodeGenUtils/CodeGenUtils.h
deleted file mode 100644
index b24f457f9537c..0000000000000
--- a/clang/include/clang/CodeGenUtils/CodeGenUtils.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//===--- CodeGenUtils.h - Shared Classic CodeGen/CIR CodeGen Utils--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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_CODEGENUTILS_CODEGENUTILS_H
-#define LLVM_CLANG_CODEGENUTILS_CODEGENUTILS_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/Basic/SourceLocation.h"
-
-namespace clang {
-class CallExpr;
-class DiagnosticsEngine;
-class FunctionDecl;
-class LangOptions;
-} // namespace clang
-
-namespace clang::CodeGenUtils {
-/// Check whether we need to initialize any vtable pointers before calling this
-/// destructor.
-bool canSkipVTablePointerInitialization(ASTContext &Ctx,
- const CXXDestructorDecl *Dtor);
-
-/// Check whether destructing \p Field has no observable behaviors, and thus can
-/// be skipped when creating a destructor body. So non-record types, anonymous
-/// structs/unions, or record types where the destructor doesnt DO anything are
-/// considered as this version of 'trivial'.
-/// Note: This is a more liberal definition of trivial destruction than the C++
-/// Standard's version, and thus cannot be used as a substitute for C++ Standard
-/// requirements.
-bool fieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field);
-
-/// Determines whether the language options require us to model
-/// unwind exceptions. We treat -fexceptions as mandating this
-/// except under the fragile ObjC ABI with only ObjC exceptions
-/// enabled. This means, for example, that C with -fexceptions
-/// enables this.
-bool hasUnwindExceptions(const LangOptions &LangOpts);
-
-/// Helper method to check if the underlying ABI is AAPCS
-bool isAAPCS(const TargetInfo &TargetInfo);
-
-bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit);
-
-/// Check that a call to a target-specific builtin has the required target
-/// features enabled in the caller, emitting an error diagnostic if not.
-/// \p caller is the FunctionDecl of the enclosing function (may be null).
-void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
- const LangOptions &LangOpts, const CallExpr *E,
- const FunctionDecl *Caller,
- const FunctionDecl *TargetDecl);
-
-/// Overload taking a raw source location instead of a CallExpr.
-void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
- const LangOptions &LangOpts, SourceLocation Loc,
- const FunctionDecl *Caller,
- const FunctionDecl *TargetDecl);
-
-} // namespace clang::CodeGenUtils
-
-#endif // LLVM_CLANG_CODEGENUTILS_CODEGENUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/FunctionUtils.h b/clang/include/clang/CodeGenUtils/FunctionUtils.h
index f924874d829e0..4e500aa8d3c0b 100644
--- a/clang/include/clang/CodeGenUtils/FunctionUtils.h
+++ b/clang/include/clang/CodeGenUtils/FunctionUtils.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
//
-// This file holds the queries that both classic CodeGen and CIR CodeGen need
-// while emitting a function body.
+// This file holds the queries and checks that both classic CodeGen and CIR
+// CodeGen need while emitting a function body.
//
//===----------------------------------------------------------------------===//
@@ -16,6 +16,14 @@
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class ASTContext;
+class CallExpr;
+class DiagnosticsEngine;
+class FunctionDecl;
+} // namespace clang
namespace clang::CodeGenUtils {
@@ -23,6 +31,20 @@ namespace clang::CodeGenUtils {
bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
const LangOptions &LangOpts);
+/// Check that a call to a target-specific builtin has the required target
+/// features enabled in the caller, emitting an error diagnostic if not.
+/// \p Caller is the FunctionDecl of the enclosing function (may be null).
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, const CallExpr *E,
+ const FunctionDecl *Caller,
+ const FunctionDecl *TargetDecl);
+
+/// Overload taking a raw source location instead of a CallExpr.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, SourceLocation Loc,
+ const FunctionDecl *Caller,
+ const FunctionDecl *TargetDecl);
+
} // namespace clang::CodeGenUtils
#endif // LLVM_CLANG_CODEGENUTILS_FUNCTIONUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/ModuleUtils.h b/clang/include/clang/CodeGenUtils/ModuleUtils.h
index 5c7423ad4fac5..3bb94184a03f0 100644
--- a/clang/include/clang/CodeGenUtils/ModuleUtils.h
+++ b/clang/include/clang/CodeGenUtils/ModuleUtils.h
@@ -19,6 +19,13 @@
namespace clang::CodeGenUtils {
+/// Determines whether the language options require us to model
+/// unwind exceptions. We treat -fexceptions as mandating this
+/// except under the fragile ObjC ABI with only ObjC exceptions
+/// enabled. This means, for example, that C with -fexceptions
+/// enables this.
+bool hasUnwindExceptions(const LangOptions &LangOpts);
+
/// Check whether \p D is a strong definition, and thus must not be given
/// common linkage. \p NoCommon reflects -fno-common.
bool isVarDeclStrongDefinition(const ASTContext &Ctx, const VarDecl *D,
diff --git a/clang/include/clang/CodeGenUtils/TargetUtils.h b/clang/include/clang/CodeGenUtils/TargetUtils.h
index a44541c572590..2c812c6a2b617 100644
--- a/clang/include/clang/CodeGenUtils/TargetUtils.h
+++ b/clang/include/clang/CodeGenUtils/TargetUtils.h
@@ -21,6 +21,7 @@
namespace clang {
class Decl;
class FunctionDecl;
+class TargetInfo;
} // namespace clang
namespace clang::CodeGenUtils {
@@ -53,6 +54,9 @@ ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *Caller,
/// TODO: Make this return false for SISD builtins.
bool hasExtraNeonArgument(unsigned BuiltinID);
+/// Helper method to check if the underlying ABI is AAPCS
+bool isAAPCS(const TargetInfo &TargetInfo);
+
/// Returns whether \p D must be given protected visibility on AMDGPU.
/// \p HasHiddenVisibility is whether the emitted global currently has hidden
/// visibility.
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 245708691b7d9..56cf268e119a6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -26,7 +26,7 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/CodeGenUtils/FunctionUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 28db1763fd3cb..9633b915bd669 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -20,7 +20,6 @@
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/MissingFeatures.h"
#include "clang/CodeGenUtils/ClassUtils.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
using namespace clang;
using namespace clang::CIRGen;
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index d285800111c45..8f57a90c06218 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -30,8 +30,8 @@
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "clang/CodeGenUtils/ExprUtils.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
#include <optional>
using namespace clang;
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 823ccbe1d2e82..0f3aca2f67e4e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -21,7 +21,7 @@
#include "clang/AST/GlobalDecl.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/CodeGenUtils/ClassUtils.h"
#include "clang/CodeGenUtils/FunctionUtils.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/IR/FPEnv.h"
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 8978f8305b267..6509df09ee8dd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -36,7 +36,6 @@
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/Interfaces/CIROpInterfaces.h"
#include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "clang/CodeGenUtils/ModuleUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index 63715e1f6e814..49651c08c76d2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -22,8 +22,8 @@
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
#include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "clang/CodeGenUtils/RecordLayoutUtils.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
#include "llvm/Support/Casting.h"
#include <memory>
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 63f5d9ae13dbf..31965c98c75bb 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -26,7 +26,6 @@
#include "clang/Basic/CodeGenOptions.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/CodeGenUtils/ClassUtils.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/SaveAndRestore.h"
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 25e775f8328b9..b23b347643dcd 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -39,8 +39,8 @@
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "clang/CodeGenUtils/ExprUtils.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringExtras.h"
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 905382f5ea939..dc6a7bfca35f6 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -21,8 +21,8 @@
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/CodeGenOptions.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "clang/CodeGenUtils/RecordLayoutUtils.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 8f4d9aae1603e..4e9883a091261 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -36,7 +36,6 @@
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "clang/CodeGenUtils/FunctionUtils.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/ScopeExit.h"
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 6cdd35d5e1308..da04faa954875 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -48,7 +48,6 @@
#include "clang/Basic/Version.h"
#include "clang/CodeGen/BackendUtil.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "clang/CodeGenUtils/ModuleUtils.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ABI/IRTypeMapper.h"
diff --git a/clang/lib/CodeGenUtils/CMakeLists.txt b/clang/lib/CodeGenUtils/CMakeLists.txt
index edd32da5b5f7c..b083d95e9d47c 100644
--- a/clang/lib/CodeGenUtils/CMakeLists.txt
+++ b/clang/lib/CodeGenUtils/CMakeLists.txt
@@ -5,7 +5,6 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangCodeGenUtils
CallUtils.cpp
ClassUtils.cpp
- CodeGenUtils.cpp
EHPersonality.cpp
ExprUtils.cpp
FunctionUtils.cpp
diff --git a/clang/lib/CodeGenUtils/ClassUtils.cpp b/clang/lib/CodeGenUtils/ClassUtils.cpp
index 90bab38280c30..5a504ca0b5beb 100644
--- a/clang/lib/CodeGenUtils/ClassUtils.cpp
+++ b/clang/lib/CodeGenUtils/ClassUtils.cpp
@@ -36,4 +36,82 @@ bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init) {
return Checker.UsesThis;
}
+static bool
+hasTrivialDestructorBody(ASTContext &Ctx, const CXXRecordDecl *BaseClassDecl,
+ const CXXRecordDecl *MostDerivedClassDecl) {
+ // If the destructor is trivial we don't have to check anything else.
+ if (BaseClassDecl->hasTrivialDestructor())
+ return true;
+
+ if (!BaseClassDecl->getDestructor()->hasTrivialBody())
+ return false;
+
+ // Check fields.
+ for (const auto *Field : BaseClassDecl->fields())
+ if (!fieldHasTrivialDestructorBody(Ctx, Field))
+ return false;
+
+ // Check non-virtual bases.
+ for (const auto &I : BaseClassDecl->bases()) {
+ if (I.isVirtual())
+ continue;
+
+ const auto *NonVirtualBase = I.getType()->castAsCXXRecordDecl();
+ if (!hasTrivialDestructorBody(Ctx, NonVirtualBase, MostDerivedClassDecl))
+ return false;
+ }
+
+ if (BaseClassDecl == MostDerivedClassDecl) {
+ // Check virtual bases.
+ for (const auto &I : BaseClassDecl->vbases()) {
+ const auto *VirtualBase = I.getType()->castAsCXXRecordDecl();
+ if (!hasTrivialDestructorBody(Ctx, VirtualBase, MostDerivedClassDecl))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool fieldHasTrivialDestructorBody(ASTContext &Ctx, const FieldDecl *Field) {
+ QualType FieldBaseElementType = Ctx.getBaseElementType(Field->getType());
+
+ auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl();
+ if (!FieldClassDecl)
+ return true;
+
+ // The destructor for an implicit anonymous union member is never invoked.
+ if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+ return true;
+
+ return hasTrivialDestructorBody(Ctx, FieldClassDecl, FieldClassDecl);
+}
+
+bool canSkipVTablePointerInitialization(ASTContext &Ctx,
+ const CXXDestructorDecl *Dtor) {
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ if (!ClassDecl->isDynamicClass())
+ return true;
+
+ // For a final class, the vtable pointer is known to already point to the
+ // class's vtable.
+ if (ClassDecl->isEffectivelyFinal())
+ return true;
+
+ if (!Dtor->hasTrivialBody())
+ return false;
+
+ // Check the fields.
+ for (const auto *Field : ClassDecl->fields())
+ if (!fieldHasTrivialDestructorBody(Ctx, Field))
+ return false;
+
+ return true;
+}
+
+bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
+ const Type *BaseType = BaseInit->getBaseClass();
+ return BaseType->castAsCXXRecordDecl()->isDynamicClass();
+}
+
} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/CodeGenUtils.cpp b/clang/lib/CodeGenUtils/CodeGenUtils.cpp
deleted file mode 100644
index 4fd78d6997e95..0000000000000
--- a/clang/lib/CodeGenUtils/CodeGenUtils.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-//==--- CodeGenUtils.cpp - Shared Classic CodeGen/CIR CodeGen Utils--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
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/CodeGenUtils/CodeGenUtils.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/Expr.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/DiagnosticFrontend.h"
-#include "clang/Basic/TargetBuiltins.h"
-#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/StringMap.h"
-
-namespace clang::CodeGenUtils {
-static bool
-hasTrivialDestructorBody(ASTContext &Context,
- const CXXRecordDecl *BaseClassDecl,
- const CXXRecordDecl *MostDerivedClassDecl) {
- // If the destructor is trivial we don't have to check anything else.
- if (BaseClassDecl->hasTrivialDestructor())
- return true;
-
- if (!BaseClassDecl->getDestructor()->hasTrivialBody())
- return false;
-
- // Check fields.
- for (const auto *Field : BaseClassDecl->fields())
- if (!fieldHasTrivialDestructorBody(Context, Field))
- return false;
-
- // Check non-virtual bases.
- for (const auto &I : BaseClassDecl->bases()) {
- if (I.isVirtual())
- continue;
-
- const auto *NonVirtualBase = I.getType()->castAsCXXRecordDecl();
- if (!hasTrivialDestructorBody(Context, NonVirtualBase,
- MostDerivedClassDecl))
- return false;
- }
-
- if (BaseClassDecl == MostDerivedClassDecl) {
- // Check virtual bases.
- for (const auto &I : BaseClassDecl->vbases()) {
- const auto *VirtualBase = I.getType()->castAsCXXRecordDecl();
- if (!hasTrivialDestructorBody(Context, VirtualBase, MostDerivedClassDecl))
- return false;
- }
- }
-
- return true;
-}
-
-bool fieldHasTrivialDestructorBody(ASTContext &Context,
- const FieldDecl *Field) {
- QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
-
- auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl();
- if (!FieldClassDecl)
- return true;
-
- // The destructor for an implicit anonymous union member is never invoked.
- if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
- return true;
-
- return hasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl);
-}
-
-/// Check whether we need to initialize any vtable pointers before calling this
-/// destructor.
-bool canSkipVTablePointerInitialization(ASTContext &Ctx,
- const CXXDestructorDecl *Dtor) {
- const CXXRecordDecl *ClassDecl = Dtor->getParent();
- if (!ClassDecl->isDynamicClass())
- return true;
-
- // For a final class, the vtable pointer is known to already point to the
- // class's vtable.
- if (ClassDecl->isEffectivelyFinal())
- return true;
-
- if (!Dtor->hasTrivialBody())
- return false;
-
- // Check the fields.
- for (const auto *Field : ClassDecl->fields())
- if (!fieldHasTrivialDestructorBody(Ctx, Field))
- return false;
-
- return true;
-}
-bool hasUnwindExceptions(const LangOptions &LangOpts) {
- // If exceptions are completely disabled, obviously this is false.
- if (!LangOpts.Exceptions)
- return false;
-
- // If C++ exceptions are enabled, this is true.
- if (LangOpts.CXXExceptions)
- return true;
-
- // If ObjC exceptions are enabled, this depends on the ABI.
- if (LangOpts.ObjCExceptions) {
- return LangOpts.ObjCRuntime.hasUnwindExceptions();
- }
-
- return true;
-}
-
-bool isAAPCS(const TargetInfo &TargetInfo) {
- return TargetInfo.getABI().starts_with("aapcs");
-}
-bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
- const Type *BaseType = BaseInit->getBaseClass();
- return BaseType->castAsCXXRecordDecl()->isDynamicClass();
-}
-
-// Emits an error if we don't have a valid set of target features for the
-// called function.
-void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
- const LangOptions &LangOpts, const CallExpr *E,
- const FunctionDecl *Caller,
- const FunctionDecl *TargetDecl) {
- // SemaChecking cannot handle these x86 builtins because they have different
- // parameter ranges depending on the caller's TargetAttribute.
- if (Ctx.getTargetInfo().getTriple().isX86()) {
- unsigned BuiltinID = TargetDecl->getBuiltinID();
- if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
- BuiltinID == X86::BI__builtin_ia32_cmpss ||
- BuiltinID == X86::BI__builtin_ia32_cmppd ||
- BuiltinID == X86::BI__builtin_ia32_cmpsd) {
- llvm::StringMap<bool> TargetFeatureMap;
- Ctx.getFunctionFeatureMap(TargetFeatureMap, Caller);
- llvm::APSInt Result = *(E->getArg(2)->getIntegerConstantExpr(Ctx));
- if (Result.getSExtValue() > 7 && !TargetFeatureMap.lookup("avx"))
- Diags.Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
- << TargetDecl->getDeclName() << "avx";
- }
- }
- checkTargetFeatures(Ctx, Diags, LangOpts, E->getBeginLoc(), Caller,
- TargetDecl);
-}
-
-// Emits an error if we don't have a valid set of target features for the
-// called function.
-void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
- const LangOptions &LangOpts, SourceLocation Loc,
- const FunctionDecl *Caller,
- const FunctionDecl *TargetDecl) {
- if (!TargetDecl || !Caller)
- return;
-
- bool IsAlwaysInline = TargetDecl->hasAttr<AlwaysInlineAttr>();
- bool IsFlatten = Caller->hasAttr<FlattenAttr>();
-
- unsigned BuiltinID = TargetDecl->getBuiltinID();
- std::string MissingFeature;
- llvm::StringMap<bool> CallerFeatureMap;
- Ctx.getFunctionFeatureMap(CallerFeatureMap, Caller);
- // When compiling in HipStdPar mode we have to be conservative in rejecting
- // target specific features in the FE, and defer the possible error to the
- // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
- // referenced by an accelerator executable function, we emit an error.
- bool IsHipStdPar = LangOpts.HIPStdPar && LangOpts.CUDAIsDevice;
- if (BuiltinID) {
- StringRef FeatureList(Ctx.BuiltinInfo.getRequiredFeatures(BuiltinID));
- if (!Builtin::evaluateRequiredTargetFeatures(FeatureList,
- CallerFeatureMap) &&
- !IsHipStdPar)
- Diags.Report(Loc, diag::err_builtin_needs_feature)
- << TargetDecl->getDeclName() << FeatureList;
- } else if (!TargetDecl->isMultiVersion() &&
- TargetDecl->hasAttr<TargetAttr>()) {
- // Get the required features for the callee.
- const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
- ParsedTargetAttr ParsedAttr = Ctx.filterFunctionTargetAttrs(TD);
-
- SmallVector<StringRef, 1> ReqFeatures;
- llvm::StringMap<bool> CalleeFeatureMap;
- Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
-
- for (const auto &F : ParsedAttr.Features) {
- if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
- ReqFeatures.push_back(StringRef(F).substr(1));
- }
- for (const auto &F : CalleeFeatureMap) {
- if (F.getValue())
- ReqFeatures.push_back(F.getKey());
- }
- if (!llvm::all_of(ReqFeatures,
- [&](StringRef Feature) {
- if (!CallerFeatureMap.lookup(Feature)) {
- MissingFeature = Feature.str();
- return false;
- }
- return true;
- }) &&
- !IsHipStdPar) {
- if (IsAlwaysInline)
- Diags.Report(Loc, diag::err_function_needs_feature)
- << Caller->getDeclName() << TargetDecl->getDeclName()
- << MissingFeature;
- else if (IsFlatten)
- Diags.Report(Loc, diag::err_flatten_function_needs_feature)
- << Caller->getDeclName() << TargetDecl->getDeclName()
- << MissingFeature;
- }
- } else if (!Caller->isMultiVersion() && Caller->hasAttr<TargetAttr>()) {
- llvm::StringMap<bool> CalleeFeatureMap;
- Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
-
- for (const auto &F : CalleeFeatureMap) {
- if (F.getValue() &&
- (!CallerFeatureMap.lookup(F.getKey()) ||
- !CallerFeatureMap.find(F.getKey())->getValue()) &&
- !IsHipStdPar) {
- if (IsAlwaysInline)
- Diags.Report(Loc, diag::err_function_needs_feature)
- << Caller->getDeclName() << TargetDecl->getDeclName()
- << F.getKey();
- else if (IsFlatten)
- Diags.Report(Loc, diag::err_flatten_function_needs_feature)
- << Caller->getDeclName() << TargetDecl->getDeclName()
- << F.getKey();
- }
- }
- }
-}
-
-} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/FunctionUtils.cpp b/clang/lib/CodeGenUtils/FunctionUtils.cpp
index 9f01745abbf82..083c04d30bec4 100644
--- a/clang/lib/CodeGenUtils/FunctionUtils.cpp
+++ b/clang/lib/CodeGenUtils/FunctionUtils.cpp
@@ -7,6 +7,14 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGenUtils/FunctionUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringMap.h"
namespace clang::CodeGenUtils {
@@ -26,4 +34,116 @@ bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
return CGOpts.OptimizationLevel != 0;
}
+// Emits an error if we don't have a valid set of target features for the
+// called function.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, const CallExpr *E,
+ const FunctionDecl *Caller,
+ const FunctionDecl *TargetDecl) {
+ // SemaChecking cannot handle these x86 builtins because they have different
+ // parameter ranges depending on the caller's TargetAttribute.
+ if (Ctx.getTargetInfo().getTriple().isX86()) {
+ unsigned BuiltinID = TargetDecl->getBuiltinID();
+ if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
+ BuiltinID == X86::BI__builtin_ia32_cmpss ||
+ BuiltinID == X86::BI__builtin_ia32_cmppd ||
+ BuiltinID == X86::BI__builtin_ia32_cmpsd) {
+ llvm::StringMap<bool> TargetFeatureMap;
+ Ctx.getFunctionFeatureMap(TargetFeatureMap, Caller);
+ llvm::APSInt Result = *(E->getArg(2)->getIntegerConstantExpr(Ctx));
+ if (Result.getSExtValue() > 7 && !TargetFeatureMap.lookup("avx"))
+ Diags.Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
+ << TargetDecl->getDeclName() << "avx";
+ }
+ }
+ checkTargetFeatures(Ctx, Diags, LangOpts, E->getBeginLoc(), Caller,
+ TargetDecl);
+}
+
+// Emits an error if we don't have a valid set of target features for the
+// called function.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, SourceLocation Loc,
+ const FunctionDecl *Caller,
+ const FunctionDecl *TargetDecl) {
+ if (!TargetDecl || !Caller)
+ return;
+
+ bool IsAlwaysInline = TargetDecl->hasAttr<AlwaysInlineAttr>();
+ bool IsFlatten = Caller->hasAttr<FlattenAttr>();
+
+ unsigned BuiltinID = TargetDecl->getBuiltinID();
+ std::string MissingFeature;
+ llvm::StringMap<bool> CallerFeatureMap;
+ Ctx.getFunctionFeatureMap(CallerFeatureMap, Caller);
+ // When compiling in HipStdPar mode we have to be conservative in rejecting
+ // target specific features in the FE, and defer the possible error to the
+ // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
+ // referenced by an accelerator executable function, we emit an error.
+ bool IsHipStdPar = LangOpts.HIPStdPar && LangOpts.CUDAIsDevice;
+ if (BuiltinID) {
+ StringRef FeatureList(Ctx.BuiltinInfo.getRequiredFeatures(BuiltinID));
+ if (!Builtin::evaluateRequiredTargetFeatures(FeatureList,
+ CallerFeatureMap) &&
+ !IsHipStdPar)
+ Diags.Report(Loc, diag::err_builtin_needs_feature)
+ << TargetDecl->getDeclName() << FeatureList;
+ } else if (!TargetDecl->isMultiVersion() &&
+ TargetDecl->hasAttr<TargetAttr>()) {
+ // Get the required features for the callee.
+ const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
+ ParsedTargetAttr ParsedAttr = Ctx.filterFunctionTargetAttrs(TD);
+
+ SmallVector<StringRef, 1> ReqFeatures;
+ llvm::StringMap<bool> CalleeFeatureMap;
+ Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
+
+ for (const auto &F : ParsedAttr.Features) {
+ if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
+ ReqFeatures.push_back(StringRef(F).substr(1));
+ }
+ for (const auto &F : CalleeFeatureMap) {
+ if (F.getValue())
+ ReqFeatures.push_back(F.getKey());
+ }
+ if (!llvm::all_of(ReqFeatures,
+ [&](StringRef Feature) {
+ if (!CallerFeatureMap.lookup(Feature)) {
+ MissingFeature = Feature.str();
+ return false;
+ }
+ return true;
+ }) &&
+ !IsHipStdPar) {
+ if (IsAlwaysInline)
+ Diags.Report(Loc, diag::err_function_needs_feature)
+ << Caller->getDeclName() << TargetDecl->getDeclName()
+ << MissingFeature;
+ else if (IsFlatten)
+ Diags.Report(Loc, diag::err_flatten_function_needs_feature)
+ << Caller->getDeclName() << TargetDecl->getDeclName()
+ << MissingFeature;
+ }
+ } else if (!Caller->isMultiVersion() && Caller->hasAttr<TargetAttr>()) {
+ llvm::StringMap<bool> CalleeFeatureMap;
+ Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
+
+ for (const auto &F : CalleeFeatureMap) {
+ if (F.getValue() &&
+ (!CallerFeatureMap.lookup(F.getKey()) ||
+ !CallerFeatureMap.find(F.getKey())->getValue()) &&
+ !IsHipStdPar) {
+ if (IsAlwaysInline)
+ Diags.Report(Loc, diag::err_function_needs_feature)
+ << Caller->getDeclName() << TargetDecl->getDeclName()
+ << F.getKey();
+ else if (IsFlatten)
+ Diags.Report(Loc, diag::err_flatten_function_needs_feature)
+ << Caller->getDeclName() << TargetDecl->getDeclName()
+ << F.getKey();
+ }
+ }
+ }
+}
+
} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/ModuleUtils.cpp b/clang/lib/CodeGenUtils/ModuleUtils.cpp
index 0d4882345e303..89655301400e6 100644
--- a/clang/lib/CodeGenUtils/ModuleUtils.cpp
+++ b/clang/lib/CodeGenUtils/ModuleUtils.cpp
@@ -12,6 +12,23 @@
namespace clang::CodeGenUtils {
+bool hasUnwindExceptions(const LangOptions &LangOpts) {
+ // If exceptions are completely disabled, obviously this is false.
+ if (!LangOpts.Exceptions)
+ return false;
+
+ // If C++ exceptions are enabled, this is true.
+ if (LangOpts.CXXExceptions)
+ return true;
+
+ // If ObjC exceptions are enabled, this depends on the ABI.
+ if (LangOpts.ObjCExceptions) {
+ return LangOpts.ObjCRuntime.hasUnwindExceptions();
+ }
+
+ return true;
+}
+
bool isVarDeclStrongDefinition(const ASTContext &Ctx, const VarDecl *D,
bool NoCommon) {
// Don't give variables common linkage if -fno-common was specified unless it
diff --git a/clang/lib/CodeGenUtils/TargetUtils.cpp b/clang/lib/CodeGenUtils/TargetUtils.cpp
index f72218f4dda2d..86ebb29410d10 100644
--- a/clang/lib/CodeGenUtils/TargetUtils.cpp
+++ b/clang/lib/CodeGenUtils/TargetUtils.cpp
@@ -10,6 +10,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
namespace clang::CodeGenUtils {
@@ -72,6 +73,10 @@ bool hasExtraNeonArgument(unsigned BuiltinID) {
return mask != 0;
}
+bool isAAPCS(const TargetInfo &TargetInfo) {
+ return TargetInfo.getABI().starts_with("aapcs");
+}
+
bool requiresAMDGPUProtectedVisibility(const Decl *D,
bool HasHiddenVisibility) {
if (!HasHiddenVisibility)
More information about the llvm-branch-commits
mailing list