[CIR] Handle vtable pure and deleted virtual functions (#183862)
Finding reproducers for these that don't use the deferred vtable (which
we haven't yet implemented) was a bit of a challenge, but I found
this setup to get these to be emitted. Fortunately it is a quite easy
implementation that doesn't do awfully much.
This patch implements both, plus the name through the itanium ABI.
This commit is contained in:
parent
6893d27757
commit
03bd4ef4ec
@ -290,6 +290,9 @@ public:
|
||||
CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
|
||||
const CXXRecordDecl *nearestVBase) = 0;
|
||||
|
||||
virtual llvm::StringRef getPureVirtualCallName() = 0;
|
||||
virtual llvm::StringRef getDeletedVirtualCallName() = 0;
|
||||
|
||||
/// Insert any ABI-specific implicit parameters into the parameter list for a
|
||||
/// function. This generally involves extra data for constructors and
|
||||
/// destructors.
|
||||
|
||||
@ -139,6 +139,12 @@ public:
|
||||
|
||||
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
|
||||
QualType ty) override;
|
||||
|
||||
StringRef getPureVirtualCallName() override { return "__cxa_pure_virtual"; }
|
||||
StringRef getDeletedVirtualCallName() override {
|
||||
return "__cxa_deleted_virtual";
|
||||
}
|
||||
|
||||
CatchTypeInfo
|
||||
getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,
|
||||
QualType catchHandlerType) override {
|
||||
|
||||
@ -176,13 +176,33 @@ mlir::Attribute CIRGenVTables::getVTableComponent(
|
||||
|
||||
assert(!cir::MissingFeatures::cudaSupport());
|
||||
|
||||
auto getSpecialVirtFn = [&](StringRef name) -> cir::FuncOp {
|
||||
assert(!cir::MissingFeatures::vtableRelativeLayout());
|
||||
|
||||
if (cgm.getLangOpts().OpenMP && cgm.getLangOpts().OpenMPIsTargetDevice &&
|
||||
cgm.getTriple().isNVPTX())
|
||||
cgm.errorNYI(gd.getDecl()->getSourceRange(),
|
||||
"getVTableComponent for OMP Device NVPTX");
|
||||
|
||||
cir::FuncType fnTy =
|
||||
cgm.getBuilder().getFuncType({}, cgm.getBuilder().getVoidTy());
|
||||
cir::FuncOp fnPtr = cgm.createRuntimeFunction(fnTy, name);
|
||||
|
||||
assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
|
||||
return fnPtr;
|
||||
};
|
||||
|
||||
cir::FuncOp fnPtr;
|
||||
if (cast<CXXMethodDecl>(gd.getDecl())->isPureVirtual()) {
|
||||
cgm.errorNYI("getVTableComponent: CK_FunctionPointer: pure virtual");
|
||||
return mlir::Attribute();
|
||||
if (!pureVirtualFn)
|
||||
pureVirtualFn =
|
||||
getSpecialVirtFn(cgm.getCXXABI().getPureVirtualCallName());
|
||||
fnPtr = pureVirtualFn;
|
||||
} else if (cast<CXXMethodDecl>(gd.getDecl())->isDeleted()) {
|
||||
cgm.errorNYI("getVTableComponent: CK_FunctionPointer: deleted virtual");
|
||||
return mlir::Attribute();
|
||||
if (!deletedVirtualFn)
|
||||
deletedVirtualFn =
|
||||
getSpecialVirtFn(cgm.getCXXABI().getDeletedVirtualCallName());
|
||||
fnPtr = deletedVirtualFn;
|
||||
} else if (nextVTableThunkIndex < layout.vtable_thunks().size() &&
|
||||
layout.vtable_thunks()[nextVTableThunkIndex].first ==
|
||||
componentIndex) {
|
||||
|
||||
@ -46,6 +46,11 @@ class CIRGenVTables {
|
||||
/// indices.
|
||||
SecondaryVirtualPointerIndicesMapTy secondaryVirtualPointerIndices;
|
||||
|
||||
/// Cache for the pure virtual member call function.
|
||||
cir::FuncOp pureVirtualFn = nullptr;
|
||||
/// Cache for the deleted virtual member call function.
|
||||
cir::FuncOp deletedVirtualFn = nullptr;
|
||||
|
||||
mlir::Attribute
|
||||
getVTableComponent(const VTableLayout &layout, unsigned componentIndex,
|
||||
mlir::Attribute rtti, unsigned &nextVTableThunkIndex,
|
||||
|
||||
27
clang/test/CIR/CodeGenCXX/vtable-pure-deleted-funcs.cpp
Normal file
27
clang/test/CIR/CodeGenCXX/vtable-pure-deleted-funcs.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2> %t-before.cir
|
||||
// RUN: FileCheck %s --input-file=%t-before.cir --check-prefixes=CIR
|
||||
// RUN: FileCheck %s --input-file=%t.cir --check-prefixes=CIR
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefixes=LLVM,LLVM-CIR
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=LLVM,LLVM-OGCG
|
||||
|
||||
struct Struct {
|
||||
virtual void f1() = 0;
|
||||
virtual void f2() = delete;
|
||||
virtual void f3();
|
||||
};
|
||||
|
||||
void Struct::f3(){}
|
||||
|
||||
|
||||
// CIR: cir.global "private" external @_ZTV6Struct = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI6Struct> : !cir.ptr<!u8i>, #cir.global_view<@__cxa_pure_virtual> : !cir.ptr<!u8i>, #cir.global_view<@__cxa_deleted_virtual> : !cir.ptr<!u8i>, #cir.global_view<@_ZN6Struct2f3Ev> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 5>}>
|
||||
// LLVM: @_ZTV6Struct = {{.*}}{ [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI6Struct, ptr @__cxa_pure_virtual, ptr @__cxa_deleted_virtual, ptr @_ZN6Struct2f3Ev] }
|
||||
|
||||
// CIR: cir.global constant external @_ZTI6Struct = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv117__class_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS6Struct> : !cir.ptr<!u8i>}>
|
||||
// LLVM-CIR: @_ZTI6Struct = constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 16), ptr @_ZTS6Struct }
|
||||
// LLVM-OGCG: @_ZTI6Struct = constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS6Struct }
|
||||
//
|
||||
// CIR: cir.func private dso_local @__cxa_pure_virtual()
|
||||
// LLVM: declare {{.*}}void @__cxa_pure_virtual()
|
||||
//
|
||||
// CIR: cir.func private dso_local @__cxa_deleted_virtual()
|
||||
// LLVM: declare {{.*}}void @__cxa_deleted_virtual()
|
||||
Loading…
x
Reference in New Issue
Block a user