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
CodeGenIntrinsicTable(const RecordKeeper & RC)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
CodeGenIntrinsic(Record * R,ArrayRef<Record * > DefaultProperties)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
setDefaultProperties(Record * R,ArrayRef<Record * > DefaultProperties)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
setProperty(Record * R)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
isParamAPointer(unsigned ParamIdx) const248 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
isParamImmArg(unsigned ParamIdx) const255 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
addArgAttribute(unsigned Idx,ArgAttrKind AK,uint64_t V)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