Skip to content

Commit ea2111c

Browse files
[SYCL] Re-implement diagnostics about virtual calls (#14141)
With `sycl_ext_oneapi_virtual_functions` extensions we would like to allow certain kernels to perform virtual function calls. That is if they were submitted with the right properties. That means that instead of simply checking for presence of virtual function calls in device code, we need to analyze call chain to see how exactly a kernel performing such call is defined. This is not a task for the front-end and therefore the diagnostics mechanism is moved to a pass, as suggested by the implementation design proposed in #10540
1 parent e0b4c7f commit ea2111c

28 files changed

+404
-79
lines changed

clang/include/clang/Basic/DiagnosticFrontendKinds.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,16 @@ def err_target_unsupported_type_for_abi
308308
: Error<"%0 requires %1 type support, but ABI '%2' does not support it">;
309309
}
310310

311+
def err_sycl_illegal_virtual_call
312+
: Error<"kernel '%0' performs a virtual function call and they are illegal "
313+
"per the core SYCL 2020 specification. To enable their support, "
314+
"submit a kernel using the 'calls_indirectly' property, see "
315+
"the sycl_ext_oneapi_virtual_functions extension for more "
316+
"information">,
317+
BackendInfo;
318+
def note_sycl_virtual_call_done_from : Note<"performed by function '%1'">,
319+
BackendInfo;
320+
311321
def err_alias_to_undefined : Error<
312322
"%select{alias|ifunc}0 must point to a defined "
313323
"%select{variable or |}1function">;

clang/include/clang/Basic/LangOptions.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,6 @@ ENUM_LANGOPT(SYCLRangeRounding, SYCLRangeRoundingPreference, 2,
316316
LANGOPT(SYCLExperimentalRangeRounding, 1, 0, "Use experimental parallel for range rounding")
317317
LANGOPT(SYCLEnableIntHeaderDiags, 1, 0, "Enable diagnostics that require the "
318318
"SYCL integration header")
319-
LANGOPT(SYCLAllowVirtualFunctions, 1, 0,
320-
"Allow virtual functions calls in code for SYCL device")
321319
LANGOPT(SYCLIsNativeCPU , 1, 0, "Generate code for SYCL Native CPU")
322320

323321
LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP")

clang/include/clang/Driver/Options.td

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8454,9 +8454,6 @@ def fsycl_use_main_file_name : Flag<["-"], "fsycl-use-main-file-name">,
84548454
HelpText<"Tells compiler that -main-file-name contains an absolute path and "
84558455
"file specified there should be used for checksum calculation.">,
84568456
MarshallingInfoFlag<CodeGenOpts<"SYCLUseMainFileName">>;
8457-
def fsycl_allow_virtual_functions : Flag<["-"], "fsycl-allow-virtual-functions">,
8458-
HelpText<"Allow virtual functions calls in code for SYCL device">,
8459-
MarshallingInfoFlag<LangOpts<"SYCLAllowVirtualFunctions">>;
84608457
def fsycl_is_native_cpu : Flag<["-"], "fsycl-is-native-cpu">,
84618458
HelpText<"Perform device compilation for Native CPU.">,
84628459
Visibility<[CC1Option]>,

clang/lib/CodeGen/BackendConsumer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ class BackendConsumer : public ASTConsumer {
160160
/// Note that misexpect remarks are emitted through ORE
161161
void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D);
162162
void AspectMismatchDiagHandler(const llvm::DiagnosticInfoAspectsMismatch &D);
163+
void SYCLIllegalVirtualCallDiagHandler(
164+
const llvm::DiagnosticInfoIllegalVirtualCall &D);
163165
};
164166

165167
} // namespace clang

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "llvm/SYCLLowerIR/SYCLConditionalCallOnDevice.h"
5959
#include "llvm/SYCLLowerIR/SYCLPropagateAspectsUsage.h"
6060
#include "llvm/SYCLLowerIR/SYCLPropagateJointMatrixUsage.h"
61+
#include "llvm/SYCLLowerIR/SYCLVirtualFunctionsAnalysis.h"
6162
#include "llvm/SYCLLowerIR/UtilsSYCLNativeCPU.h"
6263
#include "llvm/Support/BuryPointer.h"
6364
#include "llvm/Support/CommandLine.h"
@@ -992,6 +993,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
992993
if (LangOpts.SYCLIsDevice)
993994
PB.registerPipelineStartEPCallback([&](ModulePassManager &MPM,
994995
OptimizationLevel Level) {
996+
MPM.addPass(SYCLVirtualFunctionsAnalysisPass());
995997
MPM.addPass(ESIMDVerifierPass(LangOpts.SYCLESIMDForceStatelessMem));
996998
if (Level == OptimizationLevel::O0)
997999
MPM.addPass(ESIMDRemoveOptnoneNoinlinePass());

clang/lib/CodeGen/CodeGenAction.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,28 @@ void BackendConsumer::AspectMismatchDiagHandler(
806806
}
807807
}
808808

809+
void BackendConsumer::SYCLIllegalVirtualCallDiagHandler(
810+
const llvm::DiagnosticInfoIllegalVirtualCall &D) {
811+
const llvm::SmallVector<std::pair<StringRef, unsigned>, 8> &CallChain =
812+
D.getCallChain();
813+
auto &KI = CallChain.front();
814+
815+
SourceLocation LocCookie = SourceLocation::getFromRawEncoding(KI.second);
816+
assert(LocCookie.isValid() &&
817+
"Invalid location for kernel in illegal virtual call diagnostic");
818+
Diags.Report(LocCookie, diag::err_sycl_illegal_virtual_call)
819+
<< llvm::demangle(KI.first.str());
820+
821+
for (size_t I = 1; I < CallChain.size(); ++I) {
822+
auto &CalleeInfo = CallChain[I];
823+
LocCookie = SourceLocation::getFromRawEncoding(CalleeInfo.second);
824+
assert(LocCookie.isValid() &&
825+
"Invalid location for callee in illegal virtual call diagnostic");
826+
Diags.Report(LocCookie, diag::note_sycl_virtual_call_done_from)
827+
<< /* function */ 0 << llvm::demangle(CalleeInfo.first.str());
828+
}
829+
}
830+
809831
void BackendConsumer::MisExpectDiagHandler(
810832
const llvm::DiagnosticInfoMisExpect &D) {
811833
StringRef Filename;
@@ -910,6 +932,10 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
910932
case llvm::DK_AspectMismatch:
911933
AspectMismatchDiagHandler(cast<DiagnosticInfoAspectsMismatch>(DI));
912934
return;
935+
case llvm::DK_SYCLIllegalVirtualCall:
936+
SYCLIllegalVirtualCallDiagHandler(
937+
cast<DiagnosticInfoIllegalVirtualCall>(DI));
938+
return;
913939
default:
914940
// Plugin IDs are not bound to any value as they are set dynamically.
915941
ComputeDiagRemarkID(Severity, backend_plugin, DiagID);

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -598,12 +598,6 @@ class DiagDeviceFunction : public RecursiveASTVisitor<DiagDeviceFunction> {
598598
<< SemaSYCL::KernelCallRecursiveFunction;
599599
}
600600

601-
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Callee))
602-
if (Method->isVirtual() &&
603-
!SemaSYCLRef.getLangOpts().SYCLAllowVirtualFunctions)
604-
SemaSYCLRef.Diag(e->getExprLoc(), diag::err_sycl_restrict)
605-
<< SemaSYCL::KernelCallVirtualFunction;
606-
607601
if (auto const *FD = dyn_cast<FunctionDecl>(Callee)) {
608602
// FIXME: We need check all target specified attributes for error if
609603
// that function with attribute can not be called from sycl kernel. The

clang/test/CodeGenSYCL/add_ir_attributes_function_virtual.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -internal-isystem %S/Inputs -triple spir64-unknown-unknown -fsycl-is-device \
2-
// RUN: -fsycl-allow-virtual-functions -emit-llvm %s -o - | FileCheck %s
1+
// RUN: %clang_cc1 -internal-isystem %S/Inputs -triple spir64-unknown-unknown \
2+
// RUN: -fsycl-is-device -emit-llvm %s -o - | FileCheck %s
33

44
// Test IR generated for add_ir_attributes_function on virtual functions.
55

@@ -47,4 +47,4 @@ void foo() {
4747
// CHECK-NOT: PropDerived
4848
// CHECK: }
4949
// CHECK: attributes #[[BaseAttrs]] = { {{.*}}"PropBase"="PropVal"{{.*}} }
50-
// CHECK: attributes #[[Derived1Attrs]] = { {{.*}}"PropDerived"="PropVal"{{.*}} }
50+
// CHECK: attributes #[[Derived1Attrs]] = { {{.*}}"PropDerived"="PropVal"{{.*}} }

clang/test/CodeGenSYCL/attrs-on-virtual-calls.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
// Test verifies that clang codegen properly adds call site attributes to
22
// device code
33

4-
// RUN: %clang_cc1 -triple spir64 -fsycl-allow-virtual-functions \
5-
// RUN: -fsycl-is-device -emit-llvm %s -o %t.device
4+
// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -emit-llvm %s -o %t.device
65
// RUN: FileCheck %s --input-file=%t.device
7-
// RUN: %clang_cc1 -triple x86_64 -fsycl-allow-virtual-functions \
8-
// RUN: -fsycl-is-host -emit-llvm %s -o %t.host
6+
// RUN: %clang_cc1 -triple x86_64 -fsycl-is-host -emit-llvm %s -o %t.host
97
// RUN: FileCheck %s --input-file=%t.host --check-prefix=CHECK-HOST
108

119
// CHECK-HOST-NOT: attributes {{.*}} "virtual-call"

clang/test/CodeGenSYCL/force-emit-device-virtual-funcs.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -internal-isystem %S/Inputs -triple spir64-unknown-unknown -fsycl-is-device \
2-
// RUN: -fsycl-allow-virtual-functions -emit-llvm %s -o %t.ll
1+
// RUN: %clang_cc1 -internal-isystem %S/Inputs -triple spir64-unknown-unknown \
2+
// RUN: -fsycl-is-device -emit-llvm %s -o %t.ll
33
// RUN: FileCheck %s --input-file=%t.ll --implicit-check-not _ZN7Derived3baz \
44
// RUN: --implicit-check-not _ZN4Base4baz --implicit-check-not _ZN4Base3foo
55
//

0 commit comments

Comments
 (0)