From c0eb128c50b04ee4e810362cd4be2e1afa54390a Mon Sep 17 00:00:00 2001 From: Alexey Sachkov Date: Mon, 2 Dec 2024 07:31:35 -0800 Subject: [PATCH 1/3] [SYCL] Don't emit @__cxa_pure_virtual into device code This special symbol is used to handling calls to pure virtual functions in regular C++ program. However, for SYCL device code we do not have a guarantee that this symbol will be provided by SYCL backend compilers. Considering that pure virtual function call is an undefined behavior anyway, this PR replaces `@__cxa_pure_virtual` uses with `null` during SYCL device compilation to avoid issues with unresolved symbols. --- clang/lib/CodeGen/CGVTables.cpp | 13 ++++-- .../dont-emit-cxx-pure-virtual.cpp | 40 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 045fc27101357..1c866019befa9 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -831,9 +831,16 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder, // Pure virtual member functions. if (cast(GD.getDecl())->isPureVirtual()) { - if (!PureVirtualFn) - PureVirtualFn = - getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName()); + if (!PureVirtualFn) { + // There is no guarantee that special function for handling pure virtual + // calls will be provided by a SYCL backend compiler and therefore we + // simply emit nullptr here. + if (CGM.getLangOpts().SYCLIsDevice) + PureVirtualFn = llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy); + else + PureVirtualFn = + getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName()); + } fnPtr = PureVirtualFn; // Deleted virtual member functions. diff --git a/clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp b/clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp new file mode 100644 index 0000000000000..de334de871f53 --- /dev/null +++ b/clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp @@ -0,0 +1,40 @@ +// There ios no guarantee that special symbol @__cxa_pure_virtual is suppored +// by SYCL backend compiler, so we need to make sure that we don't emit it +// during SYCL device compilation. +// +// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -emit-llvm %s -o - | FileCheck %s +// +// CHECK-NOT: @__cxa_pure_virtual + +SYCL_EXTERNAL bool rand(); + +class Base { +public: + [[__sycl_detail__::add_ir_attributes_function("indirectly-callable", "a")]] + virtual void display() {} + + virtual void pure_host() = 0; + + [[__sycl_detail__::add_ir_attributes_function("indirectly-callable", "a")]] + virtual void pure_device() = 0; +}; + +class Derived1 : public Base { +public: + [[__sycl_detail__::add_ir_attributes_function("indirectly-callable", "a")]] + void display() override {} + + void pure_host() override {} + + [[__sycl_detail__::add_ir_attributes_function("indirectly-callable", "a")]] + void pure_device() override {} +}; + +SYCL_EXTERNAL void test() { + Derived1 d1; + Base *b = nullptr; + if (rand()) + b = &d1; + b->display(); +} + From 6eeb45f6cfe76f0e22017135fc63048639d9c3b4 Mon Sep 17 00:00:00 2001 From: Alexey Sachkov Date: Tue, 3 Dec 2024 01:57:42 -0800 Subject: [PATCH 2/3] Apply comments --- clang/lib/CodeGen/CGVTables.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 1c866019befa9..6310349c469da 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -803,6 +803,12 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder, } auto getSpecialVirtualFn = [&](StringRef name) -> llvm::Constant * { + // There is no guarantee that special function for handling pure virtual + // calls will be provided by a SYCL backend compiler and therefore we + // simply emit nullptr here. + if (CGM.getLangOpts().SYCLIsDevice) + return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy); + // FIXME(PR43094): When merging comdat groups, lld can select a local // symbol as the signature symbol even though it cannot be accessed // outside that symbol's TU. The relative vtables ABI would make @@ -831,16 +837,9 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder, // Pure virtual member functions. if (cast(GD.getDecl())->isPureVirtual()) { - if (!PureVirtualFn) { - // There is no guarantee that special function for handling pure virtual - // calls will be provided by a SYCL backend compiler and therefore we - // simply emit nullptr here. - if (CGM.getLangOpts().SYCLIsDevice) - PureVirtualFn = llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy); - else - PureVirtualFn = - getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName()); - } + if (!PureVirtualFn) + PureVirtualFn = + getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName()); fnPtr = PureVirtualFn; // Deleted virtual member functions. From 414d05bc7e075c3a8cc930f8f9b71563d2eaa13b Mon Sep 17 00:00:00 2001 From: Alexey Sachkov Date: Tue, 3 Dec 2024 16:38:12 +0100 Subject: [PATCH 3/3] Fix typos in test comments --- clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp b/clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp index de334de871f53..4bb19598b07a5 100644 --- a/clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp +++ b/clang/test/CodeGenSYCL/dont-emit-cxx-pure-virtual.cpp @@ -1,4 +1,4 @@ -// There ios no guarantee that special symbol @__cxa_pure_virtual is suppored +// There is no guarantee that special symbol @__cxa_pure_virtual is supported // by SYCL backend compiler, so we need to make sure that we don't emit it // during SYCL device compilation. //