diff --git a/sycl/include/sycl/stl_wrappers/corecrt.h b/sycl/include/sycl/stl_wrappers/corecrt.h new file mode 100644 index 0000000000000..f4d1ceccba4b7 --- /dev/null +++ b/sycl/include/sycl/stl_wrappers/corecrt.h @@ -0,0 +1,51 @@ +//==---------------- Wrapper around corecrt.h ------------------------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// When std::array is used in device code, MSVC's STL uses a _invalid_parameter +// function. This causes issue when _invalid_parameter is invoked from device +// code: + +// 1. `_invalid_parameter` is provided via ucrtbased.dll at runtime: DLLs are +// not loaded for device code, thus causing undefined symbol errors. + +// 2. MSVC's STL never defined the function as SYCL_EXTERNAL, errors are thrown +// when device code tries to invoke `_invalid_parameter`. + +// As a workaround, this wrapper wraps around corecrt.h and defines a custom +// _invalid_parameter for device code compilation. + +// This new SYCL_EXTERNAL definition of _invalid_parameter has to be declared +// before corecrt.h is included: Thus, we have this STL wrapper instead of +// declaring _invalid_parameter function in SYCL headers. + +#pragma once + +#if defined(__SYCL_DEVICE_ONLY__) && defined(_DEBUG) + +#include // For uintptr_t +#include // For __DPCPP_SYCL_EXTERNAL + +extern "C" __DPCPP_SYCL_EXTERNAL void __cdecl _invalid_parameter( + wchar_t const *, wchar_t const *, wchar_t const *, unsigned int, + uintptr_t) { + // Do nothing when called in device code +} + +#endif + +#if defined(__has_include_next) +// GCC/clang support go through this path. +#include_next +#else +// MSVC doesn't support "#include_next", so we have to be creative. +// Our header is located in "stl_wrappers/corecrt.h" so it won't be picked by +// the aforementioned include. MSVC's installation, on the other hand, has the +// layout where the following would result in the we want. This is +// obviously hacky, but the best we can do... +#include <../ucrt/corecrt.h> +#endif diff --git a/sycl/test-e2e/Basic/std_array.cpp b/sycl/test-e2e/Basic/std_array.cpp index b2a744012042f..12a2fb05160e2 100644 --- a/sycl/test-e2e/Basic/std_array.cpp +++ b/sycl/test-e2e/Basic/std_array.cpp @@ -1,10 +1,9 @@ -// REQUIRES: windows +// Check that std::array is supported on device in debug mode on Windows. -// RUN: not clang-cl -fsycl -o %t.exe %s /Od /MDd /Zi /EHsc 2>&1 | FileCheck %s +// REQUIRES: windows -// FIXME: This code should have compiled cleanly. -// CHECK: error: SYCL kernel cannot call an undefined function without SYCL_EXTERNAL attribute -// CHECK: note: '_invalid_parameter' declared here +// RUN: %clangxx --driver-mode=cl -fsycl -o %t.exe %s /Od /MDd /Zi /EHsc +// RUN: %{run} %t.exe #include