1 //===--- OpenBSD.cpp - OpenBSD ToolChain Implementations --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
11 #include "Arch/Mips.h"
12 #include "Arch/Sparc.h"
13 #include "CommonArgs.h"
14 #include "clang/Config/config.h"
15 #include "clang/Driver/Compilation.h"
16 #include "clang/Driver/Options.h"
17 #include "clang/Driver/SanitizerArgs.h"
18 #include "llvm/Option/ArgList.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/VirtualFileSystem.h"
22 using namespace clang::driver
;
23 using namespace clang::driver::tools
;
24 using namespace clang::driver::toolchains
;
25 using namespace clang
;
26 using namespace llvm::opt
;
28 void openbsd::Assembler::ConstructJob(Compilation
&C
, const JobAction
&JA
,
29 const InputInfo
&Output
,
30 const InputInfoList
&Inputs
,
32 const char *LinkingOutput
) const {
33 const toolchains::OpenBSD
&ToolChain
=
34 static_cast<const toolchains::OpenBSD
&>(getToolChain());
35 const Driver
&D
= ToolChain
.getDriver();
36 const llvm::Triple
&Triple
= ToolChain
.getTriple();
38 claimNoWarnArgs(Args
);
39 ArgStringList CmdArgs
;
41 switch (ToolChain
.getArch()) {
42 case llvm::Triple::x86
:
43 // When building 32-bit code on OpenBSD/amd64, we have to explicitly
44 // instruct as in the base system to assemble 32-bit code.
45 CmdArgs
.push_back("--32");
48 case llvm::Triple::arm
:
49 case llvm::Triple::armeb
: {
50 StringRef MArch
, MCPU
;
51 arm::getARMArchCPUFromArgs(Args
, MArch
, MCPU
, /*FromAs*/ true);
52 std::string Arch
= arm::getARMTargetCPU(MCPU
, MArch
, Triple
);
53 CmdArgs
.push_back(Args
.MakeArgString("-mcpu=" + Arch
));
57 case llvm::Triple::ppc
:
58 CmdArgs
.push_back("-mppc");
59 CmdArgs
.push_back("-many");
62 case llvm::Triple::sparcv9
: {
63 CmdArgs
.push_back("-64");
64 std::string CPU
= getCPUName(D
, Args
, Triple
);
65 CmdArgs
.push_back(sparc::getSparcAsmModeForCPU(CPU
, Triple
));
66 AddAssemblerKPIC(ToolChain
, Args
, CmdArgs
);
70 case llvm::Triple::mips64
:
71 case llvm::Triple::mips64el
: {
74 mips::getMipsCPUAndABI(Args
, Triple
, CPUName
, ABIName
);
76 CmdArgs
.push_back("-march");
77 CmdArgs
.push_back(CPUName
.data());
79 CmdArgs
.push_back("-mabi");
80 CmdArgs
.push_back(mips::getGnuCompatibleMipsABIName(ABIName
).data());
82 if (Triple
.isLittleEndian())
83 CmdArgs
.push_back("-EL");
85 CmdArgs
.push_back("-EB");
87 AddAssemblerKPIC(ToolChain
, Args
, CmdArgs
);
95 Args
.AddAllArgValues(CmdArgs
, options::OPT_Wa_COMMA
, options::OPT_Xassembler
);
97 CmdArgs
.push_back("-o");
98 CmdArgs
.push_back(Output
.getFilename());
100 for (const auto &II
: Inputs
)
101 CmdArgs
.push_back(II
.getFilename());
103 const char *Exec
= Args
.MakeArgString(ToolChain
.GetProgramPath("as"));
104 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
105 ResponseFileSupport::AtFileCurCP(),
106 Exec
, CmdArgs
, Inputs
, Output
));
109 void openbsd::Linker::ConstructJob(Compilation
&C
, const JobAction
&JA
,
110 const InputInfo
&Output
,
111 const InputInfoList
&Inputs
,
113 const char *LinkingOutput
) const {
114 const toolchains::OpenBSD
&ToolChain
=
115 static_cast<const toolchains::OpenBSD
&>(getToolChain());
116 const Driver
&D
= ToolChain
.getDriver();
117 const llvm::Triple::ArchType Arch
= ToolChain
.getArch();
118 ArgStringList CmdArgs
;
120 // Silence warning for "clang -g foo.o -o foo"
121 Args
.ClaimAllArgs(options::OPT_g_Group
);
122 // and "clang -emit-llvm foo.o -o foo"
123 Args
.ClaimAllArgs(options::OPT_emit_llvm
);
124 // and for "clang -w foo.o -o foo". Other warning options are already
125 // handled somewhere else.
126 Args
.ClaimAllArgs(options::OPT_w
);
128 if (!D
.SysRoot
.empty())
129 CmdArgs
.push_back(Args
.MakeArgString("--sysroot=" + D
.SysRoot
));
131 if (Arch
== llvm::Triple::mips64
)
132 CmdArgs
.push_back("-EB");
133 else if (Arch
== llvm::Triple::mips64el
)
134 CmdArgs
.push_back("-EL");
136 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_shared
)) {
137 CmdArgs
.push_back("-e");
138 CmdArgs
.push_back("__start");
141 CmdArgs
.push_back("--eh-frame-hdr");
142 if (Args
.hasArg(options::OPT_static
)) {
143 CmdArgs
.push_back("-Bstatic");
145 if (Args
.hasArg(options::OPT_rdynamic
))
146 CmdArgs
.push_back("-export-dynamic");
147 CmdArgs
.push_back("-Bdynamic");
148 if (Args
.hasArg(options::OPT_shared
)) {
149 CmdArgs
.push_back("-shared");
150 } else if (!Args
.hasArg(options::OPT_r
)) {
151 CmdArgs
.push_back("-dynamic-linker");
152 CmdArgs
.push_back("/usr/libexec/ld.so");
156 if (Args
.hasArg(options::OPT_pie
))
157 CmdArgs
.push_back("-pie");
158 if (Args
.hasArg(options::OPT_nopie
) || Args
.hasArg(options::OPT_pg
))
159 CmdArgs
.push_back("-nopie");
161 if (Arch
== llvm::Triple::riscv64
)
162 CmdArgs
.push_back("-X");
164 if (Output
.isFilename()) {
165 CmdArgs
.push_back("-o");
166 CmdArgs
.push_back(Output
.getFilename());
168 assert(Output
.isNothing() && "Invalid output.");
171 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
173 const char *crt0
= nullptr;
174 const char *crtbegin
= nullptr;
175 if (!Args
.hasArg(options::OPT_shared
)) {
176 if (Args
.hasArg(options::OPT_pg
))
178 else if (Args
.hasArg(options::OPT_static
) &&
179 !Args
.hasArg(options::OPT_nopie
))
183 crtbegin
= "crtbegin.o";
185 crtbegin
= "crtbeginS.o";
189 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath(crt0
)));
190 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath(crtbegin
)));
193 Args
.AddAllArgs(CmdArgs
, options::OPT_L
);
194 ToolChain
.AddFilePathLibArgs(Args
, CmdArgs
);
195 Args
.AddAllArgs(CmdArgs
, {options::OPT_T_Group
, options::OPT_e
,
196 options::OPT_s
, options::OPT_t
,
197 options::OPT_Z_Flag
, options::OPT_r
});
199 bool NeedsSanitizerDeps
= addSanitizerRuntimes(ToolChain
, Args
, CmdArgs
);
200 bool NeedsXRayDeps
= addXRayRuntime(ToolChain
, Args
, CmdArgs
);
201 AddLinkerInputs(ToolChain
, Inputs
, Args
, CmdArgs
, JA
);
203 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nodefaultlibs
,
205 // Use the static OpenMP runtime with -static-openmp
206 bool StaticOpenMP
= Args
.hasArg(options::OPT_static_openmp
) &&
207 !Args
.hasArg(options::OPT_static
);
208 addOpenMPRuntime(CmdArgs
, ToolChain
, Args
, StaticOpenMP
);
211 if (ToolChain
.ShouldLinkCXXStdlib(Args
))
212 ToolChain
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
213 if (Args
.hasArg(options::OPT_pg
))
214 CmdArgs
.push_back("-lm_p");
216 CmdArgs
.push_back("-lm");
218 if (NeedsSanitizerDeps
) {
219 CmdArgs
.push_back(ToolChain
.getCompilerRTArgString(Args
, "builtins"));
220 linkSanitizerRuntimeDeps(ToolChain
, CmdArgs
);
223 CmdArgs
.push_back(ToolChain
.getCompilerRTArgString(Args
, "builtins"));
224 linkXRayRuntimeDeps(ToolChain
, CmdArgs
);
226 // FIXME: For some reason GCC passes -lgcc before adding
227 // the default system libraries. Just mimic this for now.
228 CmdArgs
.push_back("-lcompiler_rt");
230 if (Args
.hasArg(options::OPT_pthread
)) {
231 if (!Args
.hasArg(options::OPT_shared
) && Args
.hasArg(options::OPT_pg
))
232 CmdArgs
.push_back("-lpthread_p");
234 CmdArgs
.push_back("-lpthread");
237 if (!Args
.hasArg(options::OPT_shared
)) {
238 if (Args
.hasArg(options::OPT_pg
))
239 CmdArgs
.push_back("-lc_p");
241 CmdArgs
.push_back("-lc");
244 CmdArgs
.push_back("-lcompiler_rt");
247 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
249 const char *crtend
= nullptr;
250 if (!Args
.hasArg(options::OPT_shared
))
253 crtend
= "crtendS.o";
255 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath(crtend
)));
258 ToolChain
.addProfileRTLibs(Args
, CmdArgs
);
260 const char *Exec
= Args
.MakeArgString(ToolChain
.GetLinkerPath());
261 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
262 ResponseFileSupport::AtFileCurCP(),
263 Exec
, CmdArgs
, Inputs
, Output
));
266 SanitizerMask
OpenBSD::getSupportedSanitizers() const {
267 const bool IsX86
= getTriple().getArch() == llvm::Triple::x86
;
268 const bool IsX86_64
= getTriple().getArch() == llvm::Triple::x86_64
;
270 // For future use, only UBsan at the moment
271 SanitizerMask Res
= ToolChain::getSupportedSanitizers();
273 if (IsX86
|| IsX86_64
) {
274 Res
|= SanitizerKind::Vptr
;
275 Res
|= SanitizerKind::Fuzzer
;
276 Res
|= SanitizerKind::FuzzerNoLink
;
282 /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
284 OpenBSD::OpenBSD(const Driver
&D
, const llvm::Triple
&Triple
,
286 : Generic_ELF(D
, Triple
, Args
) {
287 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib"));
290 void OpenBSD::AddClangSystemIncludeArgs(
291 const llvm::opt::ArgList
&DriverArgs
,
292 llvm::opt::ArgStringList
&CC1Args
) const {
293 const Driver
&D
= getDriver();
295 if (DriverArgs
.hasArg(clang::driver::options::OPT_nostdinc
))
298 if (!DriverArgs
.hasArg(options::OPT_nobuiltininc
)) {
299 SmallString
<128> Dir(D
.ResourceDir
);
300 llvm::sys::path::append(Dir
, "include");
301 addSystemInclude(DriverArgs
, CC1Args
, Dir
.str());
304 if (DriverArgs
.hasArg(options::OPT_nostdlibinc
))
307 // Check for configure-time C include directories.
308 StringRef
CIncludeDirs(C_INCLUDE_DIRS
);
309 if (CIncludeDirs
!= "") {
310 SmallVector
<StringRef
, 5> dirs
;
311 CIncludeDirs
.split(dirs
, ":");
312 for (StringRef dir
: dirs
) {
314 llvm::sys::path::is_absolute(dir
) ? StringRef(D
.SysRoot
) : "";
315 addExternCSystemInclude(DriverArgs
, CC1Args
, Prefix
+ dir
);
320 addExternCSystemInclude(DriverArgs
, CC1Args
,
321 concat(D
.SysRoot
, "/usr/include"));
324 void OpenBSD::addLibCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
325 llvm::opt::ArgStringList
&CC1Args
) const {
326 addSystemInclude(DriverArgs
, CC1Args
,
327 concat(getDriver().SysRoot
, "/usr/include/c++/v1"));
330 void OpenBSD::AddCXXStdlibLibArgs(const ArgList
&Args
,
331 ArgStringList
&CmdArgs
) const {
332 bool Profiling
= Args
.hasArg(options::OPT_pg
);
334 CmdArgs
.push_back(Profiling
? "-lc++_p" : "-lc++");
335 if (Args
.hasArg(options::OPT_fexperimental_library
))
336 CmdArgs
.push_back("-lc++experimental");
337 CmdArgs
.push_back(Profiling
? "-lc++abi_p" : "-lc++abi");
338 CmdArgs
.push_back(Profiling
? "-lpthread_p" : "-lpthread");
341 std::string
OpenBSD::getCompilerRT(const ArgList
&Args
, StringRef Component
,
342 FileType Type
) const {
343 if (Component
== "builtins") {
344 SmallString
<128> Path(getDriver().SysRoot
);
345 llvm::sys::path::append(Path
, "/usr/lib/libcompiler_rt.a");
346 return std::string(Path
.str());
348 SmallString
<128> P(getDriver().ResourceDir
);
349 std::string CRTBasename
=
350 buildCompilerRTBasename(Args
, Component
, Type
, /*AddArch=*/false);
351 llvm::sys::path::append(P
, "lib", CRTBasename
);
352 // Checks if this is the base system case which uses a different location.
353 if (getVFS().exists(P
))
354 return std::string(P
.str());
355 return ToolChain::getCompilerRT(Args
, Component
, Type
);
358 Tool
*OpenBSD::buildAssembler() const {
359 return new tools::openbsd::Assembler(*this);
362 Tool
*OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); }
364 bool OpenBSD::HasNativeLLVMSupport() const { return true; }
366 bool OpenBSD::IsUnwindTablesDefault(const ArgList
&Args
) const {
368 case llvm::Triple::arm
: