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