Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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/Support/TargetParser.h"
16
#include "llvm/Support/raw_ostream.h"
17
#include "ToolChains/CommonArgs.h"
18
19
using namespace clang::driver;
20
using namespace clang::driver::tools;
21
using namespace clang;
22
using namespace llvm::opt;
23
24
33
static StringRef getExtensionTypeDesc(StringRef Ext) {
25
33
  if (Ext.startswith("sx"))
26
7
    return "non-standard supervisor-level extension";
27
26
  if (Ext.startswith("s"))
28
8
    return "standard supervisor-level extension";
29
18
  if (Ext.startswith("x"))
30
17
    return "non-standard user-level extension";
31
1
  return StringRef();
32
1
}
33
34
33
static StringRef getExtensionType(StringRef Ext) {
35
33
  if (Ext.startswith("sx"))
36
7
    return "sx";
37
26
  if (Ext.startswith("s"))
38
8
    return "s";
39
18
  if (Ext.startswith("x"))
40
17
    return "x";
41
1
  return StringRef();
42
1
}
43
44
6
static bool isSupportedExtension(StringRef Ext) {
45
6
  // LLVM does not support "sx", "s" nor "x" extensions.
46
6
  return false;
47
6
}
48
49
// Extensions may have a version number, and may be separated by
50
// an underscore '_' e.g.: rv32i2_m2.
51
// Version number is divided into major and minor version numbers,
52
// separated by a 'p'. If the minor version is 0 then 'p0' can be
53
// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
54
static bool getExtensionVersion(const Driver &D, StringRef MArch,
55
                                StringRef Ext, StringRef In,
56
175
                                std::string &Major, std::string &Minor) {
57
175
  Major = In.take_while(isDigit);
58
175
  In = In.substr(Major.size());
59
175
  if (Major.empty())
60
167
    return true;
61
8
62
8
  if (In.consume_front("p")) {
63
6
    Minor = In.take_while(isDigit);
64
6
    In = In.substr(Major.size());
65
6
66
6
    // Expected 'p' to be followed by minor version number.
67
6
    if (Minor.empty()) {
68
2
      std::string Error =
69
2
        "minor version number missing after 'p' for extension";
70
2
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
71
2
        << MArch << Error << Ext;
72
2
      return false;
73
2
    }
74
6
  }
75
6
76
6
  // TODO: Handle extensions with version number.
77
6
  std::string Error = "unsupported version number " + Major;
78
6
  if (!Minor.empty())
79
4
    Error += "." + Minor;
80
6
  Error += " for extension";
81
6
  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
82
6
83
6
  return false;
84
6
}
85
86
// Handle other types of extensions other than the standard
87
// general purpose and standard user-level extensions.
88
// Parse the ISA string containing non-standard user-level
89
// extensions, standard supervisor-level extensions and
90
// non-standard supervisor-level extensions.
91
// These extensions start with 'x', 's', 'sx' prefixes, follow a
92
// canonical order, might have a version number (major, minor)
93
// and are separated by a single underscore '_'.
94
// Set the hardware features for the extensions that are supported.
95
static void getExtensionFeatures(const Driver &D,
96
                                 const ArgList &Args,
97
                                 std::vector<StringRef> &Features,
98
80
                                 StringRef &MArch, StringRef &Exts) {
99
80
  if (Exts.empty())
100
62
    return;
101
18
102
18
  // Multi-letter extensions are seperated by a single underscore
103
18
  // as described in RISC-V User-Level ISA V2.2.
104
18
  SmallVector<StringRef, 8> Split;
105
18
  Exts.split(Split, StringRef("_"));
106
18
107
18
  SmallVector<StringRef, 3> Prefix{"x", "s", "sx"};
108
18
  auto I = Prefix.begin();
109
18
  auto E = Prefix.end();
110
18
111
18
  SmallVector<StringRef, 8> AllExts;
112
18
113
28
  for (StringRef Ext : Split) {
114
28
    if (Ext.empty()) {
115
1
      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
116
1
        << "extension name missing after separator '_'";
117
1
      return;
118
1
    }
119
27
120
27
    StringRef Type = getExtensionType(Ext);
121
27
    StringRef Name(Ext.substr(Type.size()));
122
27
    StringRef Desc = getExtensionTypeDesc(Ext);
123
27
124
27
    if (Type.empty()) {
125
1
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
126
1
        << MArch << "invalid extension prefix" << Ext;
127
1
      return;
128
1
    }
129
26
130
26
    // Check ISA extensions are specified in the canonical order.
131
45
    
while (26
I != E &&
*I != Type43
)
132
19
      ++I;
133
26
134
26
    if (I == E) {
135
2
      std::string Error = Desc;
136
2
      Error += " not given in canonical order";
137
2
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
138
2
        << MArch <<  Error << Ext;
139
2
      return;
140
2
    }
141
24
142
24
    // The order is OK, do not advance I to the next prefix
143
24
    // to allow repeated extension type, e.g.: rv32ixabc_xdef.
144
24
145
24
    if (Name.empty()) {
146
4
      std::string Error = Desc;
147
4
      Error += " name missing after";
148
4
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
149
4
        << MArch << Error << Ext;
150
4
      return;
151
4
    }
152
20
153
20
    std::string Major, Minor;
154
20
    auto Pos = Name.find_if(isDigit);
155
20
    if (Pos != StringRef::npos) {
156
3
      auto Next =  Name.substr(Pos);
157
3
      Name = Name.substr(0, Pos);
158
3
      if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor))
159
3
        return;
160
17
    }
161
17
162
17
    // Check if duplicated extension.
163
17
    if (llvm::is_contained(AllExts, Ext)) {
164
1
      std::string Error = "duplicated ";
165
1
      Error += Desc;
166
1
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
167
1
        << MArch << Error << Ext;
168
1
      return;
169
1
    }
170
16
171
16
    // Extension format is correct, keep parsing the extensions.
172
16
    // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
173
16
    AllExts.push_back(Ext);
174
16
  }
175
18
176
18
  // Set target features.
177
18
  // TODO: Hardware features to be handled in Support/TargetParser.cpp.
178
18
  // TODO: Use version number when setting target features.
179
18
  
for (auto Ext : AllExts)6
{
180
6
    if (!isSupportedExtension(Ext)) {
181
6
      StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
182
6
      std::string Error = "unsupported ";
183
6
      Error += Desc;
184
6
      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
185
6
        << MArch << Error << Ext;
186
6
      return;
187
6
    }
188
0
    Features.push_back(Args.MakeArgString("+" + Ext));
189
0
  }
190
6
}
191
192
void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
193
166
                                   std::vector<StringRef> &Features) {
194
166
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
195
110
    StringRef MArch = A->getValue();
196
110
197
110
    // RISC-V ISA strings must be lowercase.
198
811
    if (
llvm::any_of(MArch, [](char c) 110
{ return isupper(c); })) {
199
3
      D.Diag(diag::err_drv_invalid_riscv_arch_name)
200
3
          << MArch << "string must be lowercase";
201
3
      return;
202
3
    }
203
107
204
107
    // ISA string must begin with rv32 or rv64.
205
107
    if (!(MArch.startswith("rv32") || 
MArch.startswith("rv64")38
) ||
206
107
        (MArch.size() < 5)) {
207
3
      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
208
3
        << "string must begin with rv32{i,e,g} or rv64{i,g}";
209
3
      return;
210
3
    }
211
104
212
104
    bool HasRV64 = MArch.startswith("rv64");
213
104
214
104
    // The canonical order specified in ISA manual.
215
104
    // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
216
104
    StringRef StdExts = "mafdqlcbjtpvn";
217
104
    bool HasF = false, HasD = false;
218
104
    char Baseline = MArch[4];
219
104
220
104
    // First letter should be 'e', 'i' or 'g'.
221
104
    switch (Baseline) {
222
104
    default:
223
10
      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
224
10
        << "first letter should be 'e', 'i' or 'g'";
225
10
      return;
226
104
    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)
235
2
        << MArch << Error;
236
2
      return;
237
104
    }
238
104
    case 'i':
239
86
      break;
240
104
    case 'g':
241
6
      // g = imafd
242
6
      StdExts = StdExts.drop_front(4);
243
6
      Features.push_back("+m");
244
6
      Features.push_back("+a");
245
6
      Features.push_back("+f");
246
6
      Features.push_back("+d");
247
6
      HasF = true;
248
6
      HasD = true;
249
6
      break;
250
92
    }
251
92
252
92
    // Skip rvxxx
253
92
    StringRef Exts = MArch.substr(5);
254
92
255
92
    // Remove non-standard extensions and supervisor-level extensions.
256
92
    // They have 'x', 's', 'sx' prefixes. Parse them at the end.
257
92
    // Find the very first occurrence of 's' or 'x'.
258
92
    StringRef OtherExts;
259
92
    size_t Pos = Exts.find_first_of("sx");
260
92
    if (Pos != StringRef::npos) {
261
18
      OtherExts = Exts.substr(Pos);
262
18
      Exts = Exts.substr(0, Pos);
263
18
    }
264
92
265
92
    std::string Major, Minor;
266
92
    if (!getExtensionVersion(D, MArch, std::string(1, Baseline),
267
92
                             Exts, Major, Minor))
268
4
      return;
269
88
270
88
    // TODO: Use version number when setting target features
271
88
    // and consume the underscore '_' that might follow.
272
88
273
88
    auto StdExtsItr = StdExts.begin();
274
88
    auto StdExtsEnd = StdExts.end();
275
88
276
220
    for (auto I = Exts.begin(), E = Exts.end(); I != E; 
++I132
) {
277
140
      char c = *I;
278
140
279
140
      // Check ISA extensions are specified in the canonical order.
280
333
      while (StdExtsItr != StdExtsEnd && 
*StdExtsItr != c327
)
281
193
        ++StdExtsItr;
282
140
283
140
      if (StdExtsItr == StdExtsEnd) {
284
6
        // Either c contains a valid extension but it was not given in
285
6
        // canonical order or it is an invalid extension.
286
6
        StringRef Error;
287
6
        if (StdExts.contains(c))
288
5
          Error = "standard user-level extension not given in canonical order";
289
1
        else
290
1
          Error = "invalid standard user-level extension";
291
6
        D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
292
6
          << MArch <<  Error << std::string(1, c);
293
6
        return;
294
6
      }
295
134
296
134
      // Move to next char to prevent repeated letter.
297
134
      ++StdExtsItr;
298
134
299
134
      if (std::next(I) != E) {
300
80
        // Skip c.
301
80
        std::string Next = std::string(std::next(I), E);
302
80
        std::string Major, Minor;
303
80
        if (!getExtensionVersion(D, MArch, std::string(1, c),
304
80
                                 Next, Major, Minor))
305
1
          return;
306
133
307
133
        // TODO: Use version number when setting target features
308
133
        // and consume the underscore '_' that might follow.
309
133
      }
310
133
311
133
      // The order is OK, then push it into features.
312
133
      switch (c) {
313
133
      default:
314
1
        // Currently LLVM supports only "mafdc".
315
1
        D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
316
1
          << MArch << "unsupported standard user-level extension"
317
1
          << std::string(1, c);
318
1
        return;
319
133
      case 'm':
320
28
        Features.push_back("+m");
321
28
        break;
322
133
      case 'a':
323
30
        Features.push_back("+a");
324
30
        break;
325
133
      case 'f':
326
30
        Features.push_back("+f");
327
30
        HasF = true;
328
30
        break;
329
133
      case 'd':
330
23
        Features.push_back("+d");
331
23
        HasD = true;
332
23
        break;
333
133
      case 'c':
334
21
        Features.push_back("+c");
335
21
        break;
336
133
      }
337
133
    }
338
88
339
88
    // Dependency check.
340
88
    // It's illegal to specify the 'd' (double-precision floating point)
341
88
    // extension without also specifying the 'f' (single precision
342
88
    // floating-point) extension.
343
88
    
if (80
HasD80
&&
!HasF27
)
344
2
      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
345
2
        << "d requires f extension to also be specified";
346
80
347
80
    // Additional dependency checks.
348
80
    // TODO: The 'q' extension requires rv64.
349
80
    // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
350
80
351
80
    // Handle all other types of extensions.
352
80
    getExtensionFeatures(D, Args, Features, MArch, OtherExts);
353
80
  }
354
166
355
166
  // -mrelax is default, unless -mno-relax is specified.
356
166
  
if (136
Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)136
)
357
135
    Features.push_back("+relax");
358
1
  else
359
1
    Features.push_back("-relax");
360
136
361
136
  // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
362
136
  // specified...
363
136
  if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) {
364
1
    // ... but we don't support -msave-restore, so issue a warning.
365
1
    D.Diag(diag::warn_drv_clang_unsupported)
366
1
      << Args.getLastArg(options::OPT_msave_restore)->getAsString(Args);
367
1
  }
368
136
369
136
  // Now add any that the user explicitly requested on the command line,
370
136
  // which may override the defaults.
371
136
  handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
372
136
}
373
374
59
StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
375
59
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
376
12
    return A->getValue();
377
47
378
47
  return Triple.getArch() == llvm::Triple::riscv32 ? 
"ilp32"25
:
"lp64"22
;
379
47
}