Coverage Report

Created: 2022-05-17 06:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Basic/Targets/RISCV.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- RISCV.cpp - Implement RISCV target feature support ---------------===//
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
// This file implements RISCV TargetInfo objects.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "RISCV.h"
14
#include "clang/Basic/Diagnostic.h"
15
#include "clang/Basic/MacroBuilder.h"
16
#include "clang/Basic/TargetBuiltins.h"
17
#include "llvm/ADT/StringSwitch.h"
18
#include "llvm/Support/TargetParser.h"
19
#include "llvm/Support/raw_ostream.h"
20
21
using namespace clang;
22
using namespace clang::targets;
23
24
818
ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
25
818
  static const char *const GCCRegNames[] = {
26
      // Integer registers
27
818
      "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
28
818
      "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
29
818
      "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
30
818
      "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
31
32
      // Floating point registers
33
818
      "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
34
818
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
35
818
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
36
818
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
37
38
      // Vector registers
39
818
      "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
40
818
      "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
41
818
      "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
42
818
      "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
43
818
  return llvm::makeArrayRef(GCCRegNames);
44
818
}
45
46
536
ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
47
536
  static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
48
536
      {{"zero"}, "x0"}, {{"ra"}, "x1"},   {{"sp"}, "x2"},    {{"gp"}, "x3"},
49
536
      {{"tp"}, "x4"},   {{"t0"}, "x5"},   {{"t1"}, "x6"},    {{"t2"}, "x7"},
50
536
      {{"s0"}, "x8"},   {{"s1"}, "x9"},   {{"a0"}, "x10"},   {{"a1"}, "x11"},
51
536
      {{"a2"}, "x12"},  {{"a3"}, "x13"},  {{"a4"}, "x14"},   {{"a5"}, "x15"},
52
536
      {{"a6"}, "x16"},  {{"a7"}, "x17"},  {{"s2"}, "x18"},   {{"s3"}, "x19"},
53
536
      {{"s4"}, "x20"},  {{"s5"}, "x21"},  {{"s6"}, "x22"},   {{"s7"}, "x23"},
54
536
      {{"s8"}, "x24"},  {{"s9"}, "x25"},  {{"s10"}, "x26"},  {{"s11"}, "x27"},
55
536
      {{"t3"}, "x28"},  {{"t4"}, "x29"},  {{"t5"}, "x30"},   {{"t6"}, "x31"},
56
536
      {{"ft0"}, "f0"},  {{"ft1"}, "f1"},  {{"ft2"}, "f2"},   {{"ft3"}, "f3"},
57
536
      {{"ft4"}, "f4"},  {{"ft5"}, "f5"},  {{"ft6"}, "f6"},   {{"ft7"}, "f7"},
58
536
      {{"fs0"}, "f8"},  {{"fs1"}, "f9"},  {{"fa0"}, "f10"},  {{"fa1"}, "f11"},
59
536
      {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"},  {{"fa5"}, "f15"},
60
536
      {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"},  {{"fs3"}, "f19"},
61
536
      {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"},  {{"fs7"}, "f23"},
62
536
      {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
63
536
      {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
64
536
  return llvm::makeArrayRef(GCCRegAliases);
65
536
}
66
67
bool RISCVTargetInfo::validateAsmConstraint(
68
48
    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
69
48
  switch (*Name) {
70
0
  default:
71
0
    return false;
72
12
  case 'I':
73
    // A 12-bit signed immediate.
74
12
    Info.setRequiresImmediate(-2048, 2047);
75
12
    return true;
76
8
  case 'J':
77
    // Integer zero.
78
8
    Info.setRequiresImmediate(0);
79
8
    return true;
80
12
  case 'K':
81
    // A 5-bit unsigned immediate for CSR access instructions.
82
12
    Info.setRequiresImmediate(0, 31);
83
12
    return true;
84
8
  case 'f':
85
    // A floating-point register.
86
8
    Info.setAllowsRegister();
87
8
    return true;
88
4
  case 'A':
89
    // An address that is held in a general-purpose register.
90
4
    Info.setAllowsMemory();
91
4
    return true;
92
4
  case 'S': // A symbolic address
93
4
    Info.setAllowsRegister();
94
4
    return true;
95
0
  case 'v':
96
    // A vector register.
97
0
    if (Name[1] == 'r' || Name[1] == 'm') {
98
0
      Info.setAllowsRegister();
99
0
      Name += 1;
100
0
      return true;
101
0
    }
102
0
    return false;
103
48
  }
104
48
}
105
106
18
std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
107
18
  std::string R;
108
18
  switch (*Constraint) {
109
0
  case 'v':
110
0
    R = std::string("^") + std::string(Constraint, 2);
111
0
    Constraint += 1;
112
0
    break;
113
18
  default:
114
18
    R = TargetInfo::convertConstraint(Constraint);
115
18
    break;
116
18
  }
117
18
  return R;
118
18
}
119
120
void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
121
242
                                       MacroBuilder &Builder) const {
122
242
  Builder.defineMacro("__ELF__");
123
242
  Builder.defineMacro("__riscv");
124
242
  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
125
242
  Builder.defineMacro("__riscv_xlen", Is64Bit ? 
"64"141
:
"32"101
);
126
242
  StringRef CodeModel = getTargetOpts().CodeModel;
127
242
  unsigned FLen = ISAInfo->getFLen();
128
242
  unsigned MinVLen = ISAInfo->getMinVLen();
129
242
  unsigned MaxELen = ISAInfo->getMaxELen();
130
242
  unsigned MaxELenFp = ISAInfo->getMaxELenFp();
131
242
  if (CodeModel == "default")
132
233
    CodeModel = "small";
133
134
242
  if (CodeModel == "small")
135
237
    Builder.defineMacro("__riscv_cmodel_medlow");
136
5
  else if (CodeModel == "medium")
137
4
    Builder.defineMacro("__riscv_cmodel_medany");
138
139
242
  StringRef ABIName = getABI();
140
242
  if (ABIName == "ilp32f" || 
ABIName == "lp64f"236
)
141
11
    Builder.defineMacro("__riscv_float_abi_single");
142
231
  else if (ABIName == "ilp32d" || 
ABIName == "lp64d"218
)
143
44
    Builder.defineMacro("__riscv_float_abi_double");
144
187
  else
145
187
    Builder.defineMacro("__riscv_float_abi_soft");
146
147
242
  if (ABIName == "ilp32e")
148
0
    Builder.defineMacro("__riscv_abi_rve");
149
150
242
  Builder.defineMacro("__riscv_arch_test");
151
152
786
  for (auto &Extension : ISAInfo->getExtensions()) {
153
786
    auto ExtName = Extension.first;
154
786
    auto ExtInfo = Extension.second;
155
786
    unsigned Version =
156
786
        (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000);
157
158
786
    Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
159
786
  }
160
161
242
  if (ISAInfo->hasExtension("m")) {
162
32
    Builder.defineMacro("__riscv_mul");
163
32
    Builder.defineMacro("__riscv_div");
164
32
    Builder.defineMacro("__riscv_muldiv");
165
32
  }
166
167
242
  if (ISAInfo->hasExtension("a")) {
168
34
    Builder.defineMacro("__riscv_atomic");
169
34
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
170
34
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
171
34
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
172
34
    if (Is64Bit)
173
21
      Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
174
34
  }
175
176
242
  if (FLen) {
177
65
    Builder.defineMacro("__riscv_flen", Twine(FLen));
178
65
    Builder.defineMacro("__riscv_fdiv");
179
65
    Builder.defineMacro("__riscv_fsqrt");
180
65
  }
181
182
242
  if (MinVLen) {
183
20
    Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
184
20
    Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));
185
20
    Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));
186
20
  }
187
188
242
  if (ISAInfo->hasExtension("c"))
189
32
    Builder.defineMacro("__riscv_compressed");
190
191
242
  if (ISAInfo->hasExtension("zve32x"))
192
20
    Builder.defineMacro("__riscv_vector");
193
242
}
194
195
const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = {
196
#define BUILTIN(ID, TYPE, ATTRS)                                               \
197
  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
198
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
199
    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
200
#include "clang/Basic/BuiltinsRISCVVector.def"
201
#define BUILTIN(ID, TYPE, ATTRS)                                               \
202
  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
203
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
204
    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
205
#include "clang/Basic/BuiltinsRISCV.def"
206
};
207
208
242
ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
209
242
  return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
210
242
                                             Builtin::FirstTSBuiltin);
211
242
}
212
213
bool RISCVTargetInfo::initFeatureMap(
214
    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
215
243
    const std::vector<std::string> &FeaturesVec) const {
216
217
243
  unsigned XLen = 32;
218
219
243
  if (getTriple().getArch() == llvm::Triple::riscv64) {
220
142
    Features["64bit"] = true;
221
142
    XLen = 64;
222
142
  }
223
224
243
  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
225
243
  if (!ParseResult) {
226
1
    std::string Buffer;
227
1
    llvm::raw_string_ostream OutputErrMsg(Buffer);
228
1
    handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
229
1
      OutputErrMsg << ErrMsg.getMessage();
230
1
    });
231
1
    Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
232
1
    return false;
233
1
  }
234
235
  // RISCVISAInfo makes implications for ISA features
236
242
  std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
237
  // Add non-ISA features like `relax` and `save-restore` back
238
763
  for (std::string Feature : FeaturesVec) {
239
763
    if (std::find(begin(ImpliedFeatures), end(ImpliedFeatures), Feature) ==
240
763
        end(ImpliedFeatures))
241
249
      ImpliedFeatures.push_back(Feature);
242
763
  }
243
244
242
  return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
245
243
}
246
247
/// Return true if has this feature, need to sync with handleTargetFeatures.
248
297
bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
249
297
  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
250
297
  auto Result = llvm::StringSwitch<Optional<bool>>(Feature)
251
297
                    .Case("riscv", true)
252
297
                    .Case("riscv32", !Is64Bit)
253
297
                    .Case("riscv64", Is64Bit)
254
297
                    .Case("64bit", Is64Bit)
255
297
                    .Default(None);
256
297
  if (Result.hasValue())
257
34
    return Result.getValue();
258
259
263
  if (ISAInfo->isSupportedExtensionFeature(Feature))
260
147
    return ISAInfo->hasExtension(Feature);
261
262
116
  return false;
263
263
}
264
265
/// Perform initialization based on the user configured set of features.
266
bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
267
242
                                           DiagnosticsEngine &Diags) {
268
242
  unsigned XLen = getTriple().isArch64Bit() ? 
64141
:
32101
;
269
242
  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
270
242
  if (!ParseResult) {
271
0
    std::string Buffer;
272
0
    llvm::raw_string_ostream OutputErrMsg(Buffer);
273
0
    handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
274
0
      OutputErrMsg << ErrMsg.getMessage();
275
0
    });
276
0
    Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
277
0
    return false;
278
242
  } else {
279
242
    ISAInfo = std::move(*ParseResult);
280
242
  }
281
282
242
  if (ABI.empty())
283
98
    ABI = ISAInfo->computeDefaultABI().str();
284
285
242
  return true;
286
242
}
287
288
2
bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
289
2
  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
290
2
                                   /*Is64Bit=*/false);
291
2
}
292
293
void RISCV32TargetInfo::fillValidCPUList(
294
1
    SmallVectorImpl<StringRef> &Values) const {
295
1
  llvm::RISCV::fillValidCPUArchList(Values, false);
296
1
}
297
298
1
bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
299
1
  return llvm::RISCV::checkTuneCPUKind(
300
1
      llvm::RISCV::parseTuneCPUKind(Name, false),
301
1
      /*Is64Bit=*/false);
302
1
}
303
304
void RISCV32TargetInfo::fillValidTuneCPUList(
305
1
    SmallVectorImpl<StringRef> &Values) const {
306
1
  llvm::RISCV::fillValidTuneCPUArchList(Values, false);
307
1
}
308
309
2
bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
310
2
  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
311
2
                                   /*Is64Bit=*/true);
312
2
}
313
314
void RISCV64TargetInfo::fillValidCPUList(
315
1
    SmallVectorImpl<StringRef> &Values) const {
316
1
  llvm::RISCV::fillValidCPUArchList(Values, true);
317
1
}
318
319
1
bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
320
1
  return llvm::RISCV::checkTuneCPUKind(
321
1
      llvm::RISCV::parseTuneCPUKind(Name, true),
322
1
      /*Is64Bit=*/true);
323
1
}
324
325
void RISCV64TargetInfo::fillValidTuneCPUList(
326
1
    SmallVectorImpl<StringRef> &Values) const {
327
1
  llvm::RISCV::fillValidTuneCPUArchList(Values, true);
328
1
}