Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
35294 views
1
//= LoongArchBaseInfo.cpp - Top level definitions for LoongArch MC -*- 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
// This file implements helper functions for the LoongArch target useful for the
10
// compiler back-end and the MC libraries.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "LoongArchBaseInfo.h"
15
#include "LoongArchMCTargetDesc.h"
16
#include "llvm/ADT/ArrayRef.h"
17
#include "llvm/MC/MCSubtargetInfo.h"
18
#include "llvm/Support/ErrorHandling.h"
19
#include "llvm/Support/raw_ostream.h"
20
#include "llvm/TargetParser/Triple.h"
21
22
namespace llvm {
23
24
namespace LoongArchABI {
25
26
// Check if ABI has been standardized; issue a warning if it hasn't.
27
// FIXME: Once all ABIs are standardized, this will be removed.
28
static ABI checkABIStandardized(ABI Abi) {
29
StringRef ABIName;
30
switch (Abi) {
31
case ABI_ILP32S:
32
ABIName = "ilp32s";
33
break;
34
case ABI_ILP32F:
35
ABIName = "ilp32f";
36
break;
37
case ABI_ILP32D:
38
ABIName = "ilp32d";
39
break;
40
case ABI_LP64F:
41
ABIName = "lp64f";
42
break;
43
case ABI_LP64S:
44
case ABI_LP64D:
45
return Abi;
46
default:
47
llvm_unreachable("");
48
}
49
errs() << "warning: '" << ABIName << "' has not been standardized\n";
50
return Abi;
51
}
52
53
static ABI getTripleABI(const Triple &TT) {
54
bool Is64Bit = TT.isArch64Bit();
55
ABI TripleABI;
56
switch (TT.getEnvironment()) {
57
case llvm::Triple::EnvironmentType::GNUSF:
58
TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S;
59
break;
60
case llvm::Triple::EnvironmentType::GNUF32:
61
TripleABI = Is64Bit ? ABI_LP64F : ABI_ILP32F;
62
break;
63
// Let the fallback case behave like {ILP32,LP64}D.
64
case llvm::Triple::EnvironmentType::GNUF64:
65
default:
66
TripleABI = Is64Bit ? ABI_LP64D : ABI_ILP32D;
67
break;
68
}
69
return TripleABI;
70
}
71
72
ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,
73
StringRef ABIName) {
74
bool Is64Bit = TT.isArch64Bit();
75
ABI ArgProvidedABI = getTargetABI(ABIName);
76
ABI TripleABI = getTripleABI(TT);
77
78
auto IsABIValidForFeature = [=](ABI Abi) {
79
switch (Abi) {
80
default:
81
return false;
82
case ABI_ILP32S:
83
return !Is64Bit;
84
case ABI_ILP32F:
85
return !Is64Bit && FeatureBits[LoongArch::FeatureBasicF];
86
case ABI_ILP32D:
87
return !Is64Bit && FeatureBits[LoongArch::FeatureBasicD];
88
case ABI_LP64S:
89
return Is64Bit;
90
case ABI_LP64F:
91
return Is64Bit && FeatureBits[LoongArch::FeatureBasicF];
92
case ABI_LP64D:
93
return Is64Bit && FeatureBits[LoongArch::FeatureBasicD];
94
}
95
};
96
97
// 1. If the '-target-abi' is valid, use it.
98
if (IsABIValidForFeature(ArgProvidedABI)) {
99
if (TT.hasEnvironment() && ArgProvidedABI != TripleABI)
100
errs()
101
<< "warning: triple-implied ABI conflicts with provided target-abi '"
102
<< ABIName << "', using target-abi\n";
103
return checkABIStandardized(ArgProvidedABI);
104
}
105
106
// 2. If the triple-implied ABI is valid, use it.
107
if (IsABIValidForFeature(TripleABI)) {
108
// If target-abi is not specified, use the valid triple-implied ABI.
109
if (ABIName.empty())
110
return checkABIStandardized(TripleABI);
111
112
switch (ArgProvidedABI) {
113
case ABI_Unknown:
114
// Fallback to the triple-implied ABI if ABI name is specified but
115
// invalid.
116
errs() << "warning: the '" << ABIName
117
<< "' is not a recognized ABI for this target, ignoring and "
118
"using triple-implied ABI\n";
119
return checkABIStandardized(TripleABI);
120
case ABI_ILP32S:
121
case ABI_ILP32F:
122
case ABI_ILP32D:
123
if (Is64Bit) {
124
errs() << "warning: 32-bit ABIs are not supported for 64-bit targets, "
125
"ignoring and using triple-implied ABI\n";
126
return checkABIStandardized(TripleABI);
127
}
128
break;
129
case ABI_LP64S:
130
case ABI_LP64F:
131
case ABI_LP64D:
132
if (!Is64Bit) {
133
errs() << "warning: 64-bit ABIs are not supported for 32-bit targets, "
134
"ignoring and using triple-implied ABI\n";
135
return checkABIStandardized(TripleABI);
136
}
137
break;
138
}
139
140
switch (ArgProvidedABI) {
141
case ABI_ILP32F:
142
case ABI_LP64F:
143
errs() << "warning: the '" << ABIName
144
<< "' ABI can't be used for a target that doesn't support the 'F' "
145
"instruction set, ignoring and using triple-implied ABI\n";
146
break;
147
case ABI_ILP32D:
148
case ABI_LP64D:
149
errs() << "warning: the '" << ABIName
150
<< "' ABI can't be used for a target that doesn't support the 'D' "
151
"instruction set, ignoring and using triple-implied ABI\n";
152
break;
153
default:
154
llvm_unreachable("");
155
}
156
return checkABIStandardized(TripleABI);
157
}
158
159
// 3. Parse the 'feature-abi', and use it.
160
auto GetFeatureABI = [=]() {
161
if (FeatureBits[LoongArch::FeatureBasicD])
162
return Is64Bit ? ABI_LP64D : ABI_ILP32D;
163
if (FeatureBits[LoongArch::FeatureBasicF])
164
return Is64Bit ? ABI_LP64F : ABI_ILP32F;
165
return Is64Bit ? ABI_LP64S : ABI_ILP32S;
166
};
167
if (ABIName.empty())
168
errs() << "warning: the triple-implied ABI is invalid, ignoring and using "
169
"feature-implied ABI\n";
170
else
171
errs() << "warning: both target-abi and the triple-implied ABI are "
172
"invalid, ignoring and using feature-implied ABI\n";
173
return checkABIStandardized(GetFeatureABI());
174
}
175
176
ABI getTargetABI(StringRef ABIName) {
177
auto TargetABI = StringSwitch<ABI>(ABIName)
178
.Case("ilp32s", ABI_ILP32S)
179
.Case("ilp32f", ABI_ILP32F)
180
.Case("ilp32d", ABI_ILP32D)
181
.Case("lp64s", ABI_LP64S)
182
.Case("lp64f", ABI_LP64F)
183
.Case("lp64d", ABI_LP64D)
184
.Default(ABI_Unknown);
185
return TargetABI;
186
}
187
188
// To avoid the BP value clobbered by a function call, we need to choose a
189
// callee saved register to save the value. The `last` `S` register (s9) is
190
// used for FP. So we choose the previous (s8) as BP.
191
MCRegister getBPReg() { return LoongArch::R31; }
192
193
} // end namespace LoongArchABI
194
195
} // end namespace llvm
196
197