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