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