[clang] WIP on vector deleting destructors (PR #121490)
Mariya Podchishchaeva via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 2 07:56:52 PST 2025
https://github.com/Fznamznon created https://github.com/llvm/llvm-project/pull/121490
None
>From 2a63bcb5b63f3a8fbeb206fbdbcfc1a328054fe0 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Thu, 12 Dec 2024 08:57:37 -0800
Subject: [PATCH 1/6] Add rough body emission
---
clang/lib/CodeGen/CGCXXABI.cpp | 15 +++++
clang/lib/CodeGen/CGCXXABI.h | 6 ++
clang/lib/CodeGen/CGClass.cpp | 109 ++++++++++++++++++++++++++++++---
3 files changed, 121 insertions(+), 9 deletions(-)
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index 7c6dfc3e59d8c0..e562e263abaa5f 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -273,6 +273,21 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
}
+void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
+ QualType eltTy, llvm::Value *&numElements,
+ llvm::Value *&allocPtr, CharUnits &cookieSize) {
+ // FIXME
+ // Assert that we have a cookie.
+
+ // Derive a char* in the same address space as the pointer.
+ ptr = ptr.withElementType(CGF.Int8Ty);
+
+ cookieSize = getArrayCookieSizeImpl(eltTy);
+ Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);
+ allocPtr = allocAddr.emitRawPointer(CGF);
+ numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
+}
+
llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
Address ptr,
CharUnits cookieSize) {
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 687ff7fb844445..382ad11f504b81 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -575,6 +575,12 @@ class CGCXXABI {
QualType ElementType, llvm::Value *&NumElements,
llvm::Value *&AllocPtr, CharUnits &CookieSize);
+ /// Reads the array cookie associated with the given pointer,
+ /// that should have one.
+ virtual void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
/// Return whether the given global decl needs a VTT parameter.
virtual bool NeedsVTTParameter(GlobalDecl GD);
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index c45688bd1ed3ce..05944db7247fec 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1433,6 +1433,88 @@ static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
return true;
}
+namespace {
+llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
+ const CXXDestructorDecl *DD) {
+ if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
+ return CGF.EmitScalarExpr(ThisArg);
+ return CGF.LoadCXXThis();
+}
+}
+
+void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD,
+ CodeGenFunction &CGF,
+ llvm::Value *ShouldDeleteCondition,
+ bool ReturnAfterDelete) {
+ Address ThisPtr = CGF.LoadCXXThisAddress();
+ // llvm::Value *ThisPtr = LoadThisForDtorDelete(CGF, DD);
+ // llvm::BasicBlock *End = CGF.createBasicBlock("dtor.end");
+ llvm::BasicBlock *ScalarBB = CGF.createBasicBlock("dtor.scalar");
+ llvm::BasicBlock *callDeleteBB =
+ CGF.createBasicBlock("dtor.call_delete_after_array_destroy");
+ llvm::BasicBlock *VectorBB = CGF.createBasicBlock("dtor.vector");
+ auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
+ llvm::Value *CheckTheBitForArrayDestroy = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition,
+ llvm::Constant::getIntegerValue(CondTy, llvm::APInt(CondTy->getBitWidth(),
+ /*val=*/2)));
+ llvm::Value *ShouldDestroyArray =
+ CGF.Builder.CreateIsNull(CheckTheBitForArrayDestroy);
+ CGF.Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB);
+
+ CGF.EmitBlock(VectorBB);
+
+ llvm::Value *numElements = nullptr;
+ llvm::Value *allocatedPtr = nullptr;
+ CharUnits cookieSize;
+ QualType EltTy = DD->getThisType()->getPointeeType();
+ CGF.CGM.getCXXABI().ReadArrayCookie(CGF, ThisPtr, EltTy, numElements,
+ allocatedPtr, cookieSize);
+
+ // Destroy the elements.
+ QualType::DestructionKind dtorKind = EltTy.isDestructedType();
+
+ assert(dtorKind);
+ assert(numElements && "no element count for a type with a destructor!");
+
+ CharUnits elementSize = CGF.getContext().getTypeSizeInChars(EltTy);
+ CharUnits elementAlign =
+ ThisPtr.getAlignment().alignmentOfArrayElement(elementSize);
+
+ llvm::Value *arrayBegin = ThisPtr.emitRawPointer(CGF);
+ llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP(
+ ThisPtr.getElementType(), arrayBegin, numElements, "delete.end");
+
+ // Note that it is legal to allocate a zero-length array, and we
+ // can never fold the check away because the length should always
+ // come from a cookie.
+ CGF.emitArrayDestroy(arrayBegin, arrayEnd, EltTy, elementAlign,
+ CGF.getDestroyer(dtorKind),
+ /*checkZeroLength*/ true, CGF.needsEHCleanup(dtorKind));
+
+ llvm::BasicBlock *VectorBBCont = CGF.createBasicBlock("dtor.vector.cont");
+ CGF.EmitBlock(VectorBBCont);
+
+ llvm::Value *CheckTheBitForDeleteCall = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition,
+ llvm::Constant::getIntegerValue(CondTy, llvm::APInt(CondTy->getBitWidth(),
+ /*val=*/1)));
+
+ llvm::Value *ShouldCallDelete =
+ CGF.Builder.CreateIsNull(CheckTheBitForDeleteCall);
+ CGF.Builder.CreateCondBr(ShouldCallDelete, CGF.ReturnBlock.getBlock(),
+ callDeleteBB);
+ CGF.EmitBlock(callDeleteBB);
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ CGF.EmitDeleteCall(Dtor->getOperatorDelete(), allocatedPtr,
+ CGF.getContext().getTagDeclType(ClassDecl));
+
+ // FIXME figure how to go to the end properly
+ CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+ CGF.EmitBlock(ScalarBB);
+}
+
/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
@@ -1463,6 +1545,10 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// possible to delegate the destructor body to the complete
// destructor. Do so.
if (DtorType == Dtor_Deleting) {
+ if (CXXStructorImplicitParamValue) {
+ EmitConditionalArrayDtorCall(Dtor, *this, CXXStructorImplicitParamValue,
+ false);
+ }
RunCleanupsScope DtorEpilogue(*this);
EnterDtorCleanups(Dtor, Dtor_Deleting);
if (HaveInsertPoint()) {
@@ -1567,12 +1653,12 @@ void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
}
namespace {
- llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
- const CXXDestructorDecl *DD) {
- if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
- return CGF.EmitScalarExpr(ThisArg);
- return CGF.LoadCXXThis();
- }
+ // llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
+ // const CXXDestructorDecl *DD) {
+ // if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
+ // return CGF.EmitScalarExpr(ThisArg);
+ // return CGF.LoadCXXThis();
+ // }
/// Call the operator delete associated with the current destructor.
struct CallDtorDelete final : EHScopeStack::Cleanup {
@@ -1592,8 +1678,12 @@ namespace {
bool ReturnAfterDelete) {
llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
- llvm::Value *ShouldCallDelete
- = CGF.Builder.CreateIsNull(ShouldDeleteCondition);
+ auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
+ llvm::Value *CheckTheBit = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition, llvm::Constant::getIntegerValue(
+ CondTy, llvm::APInt(CondTy->getBitWidth(),
+ /*val=*/1)));
+ llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(CheckTheBit);
CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
CGF.EmitBlock(callDeleteBB);
@@ -1857,9 +1947,10 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
if (DD->getOperatorDelete()->isDestroyingOperatorDelete())
EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue,
/*ReturnAfterDelete*/true);
- else
+ else {
EHStack.pushCleanup<CallDtorDeleteConditional>(
NormalAndEHCleanup, CXXStructorImplicitParamValue);
+ }
} else {
if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) {
const CXXRecordDecl *ClassDecl = DD->getParent();
>From 81e7dfce788d74c3718a573b3ba3a8d7e70594cb Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Tue, 13 Aug 2024 07:34:36 -0700
Subject: [PATCH 2/6] Add support for MSVC vector deleting destructors
---
clang/include/clang/Basic/ABI.h | 3 +-
clang/lib/AST/ItaniumMangle.cpp | 2 +
clang/lib/AST/MicrosoftMangle.cpp | 6 +--
clang/lib/AST/VTableBuilder.cpp | 74 ++++++++++++++++++++-------
clang/lib/CodeGen/CGCXX.cpp | 25 ++++++++-
clang/lib/CodeGen/CGClass.cpp | 1 +
clang/lib/CodeGen/CodeGenModule.h | 1 +
clang/lib/CodeGen/MicrosoftCXXABI.cpp | 13 +++--
8 files changed, 97 insertions(+), 28 deletions(-)
diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h
index 231bad799a42cb..be44f437b8b55e 100644
--- a/clang/include/clang/Basic/ABI.h
+++ b/clang/include/clang/Basic/ABI.h
@@ -34,7 +34,8 @@ enum CXXDtorType {
Dtor_Deleting, ///< Deleting dtor
Dtor_Complete, ///< Complete object dtor
Dtor_Base, ///< Base object dtor
- Dtor_Comdat ///< The COMDAT used for dtors
+ Dtor_Comdat, ///< The COMDAT used for dtors
+ Dtor_VectorDeleting ///< Vector deleting dtor
};
} // end namespace clang
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 47aa9b40dab845..827e22724fa55a 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -5994,6 +5994,8 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
case Dtor_Comdat:
Out << "D5";
break;
+ case Dtor_VectorDeleting:
+ llvm_unreachable("Itanium ABI does not use vector deleting dtors");
}
}
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index edeeaeaa9ae17c..54c377dd132482 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1484,8 +1484,7 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// <operator-name> ::= ?_G # scalar deleting destructor
case Dtor_Deleting: Out << "?_G"; return;
// <operator-name> ::= ?_E # vector deleting destructor
- // FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need
- // it.
+ case Dtor_VectorDeleting: Out << "?_E"; return;
case Dtor_Comdat:
llvm_unreachable("not expecting a COMDAT");
}
@@ -2919,7 +2918,8 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) {
// The scalar deleting destructor takes an extra int argument which is not
// reflected in the AST.
- if (StructorType == Dtor_Deleting) {
+ if (StructorType == Dtor_Deleting || StructorType == Dtor_VectorDeleting) {
+ // The deleting destructors take an extra int arguments.
Out << (PointersAre64Bit ? "PEAXI at Z" : "PAXI at Z");
return;
}
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index e941c3bedb0a7e..9c62535b7ca4b1 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -1341,10 +1341,14 @@ void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
assert(ReturnAdjustment.isEmpty() &&
"Destructor can't have return adjustment!");
-
- // Add both the complete destructor and the deleting destructor.
- Components.push_back(VTableComponent::MakeCompleteDtor(DD));
- Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // Add both the complete destructor and the deleting destructor.
+ Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+ Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+ } else {
+ // Add the vector deleting destructor.
+ Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+ }
} else {
// Add the return adjustment if necessary.
if (!ReturnAdjustment.isEmpty())
@@ -1733,10 +1737,15 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
const CXXMethodDecl *MD = I.first;
const MethodInfo &MI = I.second;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
- = MI.VTableIndex - AddressPoint;
- MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
- = MI.VTableIndex + 1 - AddressPoint;
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
+ = MI.VTableIndex - AddressPoint;
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
+ = MI.VTableIndex + 1 - AddressPoint;
+ } else {
+ MethodVTableIndices[GlobalDecl(DD, Dtor_VectorDeleting)]
+ = MI.VTableIndex + 1 - AddressPoint;
+ }
} else {
MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
}
@@ -2071,6 +2080,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
DD->printQualifiedName(Out);
if (IsComplete)
Out << "() [complete]";
+ else if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ Out << "() [vector deleting]";
else
Out << "() [deleting]";
@@ -2246,12 +2257,27 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- GlobalDecl GD(DD, Dtor_Complete);
- assert(MethodVTableIndices.count(GD));
- uint64_t VTableIndex = MethodVTableIndices[GD];
- IndicesMap[VTableIndex] = MethodName + " [complete]";
- IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // For Itanium ABI, add entries for both complete and deleting destructors.
+ GlobalDecl CompleteGD(DD, Dtor_Complete);
+ assert(MethodVTableIndices.count(CompleteGD));
+ uint64_t CompleteIndex = MethodVTableIndices[CompleteGD];
+ IndicesMap[CompleteIndex] = MethodName + " [complete]";
+
+ GlobalDecl DeletingGD(DD, Dtor_Deleting);
+ assert(MethodVTableIndices.count(DeletingGD));
+ uint64_t DeletingIndex = MethodVTableIndices[DeletingGD];
+ IndicesMap[DeletingIndex] = MethodName + " [deleting]";
+ } else {
+ // For Microsoft ABI, add an entry for the vector deleting destructor.
+ // Ensure that the index calculation is correct for the Microsoft ABI.
+ GlobalDecl VectorDeletingGD(DD, Dtor_VectorDeleting);
+ assert(MethodVTableIndices.count(VectorDeletingGD));
+ uint64_t VectorDeletingIndex = MethodVTableIndices[VectorDeletingGD];
+ IndicesMap[VectorDeletingIndex] = MethodName + " [vector deleting]";
+ }
} else {
+ // For other virtual member functions, add an entry with the method name.
assert(MethodVTableIndices.count(MD));
IndicesMap[MethodVTableIndices[MD]] = MethodName;
}
@@ -2655,7 +2681,11 @@ class VFTableBuilder {
MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
+ } else {
+ MethodVFTableLocations[GlobalDecl(DD, Dtor_VectorDeleting)] = Loc;
+ }
} else {
MethodVFTableLocations[MD] = Loc;
}
@@ -3285,7 +3315,10 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
const CXXDestructorDecl *DD = Component.getDestructorDecl();
DD->printQualifiedName(Out);
- Out << "() [scalar deleting]";
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ Out << "() [vector deleting]";
+ else
+ Out << "() [deleting]";
if (DD->isPureVirtual())
Out << " [pure]";
@@ -3756,7 +3789,7 @@ void MicrosoftVTableContext::dumpMethodLocations(
PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
if (isa<CXXDestructorDecl>(MD)) {
- IndicesMap[I.second] = MethodName + " [scalar deleting]";
+ IndicesMap[I.second] = MethodName + " [vector deleting]";
} else {
IndicesMap[I.second] = MethodName;
}
@@ -3872,8 +3905,13 @@ MethodVFTableLocation
MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
assert(hasVtableSlot(cast<CXXMethodDecl>(GD.getDecl())) &&
"Only use this method for virtual methods or dtors");
- if (isa<CXXDestructorDecl>(GD.getDecl()))
- assert(GD.getDtorType() == Dtor_Deleting);
+ if (isa<CXXDestructorDecl>(GD.getDecl())) {
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ assert(GD.getDtorType() == Dtor_Deleting);
+ } else {
+ assert(GD.getDtorType() == Dtor_VectorDeleting);
+ }
+ }
GD = GD.getCanonicalDecl();
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 78a7b021855b7e..419d38d94e9604 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -175,7 +175,10 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
// requires explicit comdat support in the IL.
if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
return true;
-
+/*
+ EmitDefinitionAsAlias(AliasDecl, TargetDecl);
+ return false;
+*/
// Create the alias with no name.
auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
Aliasee, &getModule());
@@ -200,8 +203,26 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
return false;
}
-
+/*
+/// Emit a definition as a global alias for another definition, unconditionally.
+/// Use this function with care as it can produce invalid aliases. Generally
+/// this function should be used only where there is an ABI requirement to emit
+/// an alias.
+void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl,
+ GlobalDecl TargetDecl) {
+ llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
+}
+*/
llvm::Function *CodeGenModule::codegenCXXStructor(GlobalDecl GD) {
+ /*
+ // The Microsoft ABI requires that the vector deleting destructor
+ // be weak aliased to the scalar deleting destructor.
+ // TODO: emission of the vector deleting destructor (when required).
+ if (getTarget().getCXXABI().isMicrosoft() && GD.getDtorType() == Dtor_VectorDeleting) {
+ EmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_VectorDeleting),
+ GlobalDecl(dtor, Dtor_Deleting));
+ return;
+ } */
const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(GD);
auto *Fn = cast<llvm::Function>(
getAddrOfCXXStructor(GD, &FnInfo, /*FnType=*/nullptr,
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 05944db7247fec..75a2157723db3c 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1577,6 +1577,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
switch (DtorType) {
case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT");
case Dtor_Deleting: llvm_unreachable("already handled deleting case");
+ case Dtor_VectorDeleting: llvm_unreachable("already handled vector deleting case");
case Dtor_Complete:
assert((Body || getTarget().getCXXABI().isMicrosoft()) &&
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 741b0f17da6584..ac285a63d69c25 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1485,6 +1485,7 @@ class CodeGenModule : public CodeGenTypeCache {
void EmitGlobal(GlobalDecl D);
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
+ void EmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
llvm::GlobalValue *GetGlobalValue(StringRef Ref);
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index d587daac5a88a9..4a4c4fbc569526 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -71,7 +71,8 @@ class MicrosoftCXXABI : public CGCXXABI {
case Dtor_Complete:
case Dtor_Deleting:
return true;
-
+ case Dtor_VectorDeleting:
+ return true;
case Dtor_Base:
return false;
@@ -1090,7 +1091,8 @@ bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {
static bool isDeletingDtor(GlobalDecl GD) {
return isa<CXXDestructorDecl>(GD.getDecl()) &&
- GD.getDtorType() == Dtor_Deleting;
+ (GD.getDtorType() == Dtor_Deleting ||
+ GD.getDtorType() == Dtor_VectorDeleting);
}
bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const {
@@ -1341,7 +1343,8 @@ MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD,
AddedStructorArgCounts Added;
// TODO: 'for base' flag
if (isa<CXXDestructorDecl>(GD.getDecl()) &&
- GD.getDtorType() == Dtor_Deleting) {
+ (GD.getDtorType() == Dtor_Deleting ||
+ GD.getDtorType() == Dtor_VectorDeleting)) {
// The scalar deleting destructor takes an implicit int parameter.
ArgTys.push_back(getContext().IntTy);
++Added.Suffix;
@@ -1407,6 +1410,8 @@ llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
// and are emitted everywhere they are used. They are internal if the class
// is internal.
return llvm::GlobalValue::LinkOnceODRLinkage;
+ case Dtor_VectorDeleting:
+ return llvm::GlobalValue::WeakAnyLinkage;
case Dtor_Comdat:
llvm_unreachable("MS C++ ABI does not support comdat dtors");
}
@@ -2004,7 +2009,7 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
// We have only one destructor in the vftable but can get both behaviors
// by passing an implicit int parameter.
- GlobalDecl GD(Dtor, Dtor_Deleting);
+ GlobalDecl GD(Dtor, Dtor_VectorDeleting);
const CGFunctionInfo *FInfo =
&CGM.getTypes().arrangeCXXStructorDeclaration(GD);
llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
>From 45151cd5946b609739522c5d8da34ab272dc5e77 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Tue, 13 Aug 2024 08:22:34 -0700
Subject: [PATCH 3/6] Fix fiormat
---
clang/include/clang/Basic/ABI.h | 10 +++++-----
clang/lib/AST/MicrosoftMangle.cpp | 7 +++++--
clang/lib/AST/VTableBuilder.cpp | 25 +++++++++++++------------
3 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h
index be44f437b8b55e..3d3d94d7c8485b 100644
--- a/clang/include/clang/Basic/ABI.h
+++ b/clang/include/clang/Basic/ABI.h
@@ -31,11 +31,11 @@ enum CXXCtorType {
/// C++ destructor types.
enum CXXDtorType {
- Dtor_Deleting, ///< Deleting dtor
- Dtor_Complete, ///< Complete object dtor
- Dtor_Base, ///< Base object dtor
- Dtor_Comdat, ///< The COMDAT used for dtors
- Dtor_VectorDeleting ///< Vector deleting dtor
+ Dtor_Deleting, ///< Deleting dtor
+ Dtor_Complete, ///< Complete object dtor
+ Dtor_Base, ///< Base object dtor
+ Dtor_Comdat, ///< The COMDAT used for dtors
+ Dtor_VectorDeleting ///< Vector deleting dtor
};
} // end namespace clang
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 54c377dd132482..0dfb054cf05eff 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1484,7 +1484,9 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// <operator-name> ::= ?_G # scalar deleting destructor
case Dtor_Deleting: Out << "?_G"; return;
// <operator-name> ::= ?_E # vector deleting destructor
- case Dtor_VectorDeleting: Out << "?_E"; return;
+ case Dtor_VectorDeleting:
+ Out << "?_E";
+ return;
case Dtor_Comdat:
llvm_unreachable("not expecting a COMDAT");
}
@@ -2918,7 +2920,8 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) {
// The scalar deleting destructor takes an extra int argument which is not
// reflected in the AST.
- if (StructorType == Dtor_Deleting || StructorType == Dtor_VectorDeleting) {
+ if (StructorType == Dtor_Deleting ||
+ StructorType == Dtor_VectorDeleting) {
// The deleting destructors take an extra int arguments.
Out << (PointersAre64Bit ? "PEAXI at Z" : "PAXI at Z");
return;
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index 9c62535b7ca4b1..900975115e16c0 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -1348,7 +1348,7 @@ void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
} else {
// Add the vector deleting destructor.
Components.push_back(VTableComponent::MakeDeletingDtor(DD));
- }
+ }
} else {
// Add the return adjustment if necessary.
if (!ReturnAdjustment.isEmpty())
@@ -1738,14 +1738,14 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
const MethodInfo &MI = I.second;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
- = MI.VTableIndex - AddressPoint;
- MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
- = MI.VTableIndex + 1 - AddressPoint;
- } else {
- MethodVTableIndices[GlobalDecl(DD, Dtor_VectorDeleting)]
- = MI.VTableIndex + 1 - AddressPoint;
- }
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
+ MI.VTableIndex - AddressPoint;
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
+ MI.VTableIndex + 1 - AddressPoint;
+ } else {
+ MethodVTableIndices[GlobalDecl(DD, Dtor_VectorDeleting)] =
+ MI.VTableIndex + 1 - AddressPoint;
+ }
} else {
MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
}
@@ -2258,9 +2258,10 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- // For Itanium ABI, add entries for both complete and deleting destructors.
- GlobalDecl CompleteGD(DD, Dtor_Complete);
- assert(MethodVTableIndices.count(CompleteGD));
+ // For Itanium ABI, add entries for both complete and deleting
+ // destructors.
+ GlobalDecl CompleteGD(DD, Dtor_Complete);
+ assert(MethodVTableIndices.count(CompleteGD));
uint64_t CompleteIndex = MethodVTableIndices[CompleteGD];
IndicesMap[CompleteIndex] = MethodName + " [complete]";
>From 733b22510d6b27bd97bdb150fe1da89bac88a13d Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Tue, 17 Sep 2024 08:17:32 -0700
Subject: [PATCH 4/6] Add support for EmitDefinitionAsAlias()
---
clang/lib/CodeGen/CGCXX.cpp | 56 ++++++++++++++++++++++++++++++-------
1 file changed, 46 insertions(+), 10 deletions(-)
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 419d38d94e9604..bac4d3fb307d25 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -203,26 +203,62 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
return false;
}
-/*
+
/// Emit a definition as a global alias for another definition, unconditionally.
/// Use this function with care as it can produce invalid aliases. Generally
/// this function should be used only where there is an ABI requirement to emit
/// an alias.
-void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl,
- GlobalDecl TargetDecl) {
+void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl, GlobalDecl TargetDecl) {
+ // Get the mangled names for the alias and the target.
+ StringRef AliasName = getMangledName(AliasDecl);
+ StringRef TargetName = getMangledName(TargetDecl);
+
+ // Get the LLVM function for the target.
+ llvm::Function *TargetFunction = cast<llvm::Function>(GetOrCreateLLVMFunction(
+ TargetName, /*FnType=*/nullptr, TargetDecl, /*ForVTable=*/false,
+ /*DontDefer=*/true, /*IsThunk=*/false, /*ExtraAttrs=*/llvm::AttributeList(),
+ ForDefinition));
+
+ // Determine the linkage type for the alias.
llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
+
+ // Ensure that the target has the correct linkage.
+ TargetFunction->setLinkage(Linkage);
+ llvm::Type *ElementType = TargetFunction->getValueType();
+ llvm::GlobalAlias *GA = llvm::GlobalAlias::create(
+ ElementType, // Type of the aliased value
+ 0, // Address space, usually 0 for the default address space
+ Linkage, // Linkage of the alias
+ AliasName, // Name of the alias
+ TargetFunction, // The aliased value
+ &getModule()); // The module in which to create the alias
+
+ // Set any additional necessary attributes for the alias.
+ SetCommonAttributes(AliasDecl, GA);
}
-*/
+
llvm::Function *CodeGenModule::codegenCXXStructor(GlobalDecl GD) {
- /*
// The Microsoft ABI requires that the vector deleting destructor
// be weak aliased to the scalar deleting destructor.
- // TODO: emission of the vector deleting destructor (when required).
if (getTarget().getCXXABI().isMicrosoft() && GD.getDtorType() == Dtor_VectorDeleting) {
- EmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_VectorDeleting),
- GlobalDecl(dtor, Dtor_Deleting));
- return;
- } */
+ const CXXDestructorDecl *DtorDecl = cast<CXXDestructorDecl>(GD.getDecl());
+
+ // Create GlobalDecl objects with the correct type for the vector and scalar deleting destructors.
+ GlobalDecl VectorDtorGD(DtorDecl, Dtor_VectorDeleting);
+ GlobalDecl ScalarDtorGD(DtorDecl, Dtor_Deleting);
+
+ // Emit an alias from the vector deleting destructor to the scalar deleting destructor.
+ EmitDefinitionAsAlias(VectorDtorGD, ScalarDtorGD);
+
+ // Return the scalar deleting destructor, which is now aliased by the vector deleting destructor.
+ // Use the mangled name of the scalar deleting destructor.
+ StringRef MangledName = getMangledName(ScalarDtorGD);
+ return cast<llvm::Function>(GetOrCreateLLVMFunction(
+ MangledName, /*FnType=*/nullptr,
+ ScalarDtorGD, /*ForVTable=*/false,
+ /*DontDefer=*/true, /*IsThunk=*/false, /*ExtraAttrs=*/llvm::AttributeList(),
+ ForDefinition));
+ }
const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(GD);
auto *Fn = cast<llvm::Function>(
getAddrOfCXXStructor(GD, &FnInfo, /*FnType=*/nullptr,
>From d4be52989e8292818c70436841abf9cc64aa04da Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Tue, 8 Oct 2024 06:37:12 -0700
Subject: [PATCH 5/6] Address review commnets
---
clang/include/clang/Basic/ABI.h | 8 ++---
clang/lib/AST/MicrosoftMangle.cpp | 9 +++---
clang/lib/AST/VTableBuilder.cpp | 54 ++++++++-----------------------
clang/lib/CodeGen/CGCXX.cpp | 4 ---
4 files changed, 21 insertions(+), 54 deletions(-)
diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h
index 3d3d94d7c8485b..48969e4f295c36 100644
--- a/clang/include/clang/Basic/ABI.h
+++ b/clang/include/clang/Basic/ABI.h
@@ -31,10 +31,10 @@ enum CXXCtorType {
/// C++ destructor types.
enum CXXDtorType {
- Dtor_Deleting, ///< Deleting dtor
- Dtor_Complete, ///< Complete object dtor
- Dtor_Base, ///< Base object dtor
- Dtor_Comdat, ///< The COMDAT used for dtors
+ Dtor_Deleting, ///< Deleting dtor
+ Dtor_Complete, ///< Complete object dtor
+ Dtor_Base, ///< Base object dtor
+ Dtor_Comdat, ///< The COMDAT used for dtors
Dtor_VectorDeleting ///< Vector deleting dtor
};
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 0dfb054cf05eff..0f878c2de653bf 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1484,9 +1484,7 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// <operator-name> ::= ?_G # scalar deleting destructor
case Dtor_Deleting: Out << "?_G"; return;
// <operator-name> ::= ?_E # vector deleting destructor
- case Dtor_VectorDeleting:
- Out << "?_E";
- return;
+ case Dtor_VectorDeleting: Out << "?_E"; return;
case Dtor_Comdat:
llvm_unreachable("not expecting a COMDAT");
}
@@ -2918,11 +2916,12 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// ::= @ # structors (they have no declared return type)
if (IsStructor) {
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) {
- // The scalar deleting destructor takes an extra int argument which is not
+ // The deleting destructors take an extra argument of type int that indicates
+ // whether the storage for the object should be deleted and whether a single
+ // object or an array of objects is being destroyed. This extra argument is not
// reflected in the AST.
if (StructorType == Dtor_Deleting ||
StructorType == Dtor_VectorDeleting) {
- // The deleting destructors take an extra int arguments.
Out << (PointersAre64Bit ? "PEAXI at Z" : "PAXI at Z");
return;
}
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index 900975115e16c0..d256802403952f 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -1341,14 +1341,9 @@ void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
assert(ReturnAdjustment.isEmpty() &&
"Destructor can't have return adjustment!");
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- // Add both the complete destructor and the deleting destructor.
- Components.push_back(VTableComponent::MakeCompleteDtor(DD));
- Components.push_back(VTableComponent::MakeDeletingDtor(DD));
- } else {
- // Add the vector deleting destructor.
- Components.push_back(VTableComponent::MakeDeletingDtor(DD));
- }
+ // Add both the complete destructor and the deleting destructor.
+ Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+ Components.push_back(VTableComponent::MakeDeletingDtor(DD));
} else {
// Add the return adjustment if necessary.
if (!ReturnAdjustment.isEmpty())
@@ -1737,15 +1732,10 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
const CXXMethodDecl *MD = I.first;
const MethodInfo &MI = I.second;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
- MI.VTableIndex - AddressPoint;
- MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
- MI.VTableIndex + 1 - AddressPoint;
- } else {
- MethodVTableIndices[GlobalDecl(DD, Dtor_VectorDeleting)] =
- MI.VTableIndex + 1 - AddressPoint;
- }
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
+ = MI.VTableIndex - AddressPoint;
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
+ = MI.VTableIndex + 1 - AddressPoint;
} else {
MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
}
@@ -2080,8 +2070,6 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
DD->printQualifiedName(Out);
if (IsComplete)
Out << "() [complete]";
- else if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- Out << "() [vector deleting]";
else
Out << "() [deleting]";
@@ -2257,28 +2245,12 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- // For Itanium ABI, add entries for both complete and deleting
- // destructors.
- GlobalDecl CompleteGD(DD, Dtor_Complete);
- assert(MethodVTableIndices.count(CompleteGD));
- uint64_t CompleteIndex = MethodVTableIndices[CompleteGD];
- IndicesMap[CompleteIndex] = MethodName + " [complete]";
-
- GlobalDecl DeletingGD(DD, Dtor_Deleting);
- assert(MethodVTableIndices.count(DeletingGD));
- uint64_t DeletingIndex = MethodVTableIndices[DeletingGD];
- IndicesMap[DeletingIndex] = MethodName + " [deleting]";
- } else {
- // For Microsoft ABI, add an entry for the vector deleting destructor.
- // Ensure that the index calculation is correct for the Microsoft ABI.
- GlobalDecl VectorDeletingGD(DD, Dtor_VectorDeleting);
- assert(MethodVTableIndices.count(VectorDeletingGD));
- uint64_t VectorDeletingIndex = MethodVTableIndices[VectorDeletingGD];
- IndicesMap[VectorDeletingIndex] = MethodName + " [vector deleting]";
- }
+ GlobalDecl GD(DD, Dtor_Complete);
+ assert(MethodVTableIndices.count(GD));
+ uint64_t VTableIndex = MethodVTableIndices[GD];
+ IndicesMap[VTableIndex] = MethodName + " [complete]";
+ IndicesMap[VTableIndex + 1] = MethodName + " [deleting]";
} else {
- // For other virtual member functions, add an entry with the method name.
assert(MethodVTableIndices.count(MD));
IndicesMap[MethodVTableIndices[MD]] = MethodName;
}
@@ -3790,7 +3762,7 @@ void MicrosoftVTableContext::dumpMethodLocations(
PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
if (isa<CXXDestructorDecl>(MD)) {
- IndicesMap[I.second] = MethodName + " [vector deleting]";
+ IndicesMap[I.second] = MethodName + " [deleting]";
} else {
IndicesMap[I.second] = MethodName;
}
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index bac4d3fb307d25..bef6b120f77aa4 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -175,10 +175,6 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
// requires explicit comdat support in the IL.
if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
return true;
-/*
- EmitDefinitionAsAlias(AliasDecl, TargetDecl);
- return false;
-*/
// Create the alias with no name.
auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
Aliasee, &getModule());
>From 2c388dbea786ce8fcbeb2e7a8eb4dfaff72a1dae Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Mon, 23 Dec 2024 07:42:06 -0800
Subject: [PATCH 6/6] Tweak implementation to make the functions to appear
---
clang/include/clang/AST/VTableBuilder.h | 2 +-
clang/lib/AST/VTableBuilder.cpp | 17 ++++-----
clang/lib/CodeGen/CGCXX.cpp | 47 +++++++++----------------
clang/lib/CodeGen/CGClass.cpp | 4 +--
clang/lib/CodeGen/MicrosoftCXXABI.cpp | 14 ++++----
5 files changed, 35 insertions(+), 49 deletions(-)
diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h
index a5de41dbc22f14..07217677d2b021 100644
--- a/clang/include/clang/AST/VTableBuilder.h
+++ b/clang/include/clang/AST/VTableBuilder.h
@@ -161,7 +161,7 @@ class VTableComponent {
case CK_CompleteDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete);
case CK_DeletingDtorPointer:
- return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
+ return GlobalDecl(DtorDecl, CXXDtorType::Dtor_VectorDeleting);
case CK_VCallOffset:
case CK_VBaseOffset:
case CK_OffsetToTop:
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index d256802403952f..d2a3128c28d7f5 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -2654,11 +2654,11 @@ class VFTableBuilder {
MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
- } else {
- MethodVFTableLocations[GlobalDecl(DD, Dtor_VectorDeleting)] = Loc;
- }
+ } else {
+ MethodVFTableLocations[GlobalDecl(DD, Dtor_VectorDeleting)] = Loc;
+ }
} else {
MethodVFTableLocations[MD] = Loc;
}
@@ -3879,12 +3879,9 @@ MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
assert(hasVtableSlot(cast<CXXMethodDecl>(GD.getDecl())) &&
"Only use this method for virtual methods or dtors");
if (isa<CXXDestructorDecl>(GD.getDecl())) {
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- assert(GD.getDtorType() == Dtor_Deleting);
- } else {
- assert(GD.getDtorType() == Dtor_VectorDeleting);
- }
- }
+ assert(GD.getDtorType() == Dtor_Deleting ||
+ GD.getDtorType() == Dtor_VectorDeleting);
+ }
GD = GD.getCanonicalDecl();
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index bef6b120f77aa4..2c83a87897f1ac 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -205,55 +205,42 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
/// this function should be used only where there is an ABI requirement to emit
/// an alias.
void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl, GlobalDecl TargetDecl) {
- // Get the mangled names for the alias and the target.
- StringRef AliasName = getMangledName(AliasDecl);
- StringRef TargetName = getMangledName(TargetDecl);
- // Get the LLVM function for the target.
- llvm::Function *TargetFunction = cast<llvm::Function>(GetOrCreateLLVMFunction(
- TargetName, /*FnType=*/nullptr, TargetDecl, /*ForVTable=*/false,
- /*DontDefer=*/true, /*IsThunk=*/false, /*ExtraAttrs=*/llvm::AttributeList(),
- ForDefinition));
+ // Derive the type for the alias.
+ llvm::PointerType *AliasValueType =
+ getTypes().GetFunctionType(AliasDecl)->getPointerTo();
+ auto *Aliasee = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
// Determine the linkage type for the alias.
llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
- // Ensure that the target has the correct linkage.
- TargetFunction->setLinkage(Linkage);
- llvm::Type *ElementType = TargetFunction->getValueType();
- llvm::GlobalAlias *GA = llvm::GlobalAlias::create(
- ElementType, // Type of the aliased value
- 0, // Address space, usually 0 for the default address space
- Linkage, // Linkage of the alias
- AliasName, // Name of the alias
- TargetFunction, // The aliased value
- &getModule()); // The module in which to create the alias
+ // Create the alias with no name.
+ auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
+ Aliasee, &getModule());
+ // Destructors are always unnamed_addr.
+ Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
// Set any additional necessary attributes for the alias.
- SetCommonAttributes(AliasDecl, GA);
+ SetCommonAttributes(AliasDecl, Alias);
}
llvm::Function *CodeGenModule::codegenCXXStructor(GlobalDecl GD) {
// The Microsoft ABI requires that the vector deleting destructor
// be weak aliased to the scalar deleting destructor.
- if (getTarget().getCXXABI().isMicrosoft() && GD.getDtorType() == Dtor_VectorDeleting) {
+ auto Dtor = dyn_cast<CXXDestructorDecl>(GD.getDecl());
+ if (Dtor && getTarget().getCXXABI().isMicrosoft() &&
+ GD.getDtorType() == Dtor_VectorDeleting) {
const CXXDestructorDecl *DtorDecl = cast<CXXDestructorDecl>(GD.getDecl());
- // Create GlobalDecl objects with the correct type for the vector and scalar deleting destructors.
+ // Create GlobalDecl objects with the correct type for the vector and scalar
+ // deleting destructors.
GlobalDecl VectorDtorGD(DtorDecl, Dtor_VectorDeleting);
GlobalDecl ScalarDtorGD(DtorDecl, Dtor_Deleting);
- // Emit an alias from the vector deleting destructor to the scalar deleting destructor.
+ // Emit an alias from the vector deleting destructor to the scalar deleting
+ // destructor.
EmitDefinitionAsAlias(VectorDtorGD, ScalarDtorGD);
- // Return the scalar deleting destructor, which is now aliased by the vector deleting destructor.
- // Use the mangled name of the scalar deleting destructor.
- StringRef MangledName = getMangledName(ScalarDtorGD);
- return cast<llvm::Function>(GetOrCreateLLVMFunction(
- MangledName, /*FnType=*/nullptr,
- ScalarDtorGD, /*ForVTable=*/false,
- /*DontDefer=*/true, /*IsThunk=*/false, /*ExtraAttrs=*/llvm::AttributeList(),
- ForDefinition));
}
const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(GD);
auto *Fn = cast<llvm::Function>(
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 75a2157723db3c..8b9cdf91111c94 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1544,8 +1544,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// outside of the function-try-block, which means it's always
// possible to delegate the destructor body to the complete
// destructor. Do so.
- if (DtorType == Dtor_Deleting) {
- if (CXXStructorImplicitParamValue) {
+ if (DtorType == Dtor_Deleting || DtorType == Dtor_VectorDeleting) {
+ if (CXXStructorImplicitParamValue && DtorType == Dtor_VectorDeleting) {
EmitConditionalArrayDtorCall(Dtor, *this, CXXStructorImplicitParamValue,
false);
}
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 4a4c4fbc569526..efa61fa41f3f88 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -70,9 +70,8 @@ class MicrosoftCXXABI : public CGCXXABI {
switch (GD.getDtorType()) {
case Dtor_Complete:
case Dtor_Deleting:
- return true;
case Dtor_VectorDeleting:
- return true;
+ return true;
case Dtor_Base:
return false;
@@ -261,7 +260,7 @@ class MicrosoftCXXABI : public CGCXXABI {
// There's only Dtor_Deleting in vftable but it shares the this
// adjustment with the base one, so look up the deleting one instead.
- LookupGD = GlobalDecl(DD, Dtor_Deleting);
+ LookupGD = GlobalDecl(DD, Dtor_VectorDeleting);
}
MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
@@ -895,7 +894,8 @@ void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
// FIXME: Provide a source location here even though there's no
// CXXMemberCallExpr for dtor call.
bool UseGlobalDelete = DE->isGlobalDelete();
- CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
+ // FIXME check that vector deletion is actually required.
+ CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_VectorDeleting;
llvm::Value *MDThis = EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
/*CallOrInvoke=*/nullptr);
if (UseGlobalDelete)
@@ -1443,7 +1443,7 @@ MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
// There's no Dtor_Base in vftable but it shares the this adjustment with
// the deleting one, so look it up instead.
- GD = GlobalDecl(DD, Dtor_Deleting);
+ GD = GlobalDecl(DD, Dtor_VectorDeleting);
}
MethodVFTableLocation ML =
@@ -2015,10 +2015,12 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty);
+ bool UseGlobalDelete = D->isGlobalDelete();
+ bool CallDelete = !UseGlobalDelete;
ASTContext &Context = getContext();
llvm::Value *ImplicitParam = llvm::ConstantInt::get(
llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()),
- DtorType == Dtor_Deleting);
+ 2 * (DtorType == Dtor_VectorDeleting) + CallDelete);
QualType ThisTy;
if (CE) {
More information about the cfe-commits
mailing list