1 //===- CodeGenIntrinsics.cpp - Intrinsic Class Wrapper --------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines a wrapper class for the 'Intrinsic' TableGen class.
11 //===----------------------------------------------------------------------===//
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"
24 //===----------------------------------------------------------------------===//
25 // CodeGenIntrinsic Implementation
26 //===----------------------------------------------------------------------===//
28 CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper
&RC
) {
29 std::vector
<Record
*> IntrProperties
=
30 RC
.getAllDerivedDefinitions("IntrinsicProperty");
32 std::vector
<Record
*> DefaultProperties
;
33 for (Record
*Rec
: IntrProperties
)
34 if (Rec
->getValueAsBit("IsDefault"))
35 DefaultProperties
.push_back(Rec
);
37 std::vector
<Record
*> Defs
= RC
.getAllDerivedDefinitions("Intrinsic");
38 Intrinsics
.reserve(Defs
.size());
40 for (unsigned I
= 0, e
= Defs
.size(); I
!= e
; ++I
)
41 Intrinsics
.push_back(CodeGenIntrinsic(Defs
[I
], DefaultProperties
));
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
);
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});
54 Targets
.back().Count
= Intrinsics
.size() - Targets
.back().Offset
;
57 CodeGenIntrinsic::CodeGenIntrinsic(Record
*R
,
58 std::vector
<Record
*> DefaultProperties
) {
60 std::string DefName
= std::string(R
->getName());
61 ArrayRef
<SMLoc
> DefLoc
= R
->getLoc();
64 isCommutative
= false;
72 isNoDuplicate
= false;
75 isSpeculatable
= false;
76 hasSideEffects
= false;
79 if (DefName
.size() <= 4 || DefName
.substr(0, 4) != "int_")
80 PrintFatalError(DefLoc
,
81 "Intrinsic '" + DefName
+ "' does not start with 'int_'!");
83 EnumName
= DefName
.substr(4);
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"));
91 TargetPrefix
= std::string(R
->getValueAsString("TargetPrefix"));
92 Name
= std::string(R
->getValueAsString("LLVMName"));
95 // If an explicit name isn't specified, derive one from the DefName.
98 for (unsigned i
= 0, e
= EnumName
.size(); i
!= e
; ++i
)
99 Name
+= (EnumName
[i
] == '_') ? '.' : EnumName
[i
];
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.'!");
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
+ ".'!");
117 if (auto *Types
= R
->getValue("Types")) {
118 auto *TypeList
= cast
<ListInit
>(Types
->getValue());
119 isOverloaded
= R
->getValueAsBit("isOverloaded");
122 for (unsigned E
= R
->getValueAsListInit("RetTypes")->size(); I
< E
; ++I
)
123 IS
.RetTys
.push_back(TypeList
->getElementAsRecord(I
));
125 for (unsigned E
= TypeList
->size(); I
< E
; ++I
)
126 IS
.ParamTys
.push_back(TypeList
->getElementAsRecord(I
));
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!");
136 setProperty(Property
);
139 // Set default properties to true.
140 setDefaultProperties(R
, DefaultProperties
);
142 // Also record the SDPatternOperator Properties.
143 Properties
= parseSDPatternOperatorProperties(R
);
145 // Sort the argument attributes for later benefit.
146 for (auto &Attrs
: ArgumentAttributes
)
150 void CodeGenIntrinsic::setDefaultProperties(
151 Record
*R
, std::vector
<Record
*> DefaultProperties
) {
152 // opt-out of using default attributes.
153 if (R
->getValueAsBit("DisableDefaultAttributes"))
156 for (Record
*Rec
: DefaultProperties
)
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")
185 else if (R
->getName() == "IntrNoDuplicate")
186 isNoDuplicate
= true;
187 else if (R
->getName() == "IntrNoMerge")
189 else if (R
->getName() == "IntrConvergent")
191 else if (R
->getName() == "IntrNoReturn")
193 else if (R
->getName() == "IntrNoCallback")
195 else if (R
->getName() == "IntrNoSync")
197 else if (R
->getName() == "IntrNoFree")
199 else if (R
->getName() == "IntrWillReturn")
200 isWillReturn
= !isNoReturn
;
201 else if (R
->getName() == "IntrCold")
203 else if (R
->getName() == "IntrSpeculatable")
204 isSpeculatable
= true;
205 else if (R
->getName() == "IntrHasSideEffects")
206 hasSideEffects
= true;
207 else if (R
->getName() == "IntrStrictFP")
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
);
245 llvm_unreachable("Unknown property!");
248 bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx
) const {
249 if (ParamIdx
>= IS
.ParamTys
.size())
251 return (IS
.ParamTys
[ParamIdx
]->isSubClassOf("LLVMQualPointerType") ||
252 IS
.ParamTys
[ParamIdx
]->isSubClassOf("LLVMAnyPointerType"));
255 bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx
) const {
256 // Convert argument index to attribute index starting from `FirstArgIndex`.
258 if (ParamIdx
>= ArgumentAttributes
.size())
260 ArgAttribute Val
{ImmArg
, 0};
261 return std::binary_search(ArgumentAttributes
[ParamIdx
].begin(),
262 ArgumentAttributes
[ParamIdx
].end(), Val
);
265 void CodeGenIntrinsic::addArgAttribute(unsigned Idx
, ArgAttrKind AK
,
267 if (Idx
>= ArgumentAttributes
.size())
268 ArgumentAttributes
.resize(Idx
+ 1);
269 ArgumentAttributes
[Idx
].emplace_back(AK
, V
);