1*fe013be4SDimitry Andric //===- CodeGenIntrinsics.cpp - Intrinsic Class Wrapper --------------------===//
2*fe013be4SDimitry Andric //
3*fe013be4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*fe013be4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*fe013be4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*fe013be4SDimitry Andric //
7*fe013be4SDimitry Andric //===----------------------------------------------------------------------===//
8*fe013be4SDimitry Andric //
9*fe013be4SDimitry Andric // This file defines a wrapper class for the 'Intrinsic' TableGen class.
10*fe013be4SDimitry Andric //
11*fe013be4SDimitry Andric //===----------------------------------------------------------------------===//
12*fe013be4SDimitry Andric
13*fe013be4SDimitry Andric #include "CodeGenIntrinsics.h"
14*fe013be4SDimitry Andric #include "llvm/ADT/ArrayRef.h"
15*fe013be4SDimitry Andric #include "llvm/ADT/STLExtras.h"
16*fe013be4SDimitry Andric #include "llvm/ADT/Twine.h"
17*fe013be4SDimitry Andric #include "llvm/Support/ErrorHandling.h"
18*fe013be4SDimitry Andric #include "llvm/TableGen/Error.h"
19*fe013be4SDimitry Andric #include "llvm/TableGen/Record.h"
20*fe013be4SDimitry Andric #include <algorithm>
21*fe013be4SDimitry Andric #include <cassert>
22*fe013be4SDimitry Andric using namespace llvm;
23*fe013be4SDimitry Andric
24*fe013be4SDimitry Andric //===----------------------------------------------------------------------===//
25*fe013be4SDimitry Andric // CodeGenIntrinsic Implementation
26*fe013be4SDimitry Andric //===----------------------------------------------------------------------===//
27*fe013be4SDimitry Andric
CodeGenIntrinsicTable(const RecordKeeper & RC)28*fe013be4SDimitry Andric CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
29*fe013be4SDimitry Andric std::vector<Record *> IntrProperties =
30*fe013be4SDimitry Andric RC.getAllDerivedDefinitions("IntrinsicProperty");
31*fe013be4SDimitry Andric
32*fe013be4SDimitry Andric std::vector<Record *> DefaultProperties;
33*fe013be4SDimitry Andric for (Record *Rec : IntrProperties)
34*fe013be4SDimitry Andric if (Rec->getValueAsBit("IsDefault"))
35*fe013be4SDimitry Andric DefaultProperties.push_back(Rec);
36*fe013be4SDimitry Andric
37*fe013be4SDimitry Andric std::vector<Record *> Defs = RC.getAllDerivedDefinitions("Intrinsic");
38*fe013be4SDimitry Andric Intrinsics.reserve(Defs.size());
39*fe013be4SDimitry Andric
40*fe013be4SDimitry Andric for (unsigned I = 0, e = Defs.size(); I != e; ++I)
41*fe013be4SDimitry Andric Intrinsics.push_back(CodeGenIntrinsic(Defs[I], DefaultProperties));
42*fe013be4SDimitry Andric
43*fe013be4SDimitry Andric llvm::sort(Intrinsics,
44*fe013be4SDimitry Andric [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
45*fe013be4SDimitry Andric return std::tie(LHS.TargetPrefix, LHS.Name) <
46*fe013be4SDimitry Andric std::tie(RHS.TargetPrefix, RHS.Name);
47*fe013be4SDimitry Andric });
48*fe013be4SDimitry Andric Targets.push_back({"", 0, 0});
49*fe013be4SDimitry Andric for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
50*fe013be4SDimitry Andric if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
51*fe013be4SDimitry Andric Targets.back().Count = I - Targets.back().Offset;
52*fe013be4SDimitry Andric Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
53*fe013be4SDimitry Andric }
54*fe013be4SDimitry Andric Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
55*fe013be4SDimitry Andric }
56*fe013be4SDimitry Andric
CodeGenIntrinsic(Record * R,std::vector<Record * > DefaultProperties)57*fe013be4SDimitry Andric CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
58*fe013be4SDimitry Andric std::vector<Record *> DefaultProperties) {
59*fe013be4SDimitry Andric TheDef = R;
60*fe013be4SDimitry Andric std::string DefName = std::string(R->getName());
61*fe013be4SDimitry Andric ArrayRef<SMLoc> DefLoc = R->getLoc();
62*fe013be4SDimitry Andric Properties = 0;
63*fe013be4SDimitry Andric isOverloaded = false;
64*fe013be4SDimitry Andric isCommutative = false;
65*fe013be4SDimitry Andric canThrow = false;
66*fe013be4SDimitry Andric isNoReturn = false;
67*fe013be4SDimitry Andric isNoCallback = false;
68*fe013be4SDimitry Andric isNoSync = false;
69*fe013be4SDimitry Andric isNoFree = false;
70*fe013be4SDimitry Andric isWillReturn = false;
71*fe013be4SDimitry Andric isCold = false;
72*fe013be4SDimitry Andric isNoDuplicate = false;
73*fe013be4SDimitry Andric isNoMerge = false;
74*fe013be4SDimitry Andric isConvergent = false;
75*fe013be4SDimitry Andric isSpeculatable = false;
76*fe013be4SDimitry Andric hasSideEffects = false;
77*fe013be4SDimitry Andric isStrictFP = false;
78*fe013be4SDimitry Andric
79*fe013be4SDimitry Andric if (DefName.size() <= 4 || DefName.substr(0, 4) != "int_")
80*fe013be4SDimitry Andric PrintFatalError(DefLoc,
81*fe013be4SDimitry Andric "Intrinsic '" + DefName + "' does not start with 'int_'!");
82*fe013be4SDimitry Andric
83*fe013be4SDimitry Andric EnumName = DefName.substr(4);
84*fe013be4SDimitry Andric
85*fe013be4SDimitry Andric if (R->getValue(
86*fe013be4SDimitry Andric "ClangBuiltinName")) // Ignore a missing ClangBuiltinName field.
87*fe013be4SDimitry Andric ClangBuiltinName = std::string(R->getValueAsString("ClangBuiltinName"));
88*fe013be4SDimitry Andric if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field.
89*fe013be4SDimitry Andric MSBuiltinName = std::string(R->getValueAsString("MSBuiltinName"));
90*fe013be4SDimitry Andric
91*fe013be4SDimitry Andric TargetPrefix = std::string(R->getValueAsString("TargetPrefix"));
92*fe013be4SDimitry Andric Name = std::string(R->getValueAsString("LLVMName"));
93*fe013be4SDimitry Andric
94*fe013be4SDimitry Andric if (Name == "") {
95*fe013be4SDimitry Andric // If an explicit name isn't specified, derive one from the DefName.
96*fe013be4SDimitry Andric Name = "llvm.";
97*fe013be4SDimitry Andric
98*fe013be4SDimitry Andric for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
99*fe013be4SDimitry Andric Name += (EnumName[i] == '_') ? '.' : EnumName[i];
100*fe013be4SDimitry Andric } else {
101*fe013be4SDimitry Andric // Verify it starts with "llvm.".
102*fe013be4SDimitry Andric if (Name.size() <= 5 || Name.substr(0, 5) != "llvm.")
103*fe013be4SDimitry Andric PrintFatalError(DefLoc, "Intrinsic '" + DefName +
104*fe013be4SDimitry Andric "'s name does not start with 'llvm.'!");
105*fe013be4SDimitry Andric }
106*fe013be4SDimitry Andric
107*fe013be4SDimitry Andric // If TargetPrefix is specified, make sure that Name starts with
108*fe013be4SDimitry Andric // "llvm.<targetprefix>.".
109*fe013be4SDimitry Andric if (!TargetPrefix.empty()) {
110*fe013be4SDimitry Andric if (Name.size() < 6 + TargetPrefix.size() ||
111*fe013be4SDimitry Andric Name.substr(5, 1 + TargetPrefix.size()) != (TargetPrefix + "."))
112*fe013be4SDimitry Andric PrintFatalError(DefLoc, "Intrinsic '" + DefName +
113*fe013be4SDimitry Andric "' does not start with 'llvm." +
114*fe013be4SDimitry Andric TargetPrefix + ".'!");
115*fe013be4SDimitry Andric }
116*fe013be4SDimitry Andric
117*fe013be4SDimitry Andric if (auto *Types = R->getValue("Types")) {
118*fe013be4SDimitry Andric auto *TypeList = cast<ListInit>(Types->getValue());
119*fe013be4SDimitry Andric isOverloaded = R->getValueAsBit("isOverloaded");
120*fe013be4SDimitry Andric
121*fe013be4SDimitry Andric unsigned I = 0;
122*fe013be4SDimitry Andric for (unsigned E = R->getValueAsListInit("RetTypes")->size(); I < E; ++I)
123*fe013be4SDimitry Andric IS.RetTys.push_back(TypeList->getElementAsRecord(I));
124*fe013be4SDimitry Andric
125*fe013be4SDimitry Andric for (unsigned E = TypeList->size(); I < E; ++I)
126*fe013be4SDimitry Andric IS.ParamTys.push_back(TypeList->getElementAsRecord(I));
127*fe013be4SDimitry Andric }
128*fe013be4SDimitry Andric
129*fe013be4SDimitry Andric // Parse the intrinsic properties.
130*fe013be4SDimitry Andric ListInit *PropList = R->getValueAsListInit("IntrProperties");
131*fe013be4SDimitry Andric for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
132*fe013be4SDimitry Andric Record *Property = PropList->getElementAsRecord(i);
133*fe013be4SDimitry Andric assert(Property->isSubClassOf("IntrinsicProperty") &&
134*fe013be4SDimitry Andric "Expected a property!");
135*fe013be4SDimitry Andric
136*fe013be4SDimitry Andric setProperty(Property);
137*fe013be4SDimitry Andric }
138*fe013be4SDimitry Andric
139*fe013be4SDimitry Andric // Set default properties to true.
140*fe013be4SDimitry Andric setDefaultProperties(R, DefaultProperties);
141*fe013be4SDimitry Andric
142*fe013be4SDimitry Andric // Also record the SDPatternOperator Properties.
143*fe013be4SDimitry Andric Properties = parseSDPatternOperatorProperties(R);
144*fe013be4SDimitry Andric
145*fe013be4SDimitry Andric // Sort the argument attributes for later benefit.
146*fe013be4SDimitry Andric for (auto &Attrs : ArgumentAttributes)
147*fe013be4SDimitry Andric llvm::sort(Attrs);
148*fe013be4SDimitry Andric }
149*fe013be4SDimitry Andric
setDefaultProperties(Record * R,std::vector<Record * > DefaultProperties)150*fe013be4SDimitry Andric void CodeGenIntrinsic::setDefaultProperties(
151*fe013be4SDimitry Andric Record *R, std::vector<Record *> DefaultProperties) {
152*fe013be4SDimitry Andric // opt-out of using default attributes.
153*fe013be4SDimitry Andric if (R->getValueAsBit("DisableDefaultAttributes"))
154*fe013be4SDimitry Andric return;
155*fe013be4SDimitry Andric
156*fe013be4SDimitry Andric for (Record *Rec : DefaultProperties)
157*fe013be4SDimitry Andric setProperty(Rec);
158*fe013be4SDimitry Andric }
159*fe013be4SDimitry Andric
setProperty(Record * R)160*fe013be4SDimitry Andric void CodeGenIntrinsic::setProperty(Record *R) {
161*fe013be4SDimitry Andric if (R->getName() == "IntrNoMem")
162*fe013be4SDimitry Andric ME = MemoryEffects::none();
163*fe013be4SDimitry Andric else if (R->getName() == "IntrReadMem") {
164*fe013be4SDimitry Andric if (ME.onlyWritesMemory())
165*fe013be4SDimitry Andric PrintFatalError(TheDef->getLoc(),
166*fe013be4SDimitry Andric Twine("IntrReadMem cannot be used after IntrNoMem or "
167*fe013be4SDimitry Andric "IntrWriteMem. Default is ReadWrite"));
168*fe013be4SDimitry Andric ME &= MemoryEffects::readOnly();
169*fe013be4SDimitry Andric } else if (R->getName() == "IntrWriteMem") {
170*fe013be4SDimitry Andric if (ME.onlyReadsMemory())
171*fe013be4SDimitry Andric PrintFatalError(TheDef->getLoc(),
172*fe013be4SDimitry Andric Twine("IntrWriteMem cannot be used after IntrNoMem or "
173*fe013be4SDimitry Andric "IntrReadMem. Default is ReadWrite"));
174*fe013be4SDimitry Andric ME &= MemoryEffects::writeOnly();
175*fe013be4SDimitry Andric } else if (R->getName() == "IntrArgMemOnly")
176*fe013be4SDimitry Andric ME &= MemoryEffects::argMemOnly();
177*fe013be4SDimitry Andric else if (R->getName() == "IntrInaccessibleMemOnly")
178*fe013be4SDimitry Andric ME &= MemoryEffects::inaccessibleMemOnly();
179*fe013be4SDimitry Andric else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
180*fe013be4SDimitry Andric ME &= MemoryEffects::inaccessibleOrArgMemOnly();
181*fe013be4SDimitry Andric else if (R->getName() == "Commutative")
182*fe013be4SDimitry Andric isCommutative = true;
183*fe013be4SDimitry Andric else if (R->getName() == "Throws")
184*fe013be4SDimitry Andric canThrow = true;
185*fe013be4SDimitry Andric else if (R->getName() == "IntrNoDuplicate")
186*fe013be4SDimitry Andric isNoDuplicate = true;
187*fe013be4SDimitry Andric else if (R->getName() == "IntrNoMerge")
188*fe013be4SDimitry Andric isNoMerge = true;
189*fe013be4SDimitry Andric else if (R->getName() == "IntrConvergent")
190*fe013be4SDimitry Andric isConvergent = true;
191*fe013be4SDimitry Andric else if (R->getName() == "IntrNoReturn")
192*fe013be4SDimitry Andric isNoReturn = true;
193*fe013be4SDimitry Andric else if (R->getName() == "IntrNoCallback")
194*fe013be4SDimitry Andric isNoCallback = true;
195*fe013be4SDimitry Andric else if (R->getName() == "IntrNoSync")
196*fe013be4SDimitry Andric isNoSync = true;
197*fe013be4SDimitry Andric else if (R->getName() == "IntrNoFree")
198*fe013be4SDimitry Andric isNoFree = true;
199*fe013be4SDimitry Andric else if (R->getName() == "IntrWillReturn")
200*fe013be4SDimitry Andric isWillReturn = !isNoReturn;
201*fe013be4SDimitry Andric else if (R->getName() == "IntrCold")
202*fe013be4SDimitry Andric isCold = true;
203*fe013be4SDimitry Andric else if (R->getName() == "IntrSpeculatable")
204*fe013be4SDimitry Andric isSpeculatable = true;
205*fe013be4SDimitry Andric else if (R->getName() == "IntrHasSideEffects")
206*fe013be4SDimitry Andric hasSideEffects = true;
207*fe013be4SDimitry Andric else if (R->getName() == "IntrStrictFP")
208*fe013be4SDimitry Andric isStrictFP = true;
209*fe013be4SDimitry Andric else if (R->isSubClassOf("NoCapture")) {
210*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
211*fe013be4SDimitry Andric addArgAttribute(ArgNo, NoCapture);
212*fe013be4SDimitry Andric } else if (R->isSubClassOf("NoAlias")) {
213*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
214*fe013be4SDimitry Andric addArgAttribute(ArgNo, NoAlias);
215*fe013be4SDimitry Andric } else if (R->isSubClassOf("NoUndef")) {
216*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
217*fe013be4SDimitry Andric addArgAttribute(ArgNo, NoUndef);
218*fe013be4SDimitry Andric } else if (R->isSubClassOf("NonNull")) {
219*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
220*fe013be4SDimitry Andric addArgAttribute(ArgNo, NonNull);
221*fe013be4SDimitry Andric } else if (R->isSubClassOf("Returned")) {
222*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
223*fe013be4SDimitry Andric addArgAttribute(ArgNo, Returned);
224*fe013be4SDimitry Andric } else if (R->isSubClassOf("ReadOnly")) {
225*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
226*fe013be4SDimitry Andric addArgAttribute(ArgNo, ReadOnly);
227*fe013be4SDimitry Andric } else if (R->isSubClassOf("WriteOnly")) {
228*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
229*fe013be4SDimitry Andric addArgAttribute(ArgNo, WriteOnly);
230*fe013be4SDimitry Andric } else if (R->isSubClassOf("ReadNone")) {
231*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
232*fe013be4SDimitry Andric addArgAttribute(ArgNo, ReadNone);
233*fe013be4SDimitry Andric } else if (R->isSubClassOf("ImmArg")) {
234*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
235*fe013be4SDimitry Andric addArgAttribute(ArgNo, ImmArg);
236*fe013be4SDimitry Andric } else if (R->isSubClassOf("Align")) {
237*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
238*fe013be4SDimitry Andric uint64_t Align = R->getValueAsInt("Align");
239*fe013be4SDimitry Andric addArgAttribute(ArgNo, Alignment, Align);
240*fe013be4SDimitry Andric } else if (R->isSubClassOf("Dereferenceable")) {
241*fe013be4SDimitry Andric unsigned ArgNo = R->getValueAsInt("ArgNo");
242*fe013be4SDimitry Andric uint64_t Bytes = R->getValueAsInt("Bytes");
243*fe013be4SDimitry Andric addArgAttribute(ArgNo, Dereferenceable, Bytes);
244*fe013be4SDimitry Andric } else
245*fe013be4SDimitry Andric llvm_unreachable("Unknown property!");
246*fe013be4SDimitry Andric }
247*fe013be4SDimitry Andric
isParamAPointer(unsigned ParamIdx) const248*fe013be4SDimitry Andric bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
249*fe013be4SDimitry Andric if (ParamIdx >= IS.ParamTys.size())
250*fe013be4SDimitry Andric return false;
251*fe013be4SDimitry Andric return (IS.ParamTys[ParamIdx]->isSubClassOf("LLVMQualPointerType") ||
252*fe013be4SDimitry Andric IS.ParamTys[ParamIdx]->isSubClassOf("LLVMAnyPointerType"));
253*fe013be4SDimitry Andric }
254*fe013be4SDimitry Andric
isParamImmArg(unsigned ParamIdx) const255*fe013be4SDimitry Andric bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {
256*fe013be4SDimitry Andric // Convert argument index to attribute index starting from `FirstArgIndex`.
257*fe013be4SDimitry Andric ++ParamIdx;
258*fe013be4SDimitry Andric if (ParamIdx >= ArgumentAttributes.size())
259*fe013be4SDimitry Andric return false;
260*fe013be4SDimitry Andric ArgAttribute Val{ImmArg, 0};
261*fe013be4SDimitry Andric return std::binary_search(ArgumentAttributes[ParamIdx].begin(),
262*fe013be4SDimitry Andric ArgumentAttributes[ParamIdx].end(), Val);
263*fe013be4SDimitry Andric }
264*fe013be4SDimitry Andric
addArgAttribute(unsigned Idx,ArgAttrKind AK,uint64_t V)265*fe013be4SDimitry Andric void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK,
266*fe013be4SDimitry Andric uint64_t V) {
267*fe013be4SDimitry Andric if (Idx >= ArgumentAttributes.size())
268*fe013be4SDimitry Andric ArgumentAttributes.resize(Idx + 1);
269*fe013be4SDimitry Andric ArgumentAttributes[Idx].emplace_back(AK, V);
270*fe013be4SDimitry Andric }
271