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.podchishcha...@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.ma...@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@Z" : "PAXI@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.ma...@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@Z" : "PAXI@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.ma...@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.ma...@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@Z" : "PAXI@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.podchishcha...@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) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits