xref: /llvm-project/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp (revision 0c6457b781ae8365ef2169376ae78675b5b4896b)
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   CheckOverloadSuffixConflicts();
80 }
81 
82 // Check for duplicate intrinsic names.
83 void CodeGenIntrinsicTable::CheckDuplicateIntrinsics() const {
84   // Since the Intrinsics vector is already sorted by name, if there are 2 or
85   // more intrinsics with duplicate names, they will appear adjacent in sorted
86   // order. Note that if the intrinsic name was derived from the record name
87   // there cannot be be duplicate as TableGen parser would have flagged that.
88   // However, if the name was specified in the intrinsic definition, then its
89   // possible to have duplicate names.
90   auto I = std::adjacent_find(
91       Intrinsics.begin(), Intrinsics.end(),
92       [](const CodeGenIntrinsic &Int1, const CodeGenIntrinsic &Int2) {
93         return Int1.Name == Int2.Name;
94       });
95   if (I == Intrinsics.end())
96     return;
97 
98   // Found a duplicate intrinsics.
99   const CodeGenIntrinsic &First = *I;
100   const CodeGenIntrinsic &Second = *(I + 1);
101   PrintError(Second.TheDef,
102              Twine("Intrinsic `") + First.Name + "` is already defined");
103   PrintFatalNote(First.TheDef, "Previous definition here");
104 }
105 
106 // For target independent intrinsics, check that their second dotted component
107 // does not match any target name.
108 void CodeGenIntrinsicTable::CheckTargetIndependentIntrinsics() const {
109   SmallDenseSet<StringRef> TargetNames;
110   for (const auto &Target : ArrayRef(Targets).drop_front())
111     TargetNames.insert(Target.Name);
112 
113   // Set of target independent intrinsics.
114   const auto &Set = Targets[0];
115   for (const auto &Int : ArrayRef(&Intrinsics[Set.Offset], Set.Count)) {
116     StringRef Name = Int.Name;
117     StringRef Prefix = Name.drop_front(5).split('.').first;
118     if (!TargetNames.contains(Prefix))
119       continue;
120     PrintFatalError(Int.TheDef,
121                     "target independent intrinsic `" + Name +
122                         "' has prefix `llvm." + Prefix +
123                         "` that conflicts with intrinsics for target `" +
124                         Prefix + "`");
125   }
126 }
127 
128 // Return true if the given Suffix looks like a mangled type. Note that this
129 // check is conservative, but allows all existing LLVM intrinsic suffixes to be
130 // considered as not looking like a mangling suffix.
131 static bool doesSuffixLookLikeMangledType(StringRef Suffix) {
132   // Try to match against possible mangling suffixes for various types.
133   // See getMangledTypeStr() for the mangling suffixes possible. It includes
134   //  pointer       : p[0-9]+
135   //  array         : a[0-9]+.+
136   //  struct:       : s_/sl_.+
137   //  function      : f_.+
138   //  vector        : v/nxv[0-9]+.+
139   //  target type   : t.+
140   //  integer       : i[0-9]+
141   //  named types   : See `NamedTypes` below.
142 
143   // Match anything with an _, so match function and struct types.
144   if (Suffix.contains('_'))
145     return true;
146 
147   // [av][0-9]+.+, simplified to [av][0-9].+
148   if (Suffix.size() >= 2 && is_contained("av", Suffix[0]) && isDigit(Suffix[1]))
149     return true;
150 
151   // nxv[0-9]+.+, simplified to nxv[0-9].+
152   if (Suffix.size() >= 4 && Suffix.starts_with("nxv") && isDigit(Suffix[3]))
153     return true;
154 
155   // t.+
156   if (Suffix.size() > 1 && Suffix.starts_with('t'))
157     return false;
158 
159   // [pi][0-9]+
160   if (Suffix.size() > 1 && is_contained("pi", Suffix[0]) &&
161       all_of(Suffix.drop_front(), isDigit))
162     return true;
163 
164   // Match one of the named types.
165   static constexpr StringLiteral NamedTypes[] = {
166       "isVoid", "Metadata", "f16",  "f32",     "f64",
167       "f80",    "f128",     "bf16", "ppcf128", "x86amx"};
168   return is_contained(NamedTypes, Suffix);
169 }
170 
171 // Check for conflicts with overloaded intrinsics. If there exists an overloaded
172 // intrinsic with base name `llvm.target.foo`, LLVM will add a mangling suffix
173 // to it to encode the overload types. This mangling suffix is 1 or more .
174 // prefixed mangled type string as defined in `getMangledTypeStr`. If there
175 // exists another intrinsic `llvm.target.foo[.<suffixN>]+`, which has the same
176 // prefix as the overloaded intrinsic, its possible that there may be a name
177 // conflict with the overloaded intrinsic and either one may interfere with name
178 // lookup for the other, leading to wrong intrinsic ID being assigned.
179 //
180 // The actual name lookup in the intrinsic name table is done by a search
181 // on each successive '.' separted component of the intrinsic name (see
182 // `lookupLLVMIntrinsicByName`). Consider first the case where there exists a
183 // non-overloaded intrinsic `llvm.target.foo[.suffix]+`. For the non-overloaded
184 // intrinsics, the name lookup is an exact match, so the presence of the
185 // overloaded intrinsic with the same prefix will not interfere with the
186 // search. However, a lookup intended to match the overloaded intrinsic might be
187 // affected by the presence of another entry in the name table with the same
188 // prefix.
189 //
190 // Since LLVM's name lookup first selects the target specific (or target
191 // independent) slice of the name table to look into, intrinsics in 2 different
192 // targets cannot conflict with each other. Within a specific target,
193 // if we have an overloaded intrinsic with name `llvm.target.foo` and another
194 // one with same prefix and one or more suffixes `llvm.target.foo[.<suffixN>]+`,
195 // then the name search will try to first match against suffix0, then suffix1
196 // etc. If suffix0 can match a mangled type, then the search for an
197 // `llvm.target.foo` with a mangling suffix can match against suffix0,
198 // preventing a match with `llvm.target.foo`. If suffix0 cannot match a mangled
199 // type, then that cannot happen, so we do not need to check for later suffixes.
200 //
201 // Generalizing, the `llvm.target.foo[.suffixN]+` will cause a conflict if the
202 // first suffix (.suffix0) can match a mangled type (and then we do not need to
203 // check later suffixes) and will not cause a conflict if it cannot (and then
204 // again, we do not need to check for later suffixes).
205 void CodeGenIntrinsicTable::CheckOverloadSuffixConflicts() const {
206   for (const TargetSet &Set : Targets) {
207     const CodeGenIntrinsic *Overloaded = nullptr;
208     for (const CodeGenIntrinsic &Int : (*this)[Set]) {
209       // If we do not have an overloaded intrinsic to check against, nothing
210       // to do except potentially identifying this as a candidate for checking
211       // against in future iteration.
212       if (!Overloaded) {
213         if (Int.isOverloaded)
214           Overloaded = &Int;
215         continue;
216       }
217 
218       StringRef Name = Int.Name;
219       StringRef OverloadName = Overloaded->Name;
220       // If we have an overloaded intrinsic to check again, check if its name is
221       // a proper prefix of this intrinsic.
222       if (Name.starts_with(OverloadName) && Name[OverloadName.size()] == '.') {
223         // If yes, verify suffixes and flag an error.
224         StringRef Suffixes = Name.drop_front(OverloadName.size() + 1);
225 
226         // Only need to look at the first suffix.
227         StringRef Suffix0 = Suffixes.split('.').first;
228 
229         if (!doesSuffixLookLikeMangledType(Suffix0))
230           continue;
231 
232         unsigned SuffixSize = OverloadName.size() + 1 + Suffix0.size();
233         // If suffix looks like mangling suffix, flag it as an error.
234         PrintError(Int.TheDef->getLoc(),
235                    "intrinsic `" + Name + "` cannot share prefix `" +
236                        Name.take_front(SuffixSize) +
237                        "` with another overloaded intrinsic `" + OverloadName +
238                        "`");
239         PrintNote(Overloaded->TheDef->getLoc(),
240                   "Overloaded intrinsic `" + OverloadName + "` defined here");
241         continue;
242       }
243 
244       // If we find an intrinsic that is not a proper prefix, any later
245       // intrinsic is also not going to be a proper prefix, so invalidate the
246       // overloaded to check against.
247       Overloaded = nullptr;
248     }
249   }
250 }
251 
252 const CodeGenIntrinsic &CodeGenIntrinsicMap::operator[](const Record *Record) {
253   if (!Record->isSubClassOf("Intrinsic"))
254     PrintFatalError("Intrinsic defs should be subclass of 'Intrinsic' class");
255 
256   auto [Iter, Inserted] = Map.try_emplace(Record);
257   if (Inserted)
258     Iter->second = std::make_unique<CodeGenIntrinsic>(Record, Ctx);
259   return *Iter->second;
260 }
261 
262 CodeGenIntrinsic::CodeGenIntrinsic(const Record *R,
263                                    const CodeGenIntrinsicContext &Ctx)
264     : TheDef(R) {
265   StringRef DefName = TheDef->getName();
266   ArrayRef<SMLoc> DefLoc = R->getLoc();
267 
268   if (!DefName.starts_with("int_"))
269     PrintFatalError(DefLoc,
270                     "Intrinsic '" + DefName + "' does not start with 'int_'!");
271 
272   EnumName = DefName.substr(4);
273 
274   // Ignore a missing ClangBuiltinName field.
275   ClangBuiltinName =
276       R->getValueAsOptionalString("ClangBuiltinName").value_or("");
277   // Ignore a missing MSBuiltinName field.
278   MSBuiltinName = R->getValueAsOptionalString("MSBuiltinName").value_or("");
279 
280   TargetPrefix = R->getValueAsString("TargetPrefix");
281   Name = R->getValueAsString("LLVMName").str();
282 
283   if (Name == "") {
284     // If an explicit name isn't specified, derive one from the DefName.
285     Name = "llvm." + EnumName.str();
286     llvm::replace(Name, '_', '.');
287   } else {
288     // Verify it starts with "llvm.".
289     if (!StringRef(Name).starts_with("llvm."))
290       PrintFatalError(DefLoc, "Intrinsic '" + DefName +
291                                   "'s name does not start with 'llvm.'!");
292   }
293 
294   // If TargetPrefix is specified, make sure that Name starts with
295   // "llvm.<targetprefix>.".
296   if (!TargetPrefix.empty()) {
297     StringRef Prefix = StringRef(Name).drop_front(5); // Drop llvm.
298     if (!Prefix.consume_front(TargetPrefix) || !Prefix.starts_with('.'))
299       PrintFatalError(DefLoc, "Intrinsic '" + DefName +
300                                   "' does not start with 'llvm." +
301                                   TargetPrefix + ".'!");
302   }
303 
304   unsigned NumRet = R->getValueAsListInit("RetTypes")->size();
305   if (NumRet > Ctx.MaxNumReturn)
306     PrintFatalError(DefLoc, "intrinsics can only return upto " +
307                                 Twine(Ctx.MaxNumReturn) + " values, '" +
308                                 DefName + "' returns " + Twine(NumRet) +
309                                 " values");
310 
311   const Record *TypeInfo = R->getValueAsDef("TypeInfo");
312   if (!TypeInfo->isSubClassOf("TypeInfoGen"))
313     PrintFatalError(DefLoc, "TypeInfo field in " + DefName +
314                                 " should be of subclass of TypeInfoGen!");
315 
316   isOverloaded = TypeInfo->getValueAsBit("isOverloaded");
317   const ListInit *TypeList = TypeInfo->getValueAsListInit("Types");
318 
319   // Types field is a concatenation of Return types followed by Param types.
320   unsigned Idx = 0;
321   for (; Idx < NumRet; ++Idx)
322     IS.RetTys.push_back(TypeList->getElementAsRecord(Idx));
323 
324   for (unsigned E = TypeList->size(); Idx < E; ++Idx)
325     IS.ParamTys.push_back(TypeList->getElementAsRecord(Idx));
326 
327   // Parse the intrinsic properties.
328   const ListInit *PropList = R->getValueAsListInit("IntrProperties");
329   for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
330     const Record *Property = PropList->getElementAsRecord(i);
331     assert(Property->isSubClassOf("IntrinsicProperty") &&
332            "Expected a property!");
333 
334     setProperty(Property);
335   }
336 
337   // Set default properties to true.
338   setDefaultProperties(Ctx.DefaultProperties);
339 
340   // Also record the SDPatternOperator Properties.
341   Properties = parseSDPatternOperatorProperties(R);
342 
343   // Sort the argument attributes for later benefit.
344   for (auto &Attrs : ArgumentAttributes)
345     llvm::sort(Attrs);
346 }
347 
348 void CodeGenIntrinsic::setDefaultProperties(
349     ArrayRef<const Record *> DefaultProperties) {
350   // opt-out of using default attributes.
351   if (TheDef->getValueAsBit("DisableDefaultAttributes"))
352     return;
353 
354   for (const Record *Rec : DefaultProperties)
355     setProperty(Rec);
356 }
357 
358 void CodeGenIntrinsic::setProperty(const Record *R) {
359   if (R->getName() == "IntrNoMem")
360     ME = MemoryEffects::none();
361   else if (R->getName() == "IntrReadMem") {
362     if (ME.onlyWritesMemory())
363       PrintFatalError(TheDef->getLoc(),
364                       Twine("IntrReadMem cannot be used after IntrNoMem or "
365                             "IntrWriteMem. Default is ReadWrite"));
366     ME &= MemoryEffects::readOnly();
367   } else if (R->getName() == "IntrWriteMem") {
368     if (ME.onlyReadsMemory())
369       PrintFatalError(TheDef->getLoc(),
370                       Twine("IntrWriteMem cannot be used after IntrNoMem or "
371                             "IntrReadMem. Default is ReadWrite"));
372     ME &= MemoryEffects::writeOnly();
373   } else if (R->getName() == "IntrArgMemOnly")
374     ME &= MemoryEffects::argMemOnly();
375   else if (R->getName() == "IntrInaccessibleMemOnly")
376     ME &= MemoryEffects::inaccessibleMemOnly();
377   else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
378     ME &= MemoryEffects::inaccessibleOrArgMemOnly();
379   else if (R->getName() == "Commutative")
380     isCommutative = true;
381   else if (R->getName() == "Throws")
382     canThrow = true;
383   else if (R->getName() == "IntrNoDuplicate")
384     isNoDuplicate = true;
385   else if (R->getName() == "IntrNoMerge")
386     isNoMerge = true;
387   else if (R->getName() == "IntrConvergent")
388     isConvergent = true;
389   else if (R->getName() == "IntrNoReturn")
390     isNoReturn = true;
391   else if (R->getName() == "IntrNoCallback")
392     isNoCallback = true;
393   else if (R->getName() == "IntrNoSync")
394     isNoSync = true;
395   else if (R->getName() == "IntrNoFree")
396     isNoFree = true;
397   else if (R->getName() == "IntrWillReturn")
398     isWillReturn = !isNoReturn;
399   else if (R->getName() == "IntrCold")
400     isCold = true;
401   else if (R->getName() == "IntrSpeculatable")
402     isSpeculatable = true;
403   else if (R->getName() == "IntrHasSideEffects")
404     hasSideEffects = true;
405   else if (R->getName() == "IntrStrictFP")
406     isStrictFP = true;
407   else if (R->isSubClassOf("NoCapture")) {
408     unsigned ArgNo = R->getValueAsInt("ArgNo");
409     addArgAttribute(ArgNo, NoCapture);
410   } else if (R->isSubClassOf("NoAlias")) {
411     unsigned ArgNo = R->getValueAsInt("ArgNo");
412     addArgAttribute(ArgNo, NoAlias);
413   } else if (R->isSubClassOf("NoUndef")) {
414     unsigned ArgNo = R->getValueAsInt("ArgNo");
415     addArgAttribute(ArgNo, NoUndef);
416   } else if (R->isSubClassOf("NonNull")) {
417     unsigned ArgNo = R->getValueAsInt("ArgNo");
418     addArgAttribute(ArgNo, NonNull);
419   } else if (R->isSubClassOf("Returned")) {
420     unsigned ArgNo = R->getValueAsInt("ArgNo");
421     addArgAttribute(ArgNo, Returned);
422   } else if (R->isSubClassOf("ReadOnly")) {
423     unsigned ArgNo = R->getValueAsInt("ArgNo");
424     addArgAttribute(ArgNo, ReadOnly);
425   } else if (R->isSubClassOf("WriteOnly")) {
426     unsigned ArgNo = R->getValueAsInt("ArgNo");
427     addArgAttribute(ArgNo, WriteOnly);
428   } else if (R->isSubClassOf("ReadNone")) {
429     unsigned ArgNo = R->getValueAsInt("ArgNo");
430     addArgAttribute(ArgNo, ReadNone);
431   } else if (R->isSubClassOf("ImmArg")) {
432     unsigned ArgNo = R->getValueAsInt("ArgNo");
433     addArgAttribute(ArgNo, ImmArg);
434   } else if (R->isSubClassOf("Align")) {
435     unsigned ArgNo = R->getValueAsInt("ArgNo");
436     uint64_t Align = R->getValueAsInt("Align");
437     addArgAttribute(ArgNo, Alignment, Align);
438   } else if (R->isSubClassOf("Dereferenceable")) {
439     unsigned ArgNo = R->getValueAsInt("ArgNo");
440     uint64_t Bytes = R->getValueAsInt("Bytes");
441     addArgAttribute(ArgNo, Dereferenceable, Bytes);
442   } else
443     llvm_unreachable("Unknown property!");
444 }
445 
446 bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
447   if (ParamIdx >= IS.ParamTys.size())
448     return false;
449   return (IS.ParamTys[ParamIdx]->isSubClassOf("LLVMQualPointerType") ||
450           IS.ParamTys[ParamIdx]->isSubClassOf("LLVMAnyPointerType"));
451 }
452 
453 bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {
454   // Convert argument index to attribute index starting from `FirstArgIndex`.
455   ++ParamIdx;
456   if (ParamIdx >= ArgumentAttributes.size())
457     return false;
458   ArgAttribute Val{ImmArg, 0};
459   return std::binary_search(ArgumentAttributes[ParamIdx].begin(),
460                             ArgumentAttributes[ParamIdx].end(), Val);
461 }
462 
463 void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK,
464                                        uint64_t V) {
465   if (Idx >= ArgumentAttributes.size())
466     ArgumentAttributes.resize(Idx + 1);
467   ArgumentAttributes[Idx].emplace_back(AK, V);
468 }
469