Skip to content

[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

Open
wants to merge 41 commits into
base: main
Choose a base branch
from

Conversation

schittir
Copy link
Contributor

@schittir schittir commented May 16, 2025

This patch is part of the upstreaming effort for supporting SYCL language front end.
It makes the following changes:

  1. Adds sycl_external attribute for functions with external linkage.
  2. Adds checks to avoid emitting device code when sycl_external and sycl_kernel_entry_point attributes are not enabled
  3. Fixes test failures caused by the above 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:

  1. If the SYCL backend does not support the generic address space then the function cannot use raw pointers as parameter or return types. Explicit pointer classes must be used instead;
  2. The function cannot call group::parallel_for_work_item;
  3. The function cannot be called from a parallel_for_work_group scope.

Copy link
Contributor

@tahonermann tahonermann left a 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.

@schittir
Copy link
Contributor Author

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!

Copy link

github-actions bot commented May 26, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@schittir schittir changed the title Add sycl_external attribute [SYCL] Add sycl_external attribute Jun 10, 2025
@schittir schittir marked this pull request as ready for review June 10, 2025 16:16
@schittir schittir changed the title [SYCL] Add sycl_external attribute [clang][SYCL Upstreaming] Add sycl_external attribute Jun 10, 2025
@Fznamznon Fznamznon added the SYCL https://registry.khronos.org/SYCL label Jun 10, 2025
@schittir schittir changed the title [clang][SYCL Upstreaming] Add sycl_external attribute [clang][SYCL Upstreaming] Add sycl_external attribute and restrict emitting code Jun 10, 2025
@schittir schittir changed the title [clang][SYCL Upstreaming] Add sycl_external attribute and restrict emitting code [clang][SYCL Upstreaming] Add sycl_external attribute and restrict emitting device code Jun 10, 2025
@Fznamznon Fznamznon changed the title [clang][SYCL Upstreaming] Add sycl_external attribute and restrict emitting device code [clang][SYCL] Add sycl_external attribute and restrict emitting device code Jun 11, 2025
Copy link
Contributor

@tahonermann tahonermann left a 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.

@Fznamznon
Copy link
Contributor

Oops new tests are failing.

Copy link
Contributor

@tahonermann tahonermann left a 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.

Copy link
Contributor

@tahonermann tahonermann left a 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.

Copy link
Contributor

@tahonermann tahonermann left a 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.

Copy link
Contributor

@tahonermann tahonermann left a 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!

Comment on lines +4092 to +4099
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>();
}
Copy link
Contributor

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.

Suggested change
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>();

Comment on lines +12460 to +12466
if (getLangOpts().SYCLIsDevice) {
if (FD->hasAttr<SYCLExternalAttr>()) {
Diag(FD->getLocation(), diag::err_sycl_attribute_invalid_main);
FD->setInvalidDecl();
return;
}
}
Copy link
Contributor

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.

Suggested change
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;
}

Comment on lines +1 to +3
// 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
Copy link
Contributor

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.

Suggested change
// 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
Copy link
Contributor

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.

Suggested change
// 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

Comment on lines +4 to +6
// FIXME: this case should be diagnosed.
// This attribute takes no arguments.
[[clang::sycl_external()]] void bad1();
Copy link
Contributor

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.

Suggested change
// 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();

Comment on lines +1 to +2
// 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
Copy link
Contributor

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.

Suggested change
// 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

Comment on lines +14 to +15

struct UnnX {};
Copy link
Contributor

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.

Suggested change
struct UnnX {};

Comment on lines +32 to +37
// 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}}
Copy link
Contributor

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.

Suggested change
// 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}}

Comment on lines +22 to +24
// 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.
Copy link
Contributor

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.

Suggested change
// 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.

Comment on lines +39 to +44
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}}
Copy link
Contributor

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.

Suggested change
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}}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
SYCL https://registry.khronos.org/SYCL
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants