-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang][SYCL] Add sycl_external attribute and restrict emitting device code #140282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this @schittir! I completed an initial pass of all of the code, but still need to look more closely at the documentation updates.
Thank you for the initial pass review, Tom! |
✅ With the latest revision this PR passed the C/C++ code formatter. |
Support for functions is sufficient for SYCL 2020 spec conformance.
Co-authored-by: Mariya Podchishchaeva <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @schittir, here are my initial review comments. I expect to review the newly added tests more closely once these comments are all addressed.
There seems to be an issue with the use of sycl_kernel_entry_point attribute vs __builtin_unique_stable_name
Oops new tests are failing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good @schittir! I added some comments for minor issues. I still need to review the tests more closely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more comments. I still haven't finished my review of sycl-external-attr.cpp
, but will try to later today or over the weekend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I finished an initial pass through all of the tests. I'll do another round once you've had a chance to catch up on the comments so far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great @schittir! I just realized that, since we made the change to allow the attribute to be present during host compilation that we should no longer restrict diagnostics to device compilation and that tests should exercise host compilation as well.
I suggested a few FIXME comments, but other than that, I think this is good to go!
if (LangOpts.SYCLIsDevice) { | ||
const SYCLExternalAttr *SEA = New->getAttr<SYCLExternalAttr>(); | ||
if (SEA && !Old->hasAttr<SYCLExternalAttr>()) { | ||
Diag(SEA->getLocation(), diag::err_attribute_missing_on_first_decl) | ||
<< SEA; | ||
Diag(Old->getLocation(), diag::note_previous_declaration); | ||
New->dropAttr<SYCLExternalAttr>(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have decided to allow the attribute to be present during host compilation, we don't need to, and shouldn't, check for device compilation; diagnostics should be emitted during host compilation too.
if (LangOpts.SYCLIsDevice) { | |
const SYCLExternalAttr *SEA = New->getAttr<SYCLExternalAttr>(); | |
if (SEA && !Old->hasAttr<SYCLExternalAttr>()) { | |
Diag(SEA->getLocation(), diag::err_attribute_missing_on_first_decl) | |
<< SEA; | |
Diag(Old->getLocation(), diag::note_previous_declaration); | |
New->dropAttr<SYCLExternalAttr>(); | |
} | |
const SYCLExternalAttr *SEA = New->getAttr<SYCLExternalAttr>(); | |
if (SEA && !Old->hasAttr<SYCLExternalAttr>()) { | |
Diag(SEA->getLocation(), diag::err_attribute_missing_on_first_decl) | |
<< SEA; | |
Diag(Old->getLocation(), diag::note_previous_declaration); | |
New->dropAttr<SYCLExternalAttr>(); |
if (getLangOpts().SYCLIsDevice) { | ||
if (FD->hasAttr<SYCLExternalAttr>()) { | ||
Diag(FD->getLocation(), diag::err_sycl_attribute_invalid_main); | ||
FD->setInvalidDecl(); | ||
return; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Diagnostics are desired for host compilation as well.
if (getLangOpts().SYCLIsDevice) { | |
if (FD->hasAttr<SYCLExternalAttr>()) { | |
Diag(FD->getLocation(), diag::err_sycl_attribute_invalid_main); | |
FD->setInvalidDecl(); | |
return; | |
} | |
} | |
if (FD->hasAttr<SYCLExternalAttr>()) { | |
Diag(FD->getLocation(), diag::err_sycl_attribute_invalid_main); | |
FD->setInvalidDecl(); | |
return; | |
} |
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++17 -verify %s | ||
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++20 -verify %s | ||
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++23 -verify %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate diagnostics for host compilation too.
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++17 -verify %s | |
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++20 -verify %s | |
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++23 -verify %s | |
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -std=c++17 -verify %s | |
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++17 -verify %s | |
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -std=c++20 -verify %s | |
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++20 -verify %s | |
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -std=c++23 -verify %s | |
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++23 -verify %s |
@@ -0,0 +1,15 @@ | |||
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate diagnostics for host compilation too.
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s | |
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s | |
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s |
// FIXME: this case should be diagnosed. | ||
// This attribute takes no arguments. | ||
[[clang::sycl_external()]] void bad1(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make the desired intent a little more clear.
// FIXME: this case should be diagnosed. | |
// This attribute takes no arguments. | |
[[clang::sycl_external()]] void bad1(); | |
// FIXME-expected-error@+1{{'clang::sycl_external' attribute takes no arguments}} | |
[[clang::sycl_external()]] void bad1(); |
// RUN: %clang_cc1 -fsycl-is-device -std=c++17 -fsyntax-only -verify -DCPP17 %s | ||
// RUN: %clang_cc1 -fsycl-is-device -std=c++20 -fsyntax-only -verify -DCPP20 %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate diagnostics for host compilation too.
// RUN: %clang_cc1 -fsycl-is-device -std=c++17 -fsyntax-only -verify -DCPP17 %s | |
// RUN: %clang_cc1 -fsycl-is-device -std=c++20 -fsyntax-only -verify -DCPP20 %s | |
// RUN: %clang_cc1 -fsycl-is-host -std=c++17 -fsyntax-only -verify -DCPP17 %s | |
// RUN: %clang_cc1 -fsycl-is-device -std=c++17 -fsyntax-only -verify -DCPP17 %s | |
// RUN: %clang_cc1 -fsycl-is-host -std=c++20 -fsyntax-only -verify -DCPP20 %s | |
// RUN: %clang_cc1 -fsycl-is-device -std=c++20 -fsyntax-only -verify -DCPP20 %s |
|
||
struct UnnX {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type is no longer used.
struct UnnX {}; |
// expected-error@+3 2{{'sycl_external' can only be applied to functions with external linkage}} | ||
namespace { struct S7 {}; } | ||
template<typename> | ||
[[clang::sycl_external]] void func7(); | ||
template<> void func7<S7>() {} | ||
// expected-note@-1{{in instantiation of function template specialization 'func7<(anonymous namespace)::S7>' requested here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case should not be diagnosed.
// expected-error@+3 2{{'sycl_external' can only be applied to functions with external linkage}} | |
namespace { struct S7 {}; } | |
template<typename> | |
[[clang::sycl_external]] void func7(); | |
template<> void func7<S7>() {} | |
// expected-note@-1{{in instantiation of function template specialization 'func7<(anonymous namespace)::S7>' requested here}} | |
// FIXME: C++23 [temp.expl.spec]p12 states: | |
// ... Similarly, attributes appearing in the declaration of a template | |
// have no effect on an explicit specialization of that template. | |
// Clang currently instantiates and propagates attributes from a function | |
// template to its explicit specializations resulting in the following | |
// spurious error. | |
// expected-error@+3 2{{'sycl_external' can only be applied to functions with external linkage}} | |
namespace { struct S7 {}; } | |
template<typename> | |
[[clang::sycl_external]] void func7(); | |
template<> void func7<S7>() {} | |
// expected-note@-1{{in instantiation of function template specialization 'func7<(anonymous namespace)::S7>' requested here}} |
// FIXME: This case is currently being diagnosed as an error because clang implements | ||
// default inheritance of attribute and explicit instantiation declaration names the | ||
// symbol that causes the instantiated specialization to have internal linkage. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case is correctly diagnosed. Explicit function template instantiations inherit attributes from the function template. Explicit function template specializations are the ones that shouldn't inherit from the function template.
// FIXME: This case is currently being diagnosed as an error because clang implements | |
// default inheritance of attribute and explicit instantiation declaration names the | |
// symbol that causes the instantiated specialization to have internal linkage. |
namespace { struct S8 {}; } | ||
template<typename> | ||
void func8(); | ||
template<> [[clang::sycl_external]] void func8<S8>() {} | ||
// expected-error@-1{{'clang::sycl_external' attribute does not appear on the first declaration}} | ||
// expected-note@-2{{previous declaration is here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a FIXME comment for this case. It is a weird corner case, but I have encountered programmers wanting to do this kind of thing recently. I think it should be well-formed, but I don't think it is worth trying to address now.
namespace { struct S8 {}; } | |
template<typename> | |
void func8(); | |
template<> [[clang::sycl_external]] void func8<S8>() {} | |
// expected-error@-1{{'clang::sycl_external' attribute does not appear on the first declaration}} | |
// expected-note@-2{{previous declaration is here}} | |
// FIXME: The explicit function template specialization appears to trigger | |
// instantiation of a declaration from the primary template without the | |
// attribute leading to a spurious diagnostic that the sycl_external | |
// attribute is not present on the first declaration. | |
namespace { struct S8 {}; } | |
template<typename> | |
void func8(); | |
template<> [[clang::sycl_external]] void func8<S8>() {} | |
// expected-error@-1{{'clang::sycl_external' attribute does not appear on the first declaration}} | |
// expected-note@-2{{previous declaration is here}} |
This patch is part of the upstreaming effort for supporting SYCL language front end.
It makes the following changes:
This patch is missing diagnostics for the following diagnostics listed in the SYCL 2020 specification's section 5.10.1, which will be addressed in a subsequent PR:
Functions that are declared using SYCL_EXTERNAL have the following additional restrictions beyond those imposed on other device functions: