Coverage Report

Created: 2022-07-16 07:03

/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
248
                                       MacroBuilder &Builder) const {
122
248
  Builder.defineMacro("__ELF__");
123
248
  Builder.defineMacro("__riscv");
124
248
  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
125
248
  Builder.defineMacro("__riscv_xlen", Is64Bit ? 
"64"144
:
"32"104
);
126
248
  StringRef CodeModel = getTargetOpts().CodeModel;
127
248
  unsigned FLen = ISAInfo->getFLen();
128
248
  unsigned MinVLen = ISAInfo->getMinVLen();
129
248
  unsigned MaxELen = ISAInfo->getMaxELen();
130
248
  unsigned MaxELenFp = ISAInfo->getMaxELenFp();
131
248
  if (CodeModel == "default")
132
239
    CodeModel = "small";
133
134
248
  if (CodeModel == "small")
135
243
    Builder.defineMacro("__riscv_cmodel_medlow");
136
5
  else if (CodeModel == "medium")
137
4
    Builder.defineMacro("__riscv_cmodel_medany");
138
139
248
  StringRef ABIName = getABI();
140
248
  if (ABIName == "ilp32f" || 
ABIName == "lp64f"242
)
141
11
    Builder.defineMacro("__riscv_float_abi_single");
142
237
  else if (ABIName == "ilp32d" || 
ABIName == "lp64d"224
)
143
44
    Builder.defineMacro("__riscv_float_abi_double");
144
193
  else
145
193
    Builder.defineMacro("__riscv_float_abi_soft");
146
147
248
  if (ABIName == "ilp32e")
148
0
    Builder.defineMacro("__riscv_abi_rve");
149
150
248
  Builder.defineMacro("__riscv_arch_test");
151
152
798
  for (auto &Extension : ISAInfo->getExtensions()) {
153
798
    auto ExtName = Extension.first;
154
798
    auto ExtInfo = Extension.second;
155
798
    unsigned Version =
156
798
        (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000);
157
158
798
    Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
159
798
  }
160
161
248
  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
248
  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
248
  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
248
  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
248
  if (ISAInfo->hasExtension("c"))
189
32
    Builder.defineMacro("__riscv_compressed");
190
191
248
  if (ISAInfo->hasExtension("zve32x"))
192
20
    Builder.defineMacro("__riscv_vector");
193
248
}
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
248
ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
209
248
  return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
210
248
                                             Builtin::FirstTSBuiltin);
211
248
}
212
213
bool RISCVTargetInfo::initFeatureMap(
214
    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
215
249
    const std::vector<std::string> &FeaturesVec) const {
216
217
249
  unsigned XLen = 32;
218
219
249
  if (getTriple().getArch() == llvm::Triple::riscv64) {
220
145
    Features["64bit"] = true;
221
145
    XLen = 64;
222
145
  }
223
224
249
  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
225
249
  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
248
  std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
237
  // Add non-ISA features like `relax` and `save-restore` back
238
248
  for (const std::string &Feature : FeaturesVec)
239
781
    if (!llvm::is_contained(ImpliedFeatures, Feature))
240
261
      ImpliedFeatures.push_back(Feature);
241
242
248
  return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
243
249
}
244
245
/// Return true if has this feature, need to sync with handleTargetFeatures.
246
297
bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
247
297
  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
248
297
  auto Result = llvm::StringSwitch<Optional<bool>>(Feature)
249
297
                    .Case("riscv", true)
250
297
                    .Case("riscv32", !Is64Bit)
251
297
                    .Case("riscv64", Is64Bit)
252
297
                    .Case("64bit", Is64Bit)
253
297
                    .Default(None);
254
297
  if (Result)
255
34
    return Result.value();
256
257
263
  if (ISAInfo->isSupportedExtensionFeature(Feature))
258
147
    return ISAInfo->hasExtension(Feature);
259
260
116
  return false;
261
263
}
262
263
/// Perform initialization based on the user configured set of features.
264
bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
265
248
                                           DiagnosticsEngine &Diags) {
266
248
  unsigned XLen = getTriple().isArch64Bit() ? 
64144
:
32104
;
267
248
  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
268
248
  if (!ParseResult) {
269
0
    std::string Buffer;
270
0
    llvm::raw_string_ostream OutputErrMsg(Buffer);
271
0
    handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
272
0
      OutputErrMsg << ErrMsg.getMessage();
273
0
    });
274
0
    Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
275
0
    return false;
276
248
  } else {
277
248
    ISAInfo = std::move(*ParseResult);
278
248
  }
279
280
248
  if (ABI.empty())
281
98
    ABI = ISAInfo->computeDefaultABI().str();
282
283
248
  return true;
284
248
}
285
286
2
bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
287
2
  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
288
2
                                   /*Is64Bit=*/false);
289
2
}
290
291
void RISCV32TargetInfo::fillValidCPUList(
292
1
    SmallVectorImpl<StringRef> &Values) const {
293
1
  llvm::RISCV::fillValidCPUArchList(Values, false);
294
1
}
295
296
1
bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
297
1
  return llvm::RISCV::checkTuneCPUKind(
298
1
      llvm::RISCV::parseTuneCPUKind(Name, false),
299
1
      /*Is64Bit=*/false);
300
1
}
301
302
void RISCV32TargetInfo::fillValidTuneCPUList(
303
1
    SmallVectorImpl<StringRef> &Values) const {
304
1
  llvm::RISCV::fillValidTuneCPUArchList(Values, false);
305
1
}
306
307
2
bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
308
2
  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
309
2
                                   /*Is64Bit=*/true);
310
2
}
311
312
void RISCV64TargetInfo::fillValidCPUList(
313
1
    SmallVectorImpl<StringRef> &Values) const {
314
1
  llvm::RISCV::fillValidCPUArchList(Values, true);
315
1
}
316
317
1
bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
318
1
  return llvm::RISCV::checkTuneCPUKind(
319
1
      llvm::RISCV::parseTuneCPUKind(Name, true),
320
1
      /*Is64Bit=*/true);
321
1
}
322
323
void RISCV64TargetInfo::fillValidTuneCPUList(
324
1
    SmallVectorImpl<StringRef> &Values) const {
325
1
  llvm::RISCV::fillValidTuneCPUArchList(Values, true);
326
1
}