1 //===--- Myriad.cpp - Myriad 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 //===----------------------------------------------------------------------===//
10 #include "CommonArgs.h"
11 #include "clang/Driver/Compilation.h"
12 #include "clang/Driver/Driver.h"
13 #include "clang/Driver/DriverDiagnostic.h"
14 #include "clang/Driver/Options.h"
15 #include "llvm/Option/ArgList.h"
17 using namespace clang::driver
;
18 using namespace clang::driver::toolchains
;
19 using namespace clang
;
20 using namespace llvm::opt
;
22 using tools::addPathIfExists
;
24 void tools::SHAVE::Compiler::ConstructJob(Compilation
&C
, const JobAction
&JA
,
25 const InputInfo
&Output
,
26 const InputInfoList
&Inputs
,
28 const char *LinkingOutput
) const {
29 ArgStringList CmdArgs
;
30 assert(Inputs
.size() == 1);
31 const InputInfo
&II
= Inputs
[0];
32 assert(II
.getType() == types::TY_C
|| II
.getType() == types::TY_CXX
||
33 II
.getType() == types::TY_PP_CXX
);
35 if (JA
.getKind() == Action::PreprocessJobClass
) {
37 CmdArgs
.push_back("-E");
39 assert(Output
.getType() == types::TY_PP_Asm
); // Require preprocessed asm.
40 CmdArgs
.push_back("-S");
41 CmdArgs
.push_back("-fno-exceptions"); // Always do this even if unspecified.
43 CmdArgs
.push_back("-DMYRIAD2");
45 // Append all -I, -iquote, -isystem paths, defines/undefines, 'f'
46 // flags, 'g' flags, 'M' flags, optimize flags, warning options,
47 // mcpu flags, mllvm flags, and Xclang flags.
48 // These are spelled the same way in clang and moviCompile.
49 Args
.AddAllArgsExcept(
51 {options::OPT_I_Group
, options::OPT_clang_i_Group
, options::OPT_std_EQ
,
52 options::OPT_D
, options::OPT_U
, options::OPT_f_Group
,
53 options::OPT_f_clang_Group
, options::OPT_g_Group
, options::OPT_M_Group
,
54 options::OPT_O_Group
, options::OPT_W_Group
, options::OPT_mcpu_EQ
,
55 options::OPT_mllvm
, options::OPT_Xclang
},
56 {options::OPT_fno_split_dwarf_inlining
});
57 Args
.hasArg(options::OPT_fno_split_dwarf_inlining
); // Claim it if present.
59 // If we're producing a dependency file, and assembly is the final action,
60 // then the name of the target in the dependency file should be the '.o'
61 // file, not the '.s' file produced by this step. For example, instead of
62 // /tmp/mumble.s: mumble.c .../someheader.h
63 // the filename on the lefthand side should be "mumble.o"
64 if (Args
.getLastArg(options::OPT_MF
) && !Args
.getLastArg(options::OPT_MT
) &&
65 C
.getActions().size() == 1 &&
66 C
.getActions()[0]->getKind() == Action::AssembleJobClass
) {
67 Arg
*A
= Args
.getLastArg(options::OPT_o
);
69 CmdArgs
.push_back("-MT");
70 CmdArgs
.push_back(Args
.MakeArgString(A
->getValue()));
74 CmdArgs
.push_back(II
.getFilename());
75 CmdArgs
.push_back("-o");
76 CmdArgs
.push_back(Output
.getFilename());
79 Args
.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
80 C
.addCommand(std::make_unique
<Command
>(JA
, *this, ResponseFileSupport::None(),
81 Args
.MakeArgString(Exec
), CmdArgs
,
85 void tools::SHAVE::Assembler::ConstructJob(Compilation
&C
, const JobAction
&JA
,
86 const InputInfo
&Output
,
87 const InputInfoList
&Inputs
,
89 const char *LinkingOutput
) const {
90 ArgStringList CmdArgs
;
92 assert(Inputs
.size() == 1);
93 const InputInfo
&II
= Inputs
[0];
94 assert(II
.getType() == types::TY_PP_Asm
); // Require preprocessed asm input.
95 assert(Output
.getType() == types::TY_Object
);
97 CmdArgs
.push_back("-no6thSlotCompression");
98 const Arg
*CPUArg
= Args
.getLastArg(options::OPT_mcpu_EQ
);
101 Args
.MakeArgString("-cv:" + StringRef(CPUArg
->getValue())));
102 CmdArgs
.push_back("-noSPrefixing");
103 CmdArgs
.push_back("-a"); // Mystery option.
104 Args
.AddAllArgValues(CmdArgs
, options::OPT_Wa_COMMA
, options::OPT_Xassembler
);
105 for (const Arg
*A
: Args
.filtered(options::OPT_I
, options::OPT_isystem
)) {
108 Args
.MakeArgString(std::string("-i:") + A
->getValue(0)));
110 CmdArgs
.push_back(II
.getFilename());
112 Args
.MakeArgString(std::string("-o:") + Output
.getFilename()));
115 Args
.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
116 C
.addCommand(std::make_unique
<Command
>(JA
, *this, ResponseFileSupport::None(),
117 Args
.MakeArgString(Exec
), CmdArgs
,
121 void tools::Myriad::Linker::ConstructJob(Compilation
&C
, const JobAction
&JA
,
122 const InputInfo
&Output
,
123 const InputInfoList
&Inputs
,
125 const char *LinkingOutput
) const {
127 static_cast<const toolchains::MyriadToolChain
&>(getToolChain());
128 const llvm::Triple
&T
= TC
.getTriple();
129 ArgStringList CmdArgs
;
131 !Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
);
132 bool UseDefaultLibs
=
133 !Args
.hasArg(options::OPT_nostdlib
, options::OPT_nodefaultlibs
);
134 // Silence warning if the args contain both -nostdlib and -stdlib=.
135 Args
.getLastArg(options::OPT_stdlib_EQ
);
137 if (T
.getArch() == llvm::Triple::sparc
)
138 CmdArgs
.push_back("-EB");
139 else // SHAVE assumes little-endian, and sparcel is expressly so.
140 CmdArgs
.push_back("-EL");
142 // The remaining logic is mostly like gnutools::Linker::ConstructJob,
143 // but we never pass through a --sysroot option and various other bits.
144 // For example, there are no sanitizers (yet) nor gold linker.
146 // Eat some arguments that may be present but have no effect.
147 Args
.ClaimAllArgs(options::OPT_g_Group
);
148 Args
.ClaimAllArgs(options::OPT_w
);
149 Args
.ClaimAllArgs(options::OPT_static_libgcc
);
151 if (Args
.hasArg(options::OPT_s
)) // Pass the 'strip' option.
152 CmdArgs
.push_back("-s");
154 CmdArgs
.push_back("-o");
155 CmdArgs
.push_back(Output
.getFilename());
158 // If you want startfiles, it means you want the builtin crti and crtbegin,
159 // but not crt0. Myriad link commands provide their own crt0.o as needed.
160 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("crti.o")));
161 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("crtbegin.o")));
164 Args
.AddAllArgs(CmdArgs
, {options::OPT_L
, options::OPT_T_Group
,
165 options::OPT_e
, options::OPT_s
, options::OPT_t
,
166 options::OPT_Z_Flag
, options::OPT_r
});
168 TC
.AddFilePathLibArgs(Args
, CmdArgs
);
170 bool NeedsSanitizerDeps
= addSanitizerRuntimes(TC
, Args
, CmdArgs
);
171 AddLinkerInputs(getToolChain(), Inputs
, Args
, CmdArgs
, JA
);
173 if (UseDefaultLibs
) {
174 if (NeedsSanitizerDeps
)
175 linkSanitizerRuntimeDeps(TC
, CmdArgs
);
176 if (C
.getDriver().CCCIsCXX()) {
177 if (TC
.GetCXXStdlibType(Args
) == ToolChain::CST_Libcxx
) {
178 CmdArgs
.push_back("-lc++");
179 CmdArgs
.push_back("-lc++abi");
181 CmdArgs
.push_back("-lstdc++");
183 if (T
.getOS() == llvm::Triple::RTEMS
) {
184 CmdArgs
.push_back("--start-group");
185 CmdArgs
.push_back("-lc");
186 CmdArgs
.push_back("-lgcc"); // circularly dependent on rtems
187 // You must provide your own "-L" option to enable finding these.
188 CmdArgs
.push_back("-lrtemscpu");
189 CmdArgs
.push_back("-lrtemsbsp");
190 CmdArgs
.push_back("--end-group");
192 CmdArgs
.push_back("-lc");
193 CmdArgs
.push_back("-lgcc");
197 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("crtend.o")));
198 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("crtn.o")));
202 Args
.MakeArgString(TC
.GetProgramPath("sparc-myriad-rtems-ld"));
203 C
.addCommand(std::make_unique
<Command
>(
204 JA
, *this, ResponseFileSupport::AtFileCurCP(), Args
.MakeArgString(Exec
),
205 CmdArgs
, Inputs
, Output
));
208 MyriadToolChain::MyriadToolChain(const Driver
&D
, const llvm::Triple
&Triple
,
210 : Generic_ELF(D
, Triple
, Args
) {
211 // If a target of 'sparc-myriad-elf' is specified to clang, it wants to use
212 // 'sparc-myriad--elf' (note the unknown OS) as the canonical triple.
213 // This won't work to find gcc. Instead we give the installation detector an
214 // extra triple, which is preferable to further hacks of the logic that at
215 // present is based solely on getArch(). In particular, it would be wrong to
216 // choose the myriad installation when targeting a non-myriad sparc install.
217 switch (Triple
.getArch()) {
219 D
.Diag(clang::diag::err_target_unsupported_arch
)
220 << Triple
.getArchName() << "myriad";
222 case llvm::Triple::shave
:
224 case llvm::Triple::sparc
:
225 case llvm::Triple::sparcel
:
226 GCCInstallation
.init(Triple
, Args
, {"sparc-myriad-rtems"});
229 if (GCCInstallation
.isValid()) {
230 // This directory contains crt{i,n,begin,end}.o as well as libgcc.
231 // These files are tied to a particular version of gcc.
232 SmallString
<128> CompilerSupportDir(GCCInstallation
.getInstallPath());
233 addPathIfExists(D
, CompilerSupportDir
, getFilePaths());
235 // libstd++ and libc++ must both be found in this one place.
236 addPathIfExists(D
, D
.Dir
+ "/../sparc-myriad-rtems/lib", getFilePaths());
239 MyriadToolChain::~MyriadToolChain() {}
241 void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList
&DriverArgs
,
242 ArgStringList
&CC1Args
) const {
243 if (!DriverArgs
.hasArg(clang::driver::options::OPT_nostdinc
))
244 addSystemInclude(DriverArgs
, CC1Args
, getDriver().SysRoot
+ "/include");
247 void MyriadToolChain::addLibCxxIncludePaths(
248 const llvm::opt::ArgList
&DriverArgs
,
249 llvm::opt::ArgStringList
&CC1Args
) const {
250 std::string
Path(getDriver().getInstalledDir());
251 addSystemInclude(DriverArgs
, CC1Args
, Path
+ "/../include/c++/v1");
254 void MyriadToolChain::addLibStdCxxIncludePaths(
255 const llvm::opt::ArgList
&DriverArgs
,
256 llvm::opt::ArgStringList
&CC1Args
) const {
257 StringRef LibDir
= GCCInstallation
.getParentLibPath();
258 const GCCVersion
&Version
= GCCInstallation
.getVersion();
259 StringRef TripleStr
= GCCInstallation
.getTriple().str();
260 const Multilib
&Multilib
= GCCInstallation
.getMultilib();
261 addLibStdCXXIncludePaths(
262 LibDir
.str() + "/../" + TripleStr
.str() + "/include/c++/" + Version
.Text
,
263 TripleStr
, Multilib
.includeSuffix(), DriverArgs
, CC1Args
);
266 // MyriadToolChain handles several triples:
267 // {shave,sparc{,el}}-myriad-{rtems,unknown}-elf
268 Tool
*MyriadToolChain::SelectTool(const JobAction
&JA
) const {
269 // The inherited method works fine if not targeting the SHAVE.
270 if (!isShaveCompilation(getTriple()))
271 return ToolChain::SelectTool(JA
);
272 switch (JA
.getKind()) {
273 case Action::PreprocessJobClass
:
274 case Action::CompileJobClass
:
276 Compiler
.reset(new tools::SHAVE::Compiler(*this));
277 return Compiler
.get();
278 case Action::AssembleJobClass
:
280 Assembler
.reset(new tools::SHAVE::Assembler(*this));
281 return Assembler
.get();
283 return ToolChain::getTool(JA
.getKind());
287 Tool
*MyriadToolChain::buildLinker() const {
288 return new tools::Myriad::Linker(*this);
291 SanitizerMask
MyriadToolChain::getSupportedSanitizers() const {
292 return SanitizerKind::Address
;