clang  16.0.0git
Solaris.cpp
Go to the documentation of this file.
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"
12 #include "clang/Config/config.h"
14 #include "clang/Driver/Driver.h"
16 #include "clang/Driver/Options.h"
18 #include "clang/Driver/ToolChain.h"
19 #include "llvm/Option/ArgList.h"
20 #include "llvm/Support/FileSystem.h"
21 #include "llvm/Support/Path.h"
22 
23 using namespace clang::driver;
24 using namespace clang::driver::tools;
25 using namespace clang::driver::toolchains;
26 using namespace clang;
27 using namespace llvm::opt;
28 
30  const InputInfo &Output,
31  const InputInfoList &Inputs,
32  const ArgList &Args,
33  const char *LinkingOutput) const {
34  claimNoWarnArgs(Args);
35  ArgStringList CmdArgs;
36 
37  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
38 
39  CmdArgs.push_back("-o");
40  CmdArgs.push_back(Output.getFilename());
41 
42  for (const auto &II : Inputs)
43  CmdArgs.push_back(II.getFilename());
44 
45  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
46  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
47  Exec, CmdArgs, Inputs, Output));
48 }
49 
51  const InputInfo &Output,
52  const InputInfoList &Inputs,
53  const ArgList &Args,
54  const char *LinkingOutput) const {
55  ArgStringList CmdArgs;
56 
57  // Demangle C++ names in errors
58  CmdArgs.push_back("-C");
59 
60  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
61  CmdArgs.push_back("-e");
62  CmdArgs.push_back("_start");
63  }
64 
65  if (Args.hasArg(options::OPT_static)) {
66  CmdArgs.push_back("-Bstatic");
67  CmdArgs.push_back("-dn");
68  } else {
69  CmdArgs.push_back("-Bdynamic");
70  if (Args.hasArg(options::OPT_shared)) {
71  CmdArgs.push_back("-shared");
72  }
73 
74  // libpthread has been folded into libc since Solaris 10, no need to do
75  // anything for pthreads. Claim argument to avoid warning.
76  Args.ClaimAllArgs(options::OPT_pthread);
77  Args.ClaimAllArgs(options::OPT_pthreads);
78  }
79 
80  if (Output.isFilename()) {
81  CmdArgs.push_back("-o");
82  CmdArgs.push_back(Output.getFilename());
83  } else {
84  assert(Output.isNothing() && "Invalid output.");
85  }
86 
87  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
88  options::OPT_r)) {
89  if (!Args.hasArg(options::OPT_shared))
90  CmdArgs.push_back(
91  Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
92 
93  CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
94 
95  const Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi);
96  bool HaveAnsi = false;
97  const LangStandard *LangStd = nullptr;
98  if (Std) {
99  HaveAnsi = Std->getOption().matches(options::OPT_ansi);
100  if (!HaveAnsi)
101  LangStd = LangStandard::getLangStandardForName(Std->getValue());
102  }
103 
104  const char *values_X = "values-Xa.o";
105  // Use values-Xc.o for -ansi, -std=c*, -std=iso9899:199409.
106  if (HaveAnsi || (LangStd && !LangStd->isGNUMode()))
107  values_X = "values-Xc.o";
108  CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(values_X)));
109 
110  const char *values_xpg = "values-xpg6.o";
111  // Use values-xpg4.o for -std=c90, -std=gnu90, -std=iso9899:199409.
112  if (LangStd && LangStd->getLanguage() == Language::C && !LangStd->isC99())
113  values_xpg = "values-xpg4.o";
114  CmdArgs.push_back(
115  Args.MakeArgString(getToolChain().GetFilePath(values_xpg)));
116  CmdArgs.push_back(
117  Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
118  }
119 
120  getToolChain().AddFilePathLibArgs(Args, CmdArgs);
121 
122  Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
123  options::OPT_e, options::OPT_r});
124 
125  bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
126  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
127 
128  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
129  options::OPT_r)) {
130  if (getToolChain().ShouldLinkCXXStdlib(Args))
131  getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
132  if (Args.hasArg(options::OPT_fstack_protector) ||
133  Args.hasArg(options::OPT_fstack_protector_strong) ||
134  Args.hasArg(options::OPT_fstack_protector_all)) {
135  // Explicitly link ssp libraries, not folded into Solaris libc.
136  CmdArgs.push_back("-lssp_nonshared");
137  CmdArgs.push_back("-lssp");
138  }
139  // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
140  // forcibly link with libatomic as a workaround.
141  if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {
142  CmdArgs.push_back(getAsNeededOption(getToolChain(), true));
143  CmdArgs.push_back("-latomic");
144  CmdArgs.push_back(getAsNeededOption(getToolChain(), false));
145  }
146  CmdArgs.push_back("-lgcc_s");
147  CmdArgs.push_back("-lc");
148  if (!Args.hasArg(options::OPT_shared)) {
149  CmdArgs.push_back("-lgcc");
150  CmdArgs.push_back("-lm");
151  }
152  if (NeedsSanitizerDeps) {
153  linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
154 
155  // Work around Solaris/amd64 ld bug when calling __tls_get_addr directly.
156  // However, ld -z relax=transtls is available since Solaris 11.2, but not
157  // in Illumos.
158  const SanitizerArgs &SA = getToolChain().getSanitizerArgs(Args);
159  if (getToolChain().getTriple().getArch() == llvm::Triple::x86_64 &&
160  (SA.needsAsanRt() || SA.needsStatsRt() ||
161  (SA.needsUbsanRt() && !SA.requiresMinimalRuntime())))
162  CmdArgs.push_back("-zrelax=transtls");
163  }
164  }
165 
166  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
167  options::OPT_r)) {
168  CmdArgs.push_back(
169  Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
170  CmdArgs.push_back(
171  Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
172  }
173 
174  getToolChain().addProfileRTLibs(Args, CmdArgs);
175 
176  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
177  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
178  Exec, CmdArgs, Inputs, Output));
179 }
180 
181 static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) {
182  switch (Triple.getArch()) {
183  case llvm::Triple::x86:
184  case llvm::Triple::sparc:
185  break;
186  case llvm::Triple::x86_64:
187  return "/amd64";
188  case llvm::Triple::sparcv9:
189  return "/sparcv9";
190  default:
191  llvm_unreachable("Unsupported architecture");
192  }
193  return "";
194 }
195 
196 /// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
197 
198 Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
199  const ArgList &Args)
200  : Generic_ELF(D, Triple, Args) {
201 
202  GCCInstallation.init(Triple, Args);
203 
204  StringRef LibSuffix = getSolarisLibSuffix(Triple);
205  path_list &Paths = getFilePaths();
206  if (GCCInstallation.isValid()) {
207  // On Solaris gcc uses both an architecture-specific path with triple in it
208  // as well as a more generic lib path (+arch suffix).
209  addPathIfExists(D,
212  Paths);
213  addPathIfExists(D, GCCInstallation.getParentLibPath() + LibSuffix, Paths);
214  }
215 
216  // If we are currently running Clang inside of the requested system root,
217  // add its parent library path to those searched.
218  if (StringRef(D.Dir).startswith(D.SysRoot))
219  addPathIfExists(D, D.Dir + "/../lib", Paths);
220 
221  addPathIfExists(D, D.SysRoot + "/usr/lib" + LibSuffix, Paths);
222 }
223 
225  const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
226  const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
228  // FIXME: Omit X86_64 until 64-bit support is figured out.
229  if (IsX86) {
230  Res |= SanitizerKind::Address;
231  Res |= SanitizerKind::PointerCompare;
232  Res |= SanitizerKind::PointerSubtract;
233  }
234  if (IsX86 || IsX86_64)
235  Res |= SanitizerKind::Function;
236  Res |= SanitizerKind::Vptr;
237  return Res;
238 }
239 
241  return new tools::solaris::Assembler(*this);
242 }
243 
244 Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); }
245 
246 void Solaris::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
247  ArgStringList &CC1Args) const {
248  const Driver &D = getDriver();
249 
250  if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
251  return;
252 
253  if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
254  addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/local/include");
255 
256  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
258  llvm::sys::path::append(P, "include");
259  addSystemInclude(DriverArgs, CC1Args, P);
260  }
261 
262  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
263  return;
264 
265  // Check for configure-time C include directories.
266  StringRef CIncludeDirs(C_INCLUDE_DIRS);
267  if (CIncludeDirs != "") {
269  CIncludeDirs.split(dirs, ":");
270  for (StringRef dir : dirs) {
271  StringRef Prefix =
272  llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot);
273  addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
274  }
275  return;
276  }
277 
278  // Add include directories specific to the selected multilib set and multilib.
279  if (GCCInstallation.isValid()) {
280  const MultilibSet::IncludeDirsFunc &Callback =
282  if (Callback) {
283  for (const auto &Path : Callback(GCCInstallation.getMultilib()))
285  DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path);
286  }
287  }
288 
289  addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include");
290 }
291 
293  const llvm::opt::ArgList &DriverArgs,
294  llvm::opt::ArgStringList &CC1Args) const {
295  // We need a detected GCC installation on Solaris (similar to Linux)
296  // to provide libstdc++'s headers.
297  if (!GCCInstallation.isValid())
298  return;
299 
300  // By default, look for the C++ headers in an include directory adjacent to
301  // the lib directory of the GCC installation.
302  // On Solaris this usually looks like /usr/gcc/X.Y/include/c++/X.Y.Z
303  StringRef LibDir = GCCInstallation.getParentLibPath();
304  StringRef TripleStr = GCCInstallation.getTriple().str();
306  const GCCVersion &Version = GCCInstallation.getVersion();
307 
308  // The primary search for libstdc++ supports multiarch variants.
309  addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
310  TripleStr, Multilib.includeSuffix(), DriverArgs,
311  CC1Args);
312 }
clang::driver::toolchains::Solaris::buildLinker
Tool * buildLinker() const override
Definition: Solaris.cpp:244
clang::driver::toolchains
Definition: AIX.h:55
clang::LangStandard::isC99
bool isC99() const
isC99 - Language is a superset of C99.
Definition: LangStandard.h:95
Driver.h
clang::driver::Driver::Dir
std::string Dir
The path the driver executable was in, as invoked from the command line.
Definition: Driver.h:153
llvm::SmallVector
Definition: LLVM.h:38
clang::driver::toolchains::Generic_GCC::GCCInstallation
GCCInstallationDetector GCCInstallation
Definition: Gnu.h:288
clang::driver::tools
Definition: AIX.h:17
clang::driver::tools::solaris::Assembler::ConstructJob
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs,...
Definition: Solaris.cpp:29
clang::driver::ToolChain::getDriver
const Driver & getDriver() const
Definition: ToolChain.h:232
clang::driver::toolchains::Generic_GCC::GCCInstallationDetector::isValid
bool isValid() const
Check whether we detected a valid GCC install.
Definition: Gnu.h:224
clang::driver::toolchains::Solaris::getSupportedSanitizers
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition: Solaris.cpp:224
clang::driver::MultilibSet::IncludeDirsFunc
std::function< std::vector< std::string >(const Multilib &M)> IncludeDirsFunc
Definition: Multilib.h:120
clang::driver::InputInfo
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:22
clang::driver::ToolChain::addExternCSystemIncludeIfExists
static void addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Definition: ToolChain.cpp:941
clang::driver::toolchains::Solaris::addLibStdCxxIncludePaths
void addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
Definition: Solaris.cpp:292
clang::driver::tools::AddLinkerInputs
void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA)
clang::driver::toolchains::Generic_GCC::GCCVersion
Struct to store and manipulate GCC versions.
Definition: Gnu.h:161
clang::driver::ToolChain::getFilePaths
path_list & getFilePaths()
Definition: ToolChain.h:274
clang::driver::SanitizerArgs::requiresMinimalRuntime
bool requiresMinimalRuntime() const
Definition: SanitizerArgs.h:95
clang::driver::Multilib::gccSuffix
const std::string & gccSuffix() const
Get the detected GCC installation path suffix for the multi-arch target variant.
Definition: Multilib.h:45
clang::driver::Tool
Tool - Information on a specific compilation tool.
Definition: Tool.h:32
clang::driver::tools::getAsNeededOption
const char * getAsNeededOption(const ToolChain &TC, bool as_needed)
Definition: CommonArgs.cpp:966
clang::driver::toolchains::Generic_ELF
Definition: Gnu.h:363
clang::driver::tools::claimNoWarnArgs
void claimNoWarnArgs(const llvm::opt::ArgList &Args)
Options.h
clang::driver::InputInfo::isFilename
bool isFilename() const
Definition: InputInfo.h:75
clang::driver::toolchains::Generic_GCC::GCCVersion::Text
std::string Text
The unparsed text of the version.
Definition: Gnu.h:163
clang::driver::toolchains::Generic_GCC::GCCInstallationDetector::init
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args, ArrayRef< std::string > ExtraTripleAliases=std::nullopt)
Initialize a GCCInstallationDetector from the driver.
Definition: Gnu.cpp:1997
clang::driver::MultilibSet::includeDirsCallback
const IncludeDirsFunc & includeDirsCallback() const
Definition: Multilib.h:179
llvm::opt
Definition: DiagnosticOptions.h:19
Std
LangStandard::Kind Std
Definition: InterpolatingCompilationDatabase.cpp:133
DriverDiagnostic.h
clang::driver::InputInfo::isNothing
bool isNothing() const
Definition: InputInfo.h:74
clang::driver::toolchains::Generic_GCC::GCCInstallationDetector::getTriple
const llvm::Triple & getTriple() const
Get the GCC triple for the detected install.
Definition: Gnu.h:227
clang::driver::toolchains::Generic_GCC::GCCInstallationDetector::getParentLibPath
StringRef getParentLibPath() const
Get the detected GCC parent lib path.
Definition: Gnu.h:233
clang::driver::tools::addPathIfExists
void addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths)
Definition: CommonArgs.cpp:133
llvm::SmallString< 128 >
clang::driver::ToolChain::getTriple
const llvm::Triple & getTriple() const
Definition: ToolChain.h:234
clang::Language::C
@ C
Languages that the frontend can parse and compile.
clang::driver::Driver::SysRoot
std::string SysRoot
sysroot, if present
Definition: Driver.h:181
clang::driver::SanitizerArgs::needsAsanRt
bool needsAsanRt() const
Definition: SanitizerArgs.h:78
clang::driver::Multilib
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
Definition: Multilib.h:28
clang::driver::tools::solaris::Linker
Definition: Solaris.h:35
clang::driver::SanitizerArgs
Definition: SanitizerArgs.h:24
SanitizerArgs.h
clang::driver::Driver::ResourceDir
std::string ResourceDir
The path to the compiler resource directory.
Definition: Driver.h:165
clang::driver::tools::solaris::Assembler
Definition: Solaris.h:22
clang::driver::tools::solaris::Linker::ConstructJob
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs,...
Definition: Solaris.cpp:50
clang::driver::toolchains::Solaris::AddClangSystemIncludeArgs
void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
Add the clang cc1 arguments for system include paths.
Definition: Solaris.cpp:246
ToolChain.h
P
StringRef P
Definition: ASTMatchersInternal.cpp:564
clang::driver::ToolChain::getSupportedSanitizers
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:1089
Compilation.h
LangStandard.h
clang::LangStandard::getLanguage
clang::Language getLanguage() const
Get the language that this standard describes.
Definition: LangStandard.h:89
getSolarisLibSuffix
static StringRef getSolarisLibSuffix(const llvm::Triple &Triple)
Definition: Solaris.cpp:181
clang::LangStandard::getLangStandardForName
static const LangStandard * getLangStandardForName(StringRef Name)
Definition: LangStandards.cpp:39
clang::driver::toolchains::Generic_GCC::GCCInstallationDetector::getInstallPath
StringRef getInstallPath() const
Get the detected GCC installation path.
Definition: Gnu.h:230
clang::driver::Compilation
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
clang::driver::toolchains::Generic_GCC::GCCInstallationDetector::getVersion
const GCCVersion & getVersion() const
Get the detected GCC version string.
Definition: Gnu.h:246
clang::LangStandard
LangStandard - Information about the properties of a particular language standard.
Definition: LangStandard.h:68
Solaris.h
clang::driver::toolchains::Generic_GCC::addLibStdCXXIncludePaths
bool addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple, Twine IncludeSuffix, const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, bool DetectDebian=false) const
Definition: Gnu.cpp:3097
clang::driver::InputInfo::getFilename
const char * getFilename() const
Definition: InputInfo.h:83
clang::driver::tools::linkSanitizerRuntimeDeps
void linkSanitizerRuntimeDeps(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs)
CommonArgs.h
clang
Definition: CalledOnceCheck.h:17
clang::driver::Driver
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:75
clang::driver::toolchains::Generic_GCC::GCCInstallationDetector::getMultilib
const Multilib & getMultilib() const
Get the detected Multilib.
Definition: Gnu.h:236
clang::driver::tools::addSanitizerRuntimes
bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs)
clang::driver::ToolChain::Multilibs
MultilibSet Multilibs
Definition: ToolChain.h:189
clang::driver::SanitizerArgs::needsUbsanRt
bool needsUbsanRt() const
Definition: SanitizerArgs.cpp:272
clang::driver::Multilib::includeSuffix
const std::string & includeSuffix() const
Get the include directory suffix.
Definition: Multilib.h:67
clang::driver::ToolChain::addExternCSystemInclude
static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory with extern "C" semantics to CC1 arguments.
Definition: ToolChain.cpp:934
clang::driver
Definition: Action.h:31
clang::driver::ResponseFileSupport::None
static constexpr ResponseFileSupport None()
Returns a ResponseFileSupport indicating that response files are not supported.
Definition: Job.h:78
clang::driver::ToolChain::addSystemInclude
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory to CC1 arguments.
Definition: ToolChain.cpp:919
clang::driver::JobAction
Definition: Action.h:398
clang::driver::SanitizerArgs::needsStatsRt
bool needsStatsRt() const
Definition: SanitizerArgs.h:100
clang::driver::toolchains::Solaris::buildAssembler
Tool * buildAssembler() const override
Definition: Solaris.cpp:240
clang::LangStandard::isGNUMode
bool isGNUMode() const
isGNUMode - Language includes GNU extensions.
Definition: LangStandard.h:128
clang::SanitizerMask
Definition: Sanitizers.h:30