Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- RISCV.cpp - RISC-V Helpers for Tools -------------------*- 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 "RISCV.h"
10
#include "../Clang.h"
11
#include "ToolChains/CommonArgs.h"
12
#include "clang/Basic/CharInfo.h"
13
#include "clang/Driver/Driver.h"
14
#include "clang/Driver/DriverDiagnostic.h"
15
#include "clang/Driver/Options.h"
16
#include "llvm/Option/ArgList.h"
17
#include "llvm/Support/Error.h"
18
#include "llvm/Support/RISCVISAInfo.h"
19
#include "llvm/Support/raw_ostream.h"
20
#include "llvm/TargetParser/Host.h"
21
#include "llvm/TargetParser/RISCVTargetParser.h"
22
23
using namespace clang::driver;
24
using namespace clang::driver::tools;
25
using namespace clang;
26
using namespace llvm::opt;
27
28
// Returns false if an error is diagnosed.
29
static bool getArchFeatures(const Driver &D, StringRef Arch,
30
                            std::vector<StringRef> &Features,
31
758
                            const ArgList &Args) {
32
758
  bool EnableExperimentalExtensions =
33
758
      Args.hasArg(options::OPT_menable_experimental_extensions);
34
758
  auto ISAInfo =
35
758
      llvm::RISCVISAInfo::parseArchString(Arch, EnableExperimentalExtensions);
36
758
  if (!ISAInfo) {
37
52
    handleAllErrors(ISAInfo.takeError(), [&](llvm::StringError &ErrMsg) {
38
52
      D.Diag(diag::err_drv_invalid_riscv_arch_name)
39
52
          << Arch << ErrMsg.getMessage();
40
52
    });
41
42
52
    return false;
43
52
  }
44
45
706
  (*ISAInfo)->toFeatures(
46
81.8k
      Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); },
47
706
      /*AddAllExtensions=*/true);
48
706
  return true;
49
758
}
50
51
// Get features except standard extension feature
52
static void getRISCFeaturesFromMcpu(const Driver &D, const Arg *A,
53
                                    const llvm::Triple &Triple,
54
                                    StringRef Mcpu,
55
32
                                    std::vector<StringRef> &Features) {
56
32
  bool Is64Bit = Triple.isRISCV64();
57
32
  if (!llvm::RISCV::parseCPU(Mcpu, Is64Bit)) {
58
    // Try inverting Is64Bit in case the CPU is valid, but for the wrong target.
59
3
    if (llvm::RISCV::parseCPU(Mcpu, !Is64Bit))
60
1
      D.Diag(clang::diag::err_drv_invalid_riscv_cpu_name_for_target)
61
1
          << Mcpu << Is64Bit;
62
2
    else
63
2
      D.Diag(clang::diag::err_drv_unsupported_option_argument)
64
2
          << A->getSpelling() << Mcpu;
65
3
  }
66
32
}
67
68
void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
69
                                   const ArgList &Args,
70
758
                                   std::vector<StringRef> &Features) {
71
758
  StringRef MArch = getRISCVArch(Args, Triple);
72
73
758
  if (!getArchFeatures(D, MArch, Features, Args))
74
52
    return;
75
76
  // If users give march and mcpu, get std extension feature from MArch
77
  // and other features (ex. mirco architecture feature) from mcpu
78
706
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
79
32
    StringRef CPU = A->getValue();
80
32
    if (CPU == "native")
81
1
      CPU = llvm::sys::getHostCPUName();
82
83
32
    getRISCFeaturesFromMcpu(D, A, Triple, CPU, Features);
84
32
  }
85
86
  // Handle features corresponding to "-ffixed-X" options
87
706
  if (Args.hasArg(options::OPT_ffixed_x1))
88
6
    Features.push_back("+reserve-x1");
89
706
  if (Args.hasArg(options::OPT_ffixed_x2))
90
6
    Features.push_back("+reserve-x2");
91
706
  if (Args.hasArg(options::OPT_ffixed_x3))
92
4
    Features.push_back("+reserve-x3");
93
706
  if (Args.hasArg(options::OPT_ffixed_x4))
94
4
    Features.push_back("+reserve-x4");
95
706
  if (Args.hasArg(options::OPT_ffixed_x5))
96
4
    Features.push_back("+reserve-x5");
97
706
  if (Args.hasArg(options::OPT_ffixed_x6))
98
4
    Features.push_back("+reserve-x6");
99
706
  if (Args.hasArg(options::OPT_ffixed_x7))
100
4
    Features.push_back("+reserve-x7");
101
706
  if (Args.hasArg(options::OPT_ffixed_x8))
102
4
    Features.push_back("+reserve-x8");
103
706
  if (Args.hasArg(options::OPT_ffixed_x9))
104
4
    Features.push_back("+reserve-x9");
105
706
  if (Args.hasArg(options::OPT_ffixed_x10))
106
4
    Features.push_back("+reserve-x10");
107
706
  if (Args.hasArg(options::OPT_ffixed_x11))
108
4
    Features.push_back("+reserve-x11");
109
706
  if (Args.hasArg(options::OPT_ffixed_x12))
110
4
    Features.push_back("+reserve-x12");
111
706
  if (Args.hasArg(options::OPT_ffixed_x13))
112
4
    Features.push_back("+reserve-x13");
113
706
  if (Args.hasArg(options::OPT_ffixed_x14))
114
4
    Features.push_back("+reserve-x14");
115
706
  if (Args.hasArg(options::OPT_ffixed_x15))
116
4
    Features.push_back("+reserve-x15");
117
706
  if (Args.hasArg(options::OPT_ffixed_x16))
118
4
    Features.push_back("+reserve-x16");
119
706
  if (Args.hasArg(options::OPT_ffixed_x17))
120
4
    Features.push_back("+reserve-x17");
121
706
  if (Args.hasArg(options::OPT_ffixed_x18))
122
6
    Features.push_back("+reserve-x18");
123
706
  if (Args.hasArg(options::OPT_ffixed_x19))
124
4
    Features.push_back("+reserve-x19");
125
706
  if (Args.hasArg(options::OPT_ffixed_x20))
126
4
    Features.push_back("+reserve-x20");
127
706
  if (Args.hasArg(options::OPT_ffixed_x21))
128
4
    Features.push_back("+reserve-x21");
129
706
  if (Args.hasArg(options::OPT_ffixed_x22))
130
4
    Features.push_back("+reserve-x22");
131
706
  if (Args.hasArg(options::OPT_ffixed_x23))
132
4
    Features.push_back("+reserve-x23");
133
706
  if (Args.hasArg(options::OPT_ffixed_x24))
134
4
    Features.push_back("+reserve-x24");
135
706
  if (Args.hasArg(options::OPT_ffixed_x25))
136
4
    Features.push_back("+reserve-x25");
137
706
  if (Args.hasArg(options::OPT_ffixed_x26))
138
4
    Features.push_back("+reserve-x26");
139
706
  if (Args.hasArg(options::OPT_ffixed_x27))
140
4
    Features.push_back("+reserve-x27");
141
706
  if (Args.hasArg(options::OPT_ffixed_x28))
142
4
    Features.push_back("+reserve-x28");
143
706
  if (Args.hasArg(options::OPT_ffixed_x29))
144
4
    Features.push_back("+reserve-x29");
145
706
  if (Args.hasArg(options::OPT_ffixed_x30))
146
4
    Features.push_back("+reserve-x30");
147
706
  if (Args.hasArg(options::OPT_ffixed_x31))
148
4
    Features.push_back("+reserve-x31");
149
150
  // -mrelax is default, unless -mno-relax is specified.
151
706
  if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) {
152
703
    Features.push_back("+relax");
153
    // -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing
154
    // into .debug_addr, which is currently not implemented.
155
703
    Arg *A;
156
703
    if (getDebugFissionKind(D, Args, A) != DwarfFissionKind::None)
157
2
      D.Diag(clang::diag::err_drv_riscv_unsupported_with_linker_relaxation)
158
2
          << A->getAsString(Args);
159
703
  } else {
160
3
    Features.push_back("-relax");
161
3
  }
162
163
  // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
164
  // specified.
165
706
  if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false))
166
1
    Features.push_back("+save-restore");
167
705
  else
168
705
    Features.push_back("-save-restore");
169
170
  // -mno-unaligned-access is default, unless -munaligned-access is specified.
171
706
  bool HasV = llvm::is_contained(Features, "+zve32x");
172
706
  if (const Arg *A = Args.getLastArg(options::OPT_munaligned_access,
173
706
                                     options::OPT_mno_unaligned_access)) {
174
8
    if (A->getOption().matches(options::OPT_munaligned_access)) {
175
4
      Features.push_back("+unaligned-scalar-mem");
176
4
      if (HasV)
177
2
        Features.push_back("+unaligned-vector-mem");
178
4
    } else {
179
4
      Features.push_back("-unaligned-scalar-mem");
180
4
      if (HasV)
181
2
        Features.push_back("-unaligned-vector-mem");
182
4
    }
183
8
  }
184
185
  // Now add any that the user explicitly requested on the command line,
186
  // which may override the defaults.
187
706
  handleTargetFeaturesGroup(D, Triple, Args, Features,
188
706
                            options::OPT_m_riscv_Features_Group);
189
706
}
190
191
1.34k
StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
192
1.34k
  assert(Triple.isRISCV() && "Unexpected triple");
193
194
  // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
195
  // configured using `--with-abi=`, then the logic for the default choice is
196
  // defined in config.gcc. This function is based on the logic in GCC 9.2.0.
197
  //
198
  // The logic used in GCC 9.2.0 is the following, in order:
199
  // 1. Explicit choices using `--with-abi=`
200
  // 2. A default based on `--with-arch=`, if provided
201
  // 3. A default based on the target triple's arch
202
  //
203
  // The logic in config.gcc is a little circular but it is not inconsistent.
204
  //
205
  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
206
  // and `-mabi=` respectively instead.
207
  //
208
  // In order to make chosing logic more clear, Clang uses the following logic,
209
  // in order:
210
  // 1. Explicit choices using `-mabi=`
211
  // 2. A default based on the architecture as determined by getRISCVArch
212
  // 3. Choose a default based on the triple
213
214
  // 1. If `-mabi=` is specified, use it.
215
1.34k
  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
216
90
    return A->getValue();
217
218
  // 2. Choose a default based on the target architecture.
219
  //
220
  // rv32g | rv32*d -> ilp32d
221
  // rv32e -> ilp32e
222
  // rv32* -> ilp32
223
  // rv64g | rv64*d -> lp64d
224
  // rv64* -> lp64
225
1.25k
  StringRef Arch = getRISCVArch(Args, Triple);
226
227
1.25k
  auto ParseResult = llvm::RISCVISAInfo::parseArchString(
228
1.25k
      Arch, /* EnableExperimentalExtension */ true);
229
1.25k
  if (!ParseResult)
230
    // Ignore parsing error, just go 3rd step.
231
102
    consumeError(ParseResult.takeError());
232
1.14k
  else
233
1.14k
    return (*ParseResult)->computeDefaultABI();
234
235
  // 3. Choose a default based on the triple
236
  //
237
  // We deviate from GCC's defaults here:
238
  // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
239
  // - On all other OSs we use the double floating point calling convention.
240
102
  if (Triple.isRISCV32()) {
241
90
    if (Triple.getOS() == llvm::Triple::UnknownOS)
242
90
      return "ilp32";
243
0
    else
244
0
      return "ilp32d";
245
90
  } else {
246
12
    if (Triple.getOS() == llvm::Triple::UnknownOS)
247
12
      return "lp64";
248
0
    else
249
0
      return "lp64d";
250
12
  }
251
102
}
252
253
StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
254
2.78k
                              const llvm::Triple &Triple) {
255
2.78k
  assert(Triple.isRISCV() && "Unexpected triple");
256
257
  // GCC's logic around choosing a default `-march=` is complex. If GCC is not
258
  // configured using `--with-arch=`, then the logic for the default choice is
259
  // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
260
  // deviate from GCC's default on additional `-mcpu` option (GCC does not
261
  // support `-mcpu`) and baremetal targets (UnknownOS) where neither `-march`
262
  // nor `-mabi` is specified.
263
  //
264
  // The logic used in GCC 9.2.0 is the following, in order:
265
  // 1. Explicit choices using `--with-arch=`
266
  // 2. A default based on `--with-abi=`, if provided
267
  // 3. A default based on the target triple's arch
268
  //
269
  // The logic in config.gcc is a little circular but it is not inconsistent.
270
  //
271
  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
272
  // and `-mabi=` respectively instead.
273
  //
274
  // Clang uses the following logic, in order:
275
  // 1. Explicit choices using `-march=`
276
  // 2. Based on `-mcpu` if the target CPU has a default ISA string
277
  // 3. A default based on `-mabi`, if provided
278
  // 4. A default based on the target triple's arch
279
  //
280
  // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
281
  // instead of `rv{XLEN}gc` though they are (currently) equivalent.
282
283
  // 1. If `-march=` is specified, use it.
284
2.78k
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
285
1.91k
    return A->getValue();
286
287
  // 2. Get march (isa string) based on `-mcpu=`
288
869
  if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
289
88
    StringRef CPU = A->getValue();
290
88
    if (CPU == "native")
291
3
      CPU = llvm::sys::getHostCPUName();
292
88
    StringRef MArch = llvm::RISCV::getMArchFromMcpu(CPU);
293
    // Bypass if target cpu's default march is empty.
294
88
    if (MArch != "")
295
82
      return MArch;
296
88
  }
297
298
  // 3. Choose a default based on `-mabi=`
299
  //
300
  // ilp32e -> rv32e
301
  // ilp32 | ilp32f | ilp32d -> rv32imafdc
302
  // lp64 | lp64f | lp64d -> rv64imafdc
303
787
  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
304
29
    StringRef MABI = A->getValue();
305
306
29
    if (MABI.equals_insensitive("ilp32e"))
307
2
      return "rv32e";
308
27
    else if (MABI.starts_with_insensitive("ilp32"))
309
13
      return "rv32imafdc";
310
14
    else if (MABI.starts_with_insensitive("lp64")) {
311
14
      if (Triple.isAndroid())
312
1
        return "rv64imafdc_zba_zbb_zbs";
313
314
13
      return "rv64imafdc";
315
14
    }
316
29
  }
317
318
  // 4. Choose a default based on the triple
319
  //
320
  // We deviate from GCC's defaults here:
321
  // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
322
  // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
323
758
  if (Triple.isRISCV32()) {
324
337
    if (Triple.getOS() == llvm::Triple::UnknownOS)
325
285
      return "rv32imac";
326
52
    else
327
52
      return "rv32imafdc";
328
421
  } else {
329
421
    if (Triple.getOS() == llvm::Triple::UnknownOS)
330
255
      return "rv64imac";
331
166
    else if (Triple.isAndroid())
332
33
      return "rv64imafdc_zba_zbb_zbs";
333
133
    else
334
133
      return "rv64imafdc";
335
421
  }
336
758
}
337
338
std::string riscv::getRISCVTargetCPU(const llvm::opt::ArgList &Args,
339
764
                                     const llvm::Triple &Triple) {
340
764
  std::string CPU;
341
  // If we have -mcpu, use that.
342
764
  if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
343
32
    CPU = A->getValue();
344
345
  // Handle CPU name is 'native'.
346
764
  if (CPU == "native")
347
1
    CPU = llvm::sys::getHostCPUName();
348
349
764
  if (!CPU.empty())
350
32
    return CPU;
351
352
732
  return Triple.isRISCV64() ? 
"generic-rv64"346
:
"generic-rv32"386
;
353
764
}