diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -119,6 +119,12 @@ MSVC2017_7 = 1914, }; + enum class SYCLVersionList { + SYCL_2015, + SYCL_1_2_1 = SYCL_2015, + undefined + }; + /// Clang versions with different platform ABI conformance. enum class ClangABI { /// Attempt to be ABI-compatible with code generated by Clang 3.8.x diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -230,6 +230,7 @@ LANGOPT(GPUMaxThreadsPerBlock, 32, 256, "default max threads per block for kernel launch bounds for HIP") LANGOPT(SYCLIsDevice , 1, 0, "Generate code for SYCL device") +ENUM_LANGOPT(SYCLVersion, SYCLVersionList, 4, SYCLVersionList::undefined, "Version of the SYCL standard used") LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -124,6 +124,9 @@ def opencl_Group : OptionGroup<"">, Group, DocName<"OpenCL flags">; +def sycl_Group : OptionGroup<"">, Group, + DocName<"SYCL flags">; + def m_Group : OptionGroup<"">, Group, DocName<"Target-dependent compilation options">; @@ -3405,6 +3408,11 @@ defm underscoring : BooleanFFlag<"underscoring">, Group; defm whole_file : BooleanFFlag<"whole-file">, Group; +// C++ SYCL options +def fsycl : Flag<["-"], "fsycl">, Group, + HelpText<"Enable SYCL kernels compilation for device">; +def sycl_std_EQ : Joined<["-"], "sycl-std=">, Group, Flags<[CC1Option]>, + HelpText<"SYCL language standard to compile for.">, Values<"1.2.1">; include "CC1Options.td" diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4010,6 +4010,18 @@ CmdArgs.push_back(Args.MakeArgString(NormalizedTriple)); } + bool IsSYCL = Args.hasArg(options::OPT_fsycl); + if (IsSYCL) { + CmdArgs.push_back("-fsycl-is-device"); + } + + if (Arg *A = Args.getLastArg(options::OPT_sycl_std_EQ)) { + A->render(Args, CmdArgs); + } else if (IsSYCL) { + // Ensure the default version in SYCL mode is 1.2.1 + CmdArgs.push_back("-sycl-std=1.2.1"); + } + if (IsOpenMPDevice) { // We have to pass the triple of the host if compiling for an OpenMP device. std::string NormalizedTriple = @@ -5259,6 +5271,9 @@ options::OPT_fno_hip_new_launch_api, false)) CmdArgs.push_back("-fhip-new-launch-api"); + // Forward -sycl-std option to -cc1 + Args.AddLastArg(CmdArgs, options::OPT_sycl_std_EQ); + if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) { CmdArgs.push_back( Args.MakeArgString(Twine("-fcf-protection=") + A->getValue())); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2545,6 +2545,25 @@ LangStd = OpenCLLangStd; } + // -sycl-std applies to any SYCL source, not only those containing kernels, + // but also those using the SYCL API + if (const Arg *A = Args.getLastArg(OPT_sycl_std_EQ)) { + Opts.setSYCLVersion( + llvm::StringSwitch(A->getValue()) + .Cases("2015", "1.2.1", "121", "sycl-1.2.1", + LangOptions::SYCLVersionList::SYCL_2015) + .Default(LangOptions::SYCLVersionList::undefined)); + + if (Opts.getSYCLVersion() == LangOptions::SYCLVersionList::undefined) { + // User has passed an invalid value to the flag, this is an error + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } else if (Args.hasArg(options::OPT_fsycl_is_device) || + Args.hasArg(options::OPT_fsycl)) { + Opts.setSYCLVersion(LangOptions::SYCLVersionList::SYCL_2015); + } + Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header); Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -450,6 +450,18 @@ if (LangOpts.FastRelaxedMath) Builder.defineMacro("__FAST_RELAXED_MATH__"); } + + // SYCL Version is set to a value when building SYCL applications + switch (LangOpts.getSYCLVersion()) { + case LangOptions::SYCLVersionList::SYCL_2015: + Builder.defineMacro("CL_SYCL_LANGUAGE_VERSION", "121"); + break; + case LangOptions::SYCLVersionList::undefined: + default: + // This is not a SYCL source, nothing to add + break; + } + // Not "standard" per se, but available even with the -undef flag. if (LangOpts.AsmPreprocessor) Builder.defineMacro("__ASSEMBLER__"); diff --git a/clang/test/Driver/sycl.c b/clang/test/Driver/sycl.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/sycl.c @@ -0,0 +1,5 @@ +// RUN: %clang -### -fsycl -c %s 2>&1 | FileCheck %s --check-prefix=DEFAULT +// RUN: %clang -### -fsycl %s 2>&1 | FileCheck %s --check-prefix=DEFAULT +// RUN: %clangxx -### -fsycl %s 2>&1 | FileCheck %s --check-prefix=DEFAULT + +// DEFAULT: "-fsycl-is-device" diff --git a/clang/test/Preprocessor/sycl-macro.cpp b/clang/test/Preprocessor/sycl-macro.cpp --- a/clang/test/Preprocessor/sycl-macro.cpp +++ b/clang/test/Preprocessor/sycl-macro.cpp @@ -1,5 +1,9 @@ // RUN: %clang_cc1 %s -E -dM | FileCheck %s -// RUN: %clang_cc1 %s -fsycl-is-device -E -dM | FileCheck --check-prefix=CHECK-SYCL %s +// RUN: %clang_cc1 %s -sycl-std=2015 -E -dM | FileCheck --check-prefix=CHECK-SYCL-STD %s +// RUN: %clang_cc1 %s -sycl-std=1.2.1 -E -dM | FileCheck --check-prefix=CHECK-SYCL-STD %s +// RUN: %clang_cc1 %s -fsycl-is-device -E -dM | FileCheck --check-prefixes=CHECK-SYCL,CHECK-SYCL-STD %s // CHECK-NOT:#define __SYCL_DEVICE_ONLY__ 1 +// CHECK-NOT:#define CL_SYCL_LANGUAGE_VERSION 121 +// CHECK-SYCL-STD:#define CL_SYCL_LANGUAGE_VERSION 121 // CHECK-SYCL:#define __SYCL_DEVICE_ONLY__ 1