[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 03:26:06 PDT 2026
https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223451
>From 0b708d39ddcb8b1b248e839a025282388d56a074 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Tue, 29 Sep 2026 09:56:33 +0000
Subject: [PATCH 1/3] [CIR][CodeGen][NFC] Share hasExtraNeonArgument
Both CodeGens carry the same table-driven check for whether a Neon builtin
takes a trailing type-discriminating argument. CIR's copy was marked
"TODO(cir): Share this with ARM.cpp" and had a dead second switch, which the
shared version drops; classic's if/return pair becomes `return mask != 0`.
No functional change.
---
.../include/clang/CodeGenUtils/TargetUtils.h | 6 +++
.../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 40 +------------------
clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 37 ++---------------
clang/lib/CodeGenUtils/TargetUtils.cpp | 25 ++++++++++++
4 files changed, 36 insertions(+), 72 deletions(-)
diff --git a/clang/include/clang/CodeGenUtils/TargetUtils.h b/clang/include/clang/CodeGenUtils/TargetUtils.h
index 23d3a9e8dd6c2..2216484dbea36 100644
--- a/clang/include/clang/CodeGenUtils/TargetUtils.h
+++ b/clang/include/clang/CodeGenUtils/TargetUtils.h
@@ -46,6 +46,12 @@ LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *Caller,
const FunctionDecl *Callee);
+/// Returns whether the Neon builtin \p BuiltinID takes a trailing argument
+/// that discriminates the operand type. This should be kept consistent with
+/// the logic in Sema.
+/// TODO: Make this return false for SISD builtins.
+bool hasExtraNeonArgument(unsigned BuiltinID);
+
} // namespace clang::CodeGenUtils
#endif // LLVM_CLANG_CODEGENUTILS_TARGETUTILS_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 70253221c7b7d..5b6a657e9bf98 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -16,6 +16,7 @@
#include "clang/Basic/TargetBuiltins.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
// TODO(cir): once all builtins are covered, decide whether we still
// need to use LLVM intrinsics or if there's a better approach to follow. Right
@@ -90,43 +91,6 @@ static llvm::StringRef getLLVMIntrNameNoPrefix(llvm::Intrinsic::ID intrID) {
return llvmIntrName.drop_front(/*strlen("llvm.")=*/5);
}
-//===----------------------------------------------------------------------===//
-// NEON helpers
-//===----------------------------------------------------------------------===//
-/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra
-/// argument that specifies the vector type. The additional argument is meant
-/// for Sema checking (see `CheckNeonBuiltinFunctionCall`) and this function
-/// should be kept consistent with the logic in Sema.
-/// TODO: Make this return false for SISD builtins.
-/// TODO(cir): Share this with ARM.cpp
-static bool hasExtraNeonArgument(unsigned builtinID) {
- // Required by the headers included below, but not in this particular
- // function.
- [[maybe_unused]] int PtrArgNum = -1;
- [[maybe_unused]] bool HasConstPtr = false;
-
- // The mask encodes the type. We don't care about the actual value. Instead,
- // we just check whether its been set.
- uint64_t mask = 0;
- switch (builtinID) {
-#define GET_NEON_OVERLOAD_CHECK
-#include "clang/Basic/arm_fp16.inc"
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_OVERLOAD_CHECK
- // Non-neon builtins for controling VFP that take extra argument for
- // discriminating the type.
- case ARM::BI__builtin_arm_vcvtr_f:
- case ARM::BI__builtin_arm_vcvtr_d:
- mask = 1;
- }
- switch (builtinID) {
- default:
- break;
- }
-
- return mask != 0;
-}
-
static cir::VectorType getFloatNeonType(CIRGenFunction &cgf,
NeonTypeFlags intTypeFlags) {
int isQuad = intTypeFlags.isQuad();
@@ -2733,7 +2697,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
// Skip extra arguments used to discriminate vector types and that are
// intended for Sema checking.
- bool hasExtraArg = hasExtraNeonArgument(builtinID);
+ bool hasExtraArg = CodeGenUtils::hasExtraNeonArgument(builtinID);
unsigned numArgs = expr->getNumArgs() - (hasExtraArg ? 1 : 0);
for (unsigned i = 0, e = numArgs; i != e; i++) {
if (i == 0) {
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index e20fa60ee132b..2f2c6dc513c57 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -16,6 +16,7 @@
#include "TargetInfo.h"
#include "clang/Basic/AArch64CodeGenUtils.h"
#include "clang/Basic/TargetBuiltins.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicsAArch64.h"
#include "llvm/IR/IntrinsicsARM.h"
@@ -2127,38 +2128,6 @@ static Value *EmitAtomicStoreWithHintBuiltin(CodeGenFunction &CGF,
return Store;
}
-/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra
-/// argument that specifies the vector type. The additional argument is meant
-/// for Sema checking (see `CheckNeonBuiltinFunctionCall`) and this function
-/// should be kept consistent with the logic in Sema.
-/// TODO: Make this return false for SISD builtins.
-static bool HasExtraNeonArgument(unsigned BuiltinID) {
- // Required by the headers included below, but not in this particular
- // function.
- [[maybe_unused]] int PtrArgNum = -1;
- [[maybe_unused]] bool HasConstPtr = false;
-
- // The mask encodes the type. We don't care about the actual value. Instead,
- // we just check whether its been set.
- uint64_t mask = 0;
- switch (BuiltinID) {
-#define GET_NEON_OVERLOAD_CHECK
-#include "clang/Basic/arm_fp16.inc"
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_OVERLOAD_CHECK
- // Non-neon builtins for controling VFP that take extra argument for
- // discriminating the type.
- case ARM::BI__builtin_arm_vcvtr_f:
- case ARM::BI__builtin_arm_vcvtr_d:
- mask = 1;
- }
-
- if (mask)
- return true;
-
- return false;
-}
-
Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
const CallExpr *E,
ReturnValueSlot ReturnValue,
@@ -2538,7 +2507,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Address PtrOp0 = Address::invalid();
Address PtrOp1 = Address::invalid();
SmallVector<Value*, 4> Ops;
- bool HasExtraArg = HasExtraNeonArgument(BuiltinID);
+ bool HasExtraArg = CodeGenUtils::hasExtraNeonArgument(BuiltinID);
unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0);
for (unsigned i = 0, e = NumArgs; i != e; i++) {
if (i == 0) {
@@ -5370,7 +5339,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
// Note the assumption that SISD intrinsics do not contain extra arguments.
// TODO: Fold this into a single function call instead of, effectively, two
// separate checks.
- bool HasExtraArg = !IsSISD && HasExtraNeonArgument(BuiltinID);
+ bool HasExtraArg = !IsSISD && CodeGenUtils::hasExtraNeonArgument(BuiltinID);
unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0);
for (unsigned i = 0, e = NumArgs; i != e; i++) {
if (i == 0) {
diff --git a/clang/lib/CodeGenUtils/TargetUtils.cpp b/clang/lib/CodeGenUtils/TargetUtils.cpp
index 2561d6760773b..401e361e8743d 100644
--- a/clang/lib/CodeGenUtils/TargetUtils.cpp
+++ b/clang/lib/CodeGenUtils/TargetUtils.cpp
@@ -9,6 +9,7 @@
#include "clang/CodeGenUtils/TargetUtils.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/Basic/TargetBuiltins.h"
namespace clang::CodeGenUtils {
@@ -47,4 +48,28 @@ ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *Caller,
return Inlinability;
}
+bool hasExtraNeonArgument(unsigned BuiltinID) {
+ // Required by the headers included below, but not in this particular
+ // function.
+ [[maybe_unused]] int PtrArgNum = -1;
+ [[maybe_unused]] bool HasConstPtr = false;
+
+ // The mask encodes the type. We don't care about the actual value. Instead,
+ // we just check whether its been set.
+ uint64_t mask = 0;
+ switch (BuiltinID) {
+#define GET_NEON_OVERLOAD_CHECK
+#include "clang/Basic/arm_fp16.inc"
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_OVERLOAD_CHECK
+ // Non-neon builtins for controling VFP that take extra argument for
+ // discriminating the type.
+ case ARM::BI__builtin_arm_vcvtr_f:
+ case ARM::BI__builtin_arm_vcvtr_d:
+ mask = 1;
+ }
+
+ return mask != 0;
+}
+
} // namespace clang::CodeGenUtils
>From 75cd33345958c923ec561ae9c6a7688b92db671e Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Tue, 29 Sep 2026 09:56:39 +0000
Subject: [PATCH 2/3] [CIR][CodeGen][NFC] Share
requiresAMDGPUProtectedVisibility
Both CodeGens carry the same attribute check deciding whether an AMDGPU
kernel or device variable with hidden visibility must be promoted to
protected. The shared version takes a bool saying whether the global
currently has hidden visibility. Classic passed an llvm::GlobalValue and
CIR a cir::VisibilityKind, and both only compared it against hidden.
No functional change.
---
clang/include/clang/CodeGenUtils/TargetUtils.h | 6 ++++++
clang/lib/CIR/CodeGen/TargetInfo.cpp | 8 ++++++--
clang/lib/CIR/CodeGen/TargetInfo.h | 4 ----
clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp | 14 --------------
clang/lib/CodeGen/Targets/AMDGPU.cpp | 18 +++---------------
clang/lib/CodeGenUtils/TargetUtils.cpp | 14 ++++++++++++++
6 files changed, 29 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/CodeGenUtils/TargetUtils.h b/clang/include/clang/CodeGenUtils/TargetUtils.h
index 2216484dbea36..a44541c572590 100644
--- a/clang/include/clang/CodeGenUtils/TargetUtils.h
+++ b/clang/include/clang/CodeGenUtils/TargetUtils.h
@@ -19,6 +19,7 @@
#include <cstdint>
namespace clang {
+class Decl;
class FunctionDecl;
} // namespace clang
@@ -52,6 +53,11 @@ ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *Caller,
/// TODO: Make this return false for SISD builtins.
bool hasExtraNeonArgument(unsigned BuiltinID);
+/// Returns whether \p D must be given protected visibility on AMDGPU.
+/// \p HasHiddenVisibility is whether the emitted global currently has hidden
+/// visibility.
+bool requiresAMDGPUProtectedVisibility(const Decl *D, bool HasHiddenVisibility);
+
} // namespace clang::CodeGenUtils
#endif // LLVM_CLANG_CODEGENUTILS_TARGETUTILS_H
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index 57bc5f167e460..b648ca1f2cd74 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -7,6 +7,7 @@
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/MissingFeatures.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
using namespace clang;
using namespace clang::CIRGen;
@@ -91,13 +92,16 @@ class AMDGPUTargetCIRGenInfo : public TargetCIRGenInfo {
void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global,
CIRGenModule &cgm) const override {
if (auto func = mlir::dyn_cast<cir::FuncOp>(global)) {
- if (requiresAMDGPUProtectedVisibility(decl, func.getGlobalVisibility())) {
+ if (CodeGenUtils::requiresAMDGPUProtectedVisibility(
+ decl,
+ func.getGlobalVisibility() == cir::VisibilityKind::Hidden)) {
func.setGlobalVisibility(cir::VisibilityKind::Protected);
func.setDSOLocal(true);
}
setAMDGPUTargetFunctionAttributes(decl, func, cgm);
} else if (auto gv = mlir::dyn_cast<cir::GlobalOp>(global)) {
- if (requiresAMDGPUProtectedVisibility(decl, gv.getGlobalVisibility())) {
+ if (CodeGenUtils::requiresAMDGPUProtectedVisibility(
+ decl, gv.getGlobalVisibility() == cir::VisibilityKind::Hidden)) {
gv.setGlobalVisibility(cir::VisibilityKind::Protected);
gv.setDSOLocal(true);
}
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h
index e094fa53561f5..affb09f3c85d3 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.h
+++ b/clang/lib/CIR/CodeGen/TargetInfo.h
@@ -179,10 +179,6 @@ class TargetCIRGenInfo {
std::unique_ptr<TargetCIRGenInfo>
createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt);
-/// Check if AMDGPU protected visibility is required.
-bool requiresAMDGPUProtectedVisibility(const clang::Decl *d,
- cir::VisibilityKind visibility);
-
/// Set AMDGPU-specific function attributes for HIP kernels.
void setAMDGPUTargetFunctionAttributes(const clang::Decl *decl,
cir::FuncOp func, CIRGenModule &cgm);
diff --git a/clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp
index 7f1d903853660..5f3b848ed9cb6 100644
--- a/clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp
+++ b/clang/lib/CIR/CodeGen/Targets/AMDGPU.cpp
@@ -23,20 +23,6 @@
using namespace clang;
using namespace clang::CIRGen;
-bool clang::CIRGen::requiresAMDGPUProtectedVisibility(
- const Decl *d, cir::VisibilityKind visibility) {
- if (visibility != cir::VisibilityKind::Hidden)
- return false;
-
- return !d->hasAttr<OMPDeclareTargetDeclAttr>() &&
- (d->hasAttr<DeviceKernelAttr>() ||
- (isa<FunctionDecl>(d) && d->hasAttr<CUDAGlobalAttr>()) ||
- (isa<VarDecl>(d) &&
- (d->hasAttr<CUDADeviceAttr>() || d->hasAttr<CUDAConstantAttr>() ||
- cast<VarDecl>(d)->getType()->isCUDADeviceBuiltinSurfaceType() ||
- cast<VarDecl>(d)->getType()->isCUDADeviceBuiltinTextureType())));
-}
-
namespace {
/// Handle amdgpu-flat-work-group-size attribute.
diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp
index 0b5ed1898f138..607442c899f87 100644
--- a/clang/lib/CodeGen/Targets/AMDGPU.cpp
+++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp
@@ -9,6 +9,7 @@
#include "ABIInfoImpl.h"
#include "TargetInfo.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
@@ -325,20 +326,6 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
};
}
-static bool requiresAMDGPUProtectedVisibility(const Decl *D,
- llvm::GlobalValue *GV) {
- if (GV->getVisibility() != llvm::GlobalValue::HiddenVisibility)
- return false;
-
- return !D->hasAttr<OMPDeclareTargetDeclAttr>() &&
- (D->hasAttr<DeviceKernelAttr>() ||
- (isa<FunctionDecl>(D) && D->hasAttr<CUDAGlobalAttr>()) ||
- (isa<VarDecl>(D) &&
- (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() ||
- cast<VarDecl>(D)->getType()->isCUDADeviceBuiltinSurfaceType() ||
- cast<VarDecl>(D)->getType()->isCUDADeviceBuiltinTextureType())));
-}
-
void AMDGPUTargetCodeGenInfo::setFunctionDeclAttributes(
const FunctionDecl *FD, llvm::Function *F, CodeGenModule &M) const {
const auto *ReqdWGS =
@@ -454,7 +441,8 @@ void AMDGPUTargetCodeGenInfo::setFunctionDeclAttributes(
void AMDGPUTargetCodeGenInfo::setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
- if (requiresAMDGPUProtectedVisibility(D, GV)) {
+ if (CodeGenUtils::requiresAMDGPUProtectedVisibility(
+ D, GV->getVisibility() == llvm::GlobalValue::HiddenVisibility)) {
GV->setVisibility(llvm::GlobalValue::ProtectedVisibility);
GV->setDSOLocal(true);
}
diff --git a/clang/lib/CodeGenUtils/TargetUtils.cpp b/clang/lib/CodeGenUtils/TargetUtils.cpp
index 401e361e8743d..f72218f4dda2d 100644
--- a/clang/lib/CodeGenUtils/TargetUtils.cpp
+++ b/clang/lib/CodeGenUtils/TargetUtils.cpp
@@ -72,4 +72,18 @@ bool hasExtraNeonArgument(unsigned BuiltinID) {
return mask != 0;
}
+bool requiresAMDGPUProtectedVisibility(const Decl *D,
+ bool HasHiddenVisibility) {
+ if (!HasHiddenVisibility)
+ return false;
+
+ return !D->hasAttr<OMPDeclareTargetDeclAttr>() &&
+ (D->hasAttr<DeviceKernelAttr>() ||
+ (isa<FunctionDecl>(D) && D->hasAttr<CUDAGlobalAttr>()) ||
+ (isa<VarDecl>(D) &&
+ (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() ||
+ cast<VarDecl>(D)->getType()->isCUDADeviceBuiltinSurfaceType() ||
+ cast<VarDecl>(D)->getType()->isCUDADeviceBuiltinTextureType())));
+}
+
} // namespace clang::CodeGenUtils
>From 36a70a9c20b6ba5b9073539e4c4b18e596bf4ed5 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 3/3] [CIR][CodeGen][NFC] Retire the CodeGenUtils.h catch-all
header
The preceding patches group shared helpers by the classic CodeGen file, or
file family, they came from. That leaves CodeGenUtils.h holding only the
five helpers PR #221001 started the library with and the target-features
checker from PR #223056, so they move to the same places their neighbours
went and the header goes away. The library keeps its name.
checkTargetFeatures came out of CodeGenFunction.cpp, so it joins
shouldEmitLifetimeMarkers in FunctionUtils.h. TargetUtils.h would fit it by
subject, but the series sorts by origin file, and picking origin keeps the
rule mechanical.
isAAPCS is the one case origin does not settle, since it was duplicated in
CGExpr.cpp and CGRecordLayoutBuilder.cpp rather than living in one file. It
is a plain TargetInfo predicate, so it goes with the other target
predicates.
Doing this now avoids making every helper we share from here on pick
between the catch-all and a themed header, with no rule saying which. It
only moves code already on main, so it can be dropped without affecting the
patches before it.
No functional change intended.
---
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 | 81 ++++++
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, 282 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..8bd6cf7fa427f 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 &Context, 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..588c957e3da0a 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..b8cd24177529f 100644
--- a/clang/lib/CodeGenUtils/ClassUtils.cpp
+++ b/clang/lib/CodeGenUtils/ClassUtils.cpp
@@ -36,4 +36,85 @@ bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init) {
return Checker.UsesThis;
}
+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);
+}
+
+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