David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 1 | //===--- Solaris.cpp - Solaris ToolChain Implementations --------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #include "Solaris.h" |
| 11 | #include "CommonArgs.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 | 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(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); |
| 45 | } |
| 46 | |
| 47 | void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
| 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 | } else { |
| 70 | CmdArgs.push_back("--dynamic-linker"); |
| 71 | CmdArgs.push_back( |
| 72 | Args.MakeArgString(getToolChain().GetFilePath("ld.so.1"))); |
| 73 | } |
Fedor Sergeev | 33c86f874 | 2018-02-06 13:21:12 +0000 | [diff] [blame] | 74 | |
| 75 | // libpthread has been folded into libc since Solaris 10, no need to do |
| 76 | // anything for pthreads. Claim argument to avoid warning. |
| 77 | Args.ClaimAllArgs(options::OPT_pthread); |
| 78 | Args.ClaimAllArgs(options::OPT_pthreads); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 79 | } |
| 80 | |
| 81 | if (Output.isFilename()) { |
| 82 | CmdArgs.push_back("-o"); |
| 83 | CmdArgs.push_back(Output.getFilename()); |
| 84 | } else { |
| 85 | assert(Output.isNothing() && "Invalid output."); |
| 86 | } |
| 87 | |
| 88 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { |
| 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 | CmdArgs.push_back( |
| 95 | Args.MakeArgString(getToolChain().GetFilePath("values-Xa.o"))); |
| 96 | CmdArgs.push_back( |
| 97 | Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); |
| 98 | } |
| 99 | |
Alex Shlyapnikov | 85da0f6 | 2018-02-05 23:59:13 +0000 | [diff] [blame] | 100 | // Provide __start___sancov_guards. Solaris ld doesn't automatically create |
| 101 | // __start_SECNAME labels. |
| 102 | CmdArgs.push_back("--whole-archive"); |
| 103 | CmdArgs.push_back( |
| 104 | getToolChain().getCompilerRTArgString(Args, "sancov_begin", false)); |
| 105 | CmdArgs.push_back("--no-whole-archive"); |
| 106 | |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 107 | getToolChain().AddFilePathLibArgs(Args, CmdArgs); |
| 108 | |
| 109 | Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, |
| 110 | options::OPT_e, options::OPT_r}); |
| 111 | |
Alex Shlyapnikov | 85da0f6 | 2018-02-05 23:59:13 +0000 | [diff] [blame] | 112 | bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 113 | AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); |
| 114 | |
| 115 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { |
Nico Weber | 0ee47d9 | 2017-07-25 18:02:57 +0000 | [diff] [blame] | 116 | if (getToolChain().ShouldLinkCXXStdlib(Args)) |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 117 | getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); |
Alex Shlyapnikov | 85da0f6 | 2018-02-05 23:59:13 +0000 | [diff] [blame] | 118 | if (Args.hasArg(options::OPT_fstack_protector) || |
| 119 | Args.hasArg(options::OPT_fstack_protector_strong) || |
| 120 | Args.hasArg(options::OPT_fstack_protector_all)) { |
| 121 | // Explicitly link ssp libraries, not folded into Solaris libc. |
| 122 | CmdArgs.push_back("-lssp_nonshared"); |
| 123 | CmdArgs.push_back("-lssp"); |
| 124 | } |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 125 | CmdArgs.push_back("-lgcc_s"); |
| 126 | CmdArgs.push_back("-lc"); |
| 127 | if (!Args.hasArg(options::OPT_shared)) { |
| 128 | CmdArgs.push_back("-lgcc"); |
| 129 | CmdArgs.push_back("-lm"); |
| 130 | } |
Alex Shlyapnikov | 85da0f6 | 2018-02-05 23:59:13 +0000 | [diff] [blame] | 131 | if (NeedsSanitizerDeps) |
| 132 | linkSanitizerRuntimeDeps(getToolChain(), CmdArgs); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 133 | } |
| 134 | |
Alex Shlyapnikov | 85da0f6 | 2018-02-05 23:59:13 +0000 | [diff] [blame] | 135 | // Provide __stop___sancov_guards. Solaris ld doesn't automatically create |
| 136 | // __stop_SECNAME labels. |
| 137 | CmdArgs.push_back("--whole-archive"); |
| 138 | CmdArgs.push_back( |
| 139 | getToolChain().getCompilerRTArgString(Args, "sancov_end", false)); |
| 140 | CmdArgs.push_back("--no-whole-archive"); |
| 141 | |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 142 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { |
| 143 | CmdArgs.push_back( |
| 144 | Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); |
| 145 | } |
| 146 | CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); |
| 147 | |
| 148 | getToolChain().addProfileRTLibs(Args, CmdArgs); |
| 149 | |
| 150 | const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); |
| 151 | C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); |
| 152 | } |
| 153 | |
Fedor Sergeev | faa0a82 | 2018-01-23 12:23:52 +0000 | [diff] [blame] | 154 | static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) { |
| 155 | switch (Triple.getArch()) { |
| 156 | case llvm::Triple::x86: |
| 157 | case llvm::Triple::sparc: |
| 158 | break; |
| 159 | case llvm::Triple::x86_64: |
| 160 | return "/amd64"; |
| 161 | case llvm::Triple::sparcv9: |
| 162 | return "/sparcv9"; |
| 163 | default: |
| 164 | llvm_unreachable("Unsupported architecture"); |
| 165 | } |
| 166 | return ""; |
| 167 | } |
| 168 | |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 169 | /// Solaris - Solaris tool chain which can call as(1) and ld(1) directly. |
| 170 | |
| 171 | Solaris::Solaris(const Driver &D, const llvm::Triple &Triple, |
| 172 | const ArgList &Args) |
Aaron Ballman | 4a6d7d4 | 2017-07-14 17:49:52 +0000 | [diff] [blame] | 173 | : Generic_ELF(D, Triple, Args) { |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 174 | |
| 175 | GCCInstallation.init(Triple, Args); |
| 176 | |
Fedor Sergeev | faa0a82 | 2018-01-23 12:23:52 +0000 | [diff] [blame] | 177 | StringRef LibSuffix = getSolarisLibSuffix(Triple); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 178 | path_list &Paths = getFilePaths(); |
Fedor Sergeev | faa0a82 | 2018-01-23 12:23:52 +0000 | [diff] [blame] | 179 | if (GCCInstallation.isValid()) { |
| 180 | // On Solaris gcc uses both an architecture-specific path with triple in it |
| 181 | // as well as a more generic lib path (+arch suffix). |
| 182 | addPathIfExists(D, |
| 183 | GCCInstallation.getInstallPath() + |
| 184 | GCCInstallation.getMultilib().gccSuffix(), |
| 185 | Paths); |
| 186 | addPathIfExists(D, GCCInstallation.getParentLibPath() + LibSuffix, Paths); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 187 | } |
| 188 | |
Fedor Sergeev | faa0a82 | 2018-01-23 12:23:52 +0000 | [diff] [blame] | 189 | // If we are currently running Clang inside of the requested system root, |
| 190 | // add its parent library path to those searched. |
| 191 | if (StringRef(D.Dir).startswith(D.SysRoot)) |
| 192 | addPathIfExists(D, D.Dir + "/../lib", Paths); |
| 193 | |
| 194 | addPathIfExists(D, D.SysRoot + "/usr/lib" + LibSuffix, Paths); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 195 | } |
| 196 | |
Alex Shlyapnikov | 85da0f6 | 2018-02-05 23:59:13 +0000 | [diff] [blame] | 197 | SanitizerMask Solaris::getSupportedSanitizers() const { |
| 198 | const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; |
| 199 | SanitizerMask Res = ToolChain::getSupportedSanitizers(); |
| 200 | // FIXME: Omit X86_64 until 64-bit support is figured out. |
| 201 | if (IsX86) { |
| 202 | Res |= SanitizerKind::Address; |
| 203 | } |
| 204 | Res |= SanitizerKind::Vptr; |
| 205 | return Res; |
| 206 | } |
| 207 | |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 208 | Tool *Solaris::buildAssembler() const { |
| 209 | return new tools::solaris::Assembler(*this); |
| 210 | } |
| 211 | |
| 212 | Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); } |
| 213 | |
Fedor Sergeev | faa0a82 | 2018-01-23 12:23:52 +0000 | [diff] [blame] | 214 | void Solaris::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
| 215 | ArgStringList &CC1Args) const { |
| 216 | const Driver &D = getDriver(); |
| 217 | |
| 218 | if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 219 | return; |
| 220 | |
Fedor Sergeev | faa0a82 | 2018-01-23 12:23:52 +0000 | [diff] [blame] | 221 | if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) |
| 222 | addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/local/include"); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 223 | |
Fedor Sergeev | faa0a82 | 2018-01-23 12:23:52 +0000 | [diff] [blame] | 224 | if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
| 225 | SmallString<128> P(D.ResourceDir); |
| 226 | llvm::sys::path::append(P, "include"); |
| 227 | addSystemInclude(DriverArgs, CC1Args, P); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 228 | } |
Fedor Sergeev | faa0a82 | 2018-01-23 12:23:52 +0000 | [diff] [blame] | 229 | |
| 230 | if (DriverArgs.hasArg(options::OPT_nostdlibinc)) |
| 231 | return; |
| 232 | |
| 233 | // Check for configure-time C include directories. |
| 234 | StringRef CIncludeDirs(C_INCLUDE_DIRS); |
| 235 | if (CIncludeDirs != "") { |
| 236 | SmallVector<StringRef, 5> dirs; |
| 237 | CIncludeDirs.split(dirs, ":"); |
| 238 | for (StringRef dir : dirs) { |
| 239 | StringRef Prefix = |
| 240 | llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; |
| 241 | addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); |
| 242 | } |
| 243 | return; |
| 244 | } |
| 245 | |
| 246 | // Add include directories specific to the selected multilib set and multilib. |
| 247 | if (GCCInstallation.isValid()) { |
| 248 | const MultilibSet::IncludeDirsFunc &Callback = |
| 249 | Multilibs.includeDirsCallback(); |
| 250 | if (Callback) { |
| 251 | for (const auto &Path : Callback(GCCInstallation.getMultilib())) |
| 252 | addExternCSystemIncludeIfExists( |
| 253 | DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path); |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include"); |
| 258 | } |
| 259 | |
| 260 | void Solaris::addLibStdCxxIncludePaths( |
| 261 | const llvm::opt::ArgList &DriverArgs, |
| 262 | llvm::opt::ArgStringList &CC1Args) const { |
| 263 | // We need a detected GCC installation on Solaris (similar to Linux) |
| 264 | // to provide libstdc++'s headers. |
| 265 | if (!GCCInstallation.isValid()) |
| 266 | return; |
| 267 | |
| 268 | // By default, look for the C++ headers in an include directory adjacent to |
| 269 | // the lib directory of the GCC installation. |
| 270 | // On Solaris this usually looks like /usr/gcc/X.Y/include/c++/X.Y.Z |
| 271 | StringRef LibDir = GCCInstallation.getParentLibPath(); |
| 272 | StringRef TripleStr = GCCInstallation.getTriple().str(); |
| 273 | const Multilib &Multilib = GCCInstallation.getMultilib(); |
| 274 | const GCCVersion &Version = GCCInstallation.getVersion(); |
| 275 | |
| 276 | // The primary search for libstdc++ supports multiarch variants. |
| 277 | addLibStdCXXIncludePaths(LibDir.str() + "/../include", "/c++/" + Version.Text, |
| 278 | TripleStr, |
| 279 | /*GCCMultiarchTriple*/ "", |
| 280 | /*TargetMultiarchTriple*/ "", |
| 281 | Multilib.includeSuffix(), DriverArgs, CC1Args); |
David L. Jones | f561aba | 2017-03-08 01:02:16 +0000 | [diff] [blame] | 282 | } |