Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- BareMetal.cpp - Bare Metal ToolChain --------------------*- 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 "BareMetal.h"
10
11
#include "CommonArgs.h"
12
#include "Gnu.h"
13
#include "clang/Driver/InputInfo.h"
14
15
#include "Arch/ARM.h"
16
#include "Arch/RISCV.h"
17
#include "clang/Driver/Compilation.h"
18
#include "clang/Driver/Driver.h"
19
#include "clang/Driver/DriverDiagnostic.h"
20
#include "clang/Driver/MultilibBuilder.h"
21
#include "clang/Driver/Options.h"
22
#include "llvm/ADT/StringExtras.h"
23
#include "llvm/Option/ArgList.h"
24
#include "llvm/Support/Path.h"
25
#include "llvm/Support/VirtualFileSystem.h"
26
#include "llvm/Support/raw_ostream.h"
27
28
#include <sstream>
29
30
using namespace llvm::opt;
31
using namespace clang;
32
using namespace clang::driver;
33
using namespace clang::driver::tools;
34
using namespace clang::driver::toolchains;
35
36
static bool findRISCVMultilibs(const Driver &D,
37
                               const llvm::Triple &TargetTriple,
38
228
                               const ArgList &Args, DetectedMultilibs &Result) {
39
228
  Multilib::flags_list Flags;
40
228
  StringRef Arch = riscv::getRISCVArch(Args, TargetTriple);
41
228
  StringRef Abi = tools::riscv::getRISCVABI(Args, TargetTriple);
42
43
228
  if (TargetTriple.isRISCV64()) {
44
68
    MultilibBuilder Imac =
45
68
        MultilibBuilder().flag("-march=rv64imac").flag("-mabi=lp64");
46
68
    MultilibBuilder Imafdc = MultilibBuilder("/rv64imafdc/lp64d")
47
68
                                 .flag("-march=rv64imafdc")
48
68
                                 .flag("-mabi=lp64d");
49
50
    // Multilib reuse
51
68
    bool UseImafdc =
52
68
        (Arch == "rv64imafdc") || 
(Arch == "rv64gc")61
; // gc => imafdc
53
54
68
    addMultilibFlag((Arch == "rv64imac"), "-march=rv64imac", Flags);
55
68
    addMultilibFlag(UseImafdc, "-march=rv64imafdc", Flags);
56
68
    addMultilibFlag(Abi == "lp64", "-mabi=lp64", Flags);
57
68
    addMultilibFlag(Abi == "lp64d", "-mabi=lp64d", Flags);
58
59
68
    Result.Multilibs =
60
68
        MultilibSetBuilder().Either(Imac, Imafdc).makeMultilibSet();
61
68
    return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
62
68
  }
63
160
  if (TargetTriple.isRISCV32()) {
64
160
    MultilibBuilder Imac =
65
160
        MultilibBuilder().flag("-march=rv32imac").flag("-mabi=ilp32");
66
160
    MultilibBuilder I = MultilibBuilder("/rv32i/ilp32")
67
160
                            .flag("-march=rv32i")
68
160
                            .flag("-mabi=ilp32");
69
160
    MultilibBuilder Im = MultilibBuilder("/rv32im/ilp32")
70
160
                             .flag("-march=rv32im")
71
160
                             .flag("-mabi=ilp32");
72
160
    MultilibBuilder Iac = MultilibBuilder("/rv32iac/ilp32")
73
160
                              .flag("-march=rv32iac")
74
160
                              .flag("-mabi=ilp32");
75
160
    MultilibBuilder Imafc = MultilibBuilder("/rv32imafc/ilp32f")
76
160
                                .flag("-march=rv32imafc")
77
160
                                .flag("-mabi=ilp32f");
78
79
    // Multilib reuse
80
160
    bool UseI = (Arch == "rv32i") || 
(Arch == "rv32ic")156
; // ic => i
81
160
    bool UseIm = (Arch == "rv32im") || 
(Arch == "rv32imc")158
; // imc => im
82
160
    bool UseImafc = (Arch == "rv32imafc") || 
(Arch == "rv32imafdc")158
||
83
160
                    
(Arch == "rv32gc")151
; // imafdc,gc => imafc
84
85
160
    addMultilibFlag(UseI, "-march=rv32i", Flags);
86
160
    addMultilibFlag(UseIm, "-march=rv32im", Flags);
87
160
    addMultilibFlag((Arch == "rv32iac"), "-march=rv32iac", Flags);
88
160
    addMultilibFlag((Arch == "rv32imac"), "-march=rv32imac", Flags);
89
160
    addMultilibFlag(UseImafc, "-march=rv32imafc", Flags);
90
160
    addMultilibFlag(Abi == "ilp32", "-mabi=ilp32", Flags);
91
160
    addMultilibFlag(Abi == "ilp32f", "-mabi=ilp32f", Flags);
92
93
160
    Result.Multilibs =
94
160
        MultilibSetBuilder().Either(I, Im, Iac, Imac, Imafc).makeMultilibSet();
95
160
    return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
96
160
  }
97
0
  return false;
98
160
}
99
100
BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
101
                     const ArgList &Args)
102
1.20k
    : ToolChain(D, Triple, Args) {
103
1.20k
  getProgramPaths().push_back(getDriver().getInstalledDir());
104
1.20k
  if (getDriver().getInstalledDir() != getDriver().Dir)
105
0
    getProgramPaths().push_back(getDriver().Dir);
106
107
1.20k
  findMultilibs(D, Triple, Args);
108
1.20k
  SmallString<128> SysRoot(computeSysRoot());
109
1.20k
  if (!SysRoot.empty()) {
110
1.20k
    for (const Multilib &M : getOrderedMultilibs()) {
111
1.20k
      SmallString<128> Dir(SysRoot);
112
1.20k
      llvm::sys::path::append(Dir, M.osSuffix(), "lib");
113
1.20k
      getFilePaths().push_back(std::string(Dir));
114
1.20k
      getLibraryPaths().push_back(std::string(Dir));
115
1.20k
    }
116
1.20k
  }
117
1.20k
}
118
119
/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ?
120
14.0k
static bool isARMBareMetal(const llvm::Triple &Triple) {
121
14.0k
  if (Triple.getArch() != llvm::Triple::arm &&
122
14.0k
      
Triple.getArch() != llvm::Triple::thumb12.8k
&&
123
14.0k
      
Triple.getArch() != llvm::Triple::armeb12.7k
&&
124
14.0k
      
Triple.getArch() != llvm::Triple::thumbeb12.6k
)
125
12.6k
    return false;
126
127
1.37k
  if (Triple.getVendor() != llvm::Triple::UnknownVendor)
128
33
    return false;
129
130
1.33k
  if (Triple.getOS() != llvm::Triple::UnknownOS)
131
2
    return false;
132
133
1.33k
  if (Triple.getEnvironment() != llvm::Triple::EABI &&
134
1.33k
      
Triple.getEnvironment() != llvm::Triple::EABIHF648
)
135
633
    return false;
136
137
704
  return true;
138
1.33k
}
139
140
/// Is the triple {aarch64.aarch64_be}-none-elf?
141
13.1k
static bool isAArch64BareMetal(const llvm::Triple &Triple) {
142
13.1k
  if (Triple.getArch() != llvm::Triple::aarch64 &&
143
13.1k
      
Triple.getArch() != llvm::Triple::aarch64_be12.2k
)
144
12.0k
    return false;
145
146
1.09k
  if (Triple.getVendor() != llvm::Triple::UnknownVendor)
147
0
    return false;
148
149
1.09k
  if (Triple.getOS() != llvm::Triple::UnknownOS)
150
2
    return false;
151
152
1.09k
  return Triple.getEnvironmentName() == "elf";
153
1.09k
}
154
155
14.1k
static bool isRISCVBareMetal(const llvm::Triple &Triple) {
156
14.1k
  if (!Triple.isRISCV())
157
13.6k
    return false;
158
159
418
  if (Triple.getVendor() != llvm::Triple::UnknownVendor)
160
0
    return false;
161
162
418
  if (Triple.getOS() != llvm::Triple::UnknownOS)
163
0
    return false;
164
165
418
  return Triple.getEnvironmentName() == "elf";
166
418
}
167
168
/// Is the triple powerpc[64][le]-*-none-eabi?
169
12.9k
static bool isPPCBareMetal(const llvm::Triple &Triple) {
170
12.9k
  return Triple.isPPC() && 
Triple.getOS() == llvm::Triple::UnknownOS80
&&
171
12.9k
         
Triple.getEnvironment() == llvm::Triple::EABI80
;
172
12.9k
}
173
174
static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
175
                                  StringRef MultilibPath, const ArgList &Args,
176
974
                                  DetectedMultilibs &Result) {
177
974
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
178
974
      D.getVFS().getBufferForFile(MultilibPath);
179
974
  if (!MB)
180
967
    return;
181
7
  Multilib::flags_list Flags = TC.getMultilibFlags(Args);
182
7
  llvm::ErrorOr<MultilibSet> ErrorOrMultilibSet =
183
7
      MultilibSet::parseYaml(*MB.get());
184
7
  if (ErrorOrMultilibSet.getError())
185
0
    return;
186
7
  Result.Multilibs = ErrorOrMultilibSet.get();
187
7
  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))
188
6
    return;
189
1
  D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
190
1
  std::stringstream ss;
191
1
  for (const Multilib &Multilib : Result.Multilibs)
192
11
    ss << "\n" << llvm::join(Multilib.flags(), " ");
193
1
  D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
194
1
}
195
196
static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml";
197
198
// Get the sysroot, before multilib takes effect.
199
static std::string computeBaseSysRoot(const Driver &D,
200
3.36k
                                      const llvm::Triple &Triple) {
201
3.36k
  if (!D.SysRoot.empty())
202
249
    return D.SysRoot;
203
204
3.11k
  SmallString<128> SysRootDir(D.Dir);
205
3.11k
  llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes");
206
207
3.11k
  SmallString<128> MultilibPath(SysRootDir);
208
3.11k
  llvm::sys::path::append(MultilibPath, MultilibFilename);
209
210
  // New behaviour: if multilib.yaml is found then use clang-runtimes as the
211
  // sysroot.
212
3.11k
  if (D.getVFS().exists(MultilibPath))
213
20
    return std::string(SysRootDir);
214
215
  // Otherwise fall back to the old behaviour of appending the target triple.
216
3.09k
  llvm::sys::path::append(SysRootDir, D.getTargetTriple());
217
3.09k
  return std::string(SysRootDir);
218
3.11k
}
219
220
void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
221
1.20k
                              const ArgList &Args) {
222
1.20k
  DetectedMultilibs Result;
223
1.20k
  if (isRISCVBareMetal(Triple)) {
224
228
    if (findRISCVMultilibs(D, Triple, Args, Result)) {
225
78
      SelectedMultilibs = Result.SelectedMultilibs;
226
78
      Multilibs = Result.Multilibs;
227
78
    }
228
974
  } else {
229
974
    llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple));
230
974
    llvm::sys::path::append(MultilibPath, MultilibFilename);
231
974
    findMultilibsFromYAML(*this, D, MultilibPath, Args, Result);
232
974
    SelectedMultilibs = Result.SelectedMultilibs;
233
974
    Multilibs = Result.Multilibs;
234
974
  }
235
1.20k
}
236
237
13.6k
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
238
13.6k
  return isARMBareMetal(Triple) || 
isAArch64BareMetal(Triple)13.1k
||
239
13.6k
         
isRISCVBareMetal(Triple)12.9k
||
isPPCBareMetal(Triple)12.9k
;
240
13.6k
}
241
242
357
Tool *BareMetal::buildLinker() const {
243
357
  return new tools::baremetal::Linker(*this);
244
357
}
245
246
1
Tool *BareMetal::buildStaticLibTool() const {
247
1
  return new tools::baremetal::StaticLibTool(*this);
248
1
}
249
250
2.39k
std::string BareMetal::computeSysRoot() const {
251
2.39k
  return computeBaseSysRoot(getDriver(), getTriple());
252
2.39k
}
253
254
2.39k
BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
255
  // Get multilibs in reverse order because they're ordered most-specific last.
256
2.39k
  if (!SelectedMultilibs.empty())
257
181
    return llvm::reverse(SelectedMultilibs);
258
259
  // No multilibs selected so return a single default multilib.
260
2.21k
  static const llvm::SmallVector<Multilib> Default = {Multilib()};
261
2.21k
  return llvm::reverse(Default);
262
2.39k
}
263
264
void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
265
1.13k
                                          ArgStringList &CC1Args) const {
266
1.13k
  if (DriverArgs.hasArg(options::OPT_nostdinc))
267
2
    return;
268
269
1.13k
  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
270
1.13k
    SmallString<128> Dir(getDriver().ResourceDir);
271
1.13k
    llvm::sys::path::append(Dir, "include");
272
1.13k
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
273
1.13k
  }
274
275
1.13k
  if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
276
1.13k
    const SmallString<128> SysRoot(computeSysRoot());
277
1.13k
    if (!SysRoot.empty()) {
278
1.13k
      for (const Multilib &M : getOrderedMultilibs()) {
279
1.13k
        SmallString<128> Dir(SysRoot);
280
1.13k
        llvm::sys::path::append(Dir, M.includeSuffix());
281
1.13k
        llvm::sys::path::append(Dir, "include");
282
1.13k
        addSystemInclude(DriverArgs, CC1Args, Dir.str());
283
1.13k
      }
284
1.13k
    }
285
1.13k
  }
286
1.13k
}
287
288
void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
289
                                      ArgStringList &CC1Args,
290
1.13k
                                      Action::OffloadKind) const {
291
1.13k
  CC1Args.push_back("-nostdsysteminc");
292
1.13k
}
293
294
void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
295
79
                                             ArgStringList &CC1Args) const {
296
79
  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
297
79
      
DriverArgs.hasArg(options::OPT_nostdlibinc)77
||
298
79
      
DriverArgs.hasArg(options::OPT_nostdincxx)75
)
299
20
    return;
300
301
59
  const Driver &D = getDriver();
302
59
  std::string SysRoot(computeSysRoot());
303
59
  if (SysRoot.empty())
304
0
    return;
305
306
60
  
for (const Multilib &M : getOrderedMultilibs())59
{
307
60
    SmallString<128> Dir(SysRoot);
308
60
    llvm::sys::path::append(Dir, M.gccSuffix());
309
60
    switch (GetCXXStdlibType(DriverArgs)) {
310
57
    case ToolChain::CST_Libcxx: {
311
      // First check sysroot/usr/include/c++/v1 if it exists.
312
57
      SmallString<128> TargetDir(Dir);
313
57
      llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1");
314
57
      if (D.getVFS().exists(TargetDir)) {
315
1
        addSystemInclude(DriverArgs, CC1Args, TargetDir.str());
316
1
        break;
317
1
      }
318
      // Add generic path if nothing else succeeded so far.
319
56
      llvm::sys::path::append(Dir, "include", "c++", "v1");
320
56
      addSystemInclude(DriverArgs, CC1Args, Dir.str());
321
56
      break;
322
57
    }
323
3
    case ToolChain::CST_Libstdcxx: {
324
3
      llvm::sys::path::append(Dir, "include", "c++");
325
3
      std::error_code EC;
326
3
      Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
327
      // Walk the subdirs, and find the one with the newest gcc version:
328
3
      for (llvm::vfs::directory_iterator
329
3
               LI = D.getVFS().dir_begin(Dir.str(), EC),
330
3
               LE;
331
8
           !EC && LI != LE; 
LI = LI.increment(EC)5
) {
332
5
        StringRef VersionText = llvm::sys::path::filename(LI->path());
333
5
        auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
334
5
        if (CandidateVersion.Major == -1)
335
1
          continue;
336
4
        if (CandidateVersion <= Version)
337
1
          continue;
338
3
        Version = CandidateVersion;
339
3
      }
340
3
      if (Version.Major != -1) {
341
3
        llvm::sys::path::append(Dir, Version.Text);
342
3
        addSystemInclude(DriverArgs, CC1Args, Dir.str());
343
3
      }
344
3
      break;
345
57
    }
346
60
    }
347
60
  }
348
59
}
349
350
void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
351
10
                                    ArgStringList &CmdArgs) const {
352
10
  switch (GetCXXStdlibType(Args)) {
353
7
  case ToolChain::CST_Libcxx:
354
7
    CmdArgs.push_back("-lc++");
355
7
    if (Args.hasArg(options::OPT_fexperimental_library))
356
0
      CmdArgs.push_back("-lc++experimental");
357
7
    CmdArgs.push_back("-lc++abi");
358
7
    break;
359
3
  case ToolChain::CST_Libstdcxx:
360
3
    CmdArgs.push_back("-lstdc++");
361
3
    CmdArgs.push_back("-lsupc++");
362
3
    break;
363
10
  }
364
10
  CmdArgs.push_back("-lunwind");
365
10
}
366
367
void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
368
355
                                  ArgStringList &CmdArgs) const {
369
355
  ToolChain::RuntimeLibType RLT = GetRuntimeLibType(Args);
370
355
  switch (RLT) {
371
354
  case ToolChain::RLT_CompilerRT: {
372
354
    const std::string FileName = getCompilerRT(Args, "builtins");
373
354
    llvm::StringRef BaseName = llvm::sys::path::filename(FileName);
374
354
    BaseName.consume_front("lib");
375
354
    BaseName.consume_back(".a");
376
354
    CmdArgs.push_back(Args.MakeArgString("-l" + BaseName));
377
354
    return;
378
0
  }
379
1
  case ToolChain::RLT_Libgcc:
380
1
    CmdArgs.push_back("-lgcc");
381
1
    return;
382
355
  }
383
0
  llvm_unreachable("Unhandled RuntimeLibType.");
384
0
}
385
386
void baremetal::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
387
                                            const InputInfo &Output,
388
                                            const InputInfoList &Inputs,
389
                                            const ArgList &Args,
390
1
                                            const char *LinkingOutput) const {
391
1
  const Driver &D = getToolChain().getDriver();
392
393
  // Silence warning for "clang -g foo.o -o foo"
394
1
  Args.ClaimAllArgs(options::OPT_g_Group);
395
  // and "clang -emit-llvm foo.o -o foo"
396
1
  Args.ClaimAllArgs(options::OPT_emit_llvm);
397
  // and for "clang -w foo.o -o foo". Other warning options are already
398
  // handled somewhere else.
399
1
  Args.ClaimAllArgs(options::OPT_w);
400
  // Silence warnings when linking C code with a C++ '-stdlib' argument.
401
1
  Args.ClaimAllArgs(options::OPT_stdlib_EQ);
402
403
  // ar tool command "llvm-ar <options> <output_file> <input_files>".
404
1
  ArgStringList CmdArgs;
405
  // Create and insert file members with a deterministic index.
406
1
  CmdArgs.push_back("rcsD");
407
1
  CmdArgs.push_back(Output.getFilename());
408
409
1
  for (const auto &II : Inputs) {
410
1
    if (II.isFilename()) {
411
1
      CmdArgs.push_back(II.getFilename());
412
1
    }
413
1
  }
414
415
  // Delete old output archive file if it already exists before generating a new
416
  // archive file.
417
1
  const char *OutputFileName = Output.getFilename();
418
1
  if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
419
0
    if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
420
0
      D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
421
0
      return;
422
0
    }
423
0
  }
424
425
1
  const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
426
1
  C.addCommand(std::make_unique<Command>(JA, *this,
427
1
                                         ResponseFileSupport::AtFileCurCP(),
428
1
                                         Exec, CmdArgs, Inputs, Output));
429
1
}
430
431
void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
432
                                     const InputInfo &Output,
433
                                     const InputInfoList &Inputs,
434
                                     const ArgList &Args,
435
357
                                     const char *LinkingOutput) const {
436
357
  ArgStringList CmdArgs;
437
438
357
  auto &TC = static_cast<const toolchains::BareMetal &>(getToolChain());
439
357
  const llvm::Triple::ArchType Arch = TC.getArch();
440
357
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
441
442
357
  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
443
444
357
  CmdArgs.push_back("-Bstatic");
445
446
357
  if (Triple.isARM() || 
Triple.isThumb()295
) {
447
133
    bool IsBigEndian = arm::isARMBigEndian(Triple, Args);
448
133
    if (IsBigEndian)
449
3
      arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
450
133
    CmdArgs.push_back(IsBigEndian ? 
"-EB"3
:
"-EL"130
);
451
224
  } else if (Triple.isAArch64()) {
452
84
    CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? 
"-EB"3
:
"-EL"81
);
453
84
  }
454
455
357
  Args.AddAllArgs(CmdArgs,
456
357
                  {options::OPT_L, options::OPT_T_Group, options::OPT_s,
457
357
                   options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
458
459
357
  TC.AddFilePathLibArgs(Args, CmdArgs);
460
461
357
  for (const auto &LibPath : TC.getLibraryPaths())
462
359
    CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath)));
463
464
357
  const std::string FileName = TC.getCompilerRT(Args, "builtins");
465
357
  llvm::SmallString<128> PathBuf{FileName};
466
357
  llvm::sys::path::remove_filename(PathBuf);
467
357
  CmdArgs.push_back(Args.MakeArgString("-L" + PathBuf));
468
469
357
  if (TC.ShouldLinkCXXStdlib(Args))
470
10
    TC.AddCXXStdlibLibArgs(Args, CmdArgs);
471
472
357
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
473
355
    CmdArgs.push_back("-lc");
474
355
    CmdArgs.push_back("-lm");
475
476
355
    TC.AddLinkRuntimeLib(Args, CmdArgs);
477
355
  }
478
479
357
  if (TC.getTriple().isRISCV())
480
136
    CmdArgs.push_back("-X");
481
482
  // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
483
  // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
484
  // arm*-*-*bsd).
485
357
  if (isARMBareMetal(TC.getTriple()))
486
133
    CmdArgs.push_back("--target2=rel");
487
488
357
  CmdArgs.push_back("-o");
489
357
  CmdArgs.push_back(Output.getFilename());
490
491
357
  C.addCommand(std::make_unique<Command>(
492
357
      JA, *this, ResponseFileSupport::AtFileCurCP(),
493
357
      Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs, Output));
494
357
}