Unverified Commit 94ca4909 authored by Mariya Podchishchaeva's avatar Mariya Podchishchaeva Committed by GitHub
Browse files

[clang][SYCL] Handle cdecl variadic functions for SYCL device (#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.
parent c24fc717
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -9752,7 +9752,8 @@ def warn_kern_is_inline : Warning<
  "ignored 'inline' attribute on kernel function %0">,
  InGroup<CudaCompat>;
def err_variadic_device_fn : Error<
  "CUDA device code does not support variadic functions">;
  "%enum_select<OffloadLang>{%CUDA{CUDA}|%SYCL{SYCL}}0 device code does not "
  "support variadic functions">;
def err_va_arg_in_device : Error<
"CUDA device code does not support va_arg">;
def err_alias_not_supported_on_nvptx : Error<"CUDA older than 10.0 does not support .alias">;
+6 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSPIRV.h"
#include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
@@ -4466,6 +4467,11 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
    }
  }
  if (FD && FD->isVariadic() && getLangOpts().SYCLIsDevice &&
      !isUnevaluatedContext())
    SYCL().DiagIfDeviceCode(Loc, diag::err_variadic_device_fn)
        << diag::OffloadLang::SYCL;
  if (FD)
    diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
}
+6 −8
Original line number Diff line number Diff line
@@ -5823,14 +5823,12 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
      A = HostTI->checkCallingConvention(CC);
    if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI)
      A = DeviceTI->checkCallingConvention(CC);
  } else if (LangOpts.SYCLIsDevice && TI.getTriple().isAMDGPU() &&
             CC == CC_X86VectorCall) {
    // Assuming SYCL Device AMDGPU CC_X86VectorCall functions are always to be
    // emitted on the host. The MSVC STL has CC-based specializations so we
    // cannot change the CC to be the default as that will cause a clash with
    // another specialization.
    A = TI.checkCallingConvention(CC);
    if (Aux && A != TargetInfo::CCCR_OK)
  } else if (LangOpts.SYCLIsDevice) {
    // In SYCL we may meet unsupported calling conventions in host code,
    // especially inside of included headers. Now we don't know if they will be
    // emitted, so we just defer any diagnostics. Check for the host triple if
    // we have one, since everything is still emitted for the host.
    if (Aux)
      A = Aux->checkCallingConvention(CC);
  } else {
    A = TI.checkCallingConvention(CC);
+35 −0
Original line number Diff line number Diff line
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -fsyntax-only -verify %s

// Check that there is no error/warning emitted for cdecl functions compiled for
// SYCL device. Make sure variadic calls from within device code are diagnosed.

__inline __cdecl int printf(char const* const _Format, ...) { return 0; }

// FIXME: that should be diagnosed.
[[clang::sycl_external]] int foo(int, ...) { return 0; }

__inline __cdecl int moo() { return 0; }

void bar() {
  printf("hello\n");
}

template<typename KN, typename...Args>
void sycl_kernel_launch(Args ...args) {}

template<typename KN, typename K>
[[clang::sycl_kernel_entry_point(KN)]]
__cdecl void sycl_entry_point(K k) {
  k(); // expected-note {{called by}}
}

int main() {
  //expected-error@+1 {{SYCL device code does not support variadic functions}}
  sycl_entry_point<class kn>([]() { printf("world\n");
     moo();
  //expected-error@+1 {{SYCL device code does not support variadic functions}}
     foo(1,2); });
  bar();
  return 0;
}
+45 −0
Original line number Diff line number Diff line
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -fsyntax-only -verify %s

template<typename KN, typename...Args>
void sycl_kernel_launch(Args ...args) {}

template<typename KN, typename K>
[[clang::sycl_kernel_entry_point(KN)]]
void sycl_entry_point(K k) {
  k(); // expected-note 2{{called by}}
}

void variadic(int, ...) {}
namespace NS {
void variadic(int, ...) {}
}

struct S {
  S(int, ...) {}
  void operator()(int, ...) {}
};

void foo() {
  auto x = [](int, ...) {};
  x(5, 10); //expected-error{{SYCL device code does not support variadic functions}}
}

void overloaded(int, int) {}
void overloaded(int, ...) {}

int main() {
  sycl_entry_point<class FK>([]() {
    variadic(5);        //expected-error{{SYCL device code does not support variadic functions}}
    variadic(5, 2);     //expected-error{{SYCL device code does not support variadic functions}}
    NS::variadic(5, 3); //expected-error{{SYCL device code does not support variadic functions}}
    S s(5, 4);          //expected-error{{SYCL device code does not support variadic functions}}
    S s2(5);            //expected-error{{SYCL device code does not support variadic functions}}
    s(5, 5);            //expected-error{{SYCL device code does not support variadic functions}}
    s2(5);              //expected-error{{SYCL device code does not support variadic functions}}
    foo();              //expected-note{{called by 'operator()'}}
    overloaded(5, 6);   //expected-no-error
    overloaded(5, s);   //expected-error{{SYCL device code does not support variadic functions}}
    overloaded(5);      //expected-error{{SYCL device code does not support variadic functions}}
  });
}