Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vector deleting destructors #3

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions clang/include/clang/AST/VTableBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class VTableComponent {

bool isRTTIKind() const { return isRTTIKind(getKind()); }

GlobalDecl getGlobalDecl() const {
GlobalDecl getGlobalDecl(bool isMSVC) const {
assert(isUsedFunctionPointerKind() &&
"GlobalDecl can be created only from virtual function");

Expand All @@ -161,7 +161,8 @@ class VTableComponent {
case CK_CompleteDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete);
case CK_DeletingDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
return GlobalDecl(DtorDecl, (isMSVC) ? CXXDtorType::Dtor_VectorDeleting
: CXXDtorType::Dtor_Deleting);
case CK_VCallOffset:
case CK_VBaseOffset:
case CK_OffsetToTop:
Expand Down
9 changes: 5 additions & 4 deletions clang/include/clang/Basic/ABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +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_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
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}

Expand Down
12 changes: 7 additions & 5 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -2917,9 +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) {
if (StructorType == Dtor_Deleting ||
StructorType == Dtor_VectorDeleting) {
Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z");
return;
}
Expand Down Expand Up @@ -3895,7 +3897,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
// FIXME: Actually, the dtor thunk should be emitted for vector deleting
// dtors rather than scalar deleting dtors. Just use the vector deleting dtor
// mangling manually until we support both deleting dtor types.
Comment on lines 3897 to 3899
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See into that fixme

assert(Type == Dtor_Deleting);
// assert(Type == Dtor_Deleting);
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
Mangler.getStream() << "??_E";
Expand Down
22 changes: 15 additions & 7 deletions clang/lib/AST/VTableBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,6 @@ 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));
Expand Down Expand Up @@ -1733,7 +1732,7 @@ 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)]
MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
= MI.VTableIndex - AddressPoint;
MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
= MI.VTableIndex + 1 - AddressPoint;
Expand Down Expand Up @@ -2655,7 +2654,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;
}
Expand Down Expand Up @@ -3285,7 +3288,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]";
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Out << "() [deleting]";
Out << "() [scalar deleting]";


if (DD->isPureVirtual())
Out << " [pure]";
Expand Down Expand Up @@ -3756,7 +3762,7 @@ void MicrosoftVTableContext::dumpMethodLocations(
PredefinedIdentKind::PrettyFunctionNoVirtual, MD);

if (isa<CXXDestructorDecl>(MD)) {
IndicesMap[I.second] = MethodName + " [scalar deleting]";
IndicesMap[I.second] = MethodName + " [deleting]";
} else {
IndicesMap[I.second] = MethodName;
}
Expand Down Expand Up @@ -3872,8 +3878,10 @@ 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())) {
assert(GD.getDtorType() == Dtor_Deleting ||
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert(GD.getDtorType() == Dtor_Deleting ||
assert(

GD.getDtorType() == Dtor_VectorDeleting);
}

GD = GD.getCanonicalDecl();

Expand Down
40 changes: 39 additions & 1 deletion clang/lib/CodeGen/CGCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
// requires explicit comdat support in the IL.
if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
return true;

// Create the alias with no name.
auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
Aliasee, &getModule());
Expand All @@ -201,6 +200,45 @@ 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::Type *AliasValueType = getTypes().GetFunctionType(AliasDecl);

StringRef MangledName = getMangledName(AliasDecl);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry && !Entry->isDeclaration())
return;
auto *Aliasee = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));

// Determine the linkage type for the alias.
llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);

// 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);

if (Entry) {
assert(Entry->getValueType() == AliasValueType &&
Entry->getAddressSpace() == Alias->getAddressSpace() &&
"declaration exists with different type");
Alias->takeName(Entry);
Entry->replaceAllUsesWith(Alias);
Entry->eraseFromParent();
} else {
Alias->setName(MangledName);
}

// Set any additional necessary attributes for the alias.
SetCommonAttributes(AliasDecl, Alias);
}

llvm::Function *CodeGenModule::codegenCXXStructor(GlobalDecl GD) {
const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(GD);
auto *Fn = cast<llvm::Function>(
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CGCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
23 changes: 15 additions & 8 deletions clang/lib/CodeGen/CGCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,10 @@ class CGCXXABI {

public:
virtual void emitVirtualObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
Address Ptr, QualType ElementType,
const CXXDestructorDecl *Dtor) = 0;
const CXXDeleteExpr *DE, Address Ptr,
QualType ElementType,
const CXXDestructorDecl *Dtor,
bool VectorDeleting) = 0;
virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) = 0;
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0;
virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; }
Expand All @@ -275,6 +276,7 @@ class CGCXXABI {
virtual CatchTypeInfo getCatchAllTypeInfo();

virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy) = 0;
virtual bool hasVectorDeletingDtors() = 0;
virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0;
virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
Address ThisPtr,
Expand Down Expand Up @@ -485,11 +487,10 @@ class CGCXXABI {
llvm::PointerUnion<const CXXDeleteExpr *, const CXXMemberCallExpr *>;

/// Emit the ABI-specific virtual destructor call.
virtual llvm::Value *
EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor,
CXXDtorType DtorType, Address This,
DeleteOrMemberCallExpr E,
llvm::CallBase **CallOrInvoke) = 0;
virtual llvm::Value *EmitVirtualDestructorCall(
CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke,
bool VectorDeleting = false) = 0;

virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF,
GlobalDecl GD,
Expand Down Expand Up @@ -575,6 +576,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);

Expand Down
Loading