Skip to content

Commit 2ccc77e

Browse files
authored
[CIR][CodeGen] Implemented CXXDeleteExpr (#1756)
Implemented `CXXDeleteExpr` for concrete and virtual destructors. NYI, global delete, i.e., `::delete`. Added tests for both destructor types.
1 parent 95a3e54 commit 2ccc77e

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

clang/lib/CIR/CodeGen/CIRGenCXXABI.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ class CIRGenCXXABI {
182182
virtual void registerGlobalDtor(CIRGenFunction &CGF, const VarDecl *D,
183183
cir::FuncOp dtor, mlir::Value Addr) = 0;
184184

185+
virtual void emitVirtualObjectDelete(CIRGenFunction &CGF,
186+
const CXXDeleteExpr *DE, Address Ptr,
187+
QualType ElementType,
188+
const CXXDestructorDecl *Dtor) = 0;
189+
185190
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
186191
FunctionArgList &Args) const = 0;
187192

@@ -212,6 +217,15 @@ class CIRGenCXXABI {
212217
virtual void emitVTableDefinitions(CIRGenVTables &CGVT,
213218
const CXXRecordDecl *RD) = 0;
214219

220+
using DeleteOrMemberCallExpr =
221+
llvm::PointerUnion<const CXXDeleteExpr *, const CXXMemberCallExpr *>;
222+
223+
virtual mlir::Value emitVirtualDestructorCall(CIRGenFunction &CGF,
224+
const CXXDestructorDecl *Dtor,
225+
CXXDtorType DtorType,
226+
Address This,
227+
DeleteOrMemberCallExpr E) = 0;
228+
215229
/// Emit any tables needed to implement virtual inheritance. For Itanium,
216230
/// this emits virtual table tables.
217231
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0;

clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,7 +1227,8 @@ static bool EmitObjectDelete(CIRGenFunction &CGF, const CXXDeleteExpr *DE,
12271227
}
12281228
}
12291229
if (UseVirtualCall) {
1230-
llvm_unreachable("NYI");
1230+
CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType,
1231+
Dtor);
12311232
return false;
12321233
}
12331234
}
@@ -1241,7 +1242,9 @@ static bool EmitObjectDelete(CIRGenFunction &CGF, const CXXDeleteExpr *DE,
12411242
NormalAndEHCleanup, Ptr.getPointer(), OperatorDelete, ElementType);
12421243

12431244
if (Dtor) {
1244-
llvm_unreachable("NYI");
1245+
CGF.emitCXXDestructorCall(Dtor, Dtor_Complete,
1246+
/*ForVirtualBase=*/false,
1247+
/*Delegating=*/false, Ptr, ElementType);
12451248
} else if (auto Lifetime = ElementType.getObjCLifetime()) {
12461249
switch (Lifetime) {
12471250
case Qualifiers::OCL_None:

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
187187
QualType ThisTy) override;
188188
void registerGlobalDtor(CIRGenFunction &CGF, const VarDecl *D,
189189
cir::FuncOp dtor, mlir::Value Addr) override;
190+
void emitVirtualObjectDelete(CIRGenFunction &CGF, const CXXDeleteExpr *DE,
191+
Address Ptr, QualType ElementType,
192+
const CXXDestructorDecl *Dtor) override;
190193
virtual void emitRethrow(CIRGenFunction &CGF, bool isNoReturn) override;
191194
virtual void emitThrow(CIRGenFunction &CGF, const CXXThrowExpr *E) override;
192195
CatchTypeInfo
@@ -205,6 +208,10 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
205208
CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &CGF, GlobalDecl GD,
206209
Address This, mlir::Type Ty,
207210
SourceLocation Loc) override;
211+
mlir::Value emitVirtualDestructorCall(CIRGenFunction &CGF,
212+
const CXXDestructorDecl *Dtor,
213+
CXXDtorType DtorType, Address This,
214+
DeleteOrMemberCallExpr E) override;
208215
mlir::Value getVTableAddressPoint(BaseSubobject Base,
209216
const CXXRecordDecl *VTableClass) override;
210217
mlir::Value getVTableAddressPointInStructorWithVTT(
@@ -2186,6 +2193,32 @@ void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &CGVT,
21862193
llvm_unreachable("NYI");
21872194
}
21882195

2196+
mlir::Value CIRGenItaniumCXXABI::emitVirtualDestructorCall(
2197+
CIRGenFunction &CGF, const CXXDestructorDecl *dtor, CXXDtorType dtorType,
2198+
Address thisAddr, DeleteOrMemberCallExpr expr) {
2199+
auto *callExpr = dyn_cast<const CXXMemberCallExpr *>(expr);
2200+
auto *delExpr = dyn_cast<const CXXDeleteExpr *>(expr);
2201+
assert((callExpr != nullptr) ^ (delExpr != nullptr));
2202+
assert(callExpr == nullptr || callExpr->arg_begin() == callExpr->arg_end());
2203+
assert(dtorType == Dtor_Deleting || dtorType == Dtor_Complete);
2204+
2205+
GlobalDecl globalDecl(dtor, dtorType);
2206+
const CIRGenFunctionInfo *fnInfo =
2207+
&CGM.getTypes().arrangeCXXStructorDeclaration(globalDecl);
2208+
auto fnTy = CGF.CGM.getTypes().GetFunctionType(*fnInfo);
2209+
auto callee = CIRGenCallee::forVirtual(callExpr, globalDecl, thisAddr, fnTy);
2210+
2211+
QualType thisTy;
2212+
if (callExpr)
2213+
thisTy = callExpr->getObjectType();
2214+
else
2215+
thisTy = delExpr->getDestroyedType();
2216+
2217+
CGF.emitCXXDestructorCall(globalDecl, callee, thisAddr.emitRawPointer(),
2218+
thisTy, nullptr, QualType(), nullptr);
2219+
return nullptr;
2220+
}
2221+
21892222
void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
21902223
const CXXRecordDecl *RD) {
21912224
CIRGenVTables &VTables = CGM.getVTables();
@@ -2716,6 +2749,22 @@ bool CIRGenItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
27162749
return MPT->isMemberFunctionPointer();
27172750
}
27182751

2752+
/// The Itanium ABI always places an offset to the complete object
2753+
/// at entry -2 in the vtable.
2754+
void CIRGenItaniumCXXABI::emitVirtualObjectDelete(
2755+
CIRGenFunction &CGF, const CXXDeleteExpr *delExpr, Address ptr,
2756+
QualType elementType, const CXXDestructorDecl *dtor) {
2757+
bool useGlobalDelete = delExpr->isGlobalDelete();
2758+
if (useGlobalDelete)
2759+
llvm_unreachable("NYI");
2760+
2761+
CXXDtorType dtorType = useGlobalDelete ? Dtor_Complete : Dtor_Deleting;
2762+
emitVirtualDestructorCall(CGF, dtor, dtorType, ptr, delExpr);
2763+
2764+
if (useGlobalDelete)
2765+
llvm_unreachable("NYI");
2766+
}
2767+
27192768
/************************** Array allocation cookies **************************/
27202769

27212770
CharUnits CIRGenItaniumCXXABI::getArrayCookieSizeImpl(QualType ElementType) {

clang/test/CIR/CodeGen/delete.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,38 @@ namespace test1 {
1313
// CHECK: %[[CONST:.*]] = cir.const #cir.int<4> : !u64i
1414
// CHECK: cir.call @_ZN5test11AdlEPvm({{.*}}, %[[CONST]])
1515
}
16+
17+
namespace test2 {
18+
struct A {
19+
~A() {}
20+
};
21+
struct B {
22+
A *a;
23+
~B();
24+
};
25+
// CHECK-LABEL: cir.func{{.*}} @_ZN5test21BD2Ev
26+
// CHECK: cir.call @_ZN5test21AD2Ev
27+
// CHECK: cir.call @_ZdlPvm
28+
// CHECK: cir.return
29+
B::~B() { delete a; }
30+
}
31+
32+
namespace test3 {
33+
struct X {
34+
virtual ~X();
35+
};
36+
37+
// Calling delete with a virtual destructor.
38+
// CHECK-LABEL: cir.func dso_local @_ZN5test37destroyEPNS_1XE
39+
// CHECK: %[[ARG_VAR:.*]] = cir.alloca !cir.ptr<!rec_test33A3AX>
40+
// CHECK: %[[ARG:.*]] = cir.load{{.*}} %[[ARG_VAR]] : !cir.ptr<!cir.ptr<!rec_test33A3AX>>, !cir.ptr<!rec_test33A3AX>
41+
// CHECK: %[[ARG_PTR:.*]] = cir.cast(bitcast, %[[ARG]]
42+
// CHECK: %[[VTABLE:.*]] = cir.load{{.*}} %[[ARG_PTR]]
43+
// CHECK: %[[DTOR_PTR:.*]] = cir.vtable.address_point( %[[VTABLE]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_test33A3AX>)>>>, address_point = <index = 0, offset = 1>)
44+
// CHECK: %[[DTOR_FUN:.*]] = cir.load{{.*}} %[[DTOR_PTR]]
45+
// CHECK: cir.call %[[DTOR_FUN]](%[[ARG]])
46+
// CHECK: cir.return
47+
void destroy(X *x) {
48+
delete x;
49+
}
50+
}

0 commit comments

Comments
 (0)