Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ struct MissingFeatures {
static bool dataLayoutPtrHandlingBasedOnLangAS() { return false; }
static bool deferredCXXGlobalInit() { return false; }
static bool deleteArray() { return false; }
static bool devirtualizeDestructor() { return false; }
static bool devirtualizeMemberFunction() { return false; }
static bool ehCleanupFlags() { return false; }
static bool ehCleanupHasPrebranchedFallthrough() { return false; }
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ class CIRGenCXXABI {
virtual void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
mlir::Value addr) = 0;

virtual void emitVirtualObjectDelete(CIRGenFunction &cgf,
const CXXDeleteExpr *de, Address ptr,
QualType elementType,
const CXXDestructorDecl *dtor) = 0;

/// Checks if ABI requires extra virtual offset for vtable field.
virtual bool
isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,8 +565,10 @@ static void emitObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,
dtor = rd->getDestructor();

if (dtor->isVirtual()) {
cgf.cgm.errorNYI(de->getSourceRange(),
"emitObjectDelete: virtual destructor");
assert(!cir::MissingFeatures::devirtualizeDestructor());
cgf.cgm.getCXXABI().emitVirtualObjectDelete(cgf, de, ptr, elementType,
dtor);
return;
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
QualType thisTy) override;
void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
mlir::Value addr) override;
void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,
Address ptr, QualType elementType,
const CXXDestructorDecl *dtor) override;

void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
Expand Down Expand Up @@ -2175,6 +2178,22 @@ mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf,
isRefCast, castInfo);
}

/// The Itanium ABI always places an offset to the complete object
/// at entry -2 in the vtable.
void CIRGenItaniumCXXABI::emitVirtualObjectDelete(
CIRGenFunction &cgf, const CXXDeleteExpr *delExpr, Address ptr,
QualType elementType, const CXXDestructorDecl *dtor) {
bool useGlobalDelete = delExpr->isGlobalDelete();
if (useGlobalDelete) {
cgf.cgm.errorNYI(delExpr->getSourceRange(),
"emitVirtualObjectDelete: global delete");
return;
}

CXXDtorType dtorType = useGlobalDelete ? Dtor_Complete : Dtor_Deleting;
emitVirtualDestructorCall(cgf, dtor, dtorType, ptr, delExpr);
}

/************************** Array allocation cookies **************************/

CharUnits CIRGenItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
Expand Down
39 changes: 39 additions & 0 deletions clang/test/CIR/CodeGen/delete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,42 @@ Container::~Container() { delete contents; }
// These functions are declared/defined below the calls in OGCG.
// OGCG: define linkonce_odr void @_ZN8ContentsD2Ev
// OGCG: declare void @_ZdlPvm(ptr noundef, i64 noundef)

struct StructWithVirtualDestructor {
virtual ~StructWithVirtualDestructor();
};

void destroy(StructWithVirtualDestructor *x) {
delete x;
}

// CIR: cir.func {{.*}} @_Z7destroyP27StructWithVirtualDestructor(%[[X_ARG:.*]]: !cir.ptr<!rec_StructWithVirtualDestructor> {{.*}})
// CIR: %[[X_ADDR:.*]] = cir.alloca !cir.ptr<!rec_StructWithVirtualDestructor>
// CIR: cir.store %[[X_ARG]], %[[X_ADDR]]
// CIR: %[[X:.*]] = cir.load{{.*}} %[[X_ADDR]]
// CIR: %[[VTABLE_PTR:.*]] = cir.vtable.get_vptr %[[X]] : !cir.ptr<!rec_StructWithVirtualDestructor> -> !cir.ptr<!cir.vptr>
// CIR: %[[VTABLE:.*]] = cir.load{{.*}} %[[VTABLE_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr
// CIR: %[[DTOR_FN_ADDR_PTR:.*]] = cir.vtable.get_virtual_fn_addr %[[VTABLE]][1]
// CIR: %[[DTOR_FN_ADDR:.*]] = cir.load{{.*}} %[[DTOR_FN_ADDR_PTR]]
// CIR: cir.call %[[DTOR_FN_ADDR]](%[[X]])

// LLVM: define {{.*}} void @_Z7destroyP27StructWithVirtualDestructor(ptr %[[X_ARG:.*]])
// LLVM: %[[X_ADDR:.*]] = alloca ptr
// LLVM: store ptr %[[X_ARG]], ptr %[[X_ADDR]]
// LLVM: %[[X:.*]] = load ptr, ptr %[[X_ADDR]]
// LLVM: %[[VTABLE:.*]] = load ptr, ptr %[[X]]
// LLVM: %[[DTOR_FN_ADDR_PTR:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i32 1
// LLVM: %[[DTOR_FN_ADDR:.*]] = load ptr, ptr %[[DTOR_FN_ADDR_PTR]]
// LLVM: call void %[[DTOR_FN_ADDR]](ptr %[[X]])

// OGCG: define {{.*}} void @_Z7destroyP27StructWithVirtualDestructor(ptr {{.*}} %[X_ARG:.*]])
// OGCG: %[[X_ADDR:.*]] = alloca ptr
// OGCG: store ptr %[[X_ARG]], ptr %[[X_ADDR]]
// OGCG: %[[X:.*]] = load ptr, ptr %[[X_ADDR]]
// OGCG: %[[ISNULL:.*]] = icmp eq ptr %[[X]], null
// OGCG: br i1 %[[ISNULL]], label %{{.*}}, label %[[DELETE_NOTNULL:.*]]
// OGCG: [[DELETE_NOTNULL]]:
// OGCG: %[[VTABLE:.*]] = load ptr, ptr %[[X]]
// OGCG: %[[DTOR_FN_ADDR_PTR:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i32 1
// OGCG: %[[DTOR_FN_ADDR:.*]] = load ptr, ptr %[[DTOR_FN_ADDR_PTR]]
// OGCG: call void %[[DTOR_FN_ADDR]](ptr {{.*}} %[[X]])
Loading