xref: /llvm-project/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp (revision 2f43e65955565f92d3103b4bd57f17d02385d0e3)
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 CodeGenIntrinsicContext::CodeGenIntrinsicContext(const RecordKeeper &RC) {
29   for (const Record *Rec : RC.getAllDerivedDefinitions("IntrinsicProperty"))
30     if (Rec->getValueAsBit("IsDefault"))
31       DefaultProperties.push_back(Rec);
32 
33   // The maximum number of values that an intrinsic can return is the size of
34   // of `IIT_RetNumbers` list - 1 (since we index into this list using the
35   // number of return values as the index).
36   const auto *IIT_RetNumbers =
37       dyn_cast_or_null<ListInit>(RC.getGlobal("IIT_RetNumbers"));
38   if (!IIT_RetNumbers)
39     PrintFatalError("unable to find 'IIT_RetNumbers' list");
40   MaxNumReturn = IIT_RetNumbers->size() - 1;
41 }
42 
43 CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
44   CodeGenIntrinsicContext Ctx(RC);
45 
46   ArrayRef<const Record *> Defs = RC.getAllDerivedDefinitions("Intrinsic");
47   Intrinsics.reserve(Defs.size());
48 
49   for (const Record *Def : Defs)
50     Intrinsics.emplace_back(CodeGenIntrinsic(Def, Ctx));
51 
52   llvm::sort(Intrinsics,
53              [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
54                // Order target independent intrinsics before target dependent
55                // ones.
56                bool LHSHasTarget = !LHS.TargetPrefix.empty();
57                bool RHSHasTarget = !RHS.TargetPrefix.empty();
58 
59                // To ensure deterministic sorted order when duplicates are
60                // present, use record ID as a tie-breaker similar to
61                // sortAndReportDuplicates in Utils.cpp.
62                unsigned LhsID = LHS.TheDef->getID();
63                unsigned RhsID = RHS.TheDef->getID();
64 
65                return std::tie(LHSHasTarget, LHS.Name, LhsID) <
66                       std::tie(RHSHasTarget, RHS.Name, RhsID);
67              });
68 
69   Targets.push_back({"", 0, 0});
70   for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
71     if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
72       Targets.back().Count = I - Targets.back().Offset;
73       Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
74     }
75   Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
76 
77   CheckDuplicateIntrinsics();
78   CheckTargetIndependentIntrinsics();
79 }
80 
81 // Check for duplicate intrinsic names.
82 void CodeGenIntrinsicTable::CheckDuplicateIntrinsics() const {
83   // Since the Intrinsics vector is already sorted by name, if there are 2 or
84   // more intrinsics with duplicate names, they will appear adjacent in sorted
85   // order. Note that if the intrinsic name was derived from the record name
86   // there cannot be be duplicate as TableGen parser would have flagged that.
87   // However, if the name was specified in the intrinsic definition, then its
88   // possible to have duplicate names.
89   auto I = std::adjacent_find(
90       Intrinsics.begin(), Intrinsics.end(),
91       [](const CodeGenIntrinsic &Int1, const CodeGenIntrinsic &Int2) {
92         return Int1.Name == Int2.Name;
93       });
94   if (I == Intrinsics.end())
95     return;
96 
97   // Found a duplicate intrinsics.
98   const CodeGenIntrinsic &First = *I;
99   const CodeGenIntrinsic &Second = *(I + 1);
100   PrintError(Second.TheDef,
101              Twine("Intrinsic `") + First.Name + "` is already defined");
102   PrintFatalNote(First.TheDef, "Previous definition here");
103 }
104 
105 // For target independent intrinsics, check that their second dotted component
106 // does not match any target name.
107 void CodeGenIntrinsicTable::CheckTargetIndependentIntrinsics() const {
108   SmallDenseSet<StringRef> TargetNames;
109   for (const auto &Target : ArrayRef(Targets).drop_front())
110     TargetNames.insert(Target.Name);
111 
112   // Set of target independent intrinsics.
113   const auto &Set = Targets[0];
114   for (const auto &Int : ArrayRef(&Intrinsics[Set.Offset], Set.Count)) {
115     StringRef Name = Int.Name;
116     StringRef Prefix = Name.drop_front(5).split('.').first;
117     if (!TargetNames.contains(Prefix))
118       continue;
119     PrintFatalError(Int.TheDef,
120                     "target independent intrinsic `" + Name +
121                         "' has prefix `llvm." + Prefix +
122                         "` that conflicts with intrinsics for target `" +
123                         Prefix + "`");
124   }
125 }
126 
127 CodeGenIntrinsic &CodeGenIntrinsicMap::operator[](const Record *Record) {
128   if (!Record->isSubClassOf("Intrinsic"))
129     PrintFatalError("Intrinsic defs should be subclass of 'Intrinsic' class");
130 
131   auto [Iter, Inserted] = Map.try_emplace(Record);
132   if (Inserted)
133     Iter->second = std::make_unique<CodeGenIntrinsic>(Record, Ctx);
134   return *Iter->second;
135 }
136 
137 CodeGenIntrinsic::CodeGenIntrinsic(const Record *R,
138                                    const CodeGenIntrinsicContext &Ctx)
139     : TheDef(R) {
140   StringRef DefName = TheDef->getName();
141   ArrayRef<SMLoc> DefLoc = R->getLoc();
142 
143   if (!DefName.starts_with("int_"))
144     PrintFatalError(DefLoc,
145                     "Intrinsic '" + DefName + "' does not start with 'int_'!");
146 
147   EnumName = DefName.substr(4);
148 
149   // Ignore a missing ClangBuiltinName field.
150   ClangBuiltinName =
151       R->getValueAsOptionalString("ClangBuiltinName").value_or("");
152   // Ignore a missing MSBuiltinName field.
153   MSBuiltinName = R->getValueAsOptionalString("MSBuiltinName").value_or("");
154 
155   TargetPrefix = R->getValueAsString("TargetPrefix");
156   Name = R->getValueAsString("LLVMName").str();
157 
158   if (Name == "") {
159     // If an explicit name isn't specified, derive one from the DefName.
160     Name = "llvm." + EnumName.str();
161     llvm::replace(Name, '_', '.');
162   } else {
163     // Verify it starts with "llvm.".
164     if (!StringRef(Name).starts_with("llvm."))
165       PrintFatalError(DefLoc, "Intrinsic '" + DefName +
166                                   "'s name does not start with 'llvm.'!");
167   }
168 
169   // If TargetPrefix is specified, make sure that Name starts with
170   // "llvm.<targetprefix>.".
171   if (!TargetPrefix.empty()) {
172     StringRef Prefix = StringRef(Name).drop_front(5); // Drop llvm.
173     if (!Prefix.consume_front(TargetPrefix) || !Prefix.starts_with('.'))
174       PrintFatalError(DefLoc, "Intrinsic '" + DefName +
175                                   "' does not start with 'llvm." +
176                                   TargetPrefix + ".'!");
177   }
178 
179   unsigned NumRet = R->getValueAsListInit("RetTypes")->size();
180   if (NumRet > Ctx.MaxNumReturn)
181     PrintFatalError(DefLoc, "intrinsics can only return upto " +
182                                 Twine(Ctx.MaxNumReturn) + " values, '" +
183                                 DefName + "' returns " + Twine(NumRet) +
184                                 " values");
185 
186   const Record *TypeInfo = R->getValueAsDef("TypeInfo");
187   if (!TypeInfo->isSubClassOf("TypeInfoGen"))
188     PrintFatalError(DefLoc, "TypeInfo field in " + DefName +
189                                 " should be of subclass of TypeInfoGen!");
190 
191   isOverloaded = TypeInfo->getValueAsBit("isOverloaded");
192   const ListInit *TypeList = TypeInfo->getValueAsListInit("Types");
193 
194   // Types field is a concatenation of Return types followed by Param types.
195   unsigned Idx = 0;
196   for (; Idx < NumRet; ++Idx)
197     IS.RetTys.push_back(TypeList->getElementAsRecord(Idx));
198 
199   for (unsigned E = TypeList->size(); Idx < E; ++Idx)
200     IS.ParamTys.push_back(TypeList->getElementAsRecord(Idx));
201 
202   // Parse the intrinsic properties.
203   ListInit *PropList = R->getValueAsListInit("IntrProperties");
204   for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
205     const Record *Property = PropList->getElementAsRecord(i);
206     assert(Property->isSubClassOf("IntrinsicProperty") &&
207            "Expected a property!");
208 
209     setProperty(Property);
210   }
211 
212   // Set default properties to true.
213   setDefaultProperties(Ctx.DefaultProperties);
214 
215   // Also record the SDPatternOperator Properties.
216   Properties = parseSDPatternOperatorProperties(R);
217 
218   // Sort the argument attributes for later benefit.
219   for (auto &Attrs : ArgumentAttributes)
220     llvm::sort(Attrs);
221 }
222 
223 void CodeGenIntrinsic::setDefaultProperties(
224     ArrayRef<const Record *> DefaultProperties) {
225   // opt-out of using default attributes.
226   if (TheDef->getValueAsBit("DisableDefaultAttributes"))
227     return;
228 
229   for (const Record *Rec : DefaultProperties)
230     setProperty(Rec);
231 }
232 
233 void CodeGenIntrinsic::setProperty(const Record *R) {
234   if (R->getName() == "IntrNoMem")
235     ME = MemoryEffects::none();
236   else if (R->getName() == "IntrReadMem") {
237     if (ME.onlyWritesMemory())
238       PrintFatalError(TheDef->getLoc(),
239                       Twine("IntrReadMem cannot be used after IntrNoMem or "
240                             "IntrWriteMem. Default is ReadWrite"));
241     ME &= MemoryEffects::readOnly();
242   } else if (R->getName() == "IntrWriteMem") {
243     if (ME.onlyReadsMemory())
244       PrintFatalError(TheDef->getLoc(),
245                       Twine("IntrWriteMem cannot be used after IntrNoMem or "
246                             "IntrReadMem. Default is ReadWrite"));
247     ME &= MemoryEffects::writeOnly();
248   } else if (R->getName() == "IntrArgMemOnly")
249     ME &= MemoryEffects::argMemOnly();
250   else if (R->getName() == "IntrInaccessibleMemOnly")
251     ME &= MemoryEffects::inaccessibleMemOnly();
252   else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
253     ME &= MemoryEffects::inaccessibleOrArgMemOnly();
254   else if (R->getName() == "Commutative")
255     isCommutative = true;
256   else if (R->getName() == "Throws")
257     canThrow = true;
258   else if (R->getName() == "IntrNoDuplicate")
259     isNoDuplicate = true;
260   else if (R->getName() == "IntrNoMerge")
261     isNoMerge = true;
262   else if (R->getName() == "IntrConvergent")
263     isConvergent = true;
264   else if (R->getName() == "IntrNoReturn")
265     isNoReturn = true;
266   else if (R->getName() == "IntrNoCallback")
267     isNoCallback = true;
268   else if (R->getName() == "IntrNoSync")
269     isNoSync = true;
270   else if (R->getName() == "IntrNoFree")
271     isNoFree = true;
272   else if (R->getName() == "IntrWillReturn")
273     isWillReturn = !isNoReturn;
274   else if (R->getName() == "IntrCold")
275     isCold = true;
276   else if (R->getName() == "IntrSpeculatable")
277     isSpeculatable = true;
278   else if (R->getName() == "IntrHasSideEffects")
279     hasSideEffects = true;
280   else if (R->getName() == "IntrStrictFP")
281     isStrictFP = true;
282   else if (R->isSubClassOf("NoCapture")) {
283     unsigned ArgNo = R->getValueAsInt("ArgNo");
284     addArgAttribute(ArgNo, NoCapture);
285   } else if (R->isSubClassOf("NoAlias")) {
286     unsigned ArgNo = R->getValueAsInt("ArgNo");
287     addArgAttribute(ArgNo, NoAlias);
288   } else if (R->isSubClassOf("NoUndef")) {
289     unsigned ArgNo = R->getValueAsInt("ArgNo");
290     addArgAttribute(ArgNo, NoUndef);
291   } else if (R->isSubClassOf("NonNull")) {
292     unsigned ArgNo = R->getValueAsInt("ArgNo");
293     addArgAttribute(ArgNo, NonNull);
294   } else if (R->isSubClassOf("Returned")) {
295     unsigned ArgNo = R->getValueAsInt("ArgNo");
296     addArgAttribute(ArgNo, Returned);
297   } else if (R->isSubClassOf("ReadOnly")) {
298     unsigned ArgNo = R->getValueAsInt("ArgNo");
299     addArgAttribute(ArgNo, ReadOnly);
300   } else if (R->isSubClassOf("WriteOnly")) {
301     unsigned ArgNo = R->getValueAsInt("ArgNo");
302     addArgAttribute(ArgNo, WriteOnly);
303   } else if (R->isSubClassOf("ReadNone")) {
304     unsigned ArgNo = R->getValueAsInt("ArgNo");
305     addArgAttribute(ArgNo, ReadNone);
306   } else if (R->isSubClassOf("ImmArg")) {
307     unsigned ArgNo = R->getValueAsInt("ArgNo");
308     addArgAttribute(ArgNo, ImmArg);
309   } else if (R->isSubClassOf("Align")) {
310     unsigned ArgNo = R->getValueAsInt("ArgNo");
311     uint64_t Align = R->getValueAsInt("Align");
312     addArgAttribute(ArgNo, Alignment, Align);
313   } else if (R->isSubClassOf("Dereferenceable")) {
314     unsigned ArgNo = R->getValueAsInt("ArgNo");
315     uint64_t Bytes = R->getValueAsInt("Bytes");
316     addArgAttribute(ArgNo, Dereferenceable, Bytes);
317   } else
318     llvm_unreachable("Unknown property!");
319 }
320 
321 bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
322   if (ParamIdx >= IS.ParamTys.size())
323     return false;
324   return (IS.ParamTys[ParamIdx]->isSubClassOf("LLVMQualPointerType") ||
325           IS.ParamTys[ParamIdx]->isSubClassOf("LLVMAnyPointerType"));
326 }
327 
328 bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {
329   // Convert argument index to attribute index starting from `FirstArgIndex`.
330   ++ParamIdx;
331   if (ParamIdx >= ArgumentAttributes.size())
332     return false;
333   ArgAttribute Val{ImmArg, 0};
334   return std::binary_search(ArgumentAttributes[ParamIdx].begin(),
335                             ArgumentAttributes[ParamIdx].end(), Val);
336 }
337 
338 void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK,
339                                        uint64_t V) {
340   if (Idx >= ArgumentAttributes.size())
341     ArgumentAttributes.resize(Idx + 1);
342   ArgumentAttributes[Idx].emplace_back(AK, V);
343 }
344