Skip to content

Commit 257b727

Browse files
authored
[clang][Sema][SYCL] Fix MSVC STL usage on AMDGPU (#135979)
The MSVC STL includes specializations of `_Is_memfunptr` for every function pointer type, including every calling convention. The problem is the AMDGPU target doesn't support the x86 `vectorcall` calling convention so clang sets it to the default CC. This ends up clashing with the already-existing overload for the default CC, so we get a duplicate definition error when including `type_traits` (which we heavily use in the SYCL STL) and compiling for AMDGPU on Windows. This doesn't happen for pure AMDGPU non-SYCL because it doesn't include the C++ STL, and it doesn't happen for CUDA/HIP because a similar workaround was done [here](fa49c3a). I am not an expert in Sema, so I did a kinda of hardcoded fix, please let me know if there is a better way to fix this. As far as I can tell we can't do exactly the same fix that was done for CUDA because we can't differentiate between device and host code so easily. --------- Signed-off-by: Sarnie, Nick <[email protected]>
1 parent c016a65 commit 257b727

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5495,12 +5495,12 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
54955495

54965496
TargetInfo::CallingConvCheckResult A = TargetInfo::CCCR_OK;
54975497
const TargetInfo &TI = Context.getTargetInfo();
5498+
auto *Aux = Context.getAuxTargetInfo();
54985499
// CUDA functions may have host and/or device attributes which indicate
54995500
// their targeted execution environment, therefore the calling convention
55005501
// of functions in CUDA should be checked against the target deduced based
55015502
// on their host/device attributes.
55025503
if (LangOpts.CUDA) {
5503-
auto *Aux = Context.getAuxTargetInfo();
55045504
assert(FD || CFT != CUDAFunctionTarget::InvalidTarget);
55055505
auto CudaTarget = FD ? CUDA().IdentifyTarget(FD) : CFT;
55065506
bool CheckHost = false, CheckDevice = false;
@@ -5525,6 +5525,15 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
55255525
A = HostTI->checkCallingConvention(CC);
55265526
if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI)
55275527
A = DeviceTI->checkCallingConvention(CC);
5528+
} else if (LangOpts.SYCLIsDevice && TI.getTriple().isAMDGPU() &&
5529+
CC == CC_X86VectorCall) {
5530+
// Assuming SYCL Device AMDGPU CC_X86VectorCall functions are always to be
5531+
// emitted on the host. The MSVC STL has CC-based specializations so we
5532+
// cannot change the CC to be the default as that will cause a clash with
5533+
// another specialization.
5534+
A = TI.checkCallingConvention(CC);
5535+
if (Aux && A != TargetInfo::CCCR_OK)
5536+
A = Aux->checkCallingConvention(CC);
55285537
} else {
55295538
A = TI.checkCallingConvention(CC);
55305539
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
template <typename F> struct A{};
3+
4+
template <typename Ret, typename C, typename... Args> struct A<Ret ( C::*)(Args...) noexcept> { static constexpr int value = 0; };
5+
template <typename Ret, typename C, typename... Args> struct A<Ret (__vectorcall C::*)(Args...) noexcept> { static constexpr int value = 1; };
6+
7+
template <typename F> constexpr int A_v = A<F>::value;
8+
9+
struct B
10+
{
11+
void f() noexcept {}
12+
void __vectorcall g() noexcept {}
13+
};
14+
15+
int main()
16+
{
17+
return A_v<decltype(&B::f)> + A_v<decltype(&B::g)>;
18+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple amdgcn-amd-hsa -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
2+
3+
// expected-no-diagnostics
4+
5+
#include <vectorcall.hpp>

0 commit comments

Comments
 (0)