1 //===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
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 tablegen backend emits information about intrinsic functions.
11 //===----------------------------------------------------------------------===//
13 #include "Basic/CodeGenIntrinsics.h"
14 #include "Basic/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/raw_ostream.h"
24 #include "llvm/TableGen/Error.h"
25 #include "llvm/TableGen/Record.h"
26 #include "llvm/TableGen/StringToOffsetTable.h"
27 #include "llvm/TableGen/TableGenBackend.h"
39 static cl::OptionCategory
GenIntrinsicCat("Options for -gen-intrinsic-enums");
40 static cl::opt
<std::string
>
41 IntrinsicPrefix("intrinsic-prefix",
42 cl::desc("Generate intrinsics with this target prefix"),
43 cl::value_desc("target prefix"), cl::cat(GenIntrinsicCat
));
46 class IntrinsicEmitter
{
47 const RecordKeeper
&Records
;
50 IntrinsicEmitter(const RecordKeeper
&R
) : Records(R
) {}
52 void run(raw_ostream
&OS
, bool Enums
);
54 void EmitEnumInfo(const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
);
55 void EmitArgKind(raw_ostream
&OS
);
56 void EmitIITInfo(raw_ostream
&OS
);
57 void EmitTargetInfo(const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
);
58 void EmitIntrinsicToNameTable(const CodeGenIntrinsicTable
&Ints
,
60 void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable
&Ints
,
62 void EmitGenerator(const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
);
63 void EmitAttributes(const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
);
64 void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable
&Ints
,
65 bool IsClang
, raw_ostream
&OS
);
68 // Helper class to use with `TableGen::Emitter::OptClass`.
69 template <bool Enums
> class IntrinsicEmitterOpt
: public IntrinsicEmitter
{
71 IntrinsicEmitterOpt(const RecordKeeper
&R
) : IntrinsicEmitter(R
) {}
72 void run(raw_ostream
&OS
) { IntrinsicEmitter::run(OS
, Enums
); }
75 } // End anonymous namespace
77 //===----------------------------------------------------------------------===//
78 // IntrinsicEmitter Implementation
79 //===----------------------------------------------------------------------===//
81 void IntrinsicEmitter::run(raw_ostream
&OS
, bool Enums
) {
82 emitSourceFileHeader("Intrinsic Function Source Fragment", OS
);
84 CodeGenIntrinsicTable
Ints(Records
);
87 // Emit the enum information.
88 EmitEnumInfo(Ints
, OS
);
90 // Emit ArgKind for Intrinsics.h.
93 // Emit IIT_Info constants.
96 // Emit the target metadata.
97 EmitTargetInfo(Ints
, OS
);
99 // Emit the intrinsic ID -> name table.
100 EmitIntrinsicToNameTable(Ints
, OS
);
102 // Emit the intrinsic ID -> overload table.
103 EmitIntrinsicToOverloadTable(Ints
, OS
);
105 // Emit the intrinsic declaration generator.
106 EmitGenerator(Ints
, OS
);
108 // Emit the intrinsic parameter attributes.
109 EmitAttributes(Ints
, OS
);
111 // Emit code to translate Clang builtins into LLVM intrinsics.
112 EmitIntrinsicToBuiltinMap(Ints
, true, OS
);
114 // Emit code to translate MS builtins into LLVM intrinsics.
115 EmitIntrinsicToBuiltinMap(Ints
, false, OS
);
119 void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable
&Ints
,
121 // Find the TargetSet for which to generate enums. There will be an initial
122 // set with an empty target prefix which will include target independent
123 // intrinsics like dbg.value.
124 using TargetSet
= CodeGenIntrinsicTable::TargetSet
;
125 const TargetSet
*Set
= nullptr;
126 for (const auto &Target
: Ints
.getTargets()) {
127 if (Target
.Name
== IntrinsicPrefix
) {
133 // The first entry is for target independent intrinsics, so drop it.
134 auto KnowTargets
= Ints
.getTargets().drop_front();
135 PrintFatalError([KnowTargets
](raw_ostream
&OS
) {
136 OS
<< "tried to generate intrinsics for unknown target "
137 << IntrinsicPrefix
<< "\nKnown targets are: ";
138 interleaveComma(KnowTargets
, OS
,
139 [&OS
](const TargetSet
&Target
) { OS
<< Target
.Name
; });
144 // Generate a complete header for target specific intrinsics.
145 if (IntrinsicPrefix
.empty()) {
146 OS
<< "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
148 std::string UpperPrefix
= StringRef(IntrinsicPrefix
).upper();
149 OS
<< formatv("#ifndef LLVM_IR_INTRINSIC_{}_ENUMS_H\n", UpperPrefix
);
150 OS
<< formatv("#define LLVM_IR_INTRINSIC_{}_ENUMS_H\n", UpperPrefix
);
151 OS
<< "namespace llvm::Intrinsic {\n";
152 OS
<< formatv("enum {}Intrinsics : unsigned {{\n", UpperPrefix
);
155 OS
<< "// Enum values for intrinsics.\n";
157 for (const auto &Int
: Ints
[*Set
]) {
158 OS
<< " " << Int
.EnumName
;
160 // Assign a value to the first intrinsic in this target set so that all
161 // intrinsic ids are distinct.
163 OS
<< " = " << Set
->Offset
+ 1;
168 if (Int
.EnumName
.size() < 40)
169 OS
.indent(40 - Int
.EnumName
.size());
170 OS
<< formatv(" // {}\n", Int
.Name
);
173 // Emit num_intrinsics into the target neutral enum.
174 if (IntrinsicPrefix
.empty()) {
175 OS
<< formatv(" num_intrinsics = {}\n", Ints
.size() + 1);
179 } // namespace llvm::Intrinsic
186 void IntrinsicEmitter::EmitArgKind(raw_ostream
&OS
) {
187 if (!IntrinsicPrefix
.empty())
189 OS
<< "// llvm::Intrinsic::IITDescriptor::ArgKind.\n";
190 OS
<< "#ifdef GET_INTRINSIC_ARGKIND\n";
191 if (const auto RecArgKind
= Records
.getDef("ArgKind")) {
192 for (const auto &RV
: RecArgKind
->getValues())
193 OS
<< " AK_" << RV
.getName() << " = " << *RV
.getValue() << ",\n";
195 OS
<< "#error \"ArgKind is not defined\"\n";
200 void IntrinsicEmitter::EmitIITInfo(raw_ostream
&OS
) {
201 OS
<< "#ifdef GET_INTRINSIC_IITINFO\n";
202 std::array
<StringRef
, 256> RecsByNumber
;
203 auto IIT_Base
= Records
.getAllDerivedDefinitionsIfDefined("IIT_Base");
204 for (const Record
*Rec
: IIT_Base
) {
205 auto Number
= Rec
->getValueAsInt("Number");
206 assert(0 <= Number
&& Number
< (int)RecsByNumber
.size() &&
207 "IIT_Info.Number should be uint8_t");
208 assert(RecsByNumber
[Number
].empty() && "Duplicate IIT_Info.Number");
209 RecsByNumber
[Number
] = Rec
->getName();
211 if (IIT_Base
.size() > 0) {
212 for (unsigned I
= 0, E
= RecsByNumber
.size(); I
< E
; ++I
)
213 if (!RecsByNumber
[I
].empty())
214 OS
<< " " << RecsByNumber
[I
] << " = " << I
<< ",\n";
216 OS
<< "#error \"class IIT_Base is not defined\"\n";
221 void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable
&Ints
,
223 OS
<< R
"(// Target mapping.
224 #ifdef GET_INTRINSIC_TARGET_DATA
225 struct IntrinsicTargetInfo {
230 static constexpr IntrinsicTargetInfo TargetInfos[] = {
232 for (const auto [Name
, Offset
, Count
] : Ints
.getTargets())
233 OS
<< formatv(" {{\"{}\", {}, {}},\n", Name
, Offset
, Count
);
240 void IntrinsicEmitter::EmitIntrinsicToNameTable(
241 const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
) {
242 OS
<< R
"(// Intrinsic ID to name table.
243 #ifdef GET_INTRINSIC_NAME_TABLE
244 // Note that entry #0 is the invalid intrinsic!
246 for (const auto &Int
: Ints
)
247 OS
<< " \"" << Int
.Name
<< "\",\n";
251 void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
252 const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
) {
253 OS
<< R
"(// Intrinsic ID to overload bitset.
254 #ifdef GET_INTRINSIC_OVERLOAD_TABLE
255 static constexpr uint8_t OTable[] = {
258 for (auto [I
, Int
] : enumerate(Ints
)) {
259 // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
264 if (Int
.isOverloaded
)
265 OS
<< " | (1<<" << Idx
% 8 << ')';
268 // OTable contains a true bit at the position if the intrinsic is overloaded.
269 OS
<< "return (OTable[id/8] & (1 << (id%8))) != 0;\n";
273 using TypeSigTy
= SmallVector
<unsigned char>;
275 /// Computes type signature of the intrinsic \p Int.
276 static TypeSigTy
ComputeTypeSignature(const CodeGenIntrinsic
&Int
) {
278 const Record
*TypeInfo
= Int
.TheDef
->getValueAsDef("TypeInfo");
279 const ListInit
*TypeList
= TypeInfo
->getValueAsListInit("TypeSig");
281 for (const auto *TypeListEntry
: TypeList
->getValues())
282 TypeSig
.emplace_back(cast
<IntInit
>(TypeListEntry
)->getValue());
286 // Pack the type signature into 32-bit fixed encoding word.
287 static std::optional
<uint32_t> encodePacked(const TypeSigTy
&TypeSig
) {
288 if (TypeSig
.size() > 8)
292 for (unsigned char C
: reverse(TypeSig
)) {
295 Result
= (Result
<< 4) | C
;
300 void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable
&Ints
,
302 // Note: the code below can be switched to use 32-bit fixed encoding by
303 // flipping the flag below.
304 constexpr bool Use16BitFixedEncoding
= true;
305 using FixedEncodingTy
=
306 std::conditional_t
<Use16BitFixedEncoding
, uint16_t, uint32_t>;
307 constexpr unsigned FixedEncodingBits
= sizeof(FixedEncodingTy
) * CHAR_BIT
;
308 // Mask with all bits 1 except the most significant bit.
309 const unsigned Mask
= (1U << (FixedEncodingBits
- 1)) - 1;
310 const unsigned MSBPostion
= FixedEncodingBits
- 1;
311 StringRef FixedEncodingTypeName
=
312 Use16BitFixedEncoding
? "uint16_t" : "uint32_t";
314 // If we can compute a 16/32-bit fixed encoding for this intrinsic, do so and
315 // capture it in this vector, otherwise store a ~0U.
316 std::vector
<FixedEncodingTy
> FixedEncodings
;
317 SequenceToOffsetTable
<TypeSigTy
> LongEncodingTable
;
319 FixedEncodings
.reserve(Ints
.size());
321 // Compute the unique argument type info.
322 for (const CodeGenIntrinsic
&Int
: Ints
) {
323 // Get the signature for the intrinsic.
324 TypeSigTy TypeSig
= ComputeTypeSignature(Int
);
326 // Check to see if we can encode it into a 16/32 bit word.
327 std::optional
<uint32_t> Result
= encodePacked(TypeSig
);
328 if (Result
&& (*Result
& Mask
) == Result
) {
329 FixedEncodings
.push_back(static_cast<FixedEncodingTy
>(*Result
));
333 LongEncodingTable
.add(TypeSig
);
335 // This is a placehold that we'll replace after the table is laid out.
336 FixedEncodings
.push_back(static_cast<FixedEncodingTy
>(~0U));
339 LongEncodingTable
.layout();
341 OS
<< formatv(R
"(// Global intrinsic function declaration type table.
342 #ifdef GET_INTRINSIC_GENERATOR_GLOBAL
343 static constexpr {} IIT_Table[] = {{
345 FixedEncodingTypeName
);
347 unsigned MaxOffset
= 0;
348 for (auto [Idx
, FixedEncoding
, Int
] : enumerate(FixedEncodings
, Ints
)) {
352 // If the entry fit in the table, just emit it.
353 if ((FixedEncoding
& Mask
) == FixedEncoding
) {
354 OS
<< "0x" << Twine::utohexstr(FixedEncoding
) << ", ";
358 TypeSigTy TypeSig
= ComputeTypeSignature(Int
);
359 unsigned Offset
= LongEncodingTable
.get(TypeSig
);
360 MaxOffset
= std::max(MaxOffset
, Offset
);
362 // Otherwise, emit the offset into the long encoding table. We emit it this
363 // way so that it is easier to read the offset in the .def file.
364 OS
<< formatv("(1U<<{}) | {}, ", MSBPostion
, Offset
);
369 // verify that all offsets will fit in 16/32 bits.
370 if ((MaxOffset
& Mask
) != MaxOffset
)
371 PrintFatalError("Offset of long encoding table exceeds encoding bits");
373 // Emit the shared table of register lists.
374 OS
<< "static constexpr unsigned char IIT_LongEncodingTable[] = {\n";
375 if (!LongEncodingTable
.empty())
376 LongEncodingTable
.emit(
377 OS
, [](raw_ostream
&OS
, unsigned char C
) { OS
<< (unsigned)C
; });
379 OS
<< "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
382 /// Returns the effective MemoryEffects for intrinsic \p Int.
383 static MemoryEffects
getEffectiveME(const CodeGenIntrinsic
&Int
) {
384 MemoryEffects ME
= Int
.ME
;
385 // TODO: IntrHasSideEffects should affect not only readnone intrinsics.
386 if (ME
.doesNotAccessMemory() && Int
.hasSideEffects
)
387 ME
= MemoryEffects::unknown();
391 static bool compareFnAttributes(const CodeGenIntrinsic
*L
,
392 const CodeGenIntrinsic
*R
) {
393 auto TieBoolAttributes
= [](const CodeGenIntrinsic
*I
) -> auto {
394 // Sort throwing intrinsics after non-throwing intrinsics.
395 return std::tie(I
->canThrow
, I
->isNoDuplicate
, I
->isNoMerge
, I
->isNoReturn
,
396 I
->isNoCallback
, I
->isNoSync
, I
->isNoFree
, I
->isWillReturn
,
397 I
->isCold
, I
->isConvergent
, I
->isSpeculatable
,
398 I
->hasSideEffects
, I
->isStrictFP
);
401 auto TieL
= TieBoolAttributes(L
);
402 auto TieR
= TieBoolAttributes(R
);
407 // Try to order by readonly/readnone attribute.
408 uint32_t LME
= getEffectiveME(*L
).toIntValue();
409 uint32_t RME
= getEffectiveME(*R
).toIntValue();
416 /// Returns true if \p Int has a non-empty set of function attributes. Note that
417 /// NoUnwind = !canThrow, so we need to negate it's sense to test if the
418 // intrinsic has NoUnwind attribute.
419 static bool hasFnAttributes(const CodeGenIntrinsic
&Int
) {
420 return !Int
.canThrow
|| Int
.isNoReturn
|| Int
.isNoCallback
|| Int
.isNoSync
||
421 Int
.isNoFree
|| Int
.isWillReturn
|| Int
.isCold
|| Int
.isNoDuplicate
||
422 Int
.isNoMerge
|| Int
.isConvergent
|| Int
.isSpeculatable
||
423 Int
.isStrictFP
|| getEffectiveME(Int
) != MemoryEffects::unknown();
427 struct FnAttributeComparator
{
428 bool operator()(const CodeGenIntrinsic
*L
, const CodeGenIntrinsic
*R
) const {
429 return compareFnAttributes(L
, R
);
433 struct AttributeComparator
{
434 bool operator()(const CodeGenIntrinsic
*L
, const CodeGenIntrinsic
*R
) const {
435 // Order all intrinsics with no functiona attributes before all intrinsics
436 // with function attributes.
437 bool HasFnAttrLHS
= hasFnAttributes(*L
);
438 bool HasFnAttrRHS
= hasFnAttributes(*R
);
440 // Order by argument attributes if function `hasFnAttributes` is equal.
441 // This is reliable because each side is already sorted internally.
442 return std::tie(HasFnAttrLHS
, L
->ArgumentAttributes
) <
443 std::tie(HasFnAttrRHS
, R
->ArgumentAttributes
);
446 } // End anonymous namespace
448 /// Returns the name of the IR enum for argument attribute kind \p Kind.
449 static StringRef
getArgAttrEnumName(CodeGenIntrinsic::ArgAttrKind Kind
) {
451 case CodeGenIntrinsic::NoCapture
:
453 case CodeGenIntrinsic::NoAlias
:
455 case CodeGenIntrinsic::NoUndef
:
457 case CodeGenIntrinsic::NonNull
:
459 case CodeGenIntrinsic::Returned
:
461 case CodeGenIntrinsic::ReadOnly
:
463 case CodeGenIntrinsic::WriteOnly
:
465 case CodeGenIntrinsic::ReadNone
:
467 case CodeGenIntrinsic::ImmArg
:
469 case CodeGenIntrinsic::Alignment
:
471 case CodeGenIntrinsic::Dereferenceable
:
472 return "Dereferenceable";
474 llvm_unreachable("Unknown CodeGenIntrinsic::ArgAttrKind enum");
477 /// EmitAttributes - This emits the Intrinsic::getAttributes method.
478 void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable
&Ints
,
480 OS
<< R
"(// Add parameter attributes that are not common to all intrinsics.
481 #ifdef GET_INTRINSIC_ATTRIBUTES
482 static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) {
484 default: llvm_unreachable("Invalid attribute set number
");)";
485 // Compute unique argument attribute sets.
486 std::map
<SmallVector
<CodeGenIntrinsic::ArgAttribute
, 0>, unsigned>
488 for (const CodeGenIntrinsic
&Int
: Ints
) {
489 for (auto &Attrs
: Int
.ArgumentAttributes
) {
493 unsigned ID
= UniqArgAttributes
.size();
494 if (!UniqArgAttributes
.try_emplace(Attrs
, ID
).second
)
497 assert(is_sorted(Attrs
) && "Argument attributes are not sorted");
501 return AttributeSet::get(C, {{
504 for (const CodeGenIntrinsic::ArgAttribute
&Attr
: Attrs
) {
505 StringRef AttrName
= getArgAttrEnumName(Attr
.Kind
);
506 if (Attr
.Kind
== CodeGenIntrinsic::Alignment
||
507 Attr
.Kind
== CodeGenIntrinsic::Dereferenceable
)
508 OS
<< formatv(" Attribute::get(C, Attribute::{}, {}),\n",
509 AttrName
, Attr
.Value
);
511 OS
<< formatv(" Attribute::get(C, Attribute::{}),\n", AttrName
);
518 } // getIntrinsicArgAttributeSet
521 // Compute unique function attribute sets.
522 std::map
<const CodeGenIntrinsic
*, unsigned, FnAttributeComparator
>
525 static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
527 default: llvm_unreachable("Invalid attribute set number
");)";
529 for (const CodeGenIntrinsic
&Int
: Ints
) {
530 if (!hasFnAttributes(Int
))
532 unsigned ID
= UniqFnAttributes
.size();
533 if (!UniqFnAttributes
.try_emplace(&Int
, ID
).second
)
537 return AttributeSet::get(C, {{
540 auto addAttribute
= [&OS
](StringRef Attr
) {
541 OS
<< formatv(" Attribute::get(C, Attribute::{}),\n", Attr
);
544 addAttribute("NoUnwind");
546 addAttribute("NoReturn");
547 if (Int
.isNoCallback
)
548 addAttribute("NoCallback");
550 addAttribute("NoSync");
552 addAttribute("NoFree");
553 if (Int
.isWillReturn
)
554 addAttribute("WillReturn");
556 addAttribute("Cold");
557 if (Int
.isNoDuplicate
)
558 addAttribute("NoDuplicate");
560 addAttribute("NoMerge");
561 if (Int
.isConvergent
)
562 addAttribute("Convergent");
563 if (Int
.isSpeculatable
)
564 addAttribute("Speculatable");
566 addAttribute("StrictFP");
568 const MemoryEffects ME
= getEffectiveME(Int
);
569 if (ME
!= MemoryEffects::unknown()) {
570 OS
<< formatv(" // {}\n", ME
);
571 OS
<< formatv(" Attribute::getWithMemoryEffects(C, "
572 "MemoryEffects::createFromIntValue({})),\n",
579 } // getIntrinsicFnAttributeSet
581 AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {
584 // Compute the maximum number of attribute arguments and the map. For function
585 // attributes, we only consider whether the intrinsics has any function
587 std::map
<const CodeGenIntrinsic
*, unsigned, AttributeComparator
>
589 for (const CodeGenIntrinsic
&Int
: Ints
) {
590 unsigned ID
= UniqAttributes
.size();
591 UniqAttributes
.try_emplace(&Int
, ID
);
594 // Assign a 16-bit packed ID for each intrinsic. The lower 8-bits will be its
595 // "argument attribute ID" (index in UniqAttributes) and upper 8 bits will be
596 // its "function attribute ID" (index in UniqFnAttributes).
597 if (UniqAttributes
.size() > 256)
598 PrintFatalError("Too many unique argument attributes for table!");
599 if (UniqFnAttributes
.size() > 256)
600 PrintFatalError("Too many unique function attributes for table!");
602 // Emit an array of AttributeList. Most intrinsics will have at least one
603 // entry, for the function itself (index ~1), which is usually nounwind.
604 OS
<< " static constexpr uint16_t IntrinsicsToAttributesMap[] = {";
605 for (const CodeGenIntrinsic
&Int
: Ints
) {
606 uint16_t FnAttrIndex
= hasFnAttributes(Int
) ? UniqFnAttributes
[&Int
] : 0;
607 OS
<< formatv("\n {} << 8 | {}, // {}", FnAttrIndex
,
608 UniqAttributes
[&Int
], Int
.Name
);
614 return AttributeList();
616 uint16_t PackedID = IntrinsicsToAttributesMap[id - 1];
617 uint8_t FnAttrID = PackedID >> 8;
618 switch(PackedID & 0xFF) {{
619 default: llvm_unreachable("Invalid attribute number
");
622 for (const auto [IntPtr
, UniqueID
] : UniqAttributes
) {
623 OS
<< formatv(" case {}:\n", UniqueID
);
624 const CodeGenIntrinsic
&Int
= *IntPtr
;
626 // Keep track of the number of attributes we're writing out.
628 llvm::count_if(Int
.ArgumentAttributes
,
629 [](const auto &Attrs
) { return !Attrs
.empty(); });
630 NumAttrs
+= hasFnAttributes(Int
);
632 OS
<< " return AttributeList();\n";
636 OS
<< " return AttributeList::get(C, {\n";
637 ListSeparator
LS(",\n");
638 for (const auto &[AttrIdx
, Attrs
] : enumerate(Int
.ArgumentAttributes
)) {
642 unsigned ArgAttrID
= UniqArgAttributes
.find(Attrs
)->second
;
644 << formatv(" {{{}, getIntrinsicArgAttributeSet(C, {})}", AttrIdx
,
648 if (hasFnAttributes(Int
)) {
650 << " {AttributeList::FunctionIndex, "
651 "getIntrinsicFnAttributeSet(C, FnAttrID)}";
658 #endif // GET_INTRINSIC_ATTRIBUTES
663 void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
664 const CodeGenIntrinsicTable
&Ints
, bool IsClang
, raw_ostream
&OS
) {
665 StringRef CompilerName
= IsClang
? "Clang" : "MS";
666 StringRef UpperCompilerName
= IsClang
? "CLANG" : "MS";
668 // map<TargetPrefix, pair<map<BuiltinName, EnumName>, CommonPrefix>.
669 // Note that we iterate over both the maps in the code below and both
670 // iterations need to iterate in sorted key order. For the inner map, entries
671 // need to be emitted in the sorted order of `BuiltinName` with `CommonPrefix`
672 // rempved, because we use std::lower_bound to search these entries. For the
673 // outer map as well, entries need to be emitted in sorter order of
674 // `TargetPrefix` as we use std::lower_bound to search these entries.
676 std::pair
<std::map
<StringRef
, StringRef
>, std::optional
<StringRef
>>;
677 std::map
<StringRef
, BIMEntryTy
> BuiltinMap
;
679 for (const CodeGenIntrinsic
&Int
: Ints
) {
680 StringRef BuiltinName
= IsClang
? Int
.ClangBuiltinName
: Int
.MSBuiltinName
;
681 if (BuiltinName
.empty())
683 // Get the map for this target prefix.
684 auto &[Map
, CommonPrefix
] = BuiltinMap
[Int
.TargetPrefix
];
686 if (!Map
.insert({BuiltinName
, Int
.EnumName
}).second
)
687 PrintFatalError(Int
.TheDef
->getLoc(),
688 "Intrinsic '" + Int
.TheDef
->getName() + "': duplicate " +
689 CompilerName
+ " builtin name!");
691 // Update common prefix.
693 // For the first builtin for this target, initialize the common prefix.
694 CommonPrefix
= BuiltinName
;
698 // Update the common prefix. Note that this assumes that `take_front` will
699 // never set the `Data` pointer in CommonPrefix to nullptr.
700 const char *Mismatch
= mismatch(*CommonPrefix
, BuiltinName
).first
;
701 *CommonPrefix
= CommonPrefix
->take_front(Mismatch
- CommonPrefix
->begin());
704 // Populate the string table with the names of all the builtins after
705 // removing this common prefix.
706 StringToOffsetTable Table
;
707 for (const auto &[TargetPrefix
, Entry
] : BuiltinMap
) {
708 auto &[Map
, CommonPrefix
] = Entry
;
709 for (auto &[BuiltinName
, EnumName
] : Map
) {
710 StringRef Suffix
= BuiltinName
.substr(CommonPrefix
->size());
711 Table
.GetOrAddStringOffset(Suffix
);
716 // Get the LLVM intrinsic that corresponds to a builtin. This is used by the
717 // C front-end. The builtin name is passed in as BuiltinName, and a target
718 // prefix (e.g. 'ppc') is passed in as TargetPrefix.
719 #ifdef GET_LLVM_INTRINSIC_FOR_{}_BUILTIN
721 Intrinsic::getIntrinsicFor{}Builtin(StringRef TargetPrefix,
722 StringRef BuiltinName) {{
723 using namespace Intrinsic;
725 UpperCompilerName
, CompilerName
);
727 if (BuiltinMap
.empty()) {
729 return not_intrinsic;
731 #endif // GET_LLVM_INTRINSIC_FOR_{}_BUILTIN
737 if (!Table
.empty()) {
738 Table
.EmitStringLiteralDef(OS
, "static constexpr char BuiltinNames[]");
741 struct BuiltinEntry {
743 unsigned StrTabOffset;
744 const char *getName() const { return &BuiltinNames[StrTabOffset]; }
745 bool operator<(StringRef RHS) const {
746 return strncmp(getName(), RHS.data(), RHS.size()) < 0;
753 // Emit a per target table of bultin names.
754 bool HasTargetIndependentBuiltins
= false;
755 StringRef TargetIndepndentCommonPrefix
;
756 for (const auto &[TargetPrefix
, Entry
] : BuiltinMap
) {
757 const auto &[Map
, CommonPrefix
] = Entry
;
758 if (!TargetPrefix
.empty()) {
759 OS
<< formatv(" // Builtins for {0}.\n", TargetPrefix
);
761 OS
<< " // Target independent builtins.\n";
762 HasTargetIndependentBuiltins
= true;
763 TargetIndepndentCommonPrefix
= *CommonPrefix
;
766 // Emit the builtin table for this target prefix.
767 OS
<< formatv(" static constexpr BuiltinEntry {}Names[] = {{\n",
769 for (const auto &[BuiltinName
, EnumName
] : Map
) {
770 StringRef Suffix
= BuiltinName
.substr(CommonPrefix
->size());
771 OS
<< formatv(" {{{}, {}}, // {}\n", EnumName
,
772 *Table
.GetStringOffset(Suffix
), BuiltinName
);
774 OS
<< formatv(" }; // {}Names\n\n", TargetPrefix
);
777 // After emitting the builtin tables for all targets, emit a lookup table for
778 // all targets. We will use binary search, similar to the table for builtin
779 // names to lookup into this table.
782 StringLiteral TargetPrefix;
783 ArrayRef<BuiltinEntry> Names;
784 StringLiteral CommonPrefix;
785 bool operator<(StringRef RHS) const {
786 return TargetPrefix < RHS;
789 static constexpr TargetEntry TargetTable[] = {
792 for (const auto &[TargetPrefix
, Entry
] : BuiltinMap
) {
793 const auto &[Map
, CommonPrefix
] = Entry
;
794 if (TargetPrefix
.empty())
796 OS
<< formatv(R
"( {{"{0}", {0}Names, "{1}"},)", TargetPrefix
,
802 // Now for the actual lookup, first check the target independent table if
804 if (HasTargetIndependentBuiltins
) {
806 // Check if it's a target independent builtin.
807 // Copy the builtin name so we can use it in consume_front without clobbering
808 // if for the lookup in the target specific table.
809 StringRef Suffix = BuiltinName;
810 if (Suffix.consume_front("{}")) {{
811 auto II = lower_bound(Names, Suffix);
812 if (II != std::end(Names) && II->getName() == Suffix)
813 return II->IntrinsicID;
816 TargetIndepndentCommonPrefix
);
819 // If a target independent builtin was not found, lookup the target specific.
821 auto TI = lower_bound(TargetTable, TargetPrefix);
822 if (TI == std::end(TargetTable) || TI->TargetPrefix != TargetPrefix)
823 return not_intrinsic;
824 // This is the last use of BuiltinName, so no need to copy before using it in
826 if (!BuiltinName.consume_front(TI->CommonPrefix))
827 return not_intrinsic;
828 auto II = lower_bound(TI->Names, BuiltinName);
829 if (II == std::end(TI->Names) || II->getName() != BuiltinName)
830 return not_intrinsic;
831 return II->IntrinsicID;
833 #endif // GET_LLVM_INTRINSIC_FOR_{}_BUILTIN
839 static TableGen::Emitter::OptClass
<IntrinsicEmitterOpt
</*Enums=*/true>>
840 X("gen-intrinsic-enums", "Generate intrinsic enums");
842 static TableGen::Emitter::OptClass
<IntrinsicEmitterOpt
</*Enums=*/false>>
843 Y("gen-intrinsic-impl", "Generate intrinsic implementation code");