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