Skip to content

Commit ddfe62a

Browse files
Andrew Savonichevbader
authored andcommitted
[SYCL] Allow __spirv_ocl_printf vararg function (#909)
Vararg functions are generally not allowed in SYCL. However, printf is a special case, because it can be mapped to a SPIR-V instruction, and SPIR-V translator recognizes __spirv_ocl_printf function. Signed-off-by: Andrew Savonichev <[email protected]>
1 parent e345169 commit ddfe62a

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,19 @@ static bool IsSyclMathFunc(unsigned BuiltinID) {
184184
return true;
185185
}
186186

187+
static bool isKnownGoodDecl(const Decl *D) {
188+
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
189+
const IdentifierInfo *II = FD->getIdentifier();
190+
const DeclContext *DC = FD->getDeclContext();
191+
if (II && II->isStr("__spirv_ocl_printf") &&
192+
!FD->isDefined() &&
193+
FD->getLanguageLinkage() == CXXLanguageLinkage &&
194+
DC->getEnclosingNamespaceContext()->isTranslationUnit())
195+
return true;
196+
}
197+
return false;
198+
}
199+
187200
class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
188201
public:
189202
MarkDeviceFunction(Sema &S)
@@ -312,8 +325,12 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
312325
}
313326

314327
bool VisitDeclRefExpr(DeclRefExpr *E) {
328+
Decl* D = E->getDecl();
329+
if (isKnownGoodDecl(D))
330+
return true;
331+
315332
CheckSYCLType(E->getType(), E->getSourceRange());
316-
if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
333+
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
317334
bool IsConst = VD->getType().getNonReferenceType().isConstQualified();
318335
if (!IsConst && VD->isStaticDataMember())
319336
SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict)

clang/test/SemaSYCL/sycl-varargs-cconv.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,32 @@
11
// RUN: %clang_cc1 -fsycl-is-device -verify -fsyntax-only -x c++ %s
2+
// RUN: %clang_cc1 -fsycl-is-device -verify -fsyntax-only -DPRINTF_INVALID_DEF -x c++ %s
3+
// RUN: %clang_cc1 -fsycl-is-device -verify -fsyntax-only -DPRINTF_INVALID_DECL -x c++ %s
4+
// RUN: %clang_cc1 -fsycl-is-device -verify -fsyntax-only -DPRINTF_VALID1 -x c++ %s
5+
// RUN: %clang_cc1 -fsycl-is-device -verify -fsyntax-only -DPRINTF_VALID2 -x c++ %s
6+
7+
#if defined(PRINTF_INVALID_DECL)
8+
extern "C" int __spirv_ocl_printf(const char *__format, ...);
9+
namespace A {
10+
int __spirv_ocl_printf(const char *__format, ...);
11+
}
12+
#elif defined(PRINTF_INVALID_DEF)
13+
int __spirv_ocl_printf(const char *__format, ...) {
14+
return 42;
15+
}
16+
#elif defined(PRINTF_VALID1)
17+
class A {
18+
friend int __spirv_ocl_printf(const char *__format, ...);
19+
};
20+
int __spirv_ocl_printf(const char *__format, ...);
21+
#elif defined(PRINTF_VALID2)
22+
extern "C" {
23+
extern "C++" {
24+
int __spirv_ocl_printf(const char *__format, ...);
25+
}
26+
}
27+
#else
28+
int __spirv_ocl_printf(const char *__format, ...);
29+
#endif
230

331
int __cdecl foo(int, ...); // expected-no-error
432

@@ -19,6 +47,19 @@ int main() {
1947
kernel_single_task<class fake_kernel>([]() { foo(6); });
2048
//expected-error@+1 {{SYCL kernel cannot call a variadic function}}
2149
kernel_single_task<class fake_kernel>([]() { bar(9.0); });
50+
51+
#if defined(PRINTF_INVALID_DECL)
52+
//expected-error@+1 {{SYCL kernel cannot call a variadic function}}
53+
kernel_single_task<class fake_kernel>([]() { A::__spirv_ocl_printf("Hello world! %d%d\n", 4, 2); });
54+
//expected-error@+1 {{SYCL kernel cannot call a variadic function}}
55+
kernel_single_task<class fake_kernel>([]() { __spirv_ocl_printf("Hello world! %d%d\n", 4, 2); });
56+
#elif defined(PRINTF_INVALID_DEF)
57+
//expected-error@+1 {{SYCL kernel cannot call a variadic function}}
58+
kernel_single_task<class fake_kernel>([]() { __spirv_ocl_printf("Hello world! %d%d\n", 4, 2); });
59+
#else
60+
kernel_single_task<class fake_kernel>([]() { __spirv_ocl_printf("Hello world! %d%d\n", 4, 2); });
61+
#endif
62+
2263
bar();
2364
return 0;
2465
}

0 commit comments

Comments
 (0)