Skip to content

Commit 94ca490

Browse files
authored
[clang][SYCL] Handle cdecl variadic functions for SYCL device (llvm#194922)
SYCL doesn't allow variadic functions to be called from device code. Since SYCL device compilation mostly uses targets that don't natively support variadic fucntions, we now issue an error even if the variadic function is never called from the device if it has cdecl calling convention attribute. We also now don't issue an error if a variadic function is called from the device code. This patch defers the error caused by cdecl attribute to the actual call point and adds diagnosing of variadic function calls on device side using deferred diagnostics.
1 parent c24fc71 commit 94ca490

5 files changed

Lines changed: 94 additions & 9 deletions

File tree

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9752,7 +9752,8 @@ def warn_kern_is_inline : Warning<
97529752
"ignored 'inline' attribute on kernel function %0">,
97539753
InGroup<CudaCompat>;
97549754
def err_variadic_device_fn : Error<
9755-
"CUDA device code does not support variadic functions">;
9755+
"%enum_select<OffloadLang>{%CUDA{CUDA}|%SYCL{SYCL}}0 device code does not "
9756+
"support variadic functions">;
97569757
def err_va_arg_in_device : Error<
97579758
"CUDA device code does not support va_arg">;
97589759
def err_alias_not_supported_on_nvptx : Error<"CUDA older than 10.0 does not support .alias">;

clang/lib/Sema/SemaChecking.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
#include "clang/Sema/SemaPPC.h"
7777
#include "clang/Sema/SemaRISCV.h"
7878
#include "clang/Sema/SemaSPIRV.h"
79+
#include "clang/Sema/SemaSYCL.h"
7980
#include "clang/Sema/SemaSystemZ.h"
8081
#include "clang/Sema/SemaWasm.h"
8182
#include "clang/Sema/SemaX86.h"
@@ -4466,6 +4467,11 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
44664467
}
44674468
}
44684469

4470+
if (FD && FD->isVariadic() && getLangOpts().SYCLIsDevice &&
4471+
!isUnevaluatedContext())
4472+
SYCL().DiagIfDeviceCode(Loc, diag::err_variadic_device_fn)
4473+
<< diag::OffloadLang::SYCL;
4474+
44694475
if (FD)
44704476
diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
44714477
}

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5823,14 +5823,12 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
58235823
A = HostTI->checkCallingConvention(CC);
58245824
if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI)
58255825
A = DeviceTI->checkCallingConvention(CC);
5826-
} else if (LangOpts.SYCLIsDevice && TI.getTriple().isAMDGPU() &&
5827-
CC == CC_X86VectorCall) {
5828-
// Assuming SYCL Device AMDGPU CC_X86VectorCall functions are always to be
5829-
// emitted on the host. The MSVC STL has CC-based specializations so we
5830-
// cannot change the CC to be the default as that will cause a clash with
5831-
// another specialization.
5832-
A = TI.checkCallingConvention(CC);
5833-
if (Aux && A != TargetInfo::CCCR_OK)
5826+
} else if (LangOpts.SYCLIsDevice) {
5827+
// In SYCL we may meet unsupported calling conventions in host code,
5828+
// especially inside of included headers. Now we don't know if they will be
5829+
// emitted, so we just defer any diagnostics. Check for the host triple if
5830+
// we have one, since everything is still emitted for the host.
5831+
if (Aux)
58345832
A = Aux->checkCallingConvention(CC);
58355833
} else {
58365834
A = TI.checkCallingConvention(CC);

clang/test/SemaSYCL/sycl-cconv.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -fsyntax-only -verify %s
3+
4+
// Check that there is no error/warning emitted for cdecl functions compiled for
5+
// SYCL device. Make sure variadic calls from within device code are diagnosed.
6+
7+
__inline __cdecl int printf(char const* const _Format, ...) { return 0; }
8+
9+
// FIXME: that should be diagnosed.
10+
[[clang::sycl_external]] int foo(int, ...) { return 0; }
11+
12+
__inline __cdecl int moo() { return 0; }
13+
14+
void bar() {
15+
printf("hello\n");
16+
}
17+
18+
template<typename KN, typename...Args>
19+
void sycl_kernel_launch(Args ...args) {}
20+
21+
template<typename KN, typename K>
22+
[[clang::sycl_kernel_entry_point(KN)]]
23+
__cdecl void sycl_entry_point(K k) {
24+
k(); // expected-note {{called by}}
25+
}
26+
27+
int main() {
28+
//expected-error@+1 {{SYCL device code does not support variadic functions}}
29+
sycl_entry_point<class kn>([]() { printf("world\n");
30+
moo();
31+
//expected-error@+1 {{SYCL device code does not support variadic functions}}
32+
foo(1,2); });
33+
bar();
34+
return 0;
35+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -fsyntax-only -verify %s
3+
4+
template<typename KN, typename...Args>
5+
void sycl_kernel_launch(Args ...args) {}
6+
7+
template<typename KN, typename K>
8+
[[clang::sycl_kernel_entry_point(KN)]]
9+
void sycl_entry_point(K k) {
10+
k(); // expected-note 2{{called by}}
11+
}
12+
13+
void variadic(int, ...) {}
14+
namespace NS {
15+
void variadic(int, ...) {}
16+
}
17+
18+
struct S {
19+
S(int, ...) {}
20+
void operator()(int, ...) {}
21+
};
22+
23+
void foo() {
24+
auto x = [](int, ...) {};
25+
x(5, 10); //expected-error{{SYCL device code does not support variadic functions}}
26+
}
27+
28+
void overloaded(int, int) {}
29+
void overloaded(int, ...) {}
30+
31+
int main() {
32+
sycl_entry_point<class FK>([]() {
33+
variadic(5); //expected-error{{SYCL device code does not support variadic functions}}
34+
variadic(5, 2); //expected-error{{SYCL device code does not support variadic functions}}
35+
NS::variadic(5, 3); //expected-error{{SYCL device code does not support variadic functions}}
36+
S s(5, 4); //expected-error{{SYCL device code does not support variadic functions}}
37+
S s2(5); //expected-error{{SYCL device code does not support variadic functions}}
38+
s(5, 5); //expected-error{{SYCL device code does not support variadic functions}}
39+
s2(5); //expected-error{{SYCL device code does not support variadic functions}}
40+
foo(); //expected-note{{called by 'operator()'}}
41+
overloaded(5, 6); //expected-no-error
42+
overloaded(5, s); //expected-error{{SYCL device code does not support variadic functions}}
43+
overloaded(5); //expected-error{{SYCL device code does not support variadic functions}}
44+
});
45+
}

0 commit comments

Comments
 (0)