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                                    std::vector<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, std::vector<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