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/StringSwitch.h"
17#include "llvm/ADT/Twine.h"
18#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Support/FormatVariadic.h"
20#include "llvm/Support/MathExtras.h"
21#include "llvm/TableGen/Error.h"
22#include "llvm/TableGen/Record.h"
23#include <algorithm>
24#include <cassert>
25using namespace llvm;
26
27// As the type of more than one return values is represented as an anonymous
28// struct, which is encoded with `IIT_STRUCT` followed by a byte specifying
29// the number of return values, starting from 2 (encoded as 0) to 257
30// (encoded as 255). So, the maximum number of values that an intrinsic can
31// return is 257.
32static constexpr unsigned MaxNumReturn = 257;
33
34//===----------------------------------------------------------------------===//
35// CodeGenIntrinsic Implementation
36//===----------------------------------------------------------------------===//
37
38CodeGenIntrinsicContext::CodeGenIntrinsicContext(const RecordKeeper &RC) {
39 for (const Record *Rec : RC.getAllDerivedDefinitions(ClassName: "IntrinsicProperty"))
40 if (Rec->getValueAsBit(FieldName: "IsDefault"))
41 DefaultProperties.push_back(x: Rec);
42}
43
44CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
45 CodeGenIntrinsicContext Ctx(RC);
46
47 ArrayRef<const Record *> Defs = RC.getAllDerivedDefinitions(ClassName: "Intrinsic");
48 Intrinsics.reserve(n: Defs.size());
49
50 for (const Record *Def : Defs)
51 Intrinsics.emplace_back(args: CodeGenIntrinsic(Def, Ctx));
52
53 llvm::sort(C&: Intrinsics,
54 Comp: [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
55 // Order target independent intrinsics before target dependent
56 // ones.
57 bool LHSHasTarget = !LHS.TargetPrefix.empty();
58 bool RHSHasTarget = !RHS.TargetPrefix.empty();
59
60 // To ensure deterministic sorted order when duplicates are
61 // present, use record ID as a tie-breaker similar to
62 // sortAndReportDuplicates in Utils.cpp.
63 unsigned LhsID = LHS.TheDef->getID();
64 unsigned RhsID = RHS.TheDef->getID();
65
66 return std::tie(args&: LHSHasTarget, args: LHS.Name, args&: LhsID) <
67 std::tie(args&: RHSHasTarget, args: RHS.Name, args&: RhsID);
68 });
69
70 Targets.push_back(x: {.Name: "", .Offset: 0, .Count: 0});
71 for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
72 if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
73 Targets.back().Count = I - Targets.back().Offset;
74 Targets.push_back(x: {.Name: Intrinsics[I].TargetPrefix, .Offset: I, .Count: 0});
75 }
76 Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
77
78 CheckDuplicateIntrinsics();
79 CheckTargetIndependentIntrinsics();
80 CheckOverloadSuffixConflicts();
81}
82
83// Check for duplicate intrinsic names.
84void CodeGenIntrinsicTable::CheckDuplicateIntrinsics() const {
85 // Since the Intrinsics vector is already sorted by name, if there are 2 or
86 // more intrinsics with duplicate names, they will appear adjacent in sorted
87 // order. Note that if the intrinsic name was derived from the record name
88 // there cannot be be duplicate as TableGen parser would have flagged that.
89 // However, if the name was specified in the intrinsic definition, then its
90 // possible to have duplicate names.
91 auto I = std::adjacent_find(
92 first: Intrinsics.begin(), last: Intrinsics.end(),
93 binary_pred: [](const CodeGenIntrinsic &Int1, const CodeGenIntrinsic &Int2) {
94 return Int1.Name == Int2.Name;
95 });
96 if (I == Intrinsics.end())
97 return;
98
99 // Found a duplicate intrinsics.
100 const CodeGenIntrinsic &First = *I;
101 const CodeGenIntrinsic &Second = *(I + 1);
102 PrintError(Rec: Second.TheDef,
103 Msg: Twine("Intrinsic `") + First.Name + "` is already defined");
104 PrintFatalNote(Rec: First.TheDef, Msg: "Previous definition here");
105}
106
107// For target independent intrinsics, check that their second dotted component
108// does not match any target name.
109void CodeGenIntrinsicTable::CheckTargetIndependentIntrinsics() const {
110 SmallDenseSet<StringRef> TargetNames;
111 for (const auto &Target : ArrayRef(Targets).drop_front())
112 TargetNames.insert(V: Target.Name);
113
114 // Set of target independent intrinsics.
115 const auto &Set = Targets[0];
116 for (const auto &Int : ArrayRef(&Intrinsics[Set.Offset], Set.Count)) {
117 StringRef Name = Int.Name;
118 StringRef Prefix = Name.drop_front(N: 5).split(Separator: '.').first;
119 if (!TargetNames.contains(V: Prefix))
120 continue;
121 PrintFatalError(Rec: Int.TheDef,
122 Msg: "target independent intrinsic `" + Name +
123 "' has prefix `llvm." + Prefix +
124 "` that conflicts with intrinsics for target `" +
125 Prefix + "`");
126 }
127}
128
129// Return true if the given Suffix looks like a mangled type. Note that this
130// check is conservative, but allows all existing LLVM intrinsic suffixes to be
131// considered as not looking like a mangling suffix.
132static bool doesSuffixLookLikeMangledType(StringRef Suffix) {
133 // Try to match against possible mangling suffixes for various types.
134 // See getMangledTypeStr() for the mangling suffixes possible. It includes
135 // pointer : p[0-9]+
136 // array : a[0-9]+.+
137 // struct: : s_/sl_.+
138 // function : f_.+
139 // vector : v/nxv[0-9]+.+
140 // target type : t.+
141 // integer : i[0-9]+
142 // named types : See `NamedTypes` below.
143
144 // Match anything with an _, so match function and struct types.
145 if (Suffix.contains(C: '_'))
146 return true;
147
148 // [av][0-9]+.+, simplified to [av][0-9].+
149 if (Suffix.size() >= 2 && is_contained(Range: "av", Element: Suffix[0]) && isDigit(C: Suffix[1]))
150 return true;
151
152 // nxv[0-9]+.+, simplified to nxv[0-9].+
153 if (Suffix.size() >= 4 && Suffix.starts_with(Prefix: "nxv") && isDigit(C: Suffix[3]))
154 return true;
155
156 // t.+
157 if (Suffix.size() > 1 && Suffix.starts_with(Prefix: 't'))
158 return false;
159
160 // [pi][0-9]+
161 if (Suffix.size() > 1 && is_contained(Range: "pi", Element: Suffix[0]) &&
162 all_of(Range: Suffix.drop_front(), P: isDigit))
163 return true;
164
165 // Match one of the named types.
166 static constexpr StringLiteral NamedTypes[] = {
167 "isVoid", "Metadata", "f16", "f32", "f64",
168 "f80", "f128", "bf16", "ppcf128", "x86amx"};
169 return is_contained(Range: NamedTypes, Element: Suffix);
170}
171
172// Check for conflicts with overloaded intrinsics. If there exists an overloaded
173// intrinsic with base name `llvm.target.foo`, LLVM will add a mangling suffix
174// to it to encode the overload types. This mangling suffix is 1 or more .
175// prefixed mangled type string as defined in `getMangledTypeStr`. If there
176// exists another intrinsic `llvm.target.foo[.<suffixN>]+`, which has the same
177// prefix as the overloaded intrinsic, its possible that there may be a name
178// conflict with the overloaded intrinsic and either one may interfere with name
179// lookup for the other, leading to wrong intrinsic ID being assigned.
180//
181// The actual name lookup in the intrinsic name table is done by a search
182// on each successive '.' separted component of the intrinsic name (see
183// `lookupLLVMIntrinsicByName`). Consider first the case where there exists a
184// non-overloaded intrinsic `llvm.target.foo[.suffix]+`. For the non-overloaded
185// intrinsics, the name lookup is an exact match, so the presence of the
186// overloaded intrinsic with the same prefix will not interfere with the
187// search. However, a lookup intended to match the overloaded intrinsic might be
188// affected by the presence of another entry in the name table with the same
189// prefix.
190//
191// Since LLVM's name lookup first selects the target specific (or target
192// independent) slice of the name table to look into, intrinsics in 2 different
193// targets cannot conflict with each other. Within a specific target,
194// if we have an overloaded intrinsic with name `llvm.target.foo` and another
195// one with same prefix and one or more suffixes `llvm.target.foo[.<suffixN>]+`,
196// then the name search will try to first match against suffix0, then suffix1
197// etc. If suffix0 can match a mangled type, then the search for an
198// `llvm.target.foo` with a mangling suffix can match against suffix0,
199// preventing a match with `llvm.target.foo`. If suffix0 cannot match a mangled
200// type, then that cannot happen, so we do not need to check for later suffixes.
201//
202// Generalizing, the `llvm.target.foo[.suffixN]+` will cause a conflict if the
203// first suffix (.suffix0) can match a mangled type (and then we do not need to
204// check later suffixes) and will not cause a conflict if it cannot (and then
205// again, we do not need to check for later suffixes).
206void CodeGenIntrinsicTable::CheckOverloadSuffixConflicts() const {
207 for (const TargetSet &Set : Targets) {
208 const CodeGenIntrinsic *Overloaded = nullptr;
209 for (const CodeGenIntrinsic &Int : (*this)[Set]) {
210 // If we do not have an overloaded intrinsic to check against, nothing
211 // to do except potentially identifying this as a candidate for checking
212 // against in future iteration.
213 if (!Overloaded) {
214 if (Int.isOverloaded)
215 Overloaded = &Int;
216 continue;
217 }
218
219 StringRef Name = Int.Name;
220 StringRef OverloadName = Overloaded->Name;
221 // If we have an overloaded intrinsic to check again, check if its name is
222 // a proper prefix of this intrinsic.
223 if (Name.starts_with(Prefix: OverloadName) && Name[OverloadName.size()] == '.') {
224 // If yes, verify suffixes and flag an error.
225 StringRef Suffixes = Name.drop_front(N: OverloadName.size() + 1);
226
227 // Only need to look at the first suffix.
228 StringRef Suffix0 = Suffixes.split(Separator: '.').first;
229
230 if (!doesSuffixLookLikeMangledType(Suffix: Suffix0))
231 continue;
232
233 unsigned SuffixSize = OverloadName.size() + 1 + Suffix0.size();
234 // If suffix looks like mangling suffix, flag it as an error.
235 PrintError(ErrorLoc: Int.TheDef->getLoc(),
236 Msg: "intrinsic `" + Name + "` cannot share prefix `" +
237 Name.take_front(N: SuffixSize) +
238 "` with another overloaded intrinsic `" + OverloadName +
239 "`");
240 PrintNote(NoteLoc: Overloaded->TheDef->getLoc(),
241 Msg: "Overloaded intrinsic `" + OverloadName + "` defined here");
242 continue;
243 }
244
245 // If we find an intrinsic that is not a proper prefix, any later
246 // intrinsic is also not going to be a proper prefix, so invalidate the
247 // overloaded to check against.
248 Overloaded = nullptr;
249 }
250 }
251}
252
253const CodeGenIntrinsic &CodeGenIntrinsicMap::operator[](const Record *Record) {
254 if (!Record->isSubClassOf(Name: "Intrinsic"))
255 PrintFatalError(Msg: "Intrinsic defs should be subclass of 'Intrinsic' class");
256
257 auto [Iter, Inserted] = Map.try_emplace(Key: Record);
258 if (Inserted)
259 Iter->second = std::make_unique<CodeGenIntrinsic>(args&: Record, args: Ctx);
260 return *Iter->second;
261}
262
263CodeGenIntrinsic::CodeGenIntrinsic(const Record *R,
264 const CodeGenIntrinsicContext &Ctx)
265 : TheDef(R) {
266 StringRef DefName = TheDef->getName();
267 ArrayRef<SMLoc> DefLoc = R->getLoc();
268
269 if (!DefName.starts_with(Prefix: "int_"))
270 PrintFatalError(ErrorLoc: DefLoc,
271 Msg: "Intrinsic '" + DefName + "' does not start with 'int_'!");
272
273 EnumName = DefName.substr(Start: 4);
274
275 // Ignore a missing ClangBuiltinName field.
276 ClangBuiltinName =
277 R->getValueAsOptionalString(FieldName: "ClangBuiltinName").value_or(u: "");
278 // Ignore a missing MSBuiltinName field.
279 MSBuiltinName = R->getValueAsOptionalString(FieldName: "MSBuiltinName").value_or(u: "");
280 TargetFeatures = R->getValueAsString(FieldName: "TargetFeatures");
281
282 TargetPrefix = R->getValueAsString(FieldName: "TargetPrefix");
283 Name = R->getValueAsString(FieldName: "LLVMName").str();
284
285 std::string DefaultName = "llvm." + EnumName.str();
286 llvm::replace(Range&: DefaultName, OldValue: '_', NewValue: '.');
287
288 if (Name == "") {
289 // If an explicit name isn't specified, derive one from the DefName.
290 Name = std::move(DefaultName);
291 } else {
292 // Verify it starts with "llvm.".
293 if (!StringRef(Name).starts_with(Prefix: "llvm."))
294 PrintFatalError(ErrorLoc: DefLoc, Msg: "Intrinsic '" + DefName +
295 "'s name does not start with 'llvm.'!");
296
297 if (Name == DefaultName)
298 PrintNote(NoteLoc: DefLoc, Msg: "Explicitly specified name matches default name, "
299 "consider dropping it");
300 }
301
302 // If TargetPrefix is specified, make sure that Name starts with
303 // "llvm.<targetprefix>.".
304 if (!TargetPrefix.empty()) {
305 StringRef Prefix = StringRef(Name).drop_front(N: 5); // Drop llvm.
306 if (!Prefix.consume_front(Prefix: TargetPrefix) || !Prefix.starts_with(Prefix: '.'))
307 PrintFatalError(ErrorLoc: DefLoc, Msg: "Intrinsic '" + DefName +
308 "' does not start with 'llvm." +
309 TargetPrefix + ".'!");
310 }
311
312 unsigned NumRet = R->getValueAsListInit(FieldName: "RetTypes")->size();
313 unsigned NumParam = R->getValueAsListInit(FieldName: "ParamTypes")->size();
314
315 if (NumRet > MaxNumReturn)
316 PrintFatalError(ErrorLoc: DefLoc, Msg: "intrinsics can only return upto " +
317 Twine(MaxNumReturn) + " values, '" + DefName +
318 "' returns " + Twine(NumRet) + " values");
319
320 const Record *TypeInfo = R->getValueAsDef(FieldName: "TypeInfo");
321 if (!TypeInfo->isSubClassOf(Name: "TypeInfoGen"))
322 PrintFatalError(ErrorLoc: DefLoc, Msg: "TypeInfo field in " + DefName +
323 " should be of subclass of TypeInfoGen!");
324
325 isOverloaded = TypeInfo->getValueAsBit(FieldName: "isOverloaded");
326 std::vector<const Record *> AllTypes =
327 TypeInfo->getValueAsListOfDefs(FieldName: "AllTypes");
328
329 // Validate overload index values in dependent types.
330 if (isOverloaded) {
331 const ListInit *OverloadedTypes =
332 TypeInfo->getValueAsListInit(FieldName: "OverloadTypes");
333 unsigned NumOverloadedTypes = OverloadedTypes->size();
334 for (const auto &[Idx, Ty] : enumerate(First&: AllTypes)) {
335 if (!Ty->isSubClassOf(Name: "LLVMDependentType"))
336 continue;
337 unsigned OverloadIndex = Ty->getValueAsInt(FieldName: "OverloadIndex");
338 if (OverloadIndex >= NumOverloadedTypes)
339 PrintFatalError(
340 Rec: Ty, Msg: formatv(Fmt: "for intrinsic {} overload index {} is invalid, "
341 "intrinsic only has {} overloaded types",
342 Vals&: DefName, Vals&: OverloadIndex, Vals&: NumOverloadedTypes));
343 const Record *OTy = OverloadedTypes->getElementAsRecord(Idx: OverloadIndex);
344 if (!OTy->isSubClassOf(Name: "LLVMAnyType"))
345 PrintFatalError(Rec: Ty, Msg: formatv(Fmt: "for intrinsic {} overload index {} is "
346 "invalid, dependent types must reference "
347 "an overload index of an \'llvm_any\' type",
348 Vals&: DefName, Vals&: OverloadIndex));
349
350 // Replace the dependent type with the overloaded type it references.
351 AllTypes[Idx] = OTy;
352 }
353 }
354
355 ArrayRef<const Record *> AllTypesRef = AllTypes;
356
357 // Types field is a concatenation of Return types followed by Param types.
358 for (const Record *RetTy : AllTypesRef.take_front(N: NumRet)) {
359 if (RetTy->getName() == "llvm_vararg_ty")
360 PrintFatalError(ErrorLoc: DefLoc, Msg: "cannot use llvm_vararg_ty as a return type");
361 IS.RetTys.push_back(x: RetTy);
362 }
363
364 for (const auto &[Idx, ParamTy] : enumerate(First: AllTypesRef.drop_front(N: NumRet))) {
365 if (Idx != NumParam - 1 && ParamTy->getName() == "llvm_vararg_ty")
366 PrintFatalError(ErrorLoc: DefLoc,
367 Msg: "llvm_vararg_ty can only be the last parameter type");
368 IS.ParamTys.push_back(x: ParamTy);
369 }
370
371 // Parse the intrinsic properties.
372 const ListInit *PropList = R->getValueAsListInit(FieldName: "IntrProperties");
373 for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
374 const Record *Property = PropList->getElementAsRecord(Idx: i);
375 assert(Property->isSubClassOf("IntrinsicProperty") &&
376 "Expected a property!");
377
378 setProperty(Property);
379 }
380
381 // Set default properties to true.
382 setDefaultProperties(Ctx.DefaultProperties);
383
384 // Also record the SDPatternOperator Properties.
385 Properties = parseSDPatternOperatorProperties(R);
386
387 // Sort the argument attributes for later benefit.
388 for (auto &Attrs : ArgumentAttributes)
389 llvm::sort(C&: Attrs);
390
391 // Default values are not yet supported for overloaded intrinsics
392 // (overloaded support will come in a follow-up).
393 if (isOverloaded &&
394 llvm::any_of(Range&: ParamDefaultValues, P: [](const std::optional<uint64_t> &DV) {
395 return DV.has_value();
396 }))
397 PrintFatalError(ErrorLoc: TheDef->getLoc(),
398 Msg: "default argument values are not supported for "
399 "overloaded intrinsics");
400
401 // Validate: defaults must form a contiguous trailing block ending at
402 // the last parameter (mirrors C++ default-argument rules).
403 unsigned NumParams = IS.ParamTys.size();
404 bool SeenDefault = false;
405 for (unsigned i = 0; i < NumParams; ++i) {
406 bool HasDefault =
407 (i < ParamDefaultValues.size() && ParamDefaultValues[i].has_value());
408 if (HasDefault) {
409 SeenDefault = true;
410 } else if (SeenDefault) {
411 PrintFatalError(ErrorLoc: TheDef->getLoc(),
412 Msg: "missing default argument on parameter " + Twine(i));
413 }
414 }
415
416 // Validate each declared default: the parameter must be an integer type and
417 // the value (an unsigned bit pattern) must fit in the declared width.
418 for (unsigned i = 0; i < ParamDefaultValues.size(); ++i) {
419 if (!ParamDefaultValues[i].has_value())
420 continue;
421 const Record *VT = IS.ParamTys[i]->getValueAsDef(FieldName: "VT");
422 if (!VT->getValueAsBit(FieldName: "isInteger")) {
423 PrintFatalError(ErrorLoc: TheDef->getLoc(),
424 Msg: "default argument on parameter " + Twine(i) +
425 " requires an integer parameter type");
426 }
427 unsigned Width = VT->getValueAsInt(FieldName: "Size");
428 uint64_t Value = *ParamDefaultValues[i];
429 if (!isUIntN(N: Width, x: Value)) {
430 PrintFatalError(ErrorLoc: TheDef->getLoc(),
431 Msg: "default argument value " + Twine(Value) +
432 " out of range for i" + Twine(Width) + " parameter " +
433 Twine(i));
434 }
435 }
436}
437
438void CodeGenIntrinsic::setDefaultProperties(
439 ArrayRef<const Record *> DefaultProperties) {
440 // opt-out of using default attributes.
441 if (TheDef->getValueAsBit(FieldName: "DisableDefaultAttributes"))
442 return;
443
444 for (const Record *Rec : DefaultProperties)
445 setProperty(Rec);
446}
447
448void CodeGenIntrinsic::setProperty(const Record *R) {
449 if (R->getName() == "IntrNoMem")
450 ME = MemoryEffects::none();
451 else if (R->getName() == "IntrReadMem") {
452 if (ME.onlyWritesMemory())
453 PrintFatalError(ErrorLoc: TheDef->getLoc(),
454 Msg: Twine("IntrReadMem cannot be used after IntrNoMem or "
455 "IntrWriteMem. Default is ReadWrite"));
456 ME &= MemoryEffects::readOnly();
457 } else if (R->getName() == "IntrWriteMem") {
458 if (ME.onlyReadsMemory())
459 PrintFatalError(ErrorLoc: TheDef->getLoc(),
460 Msg: Twine("IntrWriteMem cannot be used after IntrNoMem or "
461 "IntrReadMem. Default is ReadWrite"));
462 ME &= MemoryEffects::writeOnly();
463 } else if (R->getName() == "IntrArgMemOnly")
464 ME &= MemoryEffects::argMemOnly();
465 else if (R->getName() == "IntrInaccessibleMemOnly")
466 ME &= MemoryEffects::inaccessibleMemOnly();
467 else if (R->isSubClassOf(Name: "IntrRead")) {
468 MemoryEffects ReadMask = MemoryEffects::writeOnly();
469 for (const Record *RLoc : R->getValueAsListOfDefs(FieldName: "MemLoc"))
470 ReadMask = ReadMask.getWithModRef(Loc: getValueAsIRMemLocation(R: RLoc),
471 MR: ModRefInfo::ModRef);
472 ME &= ReadMask;
473 } else if (R->isSubClassOf(Name: "IntrWrite")) {
474 MemoryEffects WriteMask = MemoryEffects::readOnly();
475 for (const Record *WLoc : R->getValueAsListOfDefs(FieldName: "MemLoc"))
476 WriteMask = WriteMask.getWithModRef(Loc: getValueAsIRMemLocation(R: WLoc),
477 MR: ModRefInfo::ModRef);
478 ME &= WriteMask;
479 } else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
480 ME &= MemoryEffects::inaccessibleOrArgMemOnly();
481 else if (R->getName() == "Commutative")
482 isCommutative = true;
483 else if (R->getName() == "Throws")
484 canThrow = true;
485 else if (R->getName() == "IntrNoDuplicate")
486 isNoDuplicate = true;
487 else if (R->getName() == "IntrNoMerge")
488 isNoMerge = true;
489 else if (R->getName() == "IntrConvergent")
490 isConvergent = true;
491 else if (R->getName() == "IntrNoReturn")
492 isNoReturn = true;
493 else if (R->getName() == "IntrNoCallback")
494 isNoCallback = true;
495 else if (R->getName() == "IntrNoSync")
496 isNoSync = true;
497 else if (R->getName() == "IntrNoFree")
498 isNoFree = true;
499 else if (R->getName() == "IntrWillReturn")
500 isWillReturn = !isNoReturn;
501 else if (R->getName() == "IntrCold")
502 isCold = true;
503 else if (R->getName() == "IntrSpeculatable")
504 isSpeculatable = true;
505 else if (R->getName() == "IntrHasSideEffects")
506 hasSideEffects = true;
507 else if (R->getName() == "IntrStrictFP")
508 isStrictFP = true;
509 else if (R->getName() == "IntrNoCreateUndefOrPoison")
510 isNoCreateUndefOrPoison = true;
511 else if (R->getName() == "IntrTriviallyScalarizable")
512 isTriviallyScalarizable = true;
513 else if (R->isSubClassOf(Name: "NoCapture")) {
514 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
515 addArgAttribute(Idx: ArgNo, AK: NoCapture);
516 } else if (R->isSubClassOf(Name: "NoAlias")) {
517 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
518 addArgAttribute(Idx: ArgNo, AK: NoAlias);
519 } else if (R->isSubClassOf(Name: "NoUndef")) {
520 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
521 addArgAttribute(Idx: ArgNo, AK: NoUndef);
522 } else if (R->isSubClassOf(Name: "NonNull")) {
523 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
524 addArgAttribute(Idx: ArgNo, AK: NonNull);
525 } else if (R->isSubClassOf(Name: "Returned")) {
526 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
527 addArgAttribute(Idx: ArgNo, AK: Returned);
528 } else if (R->isSubClassOf(Name: "ReadOnly")) {
529 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
530 addArgAttribute(Idx: ArgNo, AK: ReadOnly);
531 } else if (R->isSubClassOf(Name: "WriteOnly")) {
532 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
533 addArgAttribute(Idx: ArgNo, AK: WriteOnly);
534 } else if (R->isSubClassOf(Name: "ReadNone")) {
535 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
536 addArgAttribute(Idx: ArgNo, AK: ReadNone);
537 } else if (R->isSubClassOf(Name: "ImmArg")) {
538 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
539 addArgAttribute(Idx: ArgNo, AK: ImmArg);
540
541 // If a DefaultValue (not the NoDefault sentinel) was supplied, record it.
542 // NoDefault is recognized by its Value field being unset (?).
543 const Record *DefaultField = R->getValueAsDef(FieldName: "Default");
544 const RecordVal *ValueField = DefaultField->getValue(Name: "Value");
545 if (ValueField && !isa<UnsetInit>(Val: ValueField->getValue())) {
546 int64_t Value = DefaultField->getValueAsInt(FieldName: "Value");
547 // Defaults are stored as an unsigned bit pattern; a negative literal
548 // would silently wrap, so reject it with a clear message.
549 if (Value < 0)
550 PrintFatalError(ErrorLoc: TheDef->getLoc(), Msg: "default argument value " +
551 Twine(Value) + " on parameter " +
552 Twine(ArgNo - 1) +
553 " must be non-negative");
554 addDefaultArgValue(ArgIdx: ArgNo - 1, Value);
555 }
556 } else if (R->isSubClassOf(Name: "Align")) {
557 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
558 uint64_t Align = R->getValueAsInt(FieldName: "Align");
559 addArgAttribute(Idx: ArgNo, AK: Alignment, V: Align);
560 } else if (R->isSubClassOf(Name: "Dereferenceable")) {
561 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
562 uint64_t Bytes = R->getValueAsInt(FieldName: "Bytes");
563 addArgAttribute(Idx: ArgNo, AK: Dereferenceable, V: Bytes);
564 } else if (R->isSubClassOf(Name: "Range")) {
565 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
566 int64_t Lower = R->getValueAsInt(FieldName: "Lower");
567 int64_t Upper = R->getValueAsInt(FieldName: "Upper");
568 addArgAttribute(Idx: ArgNo, AK: Range, V: Lower, V2: Upper);
569 } else if (R->isSubClassOf(Name: "ArgInfo")) {
570 unsigned ArgNo = R->getValueAsInt(FieldName: "ArgNo");
571 if (ArgNo < 1)
572 PrintFatalError(ErrorLoc: R->getLoc(),
573 Msg: "ArgInfo requires ArgNo >= 1 (0 is return value)");
574 const ListInit *Properties = R->getValueAsListInit(FieldName: "Properties");
575 StringRef ArgName;
576 StringRef FuncName;
577
578 for (const Init *PropInit : Properties->getElements()) {
579 if (const auto *PropDef = dyn_cast<DefInit>(Val: PropInit)) {
580 const Record *PropRec = PropDef->getDef();
581
582 if (PropRec->isSubClassOf(Name: "ArgName"))
583 ArgName = PropRec->getValueAsString(FieldName: "Name");
584 else if (PropRec->isSubClassOf(Name: "ImmArgPrinter"))
585 FuncName = PropRec->getValueAsString(FieldName: "FuncName");
586 else
587 PrintFatalError(ErrorLoc: PropRec->getLoc(),
588 Msg: "Unknown ArgProperty type: " + PropRec->getName());
589 }
590 }
591 addPrettyPrintFunction(ArgIdx: ArgNo - 1, ArgName, FuncName);
592 } else {
593 llvm_unreachable("Unknown property!");
594 }
595}
596
597llvm::IRMemLocation
598CodeGenIntrinsic::getValueAsIRMemLocation(const Record *R) const {
599 StringRef Name = R->getName();
600 IRMemLocation Loc =
601 StringSwitch<IRMemLocation>(Name)
602 .Case(S: "ArgMem", Value: IRMemLocation::ArgMem)
603 .Case(S: "TargetMem0", Value: IRMemLocation::TargetMem0)
604 .Case(S: "TargetMem1", Value: IRMemLocation::TargetMem1)
605 .Case(S: "InaccessibleMem", Value: IRMemLocation::InaccessibleMem)
606 .Default(Value: IRMemLocation::Other); // fallback enum
607
608 if (Loc == IRMemLocation::Other)
609 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "unknown IRMemLocation: " + Name);
610
611 return Loc;
612}
613
614bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
615 if (ParamIdx >= IS.ParamTys.size())
616 return false;
617 return IS.ParamTys[ParamIdx]->isSubClassOf(Name: "LLVMQualPointerType") ||
618 IS.ParamTys[ParamIdx]->isSubClassOf(Name: "LLVMAnyPointerType");
619}
620
621bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {
622 // Convert argument index to attribute index starting from `FirstArgIndex`.
623 ++ParamIdx;
624 if (ParamIdx >= ArgumentAttributes.size())
625 return false;
626 ArgAttribute Val{ImmArg, 0, 0};
627 return llvm::binary_search(Range: ArgumentAttributes[ParamIdx], Value&: Val);
628}
629
630void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK, uint64_t V,
631 uint64_t V2) {
632 if (Idx >= ArgumentAttributes.size())
633 ArgumentAttributes.resize(N: Idx + 1);
634 ArgumentAttributes[Idx].emplace_back(Args&: AK, Args&: V, Args&: V2);
635}
636
637void CodeGenIntrinsic::addPrettyPrintFunction(unsigned ArgIdx,
638 StringRef ArgName,
639 StringRef FuncName) {
640 auto It = llvm::find_if(Range&: PrettyPrintFunctions, P: [ArgIdx](const auto &Info) {
641 return Info.ArgIdx == ArgIdx;
642 });
643 if (It != PrettyPrintFunctions.end())
644 PrintFatalError(ErrorLoc: TheDef->getLoc(), Msg: "ArgInfo for argument " + Twine(ArgIdx) +
645 " is already defined as '" +
646 It->FuncName + "'");
647 PrettyPrintFunctions.emplace_back(Args&: ArgIdx, Args&: ArgName, Args&: FuncName);
648}
649
650void CodeGenIntrinsic::addDefaultArgValue(unsigned ArgIdx, uint64_t Value) {
651 if (ArgIdx >= ParamDefaultValues.size())
652 ParamDefaultValues.resize(N: ArgIdx + 1, NV: std::nullopt);
653
654 if (ParamDefaultValues[ArgIdx].has_value())
655 PrintFatalError(ErrorLoc: TheDef->getLoc(), Msg: "Default value for argument " +
656 Twine(ArgIdx) +
657 " is already defined");
658
659 ParamDefaultValues[ArgIdx] = Value;
660}
661