Coverage Report

Created: 2020-11-28 09:00

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