Coverage Report

Created: 2023-05-31 04:38

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Basic/Targets/LoongArch.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- LoongArch.cpp - Implement LoongArch 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 LoongArch TargetInfo objects.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "LoongArch.h"
14
#include "clang/Basic/Diagnostic.h"
15
#include "clang/Basic/MacroBuilder.h"
16
#include "clang/Basic/TargetBuiltins.h"
17
#include "llvm/Support/raw_ostream.h"
18
#include "llvm/TargetParser/TargetParser.h"
19
20
using namespace clang;
21
using namespace clang::targets;
22
23
340
ArrayRef<const char *> LoongArchTargetInfo::getGCCRegNames() const {
24
340
  static const char *const GCCRegNames[] = {
25
      // General purpose registers.
26
340
      "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", "$r8", "$r9",
27
340
      "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", "$r16", "$r17", "$r18",
28
340
      "$r19", "$r20", "$r21", "$r22", "$r23", "$r24", "$r25", "$r26", "$r27",
29
340
      "$r28", "$r29", "$r30", "$r31",
30
      // Floating point registers.
31
340
      "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",
32
340
      "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",
33
340
      "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
34
340
      "$f28", "$f29", "$f30", "$f31",
35
      // Condition flag registers.
36
340
      "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7"};
37
340
  return llvm::ArrayRef(GCCRegNames);
38
340
}
39
40
ArrayRef<TargetInfo::GCCRegAlias>
41
268
LoongArchTargetInfo::getGCCRegAliases() const {
42
268
  static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
43
268
      {{"zero", "$zero", "r0"}, "$r0"},
44
268
      {{"ra", "$ra", "r1"}, "$r1"},
45
268
      {{"tp", "$tp", "r2"}, "$r2"},
46
268
      {{"sp", "$sp", "r3"}, "$r3"},
47
268
      {{"a0", "$a0", "r4"}, "$r4"},
48
268
      {{"a1", "$a1", "r5"}, "$r5"},
49
268
      {{"a2", "$a2", "r6"}, "$r6"},
50
268
      {{"a3", "$a3", "r7"}, "$r7"},
51
268
      {{"a4", "$a4", "r8"}, "$r8"},
52
268
      {{"a5", "$a5", "r9"}, "$r9"},
53
268
      {{"a6", "$a6", "r10"}, "$r10"},
54
268
      {{"a7", "$a7", "r11"}, "$r11"},
55
268
      {{"t0", "$t0", "r12"}, "$r12"},
56
268
      {{"t1", "$t1", "r13"}, "$r13"},
57
268
      {{"t2", "$t2", "r14"}, "$r14"},
58
268
      {{"t3", "$t3", "r15"}, "$r15"},
59
268
      {{"t4", "$t4", "r16"}, "$r16"},
60
268
      {{"t5", "$t5", "r17"}, "$r17"},
61
268
      {{"t6", "$t6", "r18"}, "$r18"},
62
268
      {{"t7", "$t7", "r19"}, "$r19"},
63
268
      {{"t8", "$t8", "r20"}, "$r20"},
64
268
      {{"r21"}, "$r21"},
65
268
      {{"s9", "$s9", "r22", "fp", "$fp"}, "$r22"},
66
268
      {{"s0", "$s0", "r23"}, "$r23"},
67
268
      {{"s1", "$s1", "r24"}, "$r24"},
68
268
      {{"s2", "$s2", "r25"}, "$r25"},
69
268
      {{"s3", "$s3", "r26"}, "$r26"},
70
268
      {{"s4", "$s4", "r27"}, "$r27"},
71
268
      {{"s5", "$s5", "r28"}, "$r28"},
72
268
      {{"s6", "$s6", "r29"}, "$r29"},
73
268
      {{"s7", "$s7", "r30"}, "$r30"},
74
268
      {{"s8", "$s8", "r31"}, "$r31"},
75
268
      {{"$fa0"}, "$f0"},
76
268
      {{"$fa1"}, "$f1"},
77
268
      {{"$fa2"}, "$f2"},
78
268
      {{"$fa3"}, "$f3"},
79
268
      {{"$fa4"}, "$f4"},
80
268
      {{"$fa5"}, "$f5"},
81
268
      {{"$fa6"}, "$f6"},
82
268
      {{"$fa7"}, "$f7"},
83
268
      {{"$ft0"}, "$f8"},
84
268
      {{"$ft1"}, "$f9"},
85
268
      {{"$ft2"}, "$f10"},
86
268
      {{"$ft3"}, "$f11"},
87
268
      {{"$ft4"}, "$f12"},
88
268
      {{"$ft5"}, "$f13"},
89
268
      {{"$ft6"}, "$f14"},
90
268
      {{"$ft7"}, "$f15"},
91
268
      {{"$ft8"}, "$f16"},
92
268
      {{"$ft9"}, "$f17"},
93
268
      {{"$ft10"}, "$f18"},
94
268
      {{"$ft11"}, "$f19"},
95
268
      {{"$ft12"}, "$f20"},
96
268
      {{"$ft13"}, "$f21"},
97
268
      {{"$ft14"}, "$f22"},
98
268
      {{"$ft15"}, "$f23"},
99
268
      {{"$fs0"}, "$f24"},
100
268
      {{"$fs1"}, "$f25"},
101
268
      {{"$fs2"}, "$f26"},
102
268
      {{"$fs3"}, "$f27"},
103
268
      {{"$fs4"}, "$f28"},
104
268
      {{"$fs5"}, "$f29"},
105
268
      {{"$fs6"}, "$f30"},
106
268
      {{"$fs7"}, "$f31"},
107
268
  };
108
268
  return llvm::ArrayRef(GCCRegAliases);
109
268
}
110
111
bool LoongArchTargetInfo::validateAsmConstraint(
112
84
    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
113
  // See the GCC definitions here:
114
  // https://gcc.gnu.org/onlinedocs/gccint/Machine-Constraints.html
115
  // Note that the 'm' constraint is handled in TargetInfo.
116
84
  switch (*Name) {
117
0
  default:
118
0
    return false;
119
32
  case 'f':
120
    // A floating-point register (if available).
121
32
    Info.setAllowsRegister();
122
32
    return true;
123
4
  case 'k':
124
    // A memory operand whose address is formed by a base register and
125
    // (optionally scaled) index register.
126
4
    Info.setAllowsMemory();
127
4
    return true;
128
12
  case 'l':
129
    // A signed 16-bit constant.
130
12
    Info.setRequiresImmediate(-32768, 32767);
131
12
    return true;
132
12
  case 'I':
133
    // A signed 12-bit constant (for arithmetic instructions).
134
12
    Info.setRequiresImmediate(-2048, 2047);
135
12
    return true;
136
4
  case 'J':
137
    // Integer zero.
138
4
    Info.setRequiresImmediate(0);
139
4
    return true;
140
12
  case 'K':
141
    // An unsigned 12-bit constant (for logic instructions).
142
12
    Info.setRequiresImmediate(0, 4095);
143
12
    return true;
144
8
  case 'Z':
145
    // ZB: An address that is held in a general-purpose register. The offset is
146
    //     zero.
147
    // ZC: A memory operand whose address is formed by a base register
148
    //     and offset that is suitable for use in instructions with the same
149
    //     addressing mode as ll.w and sc.w.
150
8
    if (Name[1] == 'C' || 
Name[1] == 'B'4
) {
151
8
      Info.setAllowsMemory();
152
8
      ++Name; // Skip over 'Z'.
153
8
      return true;
154
8
    }
155
0
    return false;
156
84
  }
157
84
}
158
159
std::string
160
96
LoongArchTargetInfo::convertConstraint(const char *&Constraint) const {
161
96
  std::string R;
162
96
  switch (*Constraint) {
163
4
  case 'Z':
164
    // "ZC"/"ZB" are two-character constraints; add "^" hint for later
165
    // parsing.
166
4
    R = "^" + std::string(Constraint, 2);
167
4
    ++Constraint;
168
4
    break;
169
92
  default:
170
92
    R = TargetInfo::convertConstraint(Constraint);
171
92
    break;
172
96
  }
173
96
  return R;
174
96
}
175
176
void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts,
177
67
                                           MacroBuilder &Builder) const {
178
67
  Builder.defineMacro("__loongarch__");
179
67
  unsigned GRLen = getRegisterWidth();
180
67
  Builder.defineMacro("__loongarch_grlen", Twine(GRLen));
181
67
  if (GRLen == 64)
182
39
    Builder.defineMacro("__loongarch64");
183
184
67
  if (HasFeatureD)
185
16
    Builder.defineMacro("__loongarch_frlen", "64");
186
51
  else if (HasFeatureF)
187
10
    Builder.defineMacro("__loongarch_frlen", "32");
188
41
  else
189
41
    Builder.defineMacro("__loongarch_frlen", "0");
190
191
  // TODO: define __loongarch_arch and __loongarch_tune.
192
193
67
  StringRef ABI = getABI();
194
67
  if (ABI == "lp64d" || 
ABI == "lp64f"41
||
ABI == "lp64s"36
)
195
39
    Builder.defineMacro("__loongarch_lp64");
196
197
67
  if (ABI == "lp64d" || 
ABI == "ilp32d"41
) {
198
46
    Builder.defineMacro("__loongarch_hard_float");
199
46
    Builder.defineMacro("__loongarch_double_float");
200
46
  } else 
if (21
ABI == "lp64f"21
||
ABI == "ilp32f"16
) {
201
8
    Builder.defineMacro("__loongarch_hard_float");
202
8
    Builder.defineMacro("__loongarch_single_float");
203
13
  } else if (ABI == "lp64s" || 
ABI == "ilp32s"5
) {
204
13
    Builder.defineMacro("__loongarch_soft_float");
205
13
  }
206
207
67
  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
208
67
  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
209
67
  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
210
67
  if (GRLen == 64)
211
39
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
212
67
}
213
214
static constexpr Builtin::Info BuiltinInfo[] = {
215
#define BUILTIN(ID, TYPE, ATTRS)                                               \
216
  {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
217
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
218
  {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
219
#include "clang/Basic/BuiltinsLoongArch.def"
220
};
221
222
bool LoongArchTargetInfo::initFeatureMap(
223
    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
224
67
    const std::vector<std::string> &FeaturesVec) const {
225
67
  if (getTriple().getArch() == llvm::Triple::loongarch64)
226
39
    Features["64bit"] = true;
227
67
  if (getTriple().getArch() == llvm::Triple::loongarch32)
228
28
    Features["32bit"] = true;
229
230
67
  return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
231
67
}
232
233
/// Return true if has this feature.
234
109
bool LoongArchTargetInfo::hasFeature(StringRef Feature) const {
235
109
  bool Is64Bit = getTriple().getArch() == llvm::Triple::loongarch64;
236
  // TODO: Handle more features.
237
109
  return llvm::StringSwitch<bool>(Feature)
238
109
      .Case("loongarch32", !Is64Bit)
239
109
      .Case("loongarch64", Is64Bit)
240
109
      .Case("32bit", !Is64Bit)
241
109
      .Case("64bit", Is64Bit)
242
109
      .Default(false);
243
109
}
244
245
67
ArrayRef<Builtin::Info> LoongArchTargetInfo::getTargetBuiltins() const {
246
67
  return llvm::ArrayRef(BuiltinInfo, clang::LoongArch::LastTSBuiltin -
247
67
                                         Builtin::FirstTSBuiltin);
248
67
}
249
250
bool LoongArchTargetInfo::handleTargetFeatures(
251
67
    std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
252
137
  for (const auto &Feature : Features) {
253
137
    if (Feature == "+d" || 
Feature == "+f"121
) {
254
      // "d" implies "f".
255
42
      HasFeatureF = true;
256
42
      if (Feature == "+d") {
257
16
        HasFeatureD = true;
258
16
      }
259
42
    }
260
137
  }
261
67
  return true;
262
67
}