Coverage Report

Created: 2020-02-25 14:32

/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 - RISCV 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/Basic/CharInfo.h"
11
#include "clang/Driver/Driver.h"
12
#include "clang/Driver/DriverDiagnostic.h"
13
#include "clang/Driver/Options.h"
14
#include "llvm/Option/ArgList.h"
15
#include "llvm/ADT/Optional.h"
16
#include "llvm/Support/TargetParser.h"
17
#include "llvm/Support/raw_ostream.h"
18
#include "ToolChains/CommonArgs.h"
19
20
using namespace clang::driver;
21
using namespace clang::driver::tools;
22
using namespace clang;
23
using namespace llvm::opt;
24
25
33
static StringRef getExtensionTypeDesc(StringRef Ext) {
26
33
  if (Ext.startswith("sx"))
27
7
    return "non-standard supervisor-level extension";
28
26
  if (Ext.startswith("s"))
29
8
    return "standard supervisor-level extension";
30
18
  if (Ext.startswith("x"))
31
17
    return "non-standard user-level extension";
32
1
  return StringRef();
33
1
}
34
35
33
static StringRef getExtensionType(StringRef Ext) {
36
33
  if (Ext.startswith("sx"))
37
7
    return "sx";
38
26
  if (Ext.startswith("s"))
39
8
    return "s";
40
18
  if (Ext.startswith("x"))
41
17
    return "x";
42
1
  return StringRef();
43
1
}
44
45
6
static bool isSupportedExtension(StringRef Ext) {
46
6
  // LLVM does not support "sx", "s" nor "x" extensions.
47
6
  return false;
48
6
}
49
50
// Extensions may have a version number, and may be separated by
51
// an underscore '_' e.g.: rv32i2_m2.
52
// Version number is divided into major and minor version numbers,
53
// separated by a 'p'. If the minor version is 0 then 'p0' can be
54
// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
55
static bool getExtensionVersion(const Driver &D, StringRef MArch,
56
                                StringRef Ext, StringRef In,
57
721
                                std::string &Major, std::string &Minor) {
58
721
  Major = std::string(In.take_while(isDigit));
59
721
  In = In.substr(Major.size());
60
721
  if (Major.empty())
61
713
    return true;
62
8
63
8
  if (In.consume_front("p")) {
64
6
    Minor = std::string(In.take_while(isDigit));
65
6
    In = In.substr(Major.size());
66
6
67
6
    // Expected 'p' to be followed by minor version number.
68
6
    if (Minor.empty()) {
69
2
      std::string Error =
70
2
        "minor version number missing after 'p' for extension";
71
2
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
72
2
        << MArch << Error << Ext;
73
2
      return false;
74
2
    }
75
6
  }
76
6
77
6
  // TODO: Handle extensions with version number.
78
6
  std::string Error = "unsupported version number " + Major;
79
6
  if (!Minor.empty())
80
4
    Error += "." + Minor;
81
6
  Error += " for extension";
82
6
  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
83
6
84
6
  return false;
85
6
}
86
87
// Handle other types of extensions other than the standard
88
// general purpose and standard user-level extensions.
89
// Parse the ISA string containing non-standard user-level
90
// extensions, standard supervisor-level extensions and
91
// non-standard supervisor-level extensions.
92
// These extensions start with 'x', 's', 'sx' prefixes, follow a
93
// canonical order, might have a version number (major, minor)
94
// and are separated by a single underscore '_'.
95
// Set the hardware features for the extensions that are supported.
96
static void getExtensionFeatures(const Driver &D,
97
                                 const ArgList &Args,
98
                                 std::vector<StringRef> &Features,
99
244
                                 StringRef &MArch, StringRef &Exts) {
100
244
  if (Exts.empty())
101
226
    return;
102
18
103
18
  // Multi-letter extensions are seperated by a single underscore
104
18
  // as described in RISC-V User-Level ISA V2.2.
105
18
  SmallVector<StringRef, 8> Split;
106
18
  Exts.split(Split, StringRef("_"));
107
18
108
18
  SmallVector<StringRef, 3> Prefix{"x", "s", "sx"};
109
18
  auto I = Prefix.begin();
110
18
  auto E = Prefix.end();
111
18
112
18
  SmallVector<StringRef, 8> AllExts;
113
18
114
28
  for (StringRef Ext : Split) {
115
28
    if (Ext.empty()) {
116
1
      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
117
1
        << "extension name missing after separator '_'";
118
1
      return;
119
1
    }
120
27
121
27
    StringRef Type = getExtensionType(Ext);
122
27
    StringRef Name(Ext.substr(Type.size()));
123
27
    StringRef Desc = getExtensionTypeDesc(Ext);
124
27
125
27
    if (Type.empty()) {
126
1
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
127
1
        << MArch << "invalid extension prefix" << Ext;
128
1
      return;
129
1
    }
130
26
131
26
    // Check ISA extensions are specified in the canonical order.
132
45
    
while (26
I != E &&
*I != Type43
)
133
19
      ++I;
134
26
135
26
    if (I == E) {
136
2
      std::string Error = std::string(Desc);
137
2
      Error += " not given in canonical order";
138
2
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
139
2
        << MArch <<  Error << Ext;
140
2
      return;
141
2
    }
142
24
143
24
    // The order is OK, do not advance I to the next prefix
144
24
    // to allow repeated extension type, e.g.: rv32ixabc_xdef.
145
24
146
24
    if (Name.empty()) {
147
4
      std::string Error = std::string(Desc);
148
4
      Error += " name missing after";
149
4
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
150
4
        << MArch << Error << Ext;
151
4
      return;
152
4
    }
153
20
154
20
    std::string Major, Minor;
155
20
    auto Pos = Name.find_if(isDigit);
156
20
    if (Pos != StringRef::npos) {
157
3
      auto Next =  Name.substr(Pos);
158
3
      Name = Name.substr(0, Pos);
159
3
      if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor))
160
3
        return;
161
17
    }
162
17
163
17
    // Check if duplicated extension.
164
17
    if (llvm::is_contained(AllExts, Ext)) {
165
1
      std::string Error = "duplicated ";
166
1
      Error += Desc;
167
1
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
168
1
        << MArch << Error << Ext;
169
1
      return;
170
1
    }
171
16
172
16
    // Extension format is correct, keep parsing the extensions.
173
16
    // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
174
16
    AllExts.push_back(Ext);
175
16
  }
176
18
177
18
  // Set target features.
178
18
  // TODO: Hardware features to be handled in Support/TargetParser.cpp.
179
18
  // TODO: Use version number when setting target features.
180
18
  
for (auto Ext : AllExts)6
{
181
6
    if (!isSupportedExtension(Ext)) {
182
6
      StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
183
6
      std::string Error = "unsupported ";
184
6
      Error += Desc;
185
6
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
186
6
        << MArch << Error << Ext;
187
6
      return;
188
6
    }
189
0
    Features.push_back(Args.MakeArgString("+" + Ext));
190
0
  }
191
6
}
192
193
// Returns false if an error is diagnosed.
194
static bool getArchFeatures(const Driver &D, StringRef MArch,
195
                            std::vector<StringRef> &Features,
196
276
                            const ArgList &Args) {
197
276
  // RISC-V ISA strings must be lowercase.
198
2.17k
  if (
llvm::any_of(MArch, [](char c) 276
{ return isupper(c); })) {
199
3
    D.Diag(diag::err_drv_invalid_riscv_arch_name)
200
3
        << MArch << "string must be lowercase";
201
3
    return false;
202
3
  }
203
273
204
273
  // ISA string must begin with rv32 or rv64.
205
273
  if (!(MArch.startswith("rv32") || 
MArch.startswith("rv64")118
) ||
206
273
      (MArch.size() < 5)) {
207
3
    D.Diag(diag::err_drv_invalid_riscv_arch_name)
208
3
        << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}";
209
3
    return false;
210
3
  }
211
270
212
270
  bool HasRV64 = MArch.startswith("rv64");
213
270
214
270
  // The canonical order specified in ISA manual.
215
270
  // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
216
270
  StringRef StdExts = "mafdqlcbjtpvn";
217
270
  bool HasF = false, HasD = false;
218
270
  char Baseline = MArch[4];
219
270
220
270
  // First letter should be 'e', 'i' or 'g'.
221
270
  switch (Baseline) {
222
10
  default:
223
10
    D.Diag(diag::err_drv_invalid_riscv_arch_name)
224
10
        << MArch << "first letter should be 'e', 'i' or 'g'";
225
10
    return false;
226
2
  case 'e': {
227
2
    StringRef Error;
228
2
    // Currently LLVM does not support 'e'.
229
2
    // Extension 'e' is not allowed in rv64.
230
2
    if (HasRV64)
231
1
      Error = "standard user-level extension 'e' requires 'rv32'";
232
1
    else
233
1
      Error = "unsupported standard user-level extension 'e'";
234
2
    D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error;
235
2
    return false;
236
0
  }
237
252
  case 'i':
238
252
    break;
239
6
  case 'g':
240
6
    // g = imafd
241
6
    StdExts = StdExts.drop_front(4);
242
6
    Features.push_back("+m");
243
6
    Features.push_back("+a");
244
6
    Features.push_back("+f");
245
6
    Features.push_back("+d");
246
6
    HasF = true;
247
6
    HasD = true;
248
6
    break;
249
258
  }
250
258
251
258
  // Skip rvxxx
252
258
  StringRef Exts = MArch.substr(5);
253
258
254
258
  // Remove non-standard extensions and supervisor-level extensions.
255
258
  // They have 'x', 's', 'sx' prefixes. Parse them at the end.
256
258
  // Find the very first occurrence of 's' or 'x'.
257
258
  StringRef OtherExts;
258
258
  size_t Pos = Exts.find_first_of("sx");
259
258
  if (Pos != StringRef::npos) {
260
18
    OtherExts = Exts.substr(Pos);
261
18
    Exts = Exts.substr(0, Pos);
262
18
  }
263
258
264
258
  std::string Major, Minor;
265
258
  if (!getExtensionVersion(D, MArch, std::string(1, Baseline), Exts, Major,
266
258
                           Minor))
267
4
    return false;
268
254
269
254
  // TODO: Use version number when setting target features
270
254
  // and consume the underscore '_' that might follow.
271
254
272
254
  auto StdExtsItr = StdExts.begin();
273
254
  auto StdExtsEnd = StdExts.end();
274
254
275
918
  for (auto I = Exts.begin(), E = Exts.end(); I != E; 
++I664
) {
276
672
    char c = *I;
277
672
278
672
    // Check ISA extensions are specified in the canonical order.
279
1.39k
    while (StdExtsItr != StdExtsEnd && 
*StdExtsItr != c1.38k
)
280
719
      ++StdExtsItr;
281
672
282
672
    if (StdExtsItr == StdExtsEnd) {
283
6
      // Either c contains a valid extension but it was not given in
284
6
      // canonical order or it is an invalid extension.
285
6
      StringRef Error;
286
6
      if (StdExts.contains(c))
287
5
        Error = "standard user-level extension not given in canonical order";
288
1
      else
289
1
        Error = "invalid standard user-level extension";
290
6
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
291
6
          << MArch << Error << std::string(1, c);
292
6
      return false;
293
6
    }
294
666
295
666
    // Move to next char to prevent repeated letter.
296
666
    ++StdExtsItr;
297
666
298
666
    if (std::next(I) != E) {
299
460
      // Skip c.
300
460
      std::string Next = std::string(std::next(I), E);
301
460
      std::string Major, Minor;
302
460
      if (!getExtensionVersion(D, MArch, std::string(1, c), Next, Major, Minor))
303
1
        return false;
304
665
305
665
      // TODO: Use version number when setting target features
306
665
      // and consume the underscore '_' that might follow.
307
665
    }
308
665
309
665
    // The order is OK, then push it into features.
310
665
    switch (c) {
311
1
    default:
312
1
      // Currently LLVM supports only "mafdc".
313
1
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
314
1
          << MArch << "unsupported standard user-level extension"
315
1
          << std::string(1, c);
316
1
      return false;
317
179
    case 'm':
318
179
      Features.push_back("+m");
319
179
      break;
320
181
    case 'a':
321
181
      Features.push_back("+a");
322
181
      break;
323
70
    case 'f':
324
70
      Features.push_back("+f");
325
70
      HasF = true;
326
70
      break;
327
62
    case 'd':
328
62
      Features.push_back("+d");
329
62
      HasD = true;
330
62
      break;
331
172
    case 'c':
332
172
      Features.push_back("+c");
333
172
      break;
334
665
    }
335
665
  }
336
254
337
254
  // Dependency check.
338
254
  // It's illegal to specify the 'd' (double-precision floating point)
339
254
  // extension without also specifying the 'f' (single precision
340
254
  // floating-point) extension.
341
254
  
if (246
HasD246
&&
!HasF66
) {
342
2
    D.Diag(diag::err_drv_invalid_riscv_arch_name)
343
2
        << MArch << "d requires f extension to also be specified";
344
2
    return false;
345
2
  }
346
244
347
244
  // Additional dependency checks.
348
244
  // TODO: The 'q' extension requires rv64.
349
244
  // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
350
244
351
244
  // Handle all other types of extensions.
352
244
  getExtensionFeatures(D, Args, Features, MArch, OtherExts);
353
244
354
244
  return true;
355
244
}
356
357
void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
358
                                   const ArgList &Args,
359
276
                                   std::vector<StringRef> &Features) {
360
276
  StringRef MArch = getRISCVArch(Args, Triple);
361
276
362
276
  if (!getArchFeatures(D, MArch, Features, Args))
363
32
    return;
364
244
365
244
  // Handle features corresponding to "-ffixed-X" options
366
244
  if (Args.hasArg(options::OPT_ffixed_x1))
367
6
    Features.push_back("+reserve-x1");
368
244
  if (Args.hasArg(options::OPT_ffixed_x2))
369
6
    Features.push_back("+reserve-x2");
370
244
  if (Args.hasArg(options::OPT_ffixed_x3))
371
4
    Features.push_back("+reserve-x3");
372
244
  if (Args.hasArg(options::OPT_ffixed_x4))
373
4
    Features.push_back("+reserve-x4");
374
244
  if (Args.hasArg(options::OPT_ffixed_x5))
375
4
    Features.push_back("+reserve-x5");
376
244
  if (Args.hasArg(options::OPT_ffixed_x6))
377
4
    Features.push_back("+reserve-x6");
378
244
  if (Args.hasArg(options::OPT_ffixed_x7))
379
4
    Features.push_back("+reserve-x7");
380
244
  if (Args.hasArg(options::OPT_ffixed_x8))
381
4
    Features.push_back("+reserve-x8");
382
244
  if (Args.hasArg(options::OPT_ffixed_x9))
383
4
    Features.push_back("+reserve-x9");
384
244
  if (Args.hasArg(options::OPT_ffixed_x10))
385
4
    Features.push_back("+reserve-x10");
386
244
  if (Args.hasArg(options::OPT_ffixed_x11))
387
4
    Features.push_back("+reserve-x11");
388
244
  if (Args.hasArg(options::OPT_ffixed_x12))
389
4
    Features.push_back("+reserve-x12");
390
244
  if (Args.hasArg(options::OPT_ffixed_x13))
391
4
    Features.push_back("+reserve-x13");
392
244
  if (Args.hasArg(options::OPT_ffixed_x14))
393
4
    Features.push_back("+reserve-x14");
394
244
  if (Args.hasArg(options::OPT_ffixed_x15))
395
4
    Features.push_back("+reserve-x15");
396
244
  if (Args.hasArg(options::OPT_ffixed_x16))
397
4
    Features.push_back("+reserve-x16");
398
244
  if (Args.hasArg(options::OPT_ffixed_x17))
399
4
    Features.push_back("+reserve-x17");
400
244
  if (Args.hasArg(options::OPT_ffixed_x18))
401
6
    Features.push_back("+reserve-x18");
402
244
  if (Args.hasArg(options::OPT_ffixed_x19))
403
4
    Features.push_back("+reserve-x19");
404
244
  if (Args.hasArg(options::OPT_ffixed_x20))
405
4
    Features.push_back("+reserve-x20");
406
244
  if (Args.hasArg(options::OPT_ffixed_x21))
407
4
    Features.push_back("+reserve-x21");
408
244
  if (Args.hasArg(options::OPT_ffixed_x22))
409
4
    Features.push_back("+reserve-x22");
410
244
  if (Args.hasArg(options::OPT_ffixed_x23))
411
4
    Features.push_back("+reserve-x23");
412
244
  if (Args.hasArg(options::OPT_ffixed_x24))
413
4
    Features.push_back("+reserve-x24");
414
244
  if (Args.hasArg(options::OPT_ffixed_x25))
415
4
    Features.push_back("+reserve-x25");
416
244
  if (Args.hasArg(options::OPT_ffixed_x26))
417
4
    Features.push_back("+reserve-x26");
418
244
  if (Args.hasArg(options::OPT_ffixed_x27))
419
4
    Features.push_back("+reserve-x27");
420
244
  if (Args.hasArg(options::OPT_ffixed_x28))
421
4
    Features.push_back("+reserve-x28");
422
244
  if (Args.hasArg(options::OPT_ffixed_x29))
423
4
    Features.push_back("+reserve-x29");
424
244
  if (Args.hasArg(options::OPT_ffixed_x30))
425
4
    Features.push_back("+reserve-x30");
426
244
  if (Args.hasArg(options::OPT_ffixed_x31))
427
4
    Features.push_back("+reserve-x31");
428
244
429
244
  // -mrelax is default, unless -mno-relax is specified.
430
244
  if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
431
243
    Features.push_back("+relax");
432
1
  else
433
1
    Features.push_back("-relax");
434
244
435
244
  // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
436
244
  // specified.
437
244
  if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false))
438
1
    Features.push_back("+save-restore");
439
243
  else
440
243
    Features.push_back("-save-restore");
441
244
442
244
  // Now add any that the user explicitly requested on the command line,
443
244
  // which may override the defaults.
444
244
  handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
445
244
}
446
447
371
StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
448
371
  assert((Triple.getArch() == llvm::Triple::riscv32 ||
449
371
          Triple.getArch() == llvm::Triple::riscv64) &&
450
371
         "Unexpected triple");
451
371
452
371
  // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
453
371
  // configured using `--with-abi=`, then the logic for the default choice is
454
371
  // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
455
371
  // deviate from GCC's default only on baremetal targets (UnknownOS) where
456
371
  // neither `-march` nor `-mabi` is specified.
457
371
  //
458
371
  // The logic uses the following, in order:
459
371
  // 1. Explicit choices using `--with-abi=`
460
371
  // 2. A default based on `--with-arch=`, if provided
461
371
  // 3. A default based on the target triple's arch
462
371
  //
463
371
  // The logic in config.gcc is a little circular but it is not inconsistent.
464
371
  //
465
371
  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
466
371
  // and `-mabi=` respectively instead.
467
371
468
371
  // 1. If `-mabi=` is specified, use it.
469
371
  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
470
38
    return A->getValue();
471
333
472
333
  // 2. Choose a default based on `-march=`
473
333
  //
474
333
  // rv32g | rv32*d -> ilp32d
475
333
  // rv32e -> ilp32e
476
333
  // rv32* -> ilp32
477
333
  // rv64g | rv64*d -> lp64d
478
333
  // rv64* -> lp64
479
333
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
480
148
    StringRef MArch = A->getValue();
481
148
482
148
    if (MArch.startswith_lower("rv32")) {
483
90
      // FIXME: parse `March` to find `D` extension properly
484
90
      if (MArch.substr(4).contains_lower("d") ||
485
90
          
MArch.startswith_lower("rv32g")72
)
486
22
        return "ilp32d";
487
68
      else if (MArch.startswith_lower("rv32e"))
488
1
        return "ilp32e";
489
67
      else
490
67
        return "ilp32";
491
58
    } else if (MArch.startswith_lower("rv64")) {
492
58
      // FIXME: parse `March` to find `D` extension properly
493
58
      if (MArch.substr(4).contains_lower("d") ||
494
58
          
MArch.startswith_lower("rv64g")44
)
495
18
        return "lp64d";
496
40
      else
497
40
        return "lp64";
498
185
    }
499
148
  }
500
185
501
185
  // 3. Choose a default based on the triple
502
185
  //
503
185
  // We deviate from GCC's defaults here:
504
185
  // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
505
185
  // - On all other OSs we use the double floating point calling convention.
506
185
  if (Triple.getArch() == llvm::Triple::riscv32) {
507
92
    if (Triple.getOS() == llvm::Triple::UnknownOS)
508
63
      return "ilp32";
509
29
    else
510
29
      return "ilp32d";
511
93
  } else {
512
93
    if (Triple.getOS() == llvm::Triple::UnknownOS)
513
56
      return "lp64";
514
37
    else
515
37
      return "lp64d";
516
93
  }
517
185
}
518
519
StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
520
297
                              const llvm::Triple &Triple) {
521
297
  assert((Triple.getArch() == llvm::Triple::riscv32 ||
522
297
          Triple.getArch() == llvm::Triple::riscv64) &&
523
297
         "Unexpected triple");
524
297
525
297
  // GCC's logic around choosing a default `-march=` is complex. If GCC is not
526
297
  // configured using `--with-arch=`, then the logic for the default choice is
527
297
  // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
528
297
  // deviate from GCC's default only on baremetal targets (UnknownOS) where
529
297
  // neither `-march` nor `-mabi` is specified.
530
297
  //
531
297
  // The logic uses the following, in order:
532
297
  // 1. Explicit choices using `--with-arch=`
533
297
  // 2. A default based on `--with-abi=`, if provided
534
297
  // 3. A default based on the target triple's arch
535
297
  //
536
297
  // The logic in config.gcc is a little circular but it is not inconsistent.
537
297
  //
538
297
  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
539
297
  // and `-mabi=` respectively instead.
540
297
  //
541
297
  // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
542
297
  // instead of `rv{XLEN}gc` though they are (currently) equivalent.
543
297
544
297
  // 1. If `-march=` is specified, use it.
545
297
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
546
138
    return A->getValue();
547
159
548
159
  // 2. Choose a default based on `-mabi=`
549
159
  //
550
159
  // ilp32e -> rv32e
551
159
  // ilp32 | ilp32f | ilp32d -> rv32imafdc
552
159
  // lp64 | lp64f | lp64d -> rv64imafdc
553
159
  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
554
8
    StringRef MABI = A->getValue();
555
8
556
8
    if (MABI.equals_lower("ilp32e"))
557
0
      return "rv32e";
558
8
    else if (MABI.startswith_lower("ilp32"))
559
4
      return "rv32imafdc";
560
4
    else if (MABI.startswith_lower("lp64"))
561
4
      return "rv64imafdc";
562
151
  }
563
151
564
151
  // 3. Choose a default based on the triple
565
151
  //
566
151
  // We deviate from GCC's defaults here:
567
151
  // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
568
151
  // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
569
151
  if (Triple.getArch() == llvm::Triple::riscv32) {
570
78
    if (Triple.getOS() == llvm::Triple::UnknownOS)
571
63
      return "rv32imac";
572
15
    else
573
15
      return "rv32imafdc";
574
73
  } else {
575
73
    if (Triple.getOS() == llvm::Triple::UnknownOS)
576
56
      return "rv64imac";
577
17
    else
578
17
      return "rv64imafdc";
579
73
  }
580
151
}