Coverage Report

Created: 2021-01-23 06:44

/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 "InputInfo.h"
13
#include "Gnu.h"
14
15
#include "Arch/RISCV.h"
16
#include "clang/Driver/Compilation.h"
17
#include "clang/Driver/Driver.h"
18
#include "clang/Driver/DriverDiagnostic.h"
19
#include "clang/Driver/Options.h"
20
#include "llvm/Option/ArgList.h"
21
#include "llvm/Support/Path.h"
22
#include "llvm/Support/VirtualFileSystem.h"
23
#include "llvm/Support/raw_ostream.h"
24
25
using namespace llvm::opt;
26
using namespace clang;
27
using namespace clang::driver;
28
using namespace clang::driver::tools;
29
using namespace clang::driver::toolchains;
30
31
681
static Multilib makeMultilib(StringRef commonSuffix) {
32
681
  return Multilib(commonSuffix, commonSuffix, commonSuffix);
33
681
}
34
35
static bool findRISCVMultilibs(const Driver &D,
36
                               const llvm::Triple &TargetTriple,
37
171
                               const ArgList &Args, DetectedMultilibs &Result) {
38
171
  Multilib::flags_list Flags;
39
171
  StringRef Arch = riscv::getRISCVArch(Args, TargetTriple);
40
171
  StringRef Abi = tools::riscv::getRISCVABI(Args, TargetTriple);
41
42
171
  if (TargetTriple.getArch() == llvm::Triple::riscv64) {
43
58
    Multilib Imac = makeMultilib("").flag("+march=rv64imac").flag("+mabi=lp64");
44
58
    Multilib Imafdc = makeMultilib("/rv64imafdc/lp64d")
45
58
                          .flag("+march=rv64imafdc")
46
58
                          .flag("+mabi=lp64d");
47
48
    // Multilib reuse
49
58
    bool UseImafdc =
50
58
        (Arch == "rv64imafdc") || 
(Arch == "rv64gc")54
; // gc => imafdc
51
52
58
    addMultilibFlag((Arch == "rv64imac"), "march=rv64imac", Flags);
53
58
    addMultilibFlag(UseImafdc, "march=rv64imafdc", Flags);
54
58
    addMultilibFlag(Abi == "lp64", "mabi=lp64", Flags);
55
58
    addMultilibFlag(Abi == "lp64d", "mabi=lp64d", Flags);
56
57
58
    Result.Multilibs = MultilibSet().Either(Imac, Imafdc);
58
58
    return Result.Multilibs.select(Flags, Result.SelectedMultilib);
59
58
  }
60
113
  if (TargetTriple.getArch() == llvm::Triple::riscv32) {
61
113
    Multilib Imac =
62
113
        makeMultilib("").flag("+march=rv32imac").flag("+mabi=ilp32");
63
113
    Multilib I =
64
113
        makeMultilib("/rv32i/ilp32").flag("+march=rv32i").flag("+mabi=ilp32");
65
113
    Multilib Im =
66
113
        makeMultilib("/rv32im/ilp32").flag("+march=rv32im").flag("+mabi=ilp32");
67
113
    Multilib Iac = makeMultilib("/rv32iac/ilp32")
68
113
                       .flag("+march=rv32iac")
69
113
                       .flag("+mabi=ilp32");
70
113
    Multilib Imafc = makeMultilib("/rv32imafc/ilp32f")
71
113
                         .flag("+march=rv32imafc")
72
113
                         .flag("+mabi=ilp32f");
73
74
    // Multilib reuse
75
113
    bool UseI = (Arch == "rv32i") || 
(Arch == "rv32ic")109
; // ic => i
76
113
    bool UseIm = (Arch == "rv32im") || 
(Arch == "rv32imc")111
; // imc => im
77
113
    bool UseImafc = (Arch == "rv32imafc") || 
(Arch == "rv32imafdc")111
||
78
107
                    (Arch == "rv32gc"); // imafdc,gc => imafc
79
80
113
    addMultilibFlag(UseI, "march=rv32i", Flags);
81
113
    addMultilibFlag(UseIm, "march=rv32im", Flags);
82
113
    addMultilibFlag((Arch == "rv32iac"), "march=rv32iac", Flags);
83
113
    addMultilibFlag((Arch == "rv32imac"), "march=rv32imac", Flags);
84
113
    addMultilibFlag(UseImafc, "march=rv32imafc", Flags);
85
113
    addMultilibFlag(Abi == "ilp32", "mabi=ilp32", Flags);
86
113
    addMultilibFlag(Abi == "ilp32f", "mabi=ilp32f", Flags);
87
88
113
    Result.Multilibs = MultilibSet().Either(I, Im, Iac, Imac, Imafc);
89
113
    return Result.Multilibs.select(Flags, Result.SelectedMultilib);
90
113
  }
91
0
  return false;
92
0
}
93
94
BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
95
                           const ArgList &Args)
96
668
    : ToolChain(D, Triple, Args) {
97
668
  getProgramPaths().push_back(getDriver().getInstalledDir());
98
668
  if (getDriver().getInstalledDir() != getDriver().Dir)
99
0
    getProgramPaths().push_back(getDriver().Dir);
100
101
668
  findMultilibs(D, Triple, Args);
102
668
  SmallString<128> SysRoot(computeSysRoot());
103
668
  if (!SysRoot.empty()) {
104
668
    llvm::sys::path::append(SysRoot, "lib");
105
668
    getFilePaths().push_back(std::string(SysRoot));
106
668
  }
107
668
}
108
109
/// Is the triple {arm,thumb}-none-none-{eabi,eabihf} ?
110
11.7k
static bool isARMBareMetal(const llvm::Triple &Triple) {
111
11.7k
  if (Triple.getArch() != llvm::Triple::arm &&
112
10.8k
      Triple.getArch() != llvm::Triple::thumb)
113
10.7k
    return false;
114
115
911
  if (Triple.getVendor() != llvm::Triple::UnknownVendor)
116
27
    return false;
117
118
884
  if (Triple.getOS() != llvm::Triple::UnknownOS)
119
2
    return false;
120
121
882
  if (Triple.getEnvironment() != llvm::Triple::EABI &&
122
488
      Triple.getEnvironment() != llvm::Triple::EABIHF)
123
479
    return false;
124
125
403
  return true;
126
403
}
127
128
11.9k
static bool isRISCVBareMetal(const llvm::Triple &Triple) {
129
11.9k
  if (Triple.getArch() != llvm::Triple::riscv32 &&
130
11.8k
      Triple.getArch() != llvm::Triple::riscv64)
131
11.7k
    return false;
132
133
265
  if (Triple.getVendor() != llvm::Triple::UnknownVendor)
134
0
    return false;
135
136
265
  if (Triple.getOS() != llvm::Triple::UnknownOS)
137
0
    return false;
138
139
265
  return Triple.getEnvironmentName() == "elf";
140
265
}
141
142
void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
143
668
                              const ArgList &Args) {
144
668
  DetectedMultilibs Result;
145
668
  if (isRISCVBareMetal(Triple)) {
146
171
    if (findRISCVMultilibs(D, Triple, Args, Result)) {
147
69
      SelectedMultilib = Result.SelectedMultilib;
148
69
      Multilibs = Result.Multilibs;
149
69
    }
150
171
  }
151
668
}
152
153
11.7k
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
154
11.7k
  return isARMBareMetal(Triple) || 
isRISCVBareMetal(Triple)11.3k
;
155
11.7k
}
156
157
187
Tool *BareMetal::buildLinker() const {
158
187
  return new tools::baremetal::Linker(*this);
159
187
}
160
161
1
std::string BareMetal::getCompilerRTPath() const { return getRuntimesDir(); }
162
163
std::string BareMetal::getCompilerRTBasename(const llvm::opt::ArgList &,
164
2
                                             StringRef, FileType, bool) const {
165
2
  return ("libclang_rt.builtins-" + getTriple().getArchName() + ".a").str();
166
2
}
167
168
188
std::string BareMetal::getRuntimesDir() const {
169
188
  SmallString<128> Dir(getDriver().ResourceDir);
170
188
  llvm::sys::path::append(Dir, "lib", "baremetal");
171
188
  Dir += SelectedMultilib.gccSuffix();
172
188
  return std::string(Dir.str());
173
188
}
174
175
1.32k
std::string BareMetal::computeSysRoot() const {
176
1.32k
  if (!getDriver().SysRoot.empty())
177
76
    return getDriver().SysRoot + SelectedMultilib.osSuffix();
178
179
1.24k
  SmallString<128> SysRootDir;
180
1.24k
  llvm::sys::path::append(SysRootDir, getDriver().Dir, "../lib/clang-runtimes",
181
1.24k
                          getDriver().getTargetTriple());
182
183
1.24k
  SysRootDir += SelectedMultilib.osSuffix();
184
1.24k
  return std::string(SysRootDir);
185
1.24k
}
186
187
void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
188
626
                                          ArgStringList &CC1Args) const {
189
626
  if (DriverArgs.hasArg(options::OPT_nostdinc))
190
2
    return;
191
192
624
  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
193
622
    SmallString<128> Dir(getDriver().ResourceDir);
194
622
    llvm::sys::path::append(Dir, "include");
195
622
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
196
622
  }
197
198
624
  if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
199
622
    SmallString<128> Dir(computeSysRoot());
200
622
    if (!Dir.empty()) {
201
622
      llvm::sys::path::append(Dir, "include");
202
622
      addSystemInclude(DriverArgs, CC1Args, Dir.str());
203
622
    }
204
622
  }
205
624
}
206
207
void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
208
                                      ArgStringList &CC1Args,
209
628
                                      Action::OffloadKind) const {
210
628
  CC1Args.push_back("-nostdsysteminc");
211
628
}
212
213
void BareMetal::AddClangCXXStdlibIncludeArgs(
214
36
    const ArgList &DriverArgs, ArgStringList &CC1Args) const {
215
36
  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
216
34
      DriverArgs.hasArg(options::OPT_nostdlibinc) ||
217
32
      DriverArgs.hasArg(options::OPT_nostdincxx))
218
4
    return;
219
220
32
  std::string SysRoot(computeSysRoot());
221
32
  if (SysRoot.empty())
222
0
    return;
223
224
32
  switch (GetCXXStdlibType(DriverArgs)) {
225
29
  case ToolChain::CST_Libcxx: {
226
29
    SmallString<128> Dir(SysRoot);
227
29
    llvm::sys::path::append(Dir, "include", "c++", "v1");
228
29
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
229
29
    break;
230
0
  }
231
3
  case ToolChain::CST_Libstdcxx: {
232
3
    SmallString<128> Dir(SysRoot);
233
3
    llvm::sys::path::append(Dir, "include", "c++");
234
3
    std::error_code EC;
235
3
    Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
236
    // Walk the subdirs, and find the one with the newest gcc version:
237
3
    for (llvm::vfs::directory_iterator
238
3
             LI = getDriver().getVFS().dir_begin(Dir.str(), EC),
239
3
             LE;
240
8
         !EC && LI != LE; 
LI = LI.increment(EC)5
) {
241
5
      StringRef VersionText = llvm::sys::path::filename(LI->path());
242
5
      auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
243
5
      if (CandidateVersion.Major == -1)
244
1
        continue;
245
4
      if (CandidateVersion <= Version)
246
1
        continue;
247
3
      Version = CandidateVersion;
248
3
    }
249
3
    if (Version.Major == -1)
250
0
      return;
251
3
    llvm::sys::path::append(Dir, Version.Text);
252
3
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
253
3
    break;
254
3
  }
255
32
  }
256
32
}
257
258
void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
259
9
                                    ArgStringList &CmdArgs) const {
260
9
  switch (GetCXXStdlibType(Args)) {
261
6
  case ToolChain::CST_Libcxx:
262
6
    CmdArgs.push_back("-lc++");
263
6
    CmdArgs.push_back("-lc++abi");
264
6
    break;
265
3
  case ToolChain::CST_Libstdcxx:
266
3
    CmdArgs.push_back("-lstdc++");
267
3
    CmdArgs.push_back("-lsupc++");
268
3
    break;
269
9
  }
270
9
  CmdArgs.push_back("-lunwind");
271
9
}
272
273
void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
274
185
                                  ArgStringList &CmdArgs) const {
275
185
  ToolChain::RuntimeLibType RLT = GetRuntimeLibType(Args);
276
185
  switch (RLT) {
277
184
  case ToolChain::RLT_CompilerRT:
278
184
    CmdArgs.push_back(
279
184
        Args.MakeArgString("-lclang_rt.builtins-" + getTriple().getArchName()));
280
184
    return;
281
1
  case ToolChain::RLT_Libgcc:
282
1
    CmdArgs.push_back("-lgcc");
283
1
    return;
284
0
  }
285
0
  llvm_unreachable("Unhandled RuntimeLibType.");
286
0
}
287
288
void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
289
                                     const InputInfo &Output,
290
                                     const InputInfoList &Inputs,
291
                                     const ArgList &Args,
292
187
                                     const char *LinkingOutput) const {
293
187
  ArgStringList CmdArgs;
294
295
187
  auto &TC = static_cast<const toolchains::BareMetal&>(getToolChain());
296
297
187
  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
298
299
187
  CmdArgs.push_back("-Bstatic");
300
301
187
  CmdArgs.push_back(Args.MakeArgString("-L" + TC.getRuntimesDir()));
302
303
187
  TC.AddFilePathLibArgs(Args, CmdArgs);
304
187
  Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
305
187
                            options::OPT_e, options::OPT_s, options::OPT_t,
306
187
                            options::OPT_Z_Flag, options::OPT_r});
307
308
187
  if (TC.ShouldLinkCXXStdlib(Args))
309
9
    TC.AddCXXStdlibLibArgs(Args, CmdArgs);
310
187
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
311
185
    CmdArgs.push_back("-lc");
312
185
    CmdArgs.push_back("-lm");
313
314
185
    TC.AddLinkRuntimeLib(Args, CmdArgs);
315
185
  }
316
317
187
  CmdArgs.push_back("-o");
318
187
  CmdArgs.push_back(Output.getFilename());
319
320
187
  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
321
187
                                         Args.MakeArgString(TC.GetLinkerPath()),
322
187
                                         CmdArgs, Inputs, Output));
323
187
}