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