Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
35290 views
1
//===- CodeGenIntrinsics.cpp - Intrinsic Class Wrapper --------------------===//
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 defines a wrapper class for the 'Intrinsic' TableGen class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "CodeGenIntrinsics.h"
14
#include "llvm/ADT/ArrayRef.h"
15
#include "llvm/ADT/STLExtras.h"
16
#include "llvm/ADT/Twine.h"
17
#include "llvm/Support/ErrorHandling.h"
18
#include "llvm/TableGen/Error.h"
19
#include "llvm/TableGen/Record.h"
20
#include <algorithm>
21
#include <cassert>
22
using namespace llvm;
23
24
//===----------------------------------------------------------------------===//
25
// CodeGenIntrinsic Implementation
26
//===----------------------------------------------------------------------===//
27
28
CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
29
std::vector<Record *> IntrProperties =
30
RC.getAllDerivedDefinitions("IntrinsicProperty");
31
32
std::vector<Record *> DefaultProperties;
33
for (Record *Rec : IntrProperties)
34
if (Rec->getValueAsBit("IsDefault"))
35
DefaultProperties.push_back(Rec);
36
37
std::vector<Record *> Defs = RC.getAllDerivedDefinitions("Intrinsic");
38
Intrinsics.reserve(Defs.size());
39
40
for (unsigned I = 0, e = Defs.size(); I != e; ++I)
41
Intrinsics.push_back(CodeGenIntrinsic(Defs[I], DefaultProperties));
42
43
llvm::sort(Intrinsics,
44
[](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
45
return std::tie(LHS.TargetPrefix, LHS.Name) <
46
std::tie(RHS.TargetPrefix, RHS.Name);
47
});
48
Targets.push_back({"", 0, 0});
49
for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
50
if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
51
Targets.back().Count = I - Targets.back().Offset;
52
Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
53
}
54
Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
55
}
56
57
CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
58
ArrayRef<Record *> DefaultProperties) {
59
TheDef = R;
60
std::string DefName = std::string(R->getName());
61
ArrayRef<SMLoc> DefLoc = R->getLoc();
62
Properties = 0;
63
isOverloaded = false;
64
isCommutative = false;
65
canThrow = false;
66
isNoReturn = false;
67
isNoCallback = false;
68
isNoSync = false;
69
isNoFree = false;
70
isWillReturn = false;
71
isCold = false;
72
isNoDuplicate = false;
73
isNoMerge = false;
74
isConvergent = false;
75
isSpeculatable = false;
76
hasSideEffects = false;
77
isStrictFP = false;
78
79
if (DefName.size() <= 4 || DefName.substr(0, 4) != "int_")
80
PrintFatalError(DefLoc,
81
"Intrinsic '" + DefName + "' does not start with 'int_'!");
82
83
EnumName = DefName.substr(4);
84
85
if (R->getValue(
86
"ClangBuiltinName")) // Ignore a missing ClangBuiltinName field.
87
ClangBuiltinName = std::string(R->getValueAsString("ClangBuiltinName"));
88
if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field.
89
MSBuiltinName = std::string(R->getValueAsString("MSBuiltinName"));
90
91
TargetPrefix = std::string(R->getValueAsString("TargetPrefix"));
92
Name = std::string(R->getValueAsString("LLVMName"));
93
94
if (Name == "") {
95
// If an explicit name isn't specified, derive one from the DefName.
96
Name = "llvm.";
97
98
for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
99
Name += (EnumName[i] == '_') ? '.' : EnumName[i];
100
} else {
101
// Verify it starts with "llvm.".
102
if (Name.size() <= 5 || Name.substr(0, 5) != "llvm.")
103
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
104
"'s name does not start with 'llvm.'!");
105
}
106
107
// If TargetPrefix is specified, make sure that Name starts with
108
// "llvm.<targetprefix>.".
109
if (!TargetPrefix.empty()) {
110
if (Name.size() < 6 + TargetPrefix.size() ||
111
Name.substr(5, 1 + TargetPrefix.size()) != (TargetPrefix + "."))
112
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
113
"' does not start with 'llvm." +
114
TargetPrefix + ".'!");
115
}
116
117
if (auto *Types = R->getValue("Types")) {
118
auto *TypeList = cast<ListInit>(Types->getValue());
119
isOverloaded = R->getValueAsBit("isOverloaded");
120
121
unsigned I = 0;
122
for (unsigned E = R->getValueAsListInit("RetTypes")->size(); I < E; ++I)
123
IS.RetTys.push_back(TypeList->getElementAsRecord(I));
124
125
for (unsigned E = TypeList->size(); I < E; ++I)
126
IS.ParamTys.push_back(TypeList->getElementAsRecord(I));
127
}
128
129
// Parse the intrinsic properties.
130
ListInit *PropList = R->getValueAsListInit("IntrProperties");
131
for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
132
Record *Property = PropList->getElementAsRecord(i);
133
assert(Property->isSubClassOf("IntrinsicProperty") &&
134
"Expected a property!");
135
136
setProperty(Property);
137
}
138
139
// Set default properties to true.
140
setDefaultProperties(R, DefaultProperties);
141
142
// Also record the SDPatternOperator Properties.
143
Properties = parseSDPatternOperatorProperties(R);
144
145
// Sort the argument attributes for later benefit.
146
for (auto &Attrs : ArgumentAttributes)
147
llvm::sort(Attrs);
148
}
149
150
void CodeGenIntrinsic::setDefaultProperties(
151
Record *R, ArrayRef<Record *> DefaultProperties) {
152
// opt-out of using default attributes.
153
if (R->getValueAsBit("DisableDefaultAttributes"))
154
return;
155
156
for (Record *Rec : DefaultProperties)
157
setProperty(Rec);
158
}
159
160
void CodeGenIntrinsic::setProperty(Record *R) {
161
if (R->getName() == "IntrNoMem")
162
ME = MemoryEffects::none();
163
else if (R->getName() == "IntrReadMem") {
164
if (ME.onlyWritesMemory())
165
PrintFatalError(TheDef->getLoc(),
166
Twine("IntrReadMem cannot be used after IntrNoMem or "
167
"IntrWriteMem. Default is ReadWrite"));
168
ME &= MemoryEffects::readOnly();
169
} else if (R->getName() == "IntrWriteMem") {
170
if (ME.onlyReadsMemory())
171
PrintFatalError(TheDef->getLoc(),
172
Twine("IntrWriteMem cannot be used after IntrNoMem or "
173
"IntrReadMem. Default is ReadWrite"));
174
ME &= MemoryEffects::writeOnly();
175
} else if (R->getName() == "IntrArgMemOnly")
176
ME &= MemoryEffects::argMemOnly();
177
else if (R->getName() == "IntrInaccessibleMemOnly")
178
ME &= MemoryEffects::inaccessibleMemOnly();
179
else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
180
ME &= MemoryEffects::inaccessibleOrArgMemOnly();
181
else if (R->getName() == "Commutative")
182
isCommutative = true;
183
else if (R->getName() == "Throws")
184
canThrow = true;
185
else if (R->getName() == "IntrNoDuplicate")
186
isNoDuplicate = true;
187
else if (R->getName() == "IntrNoMerge")
188
isNoMerge = true;
189
else if (R->getName() == "IntrConvergent")
190
isConvergent = true;
191
else if (R->getName() == "IntrNoReturn")
192
isNoReturn = true;
193
else if (R->getName() == "IntrNoCallback")
194
isNoCallback = true;
195
else if (R->getName() == "IntrNoSync")
196
isNoSync = true;
197
else if (R->getName() == "IntrNoFree")
198
isNoFree = true;
199
else if (R->getName() == "IntrWillReturn")
200
isWillReturn = !isNoReturn;
201
else if (R->getName() == "IntrCold")
202
isCold = true;
203
else if (R->getName() == "IntrSpeculatable")
204
isSpeculatable = true;
205
else if (R->getName() == "IntrHasSideEffects")
206
hasSideEffects = true;
207
else if (R->getName() == "IntrStrictFP")
208
isStrictFP = true;
209
else if (R->isSubClassOf("NoCapture")) {
210
unsigned ArgNo = R->getValueAsInt("ArgNo");
211
addArgAttribute(ArgNo, NoCapture);
212
} else if (R->isSubClassOf("NoAlias")) {
213
unsigned ArgNo = R->getValueAsInt("ArgNo");
214
addArgAttribute(ArgNo, NoAlias);
215
} else if (R->isSubClassOf("NoUndef")) {
216
unsigned ArgNo = R->getValueAsInt("ArgNo");
217
addArgAttribute(ArgNo, NoUndef);
218
} else if (R->isSubClassOf("NonNull")) {
219
unsigned ArgNo = R->getValueAsInt("ArgNo");
220
addArgAttribute(ArgNo, NonNull);
221
} else if (R->isSubClassOf("Returned")) {
222
unsigned ArgNo = R->getValueAsInt("ArgNo");
223
addArgAttribute(ArgNo, Returned);
224
} else if (R->isSubClassOf("ReadOnly")) {
225
unsigned ArgNo = R->getValueAsInt("ArgNo");
226
addArgAttribute(ArgNo, ReadOnly);
227
} else if (R->isSubClassOf("WriteOnly")) {
228
unsigned ArgNo = R->getValueAsInt("ArgNo");
229
addArgAttribute(ArgNo, WriteOnly);
230
} else if (R->isSubClassOf("ReadNone")) {
231
unsigned ArgNo = R->getValueAsInt("ArgNo");
232
addArgAttribute(ArgNo, ReadNone);
233
} else if (R->isSubClassOf("ImmArg")) {
234
unsigned ArgNo = R->getValueAsInt("ArgNo");
235
addArgAttribute(ArgNo, ImmArg);
236
} else if (R->isSubClassOf("Align")) {
237
unsigned ArgNo = R->getValueAsInt("ArgNo");
238
uint64_t Align = R->getValueAsInt("Align");
239
addArgAttribute(ArgNo, Alignment, Align);
240
} else if (R->isSubClassOf("Dereferenceable")) {
241
unsigned ArgNo = R->getValueAsInt("ArgNo");
242
uint64_t Bytes = R->getValueAsInt("Bytes");
243
addArgAttribute(ArgNo, Dereferenceable, Bytes);
244
} else
245
llvm_unreachable("Unknown property!");
246
}
247
248
bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
249
if (ParamIdx >= IS.ParamTys.size())
250
return false;
251
return (IS.ParamTys[ParamIdx]->isSubClassOf("LLVMQualPointerType") ||
252
IS.ParamTys[ParamIdx]->isSubClassOf("LLVMAnyPointerType"));
253
}
254
255
bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {
256
// Convert argument index to attribute index starting from `FirstArgIndex`.
257
++ParamIdx;
258
if (ParamIdx >= ArgumentAttributes.size())
259
return false;
260
ArgAttribute Val{ImmArg, 0};
261
return std::binary_search(ArgumentAttributes[ParamIdx].begin(),
262
ArgumentAttributes[ParamIdx].end(), Val);
263
}
264
265
void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK,
266
uint64_t V) {
267
if (Idx >= ArgumentAttributes.size())
268
ArgumentAttributes.resize(Idx + 1);
269
ArgumentAttributes[Idx].emplace_back(AK, V);
270
}
271
272