1//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
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 tablegen backend emits information about intrinsic functions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CodeGenIntrinsics.h"
14#include "SequenceToOffsetTable.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/Twine.h"
19#include "llvm/Support/CommandLine.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/FormatVariadic.h"
22#include "llvm/Support/ModRef.h"
23#include "llvm/Support/SourceMgr.h"
24#include "llvm/Support/raw_ostream.h"
25#include "llvm/TableGen/CodeGenHelpers.h"
26#include "llvm/TableGen/Error.h"
27#include "llvm/TableGen/Record.h"
28#include "llvm/TableGen/StringToOffsetTable.h"
29#include "llvm/TableGen/TableGenBackend.h"
30#include <algorithm>
31#include <array>
32#include <cassert>
33#include <cctype>
34#include <map>
35#include <optional>
36#include <string>
37#include <utility>
38#include <vector>
39using namespace llvm;
40
41static cl::OptionCategory GenIntrinsicCat("Options for -gen-intrinsic-enums");
42static cl::opt<std::string>
43 IntrinsicPrefix("intrinsic-prefix",
44 cl::desc("Generate intrinsics with this target prefix"),
45 cl::value_desc("target prefix"), cl::cat(GenIntrinsicCat));
46
47namespace {
48class IntrinsicEmitter {
49 const RecordKeeper &Records;
50
51public:
52 IntrinsicEmitter(const RecordKeeper &R) : Records(R) {}
53
54 void run(raw_ostream &OS, bool Enums);
55
56 void EmitEnumInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
57 void EmitAnyKindEnums(raw_ostream &OS);
58 void EmitIITInfo(raw_ostream &OS);
59 void EmitTargetInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
60 void EmitIntrinsicToNameTable(const CodeGenIntrinsicTable &Ints,
61 raw_ostream &OS);
62 void EmitIntrinsicToTargetFeaturesTable(const CodeGenIntrinsicTable &Ints,
63 raw_ostream &OS);
64 void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints,
65 raw_ostream &OS);
66 void EmitIntrinsicToScalarizableTable(const CodeGenIntrinsicTable &Ints,
67 raw_ostream &OS);
68 void EmitIntrinsicToPrettyPrintTable(const CodeGenIntrinsicTable &Ints,
69 raw_ostream &OS);
70 void EmitIntrinsicBitTable(
71 const CodeGenIntrinsicTable &Ints, raw_ostream &OS, StringRef Guard,
72 StringRef TableName, StringRef Comment,
73 function_ref<bool(const CodeGenIntrinsic &Int)> GetProperty);
74 void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
75 void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
76 void EmitPrettyPrintArguments(const CodeGenIntrinsicTable &Ints,
77 raw_ostream &OS);
78 void EmitDefaultArgValuesTable(const CodeGenIntrinsicTable &Ints,
79 raw_ostream &OS);
80 void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints,
81 bool IsClang, raw_ostream &OS);
82};
83
84// Helper class to use with `TableGen::Emitter::OptClass`.
85template <bool Enums> class IntrinsicEmitterOpt : public IntrinsicEmitter {
86public:
87 IntrinsicEmitterOpt(const RecordKeeper &R) : IntrinsicEmitter(R) {}
88 void run(raw_ostream &OS) { IntrinsicEmitter::run(OS, Enums); }
89};
90
91} // End anonymous namespace
92
93//===----------------------------------------------------------------------===//
94// IntrinsicEmitter Implementation
95//===----------------------------------------------------------------------===//
96
97void IntrinsicEmitter::run(raw_ostream &OS, bool Enums) {
98 emitSourceFileHeader(Desc: "Intrinsic Function Source Fragment", OS);
99
100 CodeGenIntrinsicTable Ints(Records);
101
102 if (Enums) {
103 // Emit the enum information.
104 EmitEnumInfo(Ints, OS);
105
106 // Emit AnyKind enums for Intrinsics.h.
107 EmitAnyKindEnums(OS);
108 } else {
109 // Emit IIT_Info constants.
110 EmitIITInfo(OS);
111
112 // Emit the target metadata.
113 EmitTargetInfo(Ints, OS);
114
115 // Emit the intrinsic ID -> name table.
116 EmitIntrinsicToNameTable(Ints, OS);
117
118 // Emit the intrinsic ID -> required target features table.
119 EmitIntrinsicToTargetFeaturesTable(Ints, OS);
120
121 // Emit the intrinsic ID -> overload table.
122 EmitIntrinsicToOverloadTable(Ints, OS);
123
124 // Emit the intrinsic ID -> trivially scalarizable table.
125 EmitIntrinsicToScalarizableTable(Ints, OS);
126
127 // Emit the intrinsic declaration generator.
128 EmitGenerator(Ints, OS);
129
130 // Emit the intrinsic parameter attributes.
131 EmitAttributes(Ints, OS);
132
133 // Emit the intrinsic ID -> pretty print table.
134 EmitIntrinsicToPrettyPrintTable(Ints, OS);
135
136 // Emit Pretty Print attribute.
137 EmitPrettyPrintArguments(Ints, OS);
138
139 // Emit the default-argument values table and lookup function.
140 EmitDefaultArgValuesTable(Ints, OS);
141
142 // Emit code to translate Clang builtins into LLVM intrinsics.
143 EmitIntrinsicToBuiltinMap(Ints, IsClang: true, OS);
144
145 // Emit code to translate MS builtins into LLVM intrinsics.
146 EmitIntrinsicToBuiltinMap(Ints, IsClang: false, OS);
147 }
148}
149
150void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
151 raw_ostream &OS) {
152 // Find the TargetSet for which to generate enums. There will be an initial
153 // set with an empty target prefix which will include target independent
154 // intrinsics like dbg.value.
155 using TargetSet = CodeGenIntrinsicTable::TargetSet;
156 const TargetSet *Set = nullptr;
157 for (const auto &Target : Ints.getTargets()) {
158 if (Target.Name == IntrinsicPrefix) {
159 Set = &Target;
160 break;
161 }
162 }
163 if (!Set) {
164 // The first entry is for target independent intrinsics, so drop it.
165 auto KnowTargets = Ints.getTargets().drop_front();
166 PrintFatalError(PrintMsg: [KnowTargets](raw_ostream &OS) {
167 OS << "tried to generate intrinsics for unknown target "
168 << IntrinsicPrefix << "\nKnown targets are: ";
169 interleaveComma(c: KnowTargets, os&: OS,
170 each_fn: [&OS](const TargetSet &Target) { OS << Target.Name; });
171 OS << '\n';
172 });
173 }
174
175 // Generate a complete header for target specific intrinsics.
176 std::optional<IfDefEmitter> IfDef;
177 std::optional<IncludeGuardEmitter> IncGuard;
178 std::optional<NamespaceEmitter> NS;
179
180 if (IntrinsicPrefix.empty()) {
181 IfDef.emplace(args&: OS, args: "GET_INTRINSIC_ENUM_VALUES");
182 } else {
183 std::string UpperPrefix = StringRef(IntrinsicPrefix).upper();
184 IncGuard.emplace(
185 args&: OS, args: formatv(Fmt: "LLVM_IR_INTRINSIC_{}_ENUMS_H", Vals&: UpperPrefix).str());
186 NS.emplace(args&: OS, args: "llvm::Intrinsic");
187 OS << formatv(Fmt: "enum {}Intrinsics : unsigned {{\n", Vals&: UpperPrefix);
188 }
189
190 OS << "// Enum values for intrinsics.\n";
191 bool First = true;
192 for (const CodeGenIntrinsic &Int : Ints[*Set]) {
193 OS << " " << Int.EnumName;
194
195 // Assign a value to the first intrinsic in this target set so that all
196 // intrinsic ids are distinct.
197 if (First) {
198 OS << " = " << Set->Offset + 1;
199 First = false;
200 }
201
202 OS << ", ";
203 if (Int.EnumName.size() < 40)
204 OS.indent(NumSpaces: 40 - Int.EnumName.size());
205 OS << formatv(
206 Fmt: " // {} ({})\n", Vals: Int.Name,
207 Vals: SrcMgr.getFormattedLocationNoOffset(Loc: Int.TheDef->getLoc().front()));
208 }
209
210 // Emit num_intrinsics into the target neutral enum.
211 if (IntrinsicPrefix.empty())
212 OS << formatv(Fmt: " num_intrinsics = {}\n", Vals: Ints.size() + 1);
213 else
214 OS << "}; // enum\n";
215}
216
217void IntrinsicEmitter::EmitAnyKindEnums(raw_ostream &OS) {
218 if (!IntrinsicPrefix.empty())
219 return;
220 IfDefEmitter IfDef(OS, "GET_INTRINSIC_ANYKIND_ENUMS");
221
222 auto GenerateAnyKindEnums = [&OS, this](StringRef EnumName,
223 StringRef Prefix) {
224 OS << "// llvm::Intrinsic::IITDescriptor::" << EnumName << "\n";
225 if (const Record *EnumDef = Records.getDef(Name: EnumName)) {
226 OS << "enum " << EnumName << " {\n";
227 for (const auto &RV : EnumDef->getValues())
228 OS << " " << Prefix << RV.getName() << " = " << *RV.getValue()
229 << ",\n";
230 OS << "}; // " << EnumName << "\n\n";
231 } else {
232 OS << "#error \"" << EnumName << " is not defined\"\n";
233 }
234 };
235 GenerateAnyKindEnums("AnyKindVectorConstraint", "VC_");
236 GenerateAnyKindEnums("AnyKindElementConstraint", "EC_");
237}
238
239void IntrinsicEmitter::EmitIITInfo(raw_ostream &OS) {
240 IfDefEmitter IfDef(OS, "GET_INTRINSIC_IITINFO");
241 std::array<StringRef, 256> RecsByNumber;
242 auto IIT_Base = Records.getAllDerivedDefinitionsIfDefined(ClassName: "IIT_Base");
243 for (const Record *Rec : IIT_Base) {
244 auto Number = Rec->getValueAsInt(FieldName: "Number");
245 assert(0 <= Number && Number < (int)RecsByNumber.size() &&
246 "IIT_Info.Number should be uint8_t");
247 assert(RecsByNumber[Number].empty() && "Duplicate IIT_Info.Number");
248 RecsByNumber[Number] = Rec->getName();
249 }
250 if (IIT_Base.size() > 0) {
251 if (RecsByNumber[0] != "IIT_Done")
252 PrintFatalError(Msg: "IIT_Done expected to have value 0");
253 for (unsigned I = 0, E = RecsByNumber.size(); I < E; ++I)
254 if (!RecsByNumber[I].empty())
255 OS << " " << RecsByNumber[I] << " = " << I << ",\n";
256 } else {
257 OS << "#error \"class IIT_Base is not defined\"\n";
258 }
259}
260
261void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints,
262 raw_ostream &OS) {
263 IfDefEmitter IfDef(OS, "GET_INTRINSIC_TARGET_DATA");
264 OS << R"(// Target mapping.
265struct IntrinsicTargetInfo {
266 StringLiteral Name;
267 size_t Offset;
268 size_t Count;
269};
270static constexpr IntrinsicTargetInfo TargetInfos[] = {
271)";
272 for (const auto [Name, Offset, Count] : Ints.getTargets())
273 OS << formatv(Fmt: " {{\"{}\", {}, {}},\n", Vals: Name, Vals: Offset, Vals: Count);
274 OS << "};\n";
275}
276
277/// Helper function to emit a bit table for intrinsic properties.
278/// This is used for both overload and pretty print bit tables.
279void IntrinsicEmitter::EmitIntrinsicBitTable(
280 const CodeGenIntrinsicTable &Ints, raw_ostream &OS, StringRef Guard,
281 StringRef TableName, StringRef Comment,
282 function_ref<bool(const CodeGenIntrinsic &Int)> GetProperty) {
283 IfDefEmitter IfDef(OS, Guard);
284 OS << formatv(Fmt: "// {}\n", Vals&: Comment);
285 OS << formatv(Fmt: "static constexpr uint8_t {}[] = {{\n", Vals&: TableName);
286 OS << " 0\n ";
287 for (auto [I, Int] : enumerate(First: Ints)) {
288 // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
289 size_t Idx = I + 1;
290 if (Idx % 8 == 0)
291 OS << ",\n 0";
292 if (GetProperty(Int))
293 OS << " | (1<<" << Idx % 8 << ')';
294 }
295 OS << "\n};\n\n";
296 OS << formatv(Fmt: "return ({}[id/8] & (1 << (id%8))) != 0;\n", Vals&: TableName);
297}
298
299void IntrinsicEmitter::EmitIntrinsicToNameTable(
300 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
301 // Built up a table of the intrinsic names.
302 constexpr StringLiteral NotIntrinsic = "not_intrinsic";
303 StringToOffsetTable Table;
304 Table.GetOrAddStringOffset(Str: NotIntrinsic);
305 for (const auto &Int : Ints)
306 Table.GetOrAddStringOffset(Str: Int.Name);
307
308 IfDefEmitter IfDef(OS, "GET_INTRINSIC_NAME_TABLE");
309 OS << R"(// Intrinsic ID to name table.
310// Note that entry #0 is the invalid intrinsic!
311
312)";
313
314 Table.EmitStringTableDef(OS, Name: "IntrinsicNameTable");
315
316 OS << R"(
317static constexpr unsigned IntrinsicNameOffsetTable[] = {
318)";
319
320 OS << formatv(Fmt: " {}, // {}\n", Vals: Table.GetStringOffset(Str: NotIntrinsic),
321 Vals: NotIntrinsic);
322 for (const auto &Int : Ints)
323 OS << formatv(Fmt: " {}, // {}\n", Vals: Table.GetStringOffset(Str: Int.Name), Vals: Int.Name);
324
325 OS << "\n}; // IntrinsicNameOffsetTable\n";
326}
327
328void IntrinsicEmitter::EmitIntrinsicToTargetFeaturesTable(
329 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
330 StringToOffsetTable Table;
331 for (const CodeGenIntrinsic &Int : Ints)
332 Table.GetOrAddStringOffset(Str: Int.TargetFeatures);
333
334 IfDefEmitter IfDef(OS, "GET_INTRINSIC_TARGET_FEATURES_TABLE");
335 OS << R"(// Intrinsic ID to required target features table.
336// Note that entry #0 is the invalid intrinsic!
337
338)";
339
340 Table.EmitStringTableDef(OS, Name: "IntrinsicTargetFeaturesTable");
341
342 OS << R"(
343static constexpr unsigned IntrinsicTargetFeaturesOffsetTable[] = {
344)";
345
346 OS << " 0, // not_intrinsic\n";
347 for (const CodeGenIntrinsic &Int : Ints) {
348 OS << formatv(Fmt: " {}, // {}\n", Vals: *Table.GetStringOffset(Str: Int.TargetFeatures),
349 Vals: Int.Name);
350 }
351
352 OS << "\n}; // IntrinsicTargetFeaturesOffsetTable\n";
353}
354
355void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
356 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
357 EmitIntrinsicBitTable(
358 Ints, OS, Guard: "GET_INTRINSIC_OVERLOAD_TABLE", TableName: "OTable",
359 Comment: "Intrinsic ID to overload bitset.",
360 GetProperty: [](const CodeGenIntrinsic &Int) { return Int.isOverloaded; });
361}
362
363void IntrinsicEmitter::EmitIntrinsicToScalarizableTable(
364 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
365 EmitIntrinsicBitTable(
366 Ints, OS, Guard: "GET_INTRINSIC_SCALARIZABLE_TABLE", TableName: "STable",
367 Comment: "Intrinsic ID to trivially scalarizable bitset.",
368 GetProperty: [](const CodeGenIntrinsic &Int) { return Int.isTriviallyScalarizable; });
369}
370
371using TypeSigTy = SmallVector<unsigned char>;
372
373/// Computes type signature of the intrinsic \p Int.
374static TypeSigTy ComputeTypeSignature(const CodeGenIntrinsic &Int) {
375 TypeSigTy TypeSig;
376 const Record *TypeInfo = Int.TheDef->getValueAsDef(FieldName: "TypeInfo");
377 const ListInit *TypeList = TypeInfo->getValueAsListInit(FieldName: "TypeSig");
378
379 for (const auto *TypeListEntry : TypeList->getElements()) {
380 int64_t Value = cast<IntInit>(Val: TypeListEntry)->getValue();
381 if (Value < 0 || Value > 255)
382 PrintFatalError(Rec: Int.TheDef, Msg: "Unresolved type signature");
383 TypeSig.emplace_back(Args&: Value);
384 }
385 return TypeSig;
386}
387
388// Note: the code below can be switched to use 32-bit fixed encoding by
389// flipping the flag below.
390constexpr bool Use16BitFixedEncoding = true;
391using FixedEncodingTy =
392 std::conditional_t<Use16BitFixedEncoding, uint16_t, uint32_t>;
393
394// Pack the type signature into 16/32-bit fixed encoding word, where each byte
395// in the type signature is packed into a nibble (4 bits) if possible.
396static std::optional<FixedEncodingTy> encodePacked(const TypeSigTy &TypeSig) {
397 constexpr size_t NUM_NIBBLES = sizeof(FixedEncodingTy) * 2;
398 if (TypeSig.size() > NUM_NIBBLES)
399 return std::nullopt;
400
401 FixedEncodingTy Result = 0;
402 for (unsigned char C : reverse(C: TypeSig)) {
403 if (C > 15)
404 return std::nullopt;
405 Result = (Result << 4) | C;
406 }
407 return Result;
408}
409
410void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
411 raw_ostream &OS) {
412 constexpr unsigned FixedEncodingBits = sizeof(FixedEncodingTy) * CHAR_BIT;
413 constexpr unsigned MSBPosition = FixedEncodingBits - 1;
414 // Mask with all bits 1 except the most significant bit.
415 constexpr FixedEncodingTy Mask = (1U << MSBPosition) - 1;
416 StringRef FixedEncodingTypeName =
417 Use16BitFixedEncoding ? "uint16_t" : "uint32_t";
418
419 // If we can compute a 16/32-bit fixed encoding for this intrinsic, do so and
420 // capture it in this vector, otherwise store a ~0U.
421 std::vector<FixedEncodingTy> FixedEncodings;
422
423 // Each IIT encoding sequence in the long encoding table is terminated by
424 // IIT_Done(=0) token.
425 constexpr unsigned char IIT_Done = 0;
426 SequenceToOffsetTable<TypeSigTy> LongEncodingTable(IIT_Done);
427
428 FixedEncodings.reserve(n: Ints.size());
429
430 // Compute the unique argument type info.
431 for (const CodeGenIntrinsic &Int : Ints) {
432 // Get the signature for the intrinsic.
433 TypeSigTy TypeSig = ComputeTypeSignature(Int);
434
435 // Check to see if we can encode it into a 16/32 bit word.
436 std::optional<FixedEncodingTy> Result = encodePacked(TypeSig);
437 if (Result && (*Result & Mask) == *Result) {
438 FixedEncodings.push_back(x: *Result);
439 continue;
440 }
441
442 LongEncodingTable.add(Seq: TypeSig);
443
444 // This is a placehold that we'll replace after the table is laid out.
445 FixedEncodings.push_back(x: static_cast<FixedEncodingTy>(~0U));
446 }
447
448 LongEncodingTable.layout();
449
450 IfDefEmitter IfDef(OS, "GET_INTRINSIC_GENERATOR_GLOBAL");
451 OS << formatv(Fmt: R"(// Global intrinsic function declaration type table.
452using FixedEncodingTy = {};
453static constexpr FixedEncodingTy IIT_Table[] = {{
454 )",
455 Vals&: FixedEncodingTypeName);
456
457 unsigned MaxOffset = 0;
458 for (auto [Idx, FixedEncoding, Int] : enumerate(First&: FixedEncodings, Rest: Ints)) {
459 if ((Idx & 7) == 7)
460 OS << "\n ";
461
462 // If the entry fit in the table, just emit it.
463 if ((FixedEncoding & Mask) == FixedEncoding) {
464 OS << "0x" << Twine::utohexstr(Val: FixedEncoding) << ", ";
465 continue;
466 }
467
468 TypeSigTy TypeSig = ComputeTypeSignature(Int);
469 unsigned Offset = LongEncodingTable.get(Seq: TypeSig);
470 MaxOffset = std::max(a: MaxOffset, b: Offset);
471
472 // Otherwise, emit the offset into the long encoding table. We emit it this
473 // way so that it is easier to read the offset in the .def file.
474 OS << formatv(Fmt: "(1U<<{}) | {}, ", Vals: MSBPosition, Vals&: Offset);
475 }
476
477 OS << "0\n};\n\n";
478
479 // verify that all offsets will fit in 16/32 bits.
480 if ((MaxOffset & Mask) != MaxOffset)
481 PrintFatalError(Msg: "Offset of long encoding table exceeds encoding bits");
482
483 // Emit the shared table of register lists.
484 OS << "static constexpr unsigned char IIT_LongEncodingTable[] = {\n";
485 if (!LongEncodingTable.empty())
486 LongEncodingTable.emit(
487 OS, Print: [](raw_ostream &OS, unsigned char C) { OS << (unsigned)C; });
488 OS << " 255\n};\n";
489}
490
491/// Returns the effective MemoryEffects for intrinsic \p Int.
492static MemoryEffects getEffectiveME(const CodeGenIntrinsic &Int) {
493 MemoryEffects ME = Int.ME;
494 // TODO: IntrHasSideEffects should affect not only readnone intrinsics.
495 if (ME.doesNotAccessMemory() && Int.hasSideEffects)
496 ME = MemoryEffects::unknown();
497 return ME;
498}
499
500static bool compareFnAttributes(const CodeGenIntrinsic *L,
501 const CodeGenIntrinsic *R) {
502 auto TieBoolAttributes = [](const CodeGenIntrinsic *I) -> auto {
503 // Sort throwing intrinsics after non-throwing intrinsics.
504 return std::tie(args: I->canThrow, args: I->isNoDuplicate, args: I->isNoMerge, args: I->isNoReturn,
505 args: I->isNoCallback, args: I->isNoSync, args: I->isNoFree, args: I->isWillReturn,
506 args: I->isCold, args: I->isConvergent, args: I->isSpeculatable,
507 args: I->hasSideEffects, args: I->isStrictFP,
508 args: I->isNoCreateUndefOrPoison);
509 };
510
511 auto TieL = TieBoolAttributes(L);
512 auto TieR = TieBoolAttributes(R);
513
514 if (TieL != TieR)
515 return TieL < TieR;
516
517 // Try to order by readonly/readnone attribute.
518 uint32_t LME = getEffectiveME(Int: *L).toIntValue();
519 uint32_t RME = getEffectiveME(Int: *R).toIntValue();
520 if (LME != RME)
521 return LME > RME;
522
523 return false;
524}
525
526/// Returns true if \p Int has a non-empty set of function attributes. Note that
527/// NoUnwind = !canThrow, so we need to negate it's sense to test if the
528// intrinsic has NoUnwind attribute.
529static bool hasFnAttributes(const CodeGenIntrinsic &Int) {
530 return !Int.canThrow || Int.isNoReturn || Int.isNoCallback || Int.isNoSync ||
531 Int.isNoFree || Int.isWillReturn || Int.isCold || Int.isNoDuplicate ||
532 Int.isNoMerge || Int.isConvergent || Int.isSpeculatable ||
533 Int.isStrictFP || Int.isNoCreateUndefOrPoison ||
534 getEffectiveME(Int) != MemoryEffects::unknown();
535}
536
537namespace {
538struct FnAttributeComparator {
539 bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
540 return compareFnAttributes(L, R);
541 }
542};
543
544struct AttributeComparator {
545 bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
546 // This comparator is used to unique just the argument attributes of an
547 // intrinsic without considering any function attributes.
548 return L->ArgumentAttributes < R->ArgumentAttributes;
549 }
550};
551} // End anonymous namespace
552
553/// Returns the name of the IR enum for argument attribute kind \p Kind.
554static StringRef getArgAttrEnumName(CodeGenIntrinsic::ArgAttrKind Kind) {
555 switch (Kind) {
556 case CodeGenIntrinsic::NoCapture:
557 llvm_unreachable("Handled separately");
558 case CodeGenIntrinsic::NoAlias:
559 return "NoAlias";
560 case CodeGenIntrinsic::NoUndef:
561 return "NoUndef";
562 case CodeGenIntrinsic::NonNull:
563 return "NonNull";
564 case CodeGenIntrinsic::Returned:
565 return "Returned";
566 case CodeGenIntrinsic::ReadOnly:
567 return "ReadOnly";
568 case CodeGenIntrinsic::WriteOnly:
569 return "WriteOnly";
570 case CodeGenIntrinsic::ReadNone:
571 return "ReadNone";
572 case CodeGenIntrinsic::ImmArg:
573 return "ImmArg";
574 case CodeGenIntrinsic::Alignment:
575 return "Alignment";
576 case CodeGenIntrinsic::Dereferenceable:
577 return "Dereferenceable";
578 case CodeGenIntrinsic::Range:
579 return "Range";
580 }
581 llvm_unreachable("Unknown CodeGenIntrinsic::ArgAttrKind enum");
582}
583
584/// EmitAttributes - This emits the Intrinsic::getAttributes method.
585void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
586 raw_ostream &OS) {
587 IfDefEmitter IfDef(OS, "GET_INTRINSIC_ATTRIBUTES");
588 OS << R"(// Add parameter attributes that are not common to all intrinsics.
589static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID,
590 Type *ArgType) {
591 unsigned BitWidth = ArgType->getScalarSizeInBits();
592 switch (ID) {
593 default: llvm_unreachable("Invalid attribute set number");)";
594 // Compute unique argument attribute sets.
595 std::map<SmallVector<CodeGenIntrinsic::ArgAttribute, 0>, unsigned>
596 UniqArgAttributes;
597 for (const CodeGenIntrinsic &Int : Ints) {
598 for (auto &Attrs : Int.ArgumentAttributes) {
599 if (Attrs.empty())
600 continue;
601
602 unsigned ID = UniqArgAttributes.size();
603 if (!UniqArgAttributes.try_emplace(k: Attrs, args&: ID).second)
604 continue;
605
606 assert(is_sorted(Attrs) && "Argument attributes are not sorted");
607
608 OS << formatv(Fmt: R"(
609 case {}:
610 return AttributeSet::get(C, {{
611)",
612 Vals&: ID);
613 for (const CodeGenIntrinsic::ArgAttribute &Attr : Attrs) {
614 if (Attr.Kind == CodeGenIntrinsic::NoCapture) {
615 OS << " Attribute::getWithCaptureInfo(C, "
616 "CaptureInfo::none()),\n";
617 continue;
618 }
619 StringRef AttrName = getArgAttrEnumName(Kind: Attr.Kind);
620 if (Attr.Kind == CodeGenIntrinsic::Alignment ||
621 Attr.Kind == CodeGenIntrinsic::Dereferenceable)
622 OS << formatv(Fmt: " Attribute::get(C, Attribute::{}, {}),\n",
623 Vals&: AttrName, Vals: Attr.Value);
624 else if (Attr.Kind == CodeGenIntrinsic::Range)
625 // This allows implicitTrunc because the range may only fit the
626 // type based on rules implemented in the IR verifier. E.g. the
627 // [-1, 1] range for ucmp/scmp intrinsics requires a minimum i2 type.
628 // Give the verifier a chance to diagnose this instead of asserting
629 // here.
630 OS << formatv(Fmt: " Attribute::get(C, Attribute::{}, "
631 "ConstantRange(APInt(BitWidth, {}, /*isSigned=*/true, "
632 "/*implicitTrunc=*/true), APInt(BitWidth, {}, "
633 "/*isSigned=*/true, /*implicitTrunc=*/true))),\n",
634 Vals&: AttrName, Vals: (int64_t)Attr.Value, Vals: (int64_t)Attr.Value2);
635 else
636 OS << formatv(Fmt: " Attribute::get(C, Attribute::{}),\n", Vals&: AttrName);
637 }
638 OS << " });";
639 }
640 }
641 OS << R"(
642 }
643} // getIntrinsicArgAttributeSet
644)";
645
646 // Compute unique function attribute sets. Note that ID 255 will be used for
647 // intrinsics with no function attributes.
648 std::map<const CodeGenIntrinsic *, unsigned, FnAttributeComparator>
649 UniqFnAttributes;
650 OS << R"(
651static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
652 switch (ID) {
653 default: llvm_unreachable("Invalid attribute set number");)";
654
655 for (const CodeGenIntrinsic &Int : Ints) {
656 if (!hasFnAttributes(Int))
657 continue;
658 unsigned ID = UniqFnAttributes.size();
659 if (!UniqFnAttributes.try_emplace(k: &Int, args&: ID).second)
660 continue;
661 OS << formatv(Fmt: R"(
662 case {}: // {}
663 return AttributeSet::get(C, {{
664)",
665 Vals&: ID, Vals: Int.Name);
666 auto addAttribute = [&OS](StringRef Attr) {
667 OS << formatv(Fmt: " Attribute::get(C, Attribute::{}),\n", Vals&: Attr);
668 };
669 if (!Int.canThrow)
670 addAttribute("NoUnwind");
671 if (Int.isNoReturn)
672 addAttribute("NoReturn");
673 if (Int.isNoCallback)
674 addAttribute("NoCallback");
675 if (Int.isNoSync)
676 addAttribute("NoSync");
677 if (Int.isNoFree)
678 addAttribute("NoFree");
679 if (Int.isWillReturn)
680 addAttribute("WillReturn");
681 if (Int.isCold)
682 addAttribute("Cold");
683 if (Int.isNoDuplicate)
684 addAttribute("NoDuplicate");
685 if (Int.isNoMerge)
686 addAttribute("NoMerge");
687 if (Int.isConvergent)
688 addAttribute("Convergent");
689 if (Int.isSpeculatable)
690 addAttribute("Speculatable");
691 if (Int.isStrictFP)
692 addAttribute("StrictFP");
693 if (Int.isNoCreateUndefOrPoison)
694 addAttribute("NoCreateUndefOrPoison");
695
696 const MemoryEffects ME = getEffectiveME(Int);
697 if (ME != MemoryEffects::unknown()) {
698 OS << formatv(Fmt: " // {}\n", Vals: ME);
699 OS << formatv(Fmt: " Attribute::getWithMemoryEffects(C, "
700 "MemoryEffects::createFromIntValue({})),\n",
701 Vals: ME.toIntValue());
702 }
703 OS << " });";
704 }
705 OS << R"(
706 }
707} // getIntrinsicFnAttributeSet)";
708
709 // Compute unique argument attributes.
710 std::map<const CodeGenIntrinsic *, unsigned, AttributeComparator>
711 UniqAttributes;
712 for (const CodeGenIntrinsic &Int : Ints) {
713 unsigned ID = UniqAttributes.size();
714 UniqAttributes.try_emplace(k: &Int, args&: ID);
715 }
716
717 const uint8_t UniqAttributesBitSize = Log2_32_Ceil(Value: UniqAttributes.size());
718 // Note, max value is used to indicate no function attributes.
719 const uint8_t UniqFnAttributesBitSize =
720 Log2_32_Ceil(Value: UniqFnAttributes.size() + 1);
721 const uint32_t NoFunctionAttrsID =
722 maskTrailingOnes<uint32_t>(N: UniqFnAttributesBitSize);
723 uint8_t AttributesMapDataBitSize =
724 PowerOf2Ceil(A: UniqAttributesBitSize + UniqFnAttributesBitSize);
725 if (AttributesMapDataBitSize < 8)
726 AttributesMapDataBitSize = 8;
727 else if (AttributesMapDataBitSize > 64)
728 PrintFatalError(Msg: "Packed ID of IntrinsicsToAttributesMap exceeds 64b!");
729
730 // Assign a packed ID for each intrinsic. The lower bits will be its
731 // "argument attribute ID" (index in UniqAttributes) and upper bits will be
732 // its "function attribute ID" (index in UniqFnAttributes).
733 OS << formatv(Fmt: "\nstatic constexpr uint{}_t IntrinsicsToAttributesMap[] = {{",
734 Vals&: AttributesMapDataBitSize);
735 for (const CodeGenIntrinsic &Int : Ints) {
736 uint32_t FnAttrIndex =
737 hasFnAttributes(Int) ? UniqFnAttributes[&Int] : NoFunctionAttrsID;
738 OS << formatv(Fmt: "\n {} << {} | {}, // {}", Vals&: FnAttrIndex,
739 Vals: UniqAttributesBitSize, Vals&: UniqAttributes[&Int], Vals: Int.Name);
740 }
741
742 OS << R"(
743}; // IntrinsicsToAttributesMap
744)";
745
746 // For a given intrinsic, its attributes are constructed by populating the
747 // local array `AS` below with its non-empty argument attributes followed by
748 // function attributes if any. Each argument attribute is constructed as:
749 //
750 // getIntrinsicArgAttributeSet(C, ArgAttrID, FT->getContainedType(ArgNo));
751 //
752 // Create a table that records, for each argument attributes, the list of
753 // <ArgNo, ArgAttrID> pairs that are needed to construct its argument
754 // attributes. These tables for all intrinsics will be concatenated into one
755 // large table and then for each intrinsic, we remember the Staring index and
756 // number of size of its slice of entries (i.e., number of arguments with
757 // non-empty attributes), so that we can build the attribute list for an
758 // intrinsic without using a switch-case.
759
760 using ArgNoAttrIDPair = std::pair<uint16_t, uint16_t>;
761
762 // Emit the table of concatenated <ArgNo, AttrId> using SequenceToOffsetTable
763 // so that entries can be reused if possible. Individual sequences in this
764 // table do not have any terminator.
765 using ArgAttrIDSubTable = SmallVector<ArgNoAttrIDPair>;
766 SequenceToOffsetTable<ArgAttrIDSubTable> ArgAttrIdSequenceTable(std::nullopt);
767 SmallVector<ArgAttrIDSubTable> ArgAttrIdSubTables(
768 UniqAttributes.size()); // Indexed by UniqueID.
769
770 // Find the max number of attributes to create the local array.
771 unsigned MaxNumAttrs = 0;
772 for (const auto [IntPtr, UniqueID] : UniqAttributes) {
773 const CodeGenIntrinsic &Int = *IntPtr;
774 ArgAttrIDSubTable SubTable;
775
776 for (const auto &[ArgNo, Attrs] : enumerate(First: Int.ArgumentAttributes)) {
777 if (Attrs.empty())
778 continue;
779
780 uint16_t ArgAttrID = UniqArgAttributes.find(x: Attrs)->second;
781 SubTable.emplace_back(Args: (uint16_t)ArgNo, Args&: ArgAttrID);
782 }
783 ArgAttrIdSubTables[UniqueID] = SubTable;
784 if (!SubTable.empty())
785 ArgAttrIdSequenceTable.add(Seq: SubTable);
786 unsigned NumAttrs = SubTable.size() + hasFnAttributes(Int);
787 MaxNumAttrs = std::max(a: MaxNumAttrs, b: NumAttrs);
788 }
789
790 ArgAttrIdSequenceTable.layout();
791
792 if (ArgAttrIdSequenceTable.size() >= std::numeric_limits<uint16_t>::max())
793 PrintFatalError(Msg: "Size of ArgAttrIdTable exceeds supported limit");
794
795 // Emit the 2 tables (flattened ArgNo, ArgAttrID) and ArgAttributesInfoTable.
796 OS << formatv(Fmt: R"(
797namespace {{
798struct ArgNoAttrIDPair {{
799 uint16_t ArgNo, ArgAttrID;
800};
801} // namespace
802
803// Number of entries: {}
804static constexpr ArgNoAttrIDPair ArgAttrIdTable[] = {{
805)",
806 Vals: ArgAttrIdSequenceTable.size());
807
808 ArgAttrIdSequenceTable.emit(OS, Print: [](raw_ostream &OS, ArgNoAttrIDPair Elem) {
809 OS << formatv(Fmt: "{{{}, {}}", Vals&: Elem.first, Vals&: Elem.second);
810 });
811
812 OS << formatv(Fmt: R"(}; // ArgAttrIdTable
813
814namespace {{
815struct ArgAttributesInfo {{
816 uint16_t StartIndex;
817 uint16_t NumAttrs;
818};
819} // namespace
820
821// Number of entries: {}
822static constexpr ArgAttributesInfo ArgAttributesInfoTable[] = {{
823)",
824 Vals: ArgAttrIdSubTables.size());
825
826 for (const auto &SubTable : ArgAttrIdSubTables) {
827 unsigned NumAttrs = SubTable.size();
828 unsigned StartIndex = NumAttrs ? ArgAttrIdSequenceTable.get(Seq: SubTable) : 0;
829 OS << formatv(Fmt: " {{{}, {}},\n", Vals&: StartIndex, Vals&: NumAttrs);
830 }
831 OS << "}; // ArgAttributesInfoTable\n";
832
833 // Now emit the Intrinsic::getAttributes function. This will first map
834 // from intrinsic ID -> unique arg/function attr ID (using the
835 // IntrinsicsToAttributesMap) table. Then it will use the unique arg ID to
836 // construct all the argument attributes (using the ArgAttributesInfoTable and
837 // ArgAttrIdTable) and then add on the function attributes if any.
838 OS << formatv(Fmt: R"(
839
840template <typename IDTy>
841inline std::pair<uint32_t, uint32_t> unpackID(const IDTy PackedID) {{
842 constexpr uint8_t UniqAttributesBitSize = {};
843 const uint32_t FnAttrID = PackedID >> UniqAttributesBitSize;
844 const uint32_t ArgAttrID = PackedID &
845 maskTrailingOnes<uint32_t>(UniqAttributesBitSize);
846 return {{FnAttrID, ArgAttrID};
847}
848
849AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id,
850 FunctionType *FT) {{
851 if (id == 0)
852 return AttributeList();
853 auto [FnAttrID, ArgAttrID] = unpackID(IntrinsicsToAttributesMap[id - 1]);
854 using PairTy = std::pair<unsigned, AttributeSet>;
855 alignas(PairTy) char ASStorage[sizeof(PairTy) * {}];
856 PairTy *AS = reinterpret_cast<PairTy *>(ASStorage);
857
858 // Construct an ArrayRef for easier range checking.
859 ArrayRef<ArgAttributesInfo> ArgAttributesInfoTableAR(ArgAttributesInfoTable);
860 if (ArgAttrID >= ArgAttributesInfoTableAR.size())
861 llvm_unreachable("Invalid arguments attribute ID");
862
863 auto [StartIndex, NumAttrs] = ArgAttributesInfoTableAR[ArgAttrID];
864 for (unsigned Idx = 0; Idx < NumAttrs; ++Idx) {{
865 auto [ArgNo, ArgAttrID] = ArgAttrIdTable[StartIndex + Idx];
866 AS[Idx] = {{ArgNo,
867 getIntrinsicArgAttributeSet(C, ArgAttrID, FT->getContainedType(ArgNo))};
868 }
869 if (FnAttrID != {}) {
870 AS[NumAttrs++] = {{AttributeList::FunctionIndex,
871 getIntrinsicFnAttributeSet(C, FnAttrID)};
872 }
873 return AttributeList::get(C, ArrayRef(AS, NumAttrs));
874}
875
876AttributeSet Intrinsic::getFnAttributes(LLVMContext &C, ID id) {{
877 if (id == 0)
878 return AttributeSet();
879 auto [FnAttrID, _] = unpackID(IntrinsicsToAttributesMap[id - 1]);
880 if (FnAttrID == {})
881 return AttributeSet();
882 return getIntrinsicFnAttributeSet(C, FnAttrID);
883}
884)",
885 Vals: UniqAttributesBitSize, Vals&: MaxNumAttrs, Vals: NoFunctionAttrsID,
886 Vals: NoFunctionAttrsID);
887}
888
889void IntrinsicEmitter::EmitIntrinsicToPrettyPrintTable(
890 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
891 EmitIntrinsicBitTable(Ints, OS, Guard: "GET_INTRINSIC_PRETTY_PRINT_TABLE", TableName: "PPTable",
892 Comment: "Intrinsic ID to pretty print bitset.",
893 GetProperty: [](const CodeGenIntrinsic &Int) {
894 return !Int.PrettyPrintFunctions.empty();
895 });
896}
897
898void IntrinsicEmitter::EmitPrettyPrintArguments(
899 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
900 IfDefEmitter IfDef(OS, "GET_INTRINSIC_PRETTY_PRINT_ARGUMENTS");
901 OS << R"(
902void Intrinsic::printImmArg(ID IID, unsigned ArgIdx, raw_ostream &OS, const Constant *ImmArgVal) {
903 using namespace Intrinsic;
904 switch (IID) {
905)";
906
907 for (const CodeGenIntrinsic &Int : Ints) {
908 if (Int.PrettyPrintFunctions.empty())
909 continue;
910
911 OS << " case " << Int.EnumName << ":\n";
912 OS << " switch (ArgIdx) {\n";
913 for (const auto [ArgIdx, ArgName, FuncName] : Int.PrettyPrintFunctions) {
914 OS << " case " << ArgIdx << ":\n";
915 if (!ArgName.empty())
916 OS << " OS << \"" << ArgName << "=\";\n";
917 if (!FuncName.empty()) {
918 OS << " ";
919 if (!Int.TargetPrefix.empty())
920 OS << Int.TargetPrefix << "::";
921 OS << FuncName << "(OS, ImmArgVal);\n";
922 }
923 OS << " return;\n";
924 }
925 OS << " }\n";
926 OS << " break;\n";
927 }
928 OS << R"( default:
929 break;
930 }
931})";
932}
933
934void IntrinsicEmitter::EmitDefaultArgValuesTable(
935 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
936 // Build the per-intrinsic default-value sequences:
937 // [Header = (NumDefaults << 32) | FirstDefault, val0, val1, ...]
938 // Each value is the (non-negative) default for one parameter, stored as a
939 // uint64_t bit pattern.
940 //
941 // Offset 0 of the values table is reserved as the "no defaults" sentinel
942 // (a single 0 word, decoding to NumDefaults = 0). Intrinsics without
943 // defaults point to offset 0; real sequences are emitted after it.
944 // SequenceToOffsetTable deduplicates the real sequences.
945
946 using Sequence = SmallVector<uint64_t, 8>;
947
948 SequenceToOffsetTable<Sequence> Table;
949 // An empty Sequence means "no defaults" (maps to the reserved offset 0);
950 // otherwise it holds the intrinsic's value sequence.
951 SmallVector<Sequence> PerIntrinsic;
952 PerIntrinsic.reserve(N: Ints.size());
953
954 for (const CodeGenIntrinsic &Int : Ints) {
955 if (Int.ParamDefaultValues.empty()) {
956 PerIntrinsic.push_back(Elt: {});
957 continue;
958 }
959
960 // Find the first parameter with a default.
961 unsigned FirstDefault = 0;
962 for (size_t j = 0U, N = Int.ParamDefaultValues.size(); j < N; ++j) {
963 if (Int.ParamDefaultValues[j].has_value()) {
964 FirstDefault = j;
965 break;
966 }
967 }
968 unsigned NumDefaults =
969 static_cast<unsigned>(Int.ParamDefaultValues.size()) - FirstDefault;
970
971 Sequence Seq;
972 Seq.push_back(Elt: (static_cast<uint64_t>(NumDefaults) << 32) | FirstDefault);
973 for (size_t j = FirstDefault, N = Int.ParamDefaultValues.size(); j < N;
974 ++j) {
975 assert(Int.ParamDefaultValues[j].has_value() &&
976 "Default block must be contiguous");
977 Seq.push_back(Elt: *Int.ParamDefaultValues[j]);
978 }
979 Table.add(Seq);
980 PerIntrinsic.push_back(Elt: std::move(Seq));
981 }
982
983 Table.layout();
984
985 IfDefEmitter IfDef(OS, "GET_INTRINSIC_DEFAULT_ARG_VALUES");
986
987 // Emit the flat values table. Offset 0 is the reserved "no defaults"
988 // sentinel; the deduplicated real sequences follow it.
989 OS << "static constexpr uint64_t DefaultArgValuesTable[] = {\n";
990 OS << " 0, // offset 0: sentinel for intrinsics without defaults\n";
991 Table.emit(OS, Print: [](raw_ostream &OS, uint64_t Val) { OS << " " << Val; });
992 OS << "};\n\n";
993
994 // Emit the per-intrinsic offset table. Entry #0 is for the invalid
995 // Intrinsic::not_intrinsic (IID 0); it and every intrinsic without defaults
996 // point to the reserved sentinel at offset 0. Real sequences are shifted by
997 // +1 to skip past the sentinel slot.
998 OS << "static constexpr uint32_t DefaultArgValuesTableOffset[] = {\n";
999 OS << " 0, // not_intrinsic\n";
1000 for (const Sequence &Seq : PerIntrinsic) {
1001 if (!Seq.empty())
1002 OS << " " << (Table.get(Seq) + 1) << ",\n";
1003 else
1004 OS << " 0,\n";
1005 }
1006 OS << "};\n\n";
1007
1008 // Emit the lookup function body.
1009 OS << R"(
1010std::pair<unsigned, ArrayRef<uint64_t>>
1011Intrinsic::getAllDefaultArgValues(ID IID) {
1012 uint32_t Offset = DefaultArgValuesTableOffset[IID];
1013 uint64_t Header = DefaultArgValuesTable[Offset];
1014 uint32_t FirstDefault = Header & 0xFFFFFFFFu;
1015 uint32_t NumDefaults = (Header >> 32) & 0xFFFFFFFFu;
1016 if (NumDefaults == 0)
1017 return {0, {}};
1018 return {FirstDefault,
1019 ArrayRef(&DefaultArgValuesTable[Offset + 1], NumDefaults)};
1020}
1021)";
1022}
1023
1024void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
1025 const CodeGenIntrinsicTable &Ints, bool IsClang, raw_ostream &OS) {
1026 StringRef CompilerName = IsClang ? "Clang" : "MS";
1027 StringRef UpperCompilerName = IsClang ? "CLANG" : "MS";
1028
1029 // map<TargetPrefix, pair<map<BuiltinName, EnumName>, CommonPrefix>.
1030 // Note that we iterate over both the maps in the code below and both
1031 // iterations need to iterate in sorted key order. For the inner map, entries
1032 // need to be emitted in the sorted order of `BuiltinName` with `CommonPrefix`
1033 // rempved, because we use std::lower_bound to search these entries. For the
1034 // outer map as well, entries need to be emitted in sorter order of
1035 // `TargetPrefix` as we use std::lower_bound to search these entries.
1036 using BIMEntryTy =
1037 std::pair<std::map<StringRef, StringRef>, std::optional<StringRef>>;
1038 std::map<StringRef, BIMEntryTy> BuiltinMap;
1039
1040 for (const CodeGenIntrinsic &Int : Ints) {
1041 StringRef BuiltinName = IsClang ? Int.ClangBuiltinName : Int.MSBuiltinName;
1042 if (BuiltinName.empty())
1043 continue;
1044 // Get the map for this target prefix.
1045 auto &[Map, CommonPrefix] = BuiltinMap[Int.TargetPrefix];
1046
1047 if (!Map.try_emplace(k: BuiltinName, args: Int.EnumName).second)
1048 PrintFatalError(ErrorLoc: Int.TheDef->getLoc(),
1049 Msg: "Intrinsic '" + Int.TheDef->getName() + "': duplicate " +
1050 CompilerName + " builtin name!");
1051
1052 // Update common prefix.
1053 if (!CommonPrefix) {
1054 // For the first builtin for this target, initialize the common prefix.
1055 CommonPrefix = BuiltinName;
1056 continue;
1057 }
1058
1059 // Update the common prefix. Note that this assumes that `take_front` will
1060 // never set the `Data` pointer in CommonPrefix to nullptr.
1061 const char *Mismatch = mismatch(Range1&: *CommonPrefix, Range2&: BuiltinName).first;
1062 *CommonPrefix = CommonPrefix->take_front(N: Mismatch - CommonPrefix->begin());
1063 }
1064
1065 // Populate the string table with the names of all the builtins after
1066 // removing this common prefix.
1067 StringToOffsetTable Table;
1068 for (const auto &[TargetPrefix, Entry] : BuiltinMap) {
1069 auto &[Map, CommonPrefix] = Entry;
1070 for (auto &[BuiltinName, EnumName] : Map) {
1071 StringRef Suffix = BuiltinName.substr(Start: CommonPrefix->size());
1072 Table.GetOrAddStringOffset(Str: Suffix);
1073 }
1074 }
1075
1076 IfDefEmitter IfDef(
1077 OS,
1078 formatv(Fmt: "GET_LLVM_INTRINSIC_FOR_{}_BUILTIN", Vals&: UpperCompilerName).str());
1079 OS << formatv(Fmt: R"(
1080// Get the LLVM intrinsic that corresponds to a builtin. This is used by the
1081// C front-end. The builtin name is passed in as BuiltinName, and a target
1082// prefix (e.g. 'ppc') is passed in as TargetPrefix.
1083Intrinsic::ID
1084Intrinsic::getIntrinsicFor{}Builtin(StringRef TargetPrefix,
1085 StringRef BuiltinName) {{
1086 using namespace Intrinsic;
1087)",
1088 Vals&: CompilerName);
1089
1090 if (BuiltinMap.empty()) {
1091 OS << "return not_intrinsic;\n";
1092 return;
1093 }
1094
1095 if (!Table.empty()) {
1096 Table.EmitStringTableDef(OS, Name: "BuiltinNames");
1097
1098 OS << R"(
1099 struct BuiltinEntry {
1100 ID IntrinsicID;
1101 unsigned StrTabOffset;
1102 const char *getName() const { return BuiltinNames[StrTabOffset].data(); }
1103 bool operator<(StringRef RHS) const {
1104 return strncmp(getName(), RHS.data(), RHS.size()) < 0;
1105 }
1106 };
1107
1108)";
1109 }
1110
1111 // Emit a per target table of bultin names.
1112 bool HasTargetIndependentBuiltins = false;
1113 StringRef TargetIndepndentCommonPrefix;
1114 for (const auto &[TargetPrefix, Entry] : BuiltinMap) {
1115 const auto &[Map, CommonPrefix] = Entry;
1116 if (!TargetPrefix.empty()) {
1117 OS << formatv(Fmt: " // Builtins for {0}.\n", Vals: TargetPrefix);
1118 } else {
1119 OS << " // Target independent builtins.\n";
1120 HasTargetIndependentBuiltins = true;
1121 TargetIndepndentCommonPrefix = *CommonPrefix;
1122 }
1123
1124 // Emit the builtin table for this target prefix.
1125 OS << formatv(Fmt: " static constexpr BuiltinEntry {}Names[] = {{\n",
1126 Vals: TargetPrefix);
1127 for (const auto &[BuiltinName, EnumName] : Map) {
1128 StringRef Suffix = BuiltinName.substr(Start: CommonPrefix->size());
1129 OS << formatv(Fmt: " {{{}, {}}, // {}\n", Vals: EnumName,
1130 Vals: *Table.GetStringOffset(Str: Suffix), Vals: BuiltinName);
1131 }
1132 OS << formatv(Fmt: " }; // {}Names\n\n", Vals: TargetPrefix);
1133 }
1134
1135 // After emitting the builtin tables for all targets, emit a lookup table for
1136 // all targets. We will use binary search, similar to the table for builtin
1137 // names to lookup into this table.
1138 OS << R"(
1139 struct TargetEntry {
1140 StringLiteral TargetPrefix;
1141 ArrayRef<BuiltinEntry> Names;
1142 StringLiteral CommonPrefix;
1143 bool operator<(StringRef RHS) const {
1144 return TargetPrefix < RHS;
1145 };
1146 };
1147 static constexpr TargetEntry TargetTable[] = {
1148)";
1149
1150 for (const auto &[TargetPrefix, Entry] : BuiltinMap) {
1151 const auto &[Map, CommonPrefix] = Entry;
1152 if (TargetPrefix.empty())
1153 continue;
1154 OS << formatv(Fmt: R"( {{"{0}", {0}Names, "{1}"},)", Vals: TargetPrefix,
1155 Vals: CommonPrefix)
1156 << "\n";
1157 }
1158 OS << " };\n";
1159
1160 // Now for the actual lookup, first check the target independent table if
1161 // we emitted one.
1162 if (HasTargetIndependentBuiltins) {
1163 OS << formatv(Fmt: R"(
1164 // Check if it's a target independent builtin.
1165 // Copy the builtin name so we can use it in consume_front without clobbering
1166 // if for the lookup in the target specific table.
1167 StringRef Suffix = BuiltinName;
1168 if (Suffix.consume_front("{}")) {{
1169 auto II = lower_bound(Names, Suffix);
1170 if (II != std::end(Names) && II->getName() == Suffix)
1171 return II->IntrinsicID;
1172 }
1173)",
1174 Vals&: TargetIndepndentCommonPrefix);
1175 }
1176
1177 // If a target independent builtin was not found, lookup the target specific.
1178 OS << R"(
1179 auto TI = lower_bound(TargetTable, TargetPrefix);
1180 if (TI == std::end(TargetTable) || TI->TargetPrefix != TargetPrefix)
1181 return not_intrinsic;
1182 // This is the last use of BuiltinName, so no need to copy before using it in
1183 // consume_front.
1184 if (!BuiltinName.consume_front(TI->CommonPrefix))
1185 return not_intrinsic;
1186 auto II = lower_bound(TI->Names, BuiltinName);
1187 if (II == std::end(TI->Names) || II->getName() != BuiltinName)
1188 return not_intrinsic;
1189 return II->IntrinsicID;
1190}
1191)";
1192}
1193
1194static TableGen::Emitter::OptClass<IntrinsicEmitterOpt</*Enums=*/true>>
1195 X("gen-intrinsic-enums", "Generate intrinsic enums");
1196
1197static TableGen::Emitter::OptClass<IntrinsicEmitterOpt</*Enums=*/false>>
1198 Y("gen-intrinsic-impl", "Generate intrinsic implementation code");
1199