1//===--- SYCL.cpp - SYCL Tool and ToolChain Implementations -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8#include "SYCL.h"
9#include "clang/Driver/CommonArgs.h"
10#include "llvm/Support/VirtualFileSystem.h"
11
12using namespace clang::driver;
13using namespace clang::driver::toolchains;
14using namespace clang::driver::tools;
15using namespace clang;
16using namespace llvm::opt;
17
18SYCLInstallationDetector::SYCLInstallationDetector(
19 const Driver &D, const llvm::Triple &HostTriple,
20 const llvm::opt::ArgList &Args)
21 : D(D) {
22 // Detect the presence of the SYCL runtime library (libLLVMSYCL.so) in the
23 // filesystem. This is used to determine whether a usable SYCL installation
24 // is available for the current driver invocation.
25 StringRef SysRoot = D.SysRoot;
26 SmallString<128> DriverDir(D.Dir);
27 SmallString<128> LibPath(DriverDir);
28 llvm::sys::path::append(path&: LibPath, a: "..", b: "lib", c: HostTriple.str(),
29 d: "libLLVMSYCL.so");
30 if (DriverDir.starts_with(Prefix: SysRoot) &&
31 (Args.hasArg(Ids: options::OPT_fsycl) || D.getVFS().exists(Path: LibPath))) {
32 llvm::sys::path::append(path&: DriverDir, a: "..", b: "lib", c: HostTriple.str());
33 SYCLRTLibPath = DriverDir;
34 }
35}
36
37void SYCLInstallationDetector::addSYCLIncludeArgs(
38 const ArgList &DriverArgs, ArgStringList &CC1Args) const {
39 if (DriverArgs.hasArg(Ids: options::OPT_nobuiltininc))
40 return;
41
42 // Add the SYCL header search locations.
43 // These are included for both SYCL host and device compilations.
44 SmallString<128> IncludePath(D.Dir);
45 llvm::sys::path::append(path&: IncludePath, a: "..", b: "include");
46 CC1Args.push_back(Elt: "-internal-isystem");
47 CC1Args.push_back(Elt: DriverArgs.MakeArgString(Str: IncludePath));
48}
49
50// Unsupported options for SYCL device compilation.
51static ArrayRef<options::ID> getUnsupportedOpts() {
52 static constexpr options::ID UnsupportedOpts[] = {
53 options::OPT_fsanitize_EQ, // -fsanitize
54 options::OPT_fcf_protection_EQ, // -fcf-protection
55 options::OPT_fprofile_generate,
56 options::OPT_fprofile_generate_EQ,
57 options::OPT_fno_profile_generate, // -f[no-]profile-generate
58 options::OPT_ftest_coverage,
59 options::OPT_fno_test_coverage, // -f[no-]test-coverage
60 options::OPT_fcoverage_mapping,
61 options::OPT_fno_coverage_mapping, // -f[no-]coverage-mapping
62 options::OPT_coverage, // --coverage
63 options::OPT_fprofile_instr_generate,
64 options::OPT_fprofile_instr_generate_EQ,
65 options::OPT_fno_profile_instr_generate, // -f[no-]profile-instr-generate
66 options::OPT_fprofile_arcs,
67 options::OPT_fno_profile_arcs, // -f[no-]profile-arcs
68 options::OPT_fcreate_profile, // -fcreate-profile
69 options::OPT_fprofile_instr_use,
70 options::OPT_fprofile_instr_use_EQ, // -fprofile-instr-use
71 options::OPT_fcs_profile_generate, // -fcs-profile-generate
72 options::OPT_fcs_profile_generate_EQ,
73 };
74 return UnsupportedOpts;
75}
76
77SYCLToolChain::SYCLToolChain(const Driver &D, const llvm::Triple &Triple,
78 const ToolChain &HostTC, const ArgList &Args)
79 : ToolChain(D, Triple, Args), HostTC(HostTC),
80 SYCLInstallation(D, Triple, Args) {
81 // Lookup binaries into the driver directory, this is used to discover any
82 // dependent SYCL offload compilation tools.
83 getProgramPaths().push_back(Elt: getDriver().Dir);
84
85 // Diagnose unsupported options only once.
86 for (OptSpecifier Opt : getUnsupportedOpts()) {
87 if (const Arg *A = Args.getLastArg(Ids: Opt)) {
88 D.Diag(DiagID: clang::diag::warn_drv_unsupported_option_for_target)
89 << A->getAsString(Args) << getTriple().str();
90 }
91 }
92}
93
94void SYCLToolChain::addClangTargetOptions(
95 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
96 Action::OffloadKind DeviceOffloadingKind) const {
97 HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind: DeviceOffloadingKind);
98}
99
100llvm::opt::DerivedArgList *
101SYCLToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
102 StringRef BoundArch,
103 Action::OffloadKind DeviceOffloadKind) const {
104 DerivedArgList *DAL =
105 HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
106
107 bool IsNewDAL = false;
108 if (!DAL) {
109 DAL = new DerivedArgList(Args.getBaseArgs());
110 IsNewDAL = true;
111 }
112
113 for (Arg *A : Args) {
114 // Filter out any options we do not want to pass along to the device
115 // compilation.
116 auto Opt(A->getOption());
117 bool Unsupported = false;
118 for (OptSpecifier UnsupportedOpt : getUnsupportedOpts()) {
119 if (Opt.matches(ID: UnsupportedOpt)) {
120 if (Opt.getID() == options::OPT_fsanitize_EQ &&
121 A->getValues().size() == 1) {
122 std::string SanitizeVal = A->getValue();
123 if (SanitizeVal == "address") {
124 if (IsNewDAL)
125 DAL->append(A);
126 continue;
127 }
128 }
129 if (!IsNewDAL)
130 DAL->eraseArg(Id: Opt.getID());
131 Unsupported = true;
132 }
133 }
134 if (Unsupported)
135 continue;
136 if (IsNewDAL)
137 DAL->append(A);
138 }
139
140 const OptTable &Opts = getDriver().getOpts();
141 if (!BoundArch.empty()) {
142 DAL->eraseArg(Id: options::OPT_march_EQ);
143 DAL->AddJoinedArg(BaseArg: nullptr, Opt: Opts.getOption(Opt: options::OPT_march_EQ),
144 Value: BoundArch);
145 }
146 return DAL;
147}
148
149void SYCLToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
150 HostTC.addClangWarningOptions(CC1Args);
151}
152
153ToolChain::CXXStdlibType
154SYCLToolChain::GetCXXStdlibType(const ArgList &Args) const {
155 return HostTC.GetCXXStdlibType(Args);
156}
157
158void SYCLToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs,
159 ArgStringList &CC1Args) const {
160 SYCLInstallation.addSYCLIncludeArgs(DriverArgs, CC1Args);
161}
162
163void SYCLToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
164 ArgStringList &CC1Args) const {
165 HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
166}
167
168void SYCLToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
169 ArgStringList &CC1Args) const {
170 HostTC.AddClangCXXStdlibIncludeArgs(DriverArgs: Args, CC1Args);
171}
172