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 "CodeGenIntrinsics.h"
14 #include "SequenceToOffsetTable.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/ErrorHandling.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"
38 cl::OptionCategory
GenIntrinsicCat("Options for -gen-intrinsic-enums");
40 IntrinsicPrefix("intrinsic-prefix",
41 cl::desc("Generate intrinsics with this target prefix"),
42 cl::value_desc("target prefix"), cl::cat(GenIntrinsicCat
));
45 class IntrinsicEmitter
{
46 RecordKeeper
&Records
;
49 IntrinsicEmitter(RecordKeeper
&R
) : Records(R
) {}
51 void run(raw_ostream
&OS
, bool Enums
);
53 void EmitEnumInfo(const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
);
54 void EmitArgKind(raw_ostream
&OS
);
55 void EmitIITInfo(raw_ostream
&OS
);
56 void EmitTargetInfo(const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
);
57 void EmitIntrinsicToNameTable(const CodeGenIntrinsicTable
&Ints
,
59 void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable
&Ints
,
61 void EmitGenerator(const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
);
62 void EmitAttributes(const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
);
63 void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable
&Ints
, bool IsClang
,
66 } // End anonymous namespace
68 //===----------------------------------------------------------------------===//
69 // IntrinsicEmitter Implementation
70 //===----------------------------------------------------------------------===//
72 void IntrinsicEmitter::run(raw_ostream
&OS
, bool Enums
) {
73 emitSourceFileHeader("Intrinsic Function Source Fragment", OS
);
75 CodeGenIntrinsicTable
Ints(Records
);
78 // Emit the enum information.
79 EmitEnumInfo(Ints
, OS
);
81 // Emit ArgKind for Intrinsics.h.
84 // Emit IIT_Info constants.
87 // Emit the target metadata.
88 EmitTargetInfo(Ints
, OS
);
90 // Emit the intrinsic ID -> name table.
91 EmitIntrinsicToNameTable(Ints
, OS
);
93 // Emit the intrinsic ID -> overload table.
94 EmitIntrinsicToOverloadTable(Ints
, OS
);
96 // Emit the intrinsic declaration generator.
97 EmitGenerator(Ints
, OS
);
99 // Emit the intrinsic parameter attributes.
100 EmitAttributes(Ints
, OS
);
102 // Emit code to translate GCC builtins into LLVM intrinsics.
103 EmitIntrinsicToBuiltinMap(Ints
, true, OS
);
105 // Emit code to translate MS builtins into LLVM intrinsics.
106 EmitIntrinsicToBuiltinMap(Ints
, false, OS
);
110 void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable
&Ints
,
112 // Find the TargetSet for which to generate enums. There will be an initial
113 // set with an empty target prefix which will include target independent
114 // intrinsics like dbg.value.
115 const CodeGenIntrinsicTable::TargetSet
*Set
= nullptr;
116 for (const auto &Target
: Ints
.Targets
) {
117 if (Target
.Name
== IntrinsicPrefix
) {
123 std::vector
<std::string
> KnownTargets
;
124 for (const auto &Target
: Ints
.Targets
)
125 if (!Target
.Name
.empty())
126 KnownTargets
.push_back(Target
.Name
);
127 PrintFatalError("tried to generate intrinsics for unknown target " +
129 "\nKnown targets are: " + join(KnownTargets
, ", ") + "\n");
132 // Generate a complete header for target specific intrinsics.
133 if (IntrinsicPrefix
.empty()) {
134 OS
<< "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
136 std::string UpperPrefix
= StringRef(IntrinsicPrefix
).upper();
137 OS
<< "#ifndef LLVM_IR_INTRINSIC_" << UpperPrefix
<< "_ENUMS_H\n";
138 OS
<< "#define LLVM_IR_INTRINSIC_" << UpperPrefix
<< "_ENUMS_H\n\n";
139 OS
<< "namespace llvm {\n";
140 OS
<< "namespace Intrinsic {\n";
141 OS
<< "enum " << UpperPrefix
<< "Intrinsics : unsigned {\n";
144 OS
<< "// Enum values for intrinsics\n";
145 for (unsigned i
= Set
->Offset
, e
= Set
->Offset
+ Set
->Count
; i
!= e
; ++i
) {
146 OS
<< " " << Ints
[i
].EnumName
;
148 // Assign a value to the first intrinsic in this target set so that all
149 // intrinsic ids are distinct.
150 if (i
== Set
->Offset
)
151 OS
<< " = " << (Set
->Offset
+ 1);
154 if (Ints
[i
].EnumName
.size() < 40)
155 OS
.indent(40 - Ints
[i
].EnumName
.size());
156 OS
<< " // " << Ints
[i
].Name
<< "\n";
159 // Emit num_intrinsics into the target neutral enum.
160 if (IntrinsicPrefix
.empty()) {
161 OS
<< " num_intrinsics = " << (Ints
.size() + 1) << "\n";
164 OS
<< "}; // enum\n";
165 OS
<< "} // namespace Intrinsic\n";
166 OS
<< "} // namespace llvm\n\n";
171 void IntrinsicEmitter::EmitArgKind(raw_ostream
&OS
) {
172 if (!IntrinsicPrefix
.empty())
174 OS
<< "// llvm::Intrinsic::IITDescriptor::ArgKind\n";
175 OS
<< "#ifdef GET_INTRINSIC_ARGKIND\n";
176 if (auto RecArgKind
= Records
.getDef("ArgKind")) {
177 for (auto &RV
: RecArgKind
->getValues())
178 OS
<< " AK_" << RV
.getName() << " = " << *RV
.getValue() << ",\n";
180 OS
<< "#error \"ArgKind is not defined\"\n";
185 void IntrinsicEmitter::EmitIITInfo(raw_ostream
&OS
) {
186 OS
<< "#ifdef GET_INTRINSIC_IITINFO\n";
187 std::array
<StringRef
, 256> RecsByNumber
;
188 auto IIT_Base
= Records
.getAllDerivedDefinitionsIfDefined("IIT_Base");
189 for (auto Rec
: IIT_Base
) {
190 auto Number
= Rec
->getValueAsInt("Number");
191 assert(0 <= Number
&& Number
< (int)RecsByNumber
.size() &&
192 "IIT_Info.Number should be uint8_t");
193 assert(RecsByNumber
[Number
].empty() && "Duplicate IIT_Info.Number");
194 RecsByNumber
[Number
] = Rec
->getName();
196 if (IIT_Base
.size() > 0) {
197 for (unsigned I
= 0, E
= RecsByNumber
.size(); I
< E
; ++I
)
198 if (!RecsByNumber
[I
].empty())
199 OS
<< " " << RecsByNumber
[I
] << " = " << I
<< ",\n";
201 OS
<< "#error \"class IIT_Base is not defined\"\n";
206 void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable
&Ints
,
208 OS
<< "// Target mapping\n";
209 OS
<< "#ifdef GET_INTRINSIC_TARGET_DATA\n";
210 OS
<< "struct IntrinsicTargetInfo {\n"
211 << " llvm::StringLiteral Name;\n"
212 << " size_t Offset;\n"
213 << " size_t Count;\n"
215 OS
<< "static constexpr IntrinsicTargetInfo TargetInfos[] = {\n";
216 for (const auto &Target
: Ints
.Targets
)
217 OS
<< " {llvm::StringLiteral(\"" << Target
.Name
<< "\"), " << Target
.Offset
218 << ", " << Target
.Count
<< "},\n";
223 void IntrinsicEmitter::EmitIntrinsicToNameTable(
224 const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
) {
225 OS
<< "// Intrinsic ID to name table\n";
226 OS
<< "#ifdef GET_INTRINSIC_NAME_TABLE\n";
227 OS
<< " // Note that entry #0 is the invalid intrinsic!\n";
228 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
)
229 OS
<< " \"" << Ints
[i
].Name
<< "\",\n";
233 void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
234 const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
) {
235 OS
<< "// Intrinsic ID to overload bitset\n";
236 OS
<< "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
237 OS
<< "static const uint8_t OTable[] = {\n";
239 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
240 // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
243 if (Ints
[i
].isOverloaded
)
244 OS
<< " | (1<<" << (i
+1)%8 << ')';
247 // OTable contains a true bit at the position if the intrinsic is overloaded.
248 OS
<< "return (OTable[id/8] & (1 << (id%8))) != 0;\n";
252 /// ComputeFixedEncoding - If we can encode the type signature for this
253 /// intrinsic into 32 bits, return it. If not, return ~0U.
254 static void ComputeFixedEncoding(const CodeGenIntrinsic
&Int
,
255 std::vector
<unsigned char> &TypeSig
) {
256 if (auto *R
= Int
.TheDef
->getValue("TypeSig")) {
257 for (auto &a
: cast
<ListInit
>(R
->getValue())->getValues()) {
258 for (auto &b
: cast
<ListInit
>(a
)->getValues())
259 TypeSig
.push_back(cast
<IntInit
>(b
)->getValue());
264 static void printIITEntry(raw_ostream
&OS
, unsigned char X
) {
268 void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable
&Ints
,
270 // If we can compute a 32-bit fixed encoding for this intrinsic, do so and
271 // capture it in this vector, otherwise store a ~0U.
272 std::vector
<unsigned> FixedEncodings
;
274 SequenceToOffsetTable
<std::vector
<unsigned char> > LongEncodingTable
;
276 std::vector
<unsigned char> TypeSig
;
278 // Compute the unique argument type info.
279 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
280 // Get the signature for the intrinsic.
282 ComputeFixedEncoding(Ints
[i
], TypeSig
);
284 // Check to see if we can encode it into a 32-bit word. We can only encode
285 // 8 nibbles into a 32-bit word.
286 if (TypeSig
.size() <= 8) {
289 for (unsigned i
= 0, e
= TypeSig
.size(); i
!= e
; ++i
) {
290 // If we had an unencodable argument, bail out.
291 if (TypeSig
[i
] > 15) {
295 Result
= (Result
<< 4) | TypeSig
[e
-i
-1];
298 // If this could be encoded into a 31-bit word, return it.
299 if (!Failed
&& (Result
>> 31) == 0) {
300 FixedEncodings
.push_back(Result
);
305 // Otherwise, we're going to unique the sequence into the
306 // LongEncodingTable, and use its offset in the 32-bit table instead.
307 LongEncodingTable
.add(TypeSig
);
309 // This is a placehold that we'll replace after the table is laid out.
310 FixedEncodings
.push_back(~0U);
313 LongEncodingTable
.layout();
315 OS
<< "// Global intrinsic function declaration type table.\n";
316 OS
<< "#ifdef GET_INTRINSIC_GENERATOR_GLOBAL\n";
318 OS
<< "static const unsigned IIT_Table[] = {\n ";
320 for (unsigned i
= 0, e
= FixedEncodings
.size(); i
!= e
; ++i
) {
324 // If the entry fit in the table, just emit it.
325 if (FixedEncodings
[i
] != ~0U) {
326 OS
<< "0x" << Twine::utohexstr(FixedEncodings
[i
]) << ", ";
331 ComputeFixedEncoding(Ints
[i
], TypeSig
);
334 // Otherwise, emit the offset into the long encoding table. We emit it this
335 // way so that it is easier to read the offset in the .def file.
336 OS
<< "(1U<<31) | " << LongEncodingTable
.get(TypeSig
) << ", ";
341 // Emit the shared table of register lists.
342 OS
<< "static const unsigned char IIT_LongEncodingTable[] = {\n";
343 if (!LongEncodingTable
.empty())
344 LongEncodingTable
.emit(OS
, printIITEntry
);
345 OS
<< " 255\n};\n\n";
347 OS
<< "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
351 std::optional
<bool> compareFnAttributes(const CodeGenIntrinsic
*L
,
352 const CodeGenIntrinsic
*R
) {
353 // Sort throwing intrinsics after non-throwing intrinsics.
354 if (L
->canThrow
!= R
->canThrow
)
357 if (L
->isNoDuplicate
!= R
->isNoDuplicate
)
358 return R
->isNoDuplicate
;
360 if (L
->isNoMerge
!= R
->isNoMerge
)
363 if (L
->isNoReturn
!= R
->isNoReturn
)
364 return R
->isNoReturn
;
366 if (L
->isNoCallback
!= R
->isNoCallback
)
367 return R
->isNoCallback
;
369 if (L
->isNoSync
!= R
->isNoSync
)
372 if (L
->isNoFree
!= R
->isNoFree
)
375 if (L
->isWillReturn
!= R
->isWillReturn
)
376 return R
->isWillReturn
;
378 if (L
->isCold
!= R
->isCold
)
381 if (L
->isConvergent
!= R
->isConvergent
)
382 return R
->isConvergent
;
384 if (L
->isSpeculatable
!= R
->isSpeculatable
)
385 return R
->isSpeculatable
;
387 if (L
->hasSideEffects
!= R
->hasSideEffects
)
388 return R
->hasSideEffects
;
390 if (L
->isStrictFP
!= R
->isStrictFP
)
391 return R
->isStrictFP
;
393 // Try to order by readonly/readnone attribute.
394 uint32_t LK
= L
->ME
.toIntValue();
395 uint32_t RK
= R
->ME
.toIntValue();
396 if (LK
!= RK
) return (LK
> RK
);
401 struct FnAttributeComparator
{
402 bool operator()(const CodeGenIntrinsic
*L
, const CodeGenIntrinsic
*R
) const {
403 return compareFnAttributes(L
, R
).value_or(false);
407 struct AttributeComparator
{
408 bool operator()(const CodeGenIntrinsic
*L
, const CodeGenIntrinsic
*R
) const {
409 if (std::optional
<bool> Res
= compareFnAttributes(L
, R
))
412 // Order by argument attributes.
413 // This is reliable because each side is already sorted internally.
414 return (L
->ArgumentAttributes
< R
->ArgumentAttributes
);
417 } // End anonymous namespace
419 /// EmitAttributes - This emits the Intrinsic::getAttributes method.
420 void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable
&Ints
,
422 OS
<< "// Add parameter attributes that are not common to all intrinsics.\n";
423 OS
<< "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
425 // Compute unique argument attribute sets.
426 std::map
<SmallVector
<CodeGenIntrinsic::ArgAttribute
, 0>, unsigned>
428 OS
<< "static AttributeSet getIntrinsicArgAttributeSet("
429 << "LLVMContext &C, unsigned ID) {\n"
430 << " switch (ID) {\n"
431 << " default: llvm_unreachable(\"Invalid attribute set number\");\n";
432 for (const CodeGenIntrinsic
&Int
: Ints
) {
433 for (auto &Attrs
: Int
.ArgumentAttributes
) {
437 unsigned ID
= UniqArgAttributes
.size();
438 if (!UniqArgAttributes
.try_emplace(Attrs
, ID
).second
)
441 assert(is_sorted(Attrs
) &&
442 "Argument attributes are not sorted");
444 OS
<< " case " << ID
<< ":\n";
445 OS
<< " return AttributeSet::get(C, {\n";
446 for (const CodeGenIntrinsic::ArgAttribute
&Attr
: Attrs
) {
448 case CodeGenIntrinsic::NoCapture
:
449 OS
<< " Attribute::get(C, Attribute::NoCapture),\n";
451 case CodeGenIntrinsic::NoAlias
:
452 OS
<< " Attribute::get(C, Attribute::NoAlias),\n";
454 case CodeGenIntrinsic::NoUndef
:
455 OS
<< " Attribute::get(C, Attribute::NoUndef),\n";
457 case CodeGenIntrinsic::NonNull
:
458 OS
<< " Attribute::get(C, Attribute::NonNull),\n";
460 case CodeGenIntrinsic::Returned
:
461 OS
<< " Attribute::get(C, Attribute::Returned),\n";
463 case CodeGenIntrinsic::ReadOnly
:
464 OS
<< " Attribute::get(C, Attribute::ReadOnly),\n";
466 case CodeGenIntrinsic::WriteOnly
:
467 OS
<< " Attribute::get(C, Attribute::WriteOnly),\n";
469 case CodeGenIntrinsic::ReadNone
:
470 OS
<< " Attribute::get(C, Attribute::ReadNone),\n";
472 case CodeGenIntrinsic::ImmArg
:
473 OS
<< " Attribute::get(C, Attribute::ImmArg),\n";
475 case CodeGenIntrinsic::Alignment
:
476 OS
<< " Attribute::get(C, Attribute::Alignment, "
477 << Attr
.Value
<< "),\n";
479 case CodeGenIntrinsic::Dereferenceable
:
480 OS
<< " Attribute::get(C, Attribute::Dereferenceable, "
481 << Attr
.Value
<< "),\n";
491 // Compute unique function attribute sets.
492 std::map
<const CodeGenIntrinsic
*, unsigned, FnAttributeComparator
>
494 OS
<< "static AttributeSet getIntrinsicFnAttributeSet("
495 << "LLVMContext &C, unsigned ID) {\n"
496 << " switch (ID) {\n"
497 << " default: llvm_unreachable(\"Invalid attribute set number\");\n";
498 for (const CodeGenIntrinsic
&Intrinsic
: Ints
) {
499 unsigned ID
= UniqFnAttributes
.size();
500 if (!UniqFnAttributes
.try_emplace(&Intrinsic
, ID
).second
)
503 OS
<< " case " << ID
<< ":\n"
504 << " return AttributeSet::get(C, {\n";
505 if (!Intrinsic
.canThrow
)
506 OS
<< " Attribute::get(C, Attribute::NoUnwind),\n";
507 if (Intrinsic
.isNoReturn
)
508 OS
<< " Attribute::get(C, Attribute::NoReturn),\n";
509 if (Intrinsic
.isNoCallback
)
510 OS
<< " Attribute::get(C, Attribute::NoCallback),\n";
511 if (Intrinsic
.isNoSync
)
512 OS
<< " Attribute::get(C, Attribute::NoSync),\n";
513 if (Intrinsic
.isNoFree
)
514 OS
<< " Attribute::get(C, Attribute::NoFree),\n";
515 if (Intrinsic
.isWillReturn
)
516 OS
<< " Attribute::get(C, Attribute::WillReturn),\n";
517 if (Intrinsic
.isCold
)
518 OS
<< " Attribute::get(C, Attribute::Cold),\n";
519 if (Intrinsic
.isNoDuplicate
)
520 OS
<< " Attribute::get(C, Attribute::NoDuplicate),\n";
521 if (Intrinsic
.isNoMerge
)
522 OS
<< " Attribute::get(C, Attribute::NoMerge),\n";
523 if (Intrinsic
.isConvergent
)
524 OS
<< " Attribute::get(C, Attribute::Convergent),\n";
525 if (Intrinsic
.isSpeculatable
)
526 OS
<< " Attribute::get(C, Attribute::Speculatable),\n";
527 if (Intrinsic
.isStrictFP
)
528 OS
<< " Attribute::get(C, Attribute::StrictFP),\n";
530 MemoryEffects ME
= Intrinsic
.ME
;
531 // TODO: IntrHasSideEffects should affect not only readnone intrinsics.
532 if (ME
.doesNotAccessMemory() && Intrinsic
.hasSideEffects
)
533 ME
= MemoryEffects::unknown();
534 if (ME
!= MemoryEffects::unknown()) {
535 OS
<< " Attribute::getWithMemoryEffects(C, "
536 << "MemoryEffects::createFromIntValue(" << ME
.toIntValue() << ")),\n";
542 OS
<< "AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {\n";
544 // Compute the maximum number of attribute arguments and the map
545 typedef std::map
<const CodeGenIntrinsic
*, unsigned,
546 AttributeComparator
> UniqAttrMapTy
;
547 UniqAttrMapTy UniqAttributes
;
548 unsigned maxArgAttrs
= 0;
549 unsigned AttrNum
= 0;
550 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
551 const CodeGenIntrinsic
&intrinsic
= Ints
[i
];
553 std::max(maxArgAttrs
, unsigned(intrinsic
.ArgumentAttributes
.size()));
554 unsigned &N
= UniqAttributes
[&intrinsic
];
557 assert(N
< 65536 && "Too many unique attributes for table!");
560 // Emit an array of AttributeList. Most intrinsics will have at least one
561 // entry, for the function itself (index ~1), which is usually nounwind.
562 OS
<< " static const uint16_t IntrinsicsToAttributesMap[] = {\n";
564 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
565 const CodeGenIntrinsic
&intrinsic
= Ints
[i
];
567 OS
<< " " << UniqAttributes
[&intrinsic
] << ", // "
568 << intrinsic
.Name
<< "\n";
572 OS
<< " std::pair<unsigned, AttributeSet> AS[" << maxArgAttrs
+ 1 << "];\n";
573 OS
<< " unsigned NumAttrs = 0;\n";
574 OS
<< " if (id != 0) {\n";
575 OS
<< " switch(IntrinsicsToAttributesMap[id - 1]) {\n";
576 OS
<< " default: llvm_unreachable(\"Invalid attribute number\");\n";
577 for (auto UniqAttribute
: UniqAttributes
) {
578 OS
<< " case " << UniqAttribute
.second
<< ": {\n";
580 const CodeGenIntrinsic
&Intrinsic
= *(UniqAttribute
.first
);
582 // Keep track of the number of attributes we're writing out.
583 unsigned numAttrs
= 0;
585 for (const auto &[AttrIdx
, Attrs
] :
586 enumerate(Intrinsic
.ArgumentAttributes
)) {
590 unsigned ID
= UniqArgAttributes
.find(Attrs
)->second
;
591 OS
<< " AS[" << numAttrs
++ << "] = {" << AttrIdx
592 << ", getIntrinsicArgAttributeSet(C, " << ID
<< ")};\n";
595 if (!Intrinsic
.canThrow
||
596 (Intrinsic
.ME
!= MemoryEffects::unknown() &&
597 !Intrinsic
.hasSideEffects
) ||
598 Intrinsic
.isNoReturn
|| Intrinsic
.isNoCallback
|| Intrinsic
.isNoSync
||
599 Intrinsic
.isNoFree
|| Intrinsic
.isWillReturn
|| Intrinsic
.isCold
||
600 Intrinsic
.isNoDuplicate
|| Intrinsic
.isNoMerge
||
601 Intrinsic
.isConvergent
|| Intrinsic
.isSpeculatable
||
602 Intrinsic
.isStrictFP
) {
603 unsigned ID
= UniqFnAttributes
.find(&Intrinsic
)->second
;
604 OS
<< " AS[" << numAttrs
++ << "] = {AttributeList::FunctionIndex, "
605 << "getIntrinsicFnAttributeSet(C, " << ID
<< ")};\n";
609 OS
<< " NumAttrs = " << numAttrs
<< ";\n";
613 OS
<< " return AttributeList();\n";
620 OS
<< " return AttributeList::get(C, ArrayRef(AS, NumAttrs));\n";
622 OS
<< "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
625 void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
626 const CodeGenIntrinsicTable
&Ints
, bool IsClang
, raw_ostream
&OS
) {
627 StringRef CompilerName
= (IsClang
? "Clang" : "MS");
628 StringRef UpperCompilerName
= (IsClang
? "CLANG" : "MS");
629 typedef std::map
<std::string
, std::map
<std::string
, std::string
>> BIMTy
;
631 StringToOffsetTable Table
;
632 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
633 const std::string
&BuiltinName
=
634 IsClang
? Ints
[i
].ClangBuiltinName
: Ints
[i
].MSBuiltinName
;
635 if (!BuiltinName
.empty()) {
636 // Get the map for this target prefix.
637 std::map
<std::string
, std::string
> &BIM
=
638 BuiltinMap
[Ints
[i
].TargetPrefix
];
640 if (!BIM
.insert(std::make_pair(BuiltinName
, Ints
[i
].EnumName
)).second
)
641 PrintFatalError(Ints
[i
].TheDef
->getLoc(),
642 "Intrinsic '" + Ints
[i
].TheDef
->getName() +
643 "': duplicate " + CompilerName
+ " builtin name!");
644 Table
.GetOrAddStringOffset(BuiltinName
);
648 OS
<< "// Get the LLVM intrinsic that corresponds to a builtin.\n";
649 OS
<< "// This is used by the C front-end. The builtin name is passed\n";
650 OS
<< "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
651 OS
<< "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
652 OS
<< "#ifdef GET_LLVM_INTRINSIC_FOR_" << UpperCompilerName
<< "_BUILTIN\n";
654 OS
<< "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName
655 << "Builtin(const char "
656 << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n";
659 OS
<< " return Intrinsic::not_intrinsic;\n";
665 OS
<< " static const char BuiltinNames[] = {\n";
666 Table
.EmitCharArray(OS
);
669 OS
<< " struct BuiltinEntry {\n";
670 OS
<< " Intrinsic::ID IntrinID;\n";
671 OS
<< " unsigned StrTabOffset;\n";
672 OS
<< " const char *getName() const {\n";
673 OS
<< " return &BuiltinNames[StrTabOffset];\n";
675 OS
<< " bool operator<(StringRef RHS) const {\n";
676 OS
<< " return strncmp(getName(), RHS.data(), RHS.size()) < 0;\n";
680 OS
<< " StringRef TargetPrefix(TargetPrefixStr);\n\n";
682 // Note: this could emit significantly better code if we cared.
683 for (auto &I
: BuiltinMap
) {
685 if (!I
.first
.empty())
686 OS
<< "if (TargetPrefix == \"" << I
.first
<< "\") ";
688 OS
<< "/* Target Independent Builtins */ ";
691 // Emit the comparisons for this target prefix.
692 OS
<< " static const BuiltinEntry " << I
.first
<< "Names[] = {\n";
693 for (const auto &P
: I
.second
) {
694 OS
<< " {Intrinsic::" << P
.second
<< ", "
695 << Table
.GetOrAddStringOffset(P
.first
) << "}, // " << P
.first
<< "\n";
698 OS
<< " auto I = std::lower_bound(std::begin(" << I
.first
<< "Names),\n";
699 OS
<< " std::end(" << I
.first
<< "Names),\n";
700 OS
<< " BuiltinNameStr);\n";
701 OS
<< " if (I != std::end(" << I
.first
<< "Names) &&\n";
702 OS
<< " I->getName() == BuiltinNameStr)\n";
703 OS
<< " return I->IntrinID;\n";
707 OS
<< "Intrinsic::not_intrinsic;\n";
712 static void EmitIntrinsicEnums(RecordKeeper
&RK
, raw_ostream
&OS
) {
713 IntrinsicEmitter(RK
).run(OS
, /*Enums=*/true);
716 static TableGen::Emitter::Opt
X("gen-intrinsic-enums", EmitIntrinsicEnums
,
717 "Generate intrinsic enums");
719 static void EmitIntrinsicImpl(RecordKeeper
&RK
, raw_ostream
&OS
) {
720 IntrinsicEmitter(RK
).run(OS
, /*Enums=*/false);
723 static TableGen::Emitter::Opt
Y("gen-intrinsic-impl", EmitIntrinsicImpl
,
724 "Generate intrinsic information");