/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- Solaris.cpp - Solaris 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 | | |
9 | | #include "Solaris.h" |
10 | | #include "CommonArgs.h" |
11 | | #include "clang/Basic/LangStandard.h" |
12 | | #include "clang/Config/config.h" |
13 | | #include "clang/Driver/Compilation.h" |
14 | | #include "clang/Driver/Driver.h" |
15 | | #include "clang/Driver/DriverDiagnostic.h" |
16 | | #include "clang/Driver/Options.h" |
17 | | #include "llvm/Option/ArgList.h" |
18 | | #include "llvm/Support/FileSystem.h" |
19 | | #include "llvm/Support/Path.h" |
20 | | |
21 | | using namespace clang::driver; |
22 | | using namespace clang::driver::tools; |
23 | | using namespace clang::driver::toolchains; |
24 | | using namespace clang; |
25 | | using namespace llvm::opt; |
26 | | |
27 | | void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA, |
28 | | const InputInfo &Output, |
29 | | const InputInfoList &Inputs, |
30 | | const ArgList &Args, |
31 | 0 | const char *LinkingOutput) const { |
32 | 0 | claimNoWarnArgs(Args); |
33 | 0 | ArgStringList CmdArgs; |
34 | |
|
35 | 0 | Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); |
36 | |
|
37 | 0 | CmdArgs.push_back("-o"); |
38 | 0 | CmdArgs.push_back(Output.getFilename()); |
39 | |
|
40 | 0 | for (const auto &II : Inputs) |
41 | 0 | CmdArgs.push_back(II.getFilename()); |
42 | |
|
43 | 0 | const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); |
44 | 0 | C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), |
45 | 0 | Exec, CmdArgs, Inputs, Output)); |
46 | 0 | } |
47 | | |
48 | | void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
49 | | const InputInfo &Output, |
50 | | const InputInfoList &Inputs, |
51 | | const ArgList &Args, |
52 | 22 | const char *LinkingOutput) const { |
53 | 22 | ArgStringList CmdArgs; |
54 | | |
55 | | // Demangle C++ names in errors |
56 | 22 | CmdArgs.push_back("-C"); |
57 | | |
58 | 22 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) { |
59 | 21 | CmdArgs.push_back("-e"); |
60 | 21 | CmdArgs.push_back("_start"); |
61 | 21 | } |
62 | | |
63 | 22 | if (Args.hasArg(options::OPT_static)) { |
64 | 0 | CmdArgs.push_back("-Bstatic"); |
65 | 0 | CmdArgs.push_back("-dn"); |
66 | 22 | } else { |
67 | 22 | CmdArgs.push_back("-Bdynamic"); |
68 | 22 | if (Args.hasArg(options::OPT_shared)) { |
69 | 1 | CmdArgs.push_back("-shared"); |
70 | 1 | } |
71 | | |
72 | | // libpthread has been folded into libc since Solaris 10, no need to do |
73 | | // anything for pthreads. Claim argument to avoid warning. |
74 | 22 | Args.ClaimAllArgs(options::OPT_pthread); |
75 | 22 | Args.ClaimAllArgs(options::OPT_pthreads); |
76 | 22 | } |
77 | | |
78 | 22 | if (Output.isFilename()) { |
79 | 22 | CmdArgs.push_back("-o"); |
80 | 22 | CmdArgs.push_back(Output.getFilename()); |
81 | 0 | } else { |
82 | 0 | assert(Output.isNothing() && "Invalid output."); |
83 | 0 | } |
84 | | |
85 | 22 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { |
86 | 22 | if (!Args.hasArg(options::OPT_shared)) |
87 | 21 | CmdArgs.push_back( |
88 | 21 | Args.MakeArgString(getToolChain().GetFilePath("crt1.o"))); |
89 | | |
90 | 22 | CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o"))); |
91 | | |
92 | 22 | const Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi); |
93 | 22 | bool HaveAnsi = false; |
94 | 22 | const LangStandard *LangStd = nullptr; |
95 | 22 | if (Std) { |
96 | 13 | HaveAnsi = Std->getOption().matches(options::OPT_ansi); |
97 | 13 | if (!HaveAnsi) |
98 | 10 | LangStd = LangStandard::getLangStandardForName(Std->getValue()); |
99 | 13 | } |
100 | | |
101 | 22 | const char *values_X = "values-Xa.o"; |
102 | | // Use values-Xc.o for -ansi, -std=c*, -std=iso9899:199409. |
103 | 22 | if (HaveAnsi || (19 LangStd19 && !LangStd->isGNUMode()10 )) |
104 | 9 | values_X = "values-Xc.o"; |
105 | 22 | CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(values_X))); |
106 | | |
107 | 22 | const char *values_xpg = "values-xpg6.o"; |
108 | | // Use values-xpg4.o for -std=c90, -std=gnu90, -std=iso9899:199409. |
109 | 22 | if (LangStd && LangStd->getLanguage() == Language::C10 && !LangStd->isC99()7 ) |
110 | 5 | values_xpg = "values-xpg4.o"; |
111 | 22 | CmdArgs.push_back( |
112 | 22 | Args.MakeArgString(getToolChain().GetFilePath(values_xpg))); |
113 | 22 | CmdArgs.push_back( |
114 | 22 | Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); |
115 | 22 | } |
116 | | |
117 | 22 | getToolChain().AddFilePathLibArgs(Args, CmdArgs); |
118 | | |
119 | 22 | Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, |
120 | 22 | options::OPT_e, options::OPT_r}); |
121 | | |
122 | 22 | bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs); |
123 | 22 | AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); |
124 | | |
125 | 22 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { |
126 | 22 | if (getToolChain().ShouldLinkCXXStdlib(Args)) |
127 | 0 | getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); |
128 | 22 | if (Args.hasArg(options::OPT_fstack_protector) || |
129 | 22 | Args.hasArg(options::OPT_fstack_protector_strong) || |
130 | 22 | Args.hasArg(options::OPT_fstack_protector_all)) { |
131 | | // Explicitly link ssp libraries, not folded into Solaris libc. |
132 | 0 | CmdArgs.push_back("-lssp_nonshared"); |
133 | 0 | CmdArgs.push_back("-lssp"); |
134 | 0 | } |
135 | 22 | CmdArgs.push_back("-lgcc_s"); |
136 | 22 | CmdArgs.push_back("-lc"); |
137 | 22 | if (!Args.hasArg(options::OPT_shared)) { |
138 | 21 | CmdArgs.push_back("-lgcc"); |
139 | 21 | CmdArgs.push_back("-lm"); |
140 | 21 | } |
141 | 22 | if (NeedsSanitizerDeps) |
142 | 2 | linkSanitizerRuntimeDeps(getToolChain(), CmdArgs); |
143 | 22 | } |
144 | | |
145 | 22 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { |
146 | 22 | CmdArgs.push_back( |
147 | 22 | Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); |
148 | 22 | } |
149 | 22 | CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); |
150 | | |
151 | 22 | getToolChain().addProfileRTLibs(Args, CmdArgs); |
152 | | |
153 | 22 | const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); |
154 | 22 | C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), |
155 | 22 | Exec, CmdArgs, Inputs, Output)); |
156 | 22 | } |
157 | | |
158 | 36 | static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) { |
159 | 36 | switch (Triple.getArch()) { |
160 | 11 | case llvm::Triple::x86: |
161 | 31 | case llvm::Triple::sparc: |
162 | 31 | break; |
163 | 3 | case llvm::Triple::x86_64: |
164 | 3 | return "/amd64"; |
165 | 2 | case llvm::Triple::sparcv9: |
166 | 2 | return "/sparcv9"; |
167 | 0 | default: |
168 | 0 | llvm_unreachable("Unsupported architecture"); |
169 | 31 | } |
170 | 31 | return ""; |
171 | 31 | } |
172 | | |
173 | | /// Solaris - Solaris tool chain which can call as(1) and ld(1) directly. |
174 | | |
175 | | Solaris::Solaris(const Driver &D, const llvm::Triple &Triple, |
176 | | const ArgList &Args) |
177 | 36 | : Generic_ELF(D, Triple, Args) { |
178 | | |
179 | 36 | GCCInstallation.init(Triple, Args); |
180 | | |
181 | 36 | StringRef LibSuffix = getSolarisLibSuffix(Triple); |
182 | 36 | path_list &Paths = getFilePaths(); |
183 | 36 | if (GCCInstallation.isValid()) { |
184 | | // On Solaris gcc uses both an architecture-specific path with triple in it |
185 | | // as well as a more generic lib path (+arch suffix). |
186 | 23 | addPathIfExists(D, |
187 | 23 | GCCInstallation.getInstallPath() + |
188 | 23 | GCCInstallation.getMultilib().gccSuffix(), |
189 | 23 | Paths); |
190 | 23 | addPathIfExists(D, GCCInstallation.getParentLibPath() + LibSuffix, Paths); |
191 | 23 | } |
192 | | |
193 | | // If we are currently running Clang inside of the requested system root, |
194 | | // add its parent library path to those searched. |
195 | 36 | if (StringRef(D.Dir).startswith(D.SysRoot)) |
196 | 13 | addPathIfExists(D, D.Dir + "/../lib", Paths); |
197 | | |
198 | 36 | addPathIfExists(D, D.SysRoot + "/usr/lib" + LibSuffix, Paths); |
199 | 36 | } |
200 | | |
201 | 36 | SanitizerMask Solaris::getSupportedSanitizers() const { |
202 | 36 | const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; |
203 | 36 | const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; |
204 | 36 | SanitizerMask Res = ToolChain::getSupportedSanitizers(); |
205 | | // FIXME: Omit X86_64 until 64-bit support is figured out. |
206 | 36 | if (IsX86) { |
207 | 11 | Res |= SanitizerKind::Address; |
208 | 11 | Res |= SanitizerKind::PointerCompare; |
209 | 11 | Res |= SanitizerKind::PointerSubtract; |
210 | 11 | } |
211 | 36 | if (IsX86 || IsX86_6425 ) |
212 | 14 | Res |= SanitizerKind::Function; |
213 | 36 | Res |= SanitizerKind::Vptr; |
214 | 36 | return Res; |
215 | 36 | } |
216 | | |
217 | 0 | Tool *Solaris::buildAssembler() const { |
218 | 0 | return new tools::solaris::Assembler(*this); |
219 | 0 | } |
220 | | |
221 | 22 | Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); } |
222 | | |
223 | | void Solaris::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
224 | 36 | ArgStringList &CC1Args) const { |
225 | 36 | const Driver &D = getDriver(); |
226 | | |
227 | 36 | if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) |
228 | 0 | return; |
229 | | |
230 | 36 | if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) |
231 | 36 | addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/local/include"); |
232 | | |
233 | 36 | if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
234 | 36 | SmallString<128> P(D.ResourceDir); |
235 | 36 | llvm::sys::path::append(P, "include"); |
236 | 36 | addSystemInclude(DriverArgs, CC1Args, P); |
237 | 36 | } |
238 | | |
239 | 36 | if (DriverArgs.hasArg(options::OPT_nostdlibinc)) |
240 | 0 | return; |
241 | | |
242 | | // Check for configure-time C include directories. |
243 | 36 | StringRef CIncludeDirs(C_INCLUDE_DIRS); |
244 | 36 | if (CIncludeDirs != "") { |
245 | 0 | SmallVector<StringRef, 5> dirs; |
246 | 0 | CIncludeDirs.split(dirs, ":"); |
247 | 0 | for (StringRef dir : dirs) { |
248 | 0 | StringRef Prefix = |
249 | 0 | llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot); |
250 | 0 | addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); |
251 | 0 | } |
252 | 0 | return; |
253 | 0 | } |
254 | | |
255 | | // Add include directories specific to the selected multilib set and multilib. |
256 | 36 | if (GCCInstallation.isValid()) { |
257 | 23 | const MultilibSet::IncludeDirsFunc &Callback = |
258 | 23 | Multilibs.includeDirsCallback(); |
259 | 23 | if (Callback) { |
260 | 0 | for (const auto &Path : Callback(GCCInstallation.getMultilib())) |
261 | 0 | addExternCSystemIncludeIfExists( |
262 | 0 | DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path); |
263 | 0 | } |
264 | 23 | } |
265 | | |
266 | 36 | addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include"); |
267 | 36 | } |
268 | | |
269 | | void Solaris::addLibStdCxxIncludePaths( |
270 | | const llvm::opt::ArgList &DriverArgs, |
271 | 10 | llvm::opt::ArgStringList &CC1Args) const { |
272 | | // We need a detected GCC installation on Solaris (similar to Linux) |
273 | | // to provide libstdc++'s headers. |
274 | 10 | if (!GCCInstallation.isValid()) |
275 | 1 | return; |
276 | | |
277 | | // By default, look for the C++ headers in an include directory adjacent to |
278 | | // the lib directory of the GCC installation. |
279 | | // On Solaris this usually looks like /usr/gcc/X.Y/include/c++/X.Y.Z |
280 | 9 | StringRef LibDir = GCCInstallation.getParentLibPath(); |
281 | 9 | StringRef TripleStr = GCCInstallation.getTriple().str(); |
282 | 9 | const Multilib &Multilib = GCCInstallation.getMultilib(); |
283 | 9 | const GCCVersion &Version = GCCInstallation.getVersion(); |
284 | | |
285 | | // The primary search for libstdc++ supports multiarch variants. |
286 | 9 | addLibStdCXXIncludePaths(LibDir.str() + "/../include", "/c++/" + Version.Text, |
287 | 9 | TripleStr, |
288 | 9 | /*GCCMultiarchTriple*/ "", |
289 | 9 | /*TargetMultiarchTriple*/ "", |
290 | 9 | Multilib.includeSuffix(), DriverArgs, CC1Args); |
291 | 9 | } |