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/ArrayRef.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/ADT/Twine.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/ModRef.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/TableGen/Error.h"
26 #include "llvm/TableGen/Record.h"
27 #include "llvm/TableGen/StringToOffsetTable.h"
28 #include "llvm/TableGen/TableGenBackend.h"
39 cl::OptionCategory
GenIntrinsicCat("Options for -gen-intrinsic-enums");
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 RecordKeeper
&Records
;
50 IntrinsicEmitter(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
, bool IsClang
,
67 } // End anonymous namespace
69 //===----------------------------------------------------------------------===//
70 // IntrinsicEmitter Implementation
71 //===----------------------------------------------------------------------===//
73 void IntrinsicEmitter::run(raw_ostream
&OS
, bool Enums
) {
74 emitSourceFileHeader("Intrinsic Function Source Fragment", OS
);
76 CodeGenIntrinsicTable
Ints(Records
);
79 // Emit the enum information.
80 EmitEnumInfo(Ints
, OS
);
82 // Emit ArgKind for Intrinsics.h.
85 // Emit IIT_Info constants.
88 // Emit the target metadata.
89 EmitTargetInfo(Ints
, OS
);
91 // Emit the intrinsic ID -> name table.
92 EmitIntrinsicToNameTable(Ints
, OS
);
94 // Emit the intrinsic ID -> overload table.
95 EmitIntrinsicToOverloadTable(Ints
, OS
);
97 // Emit the intrinsic declaration generator.
98 EmitGenerator(Ints
, OS
);
100 // Emit the intrinsic parameter attributes.
101 EmitAttributes(Ints
, OS
);
103 // Emit code to translate GCC builtins into LLVM intrinsics.
104 EmitIntrinsicToBuiltinMap(Ints
, true, OS
);
106 // Emit code to translate MS builtins into LLVM intrinsics.
107 EmitIntrinsicToBuiltinMap(Ints
, false, OS
);
111 void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable
&Ints
,
113 // Find the TargetSet for which to generate enums. There will be an initial
114 // set with an empty target prefix which will include target independent
115 // intrinsics like dbg.value.
116 const CodeGenIntrinsicTable::TargetSet
*Set
= nullptr;
117 for (const auto &Target
: Ints
.Targets
) {
118 if (Target
.Name
== IntrinsicPrefix
) {
124 std::vector
<std::string
> KnownTargets
;
125 for (const auto &Target
: Ints
.Targets
)
126 if (!Target
.Name
.empty())
127 KnownTargets
.push_back(Target
.Name
);
128 PrintFatalError("tried to generate intrinsics for unknown target " +
130 "\nKnown targets are: " + join(KnownTargets
, ", ") + "\n");
133 // Generate a complete header for target specific intrinsics.
134 if (IntrinsicPrefix
.empty()) {
135 OS
<< "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
137 std::string UpperPrefix
= StringRef(IntrinsicPrefix
).upper();
138 OS
<< "#ifndef LLVM_IR_INTRINSIC_" << UpperPrefix
<< "_ENUMS_H\n";
139 OS
<< "#define LLVM_IR_INTRINSIC_" << UpperPrefix
<< "_ENUMS_H\n\n";
140 OS
<< "namespace llvm {\n";
141 OS
<< "namespace Intrinsic {\n";
142 OS
<< "enum " << UpperPrefix
<< "Intrinsics : unsigned {\n";
145 OS
<< "// Enum values for intrinsics\n";
146 for (unsigned i
= Set
->Offset
, e
= Set
->Offset
+ Set
->Count
; i
!= e
; ++i
) {
147 OS
<< " " << Ints
[i
].EnumName
;
149 // Assign a value to the first intrinsic in this target set so that all
150 // intrinsic ids are distinct.
151 if (i
== Set
->Offset
)
152 OS
<< " = " << (Set
->Offset
+ 1);
155 if (Ints
[i
].EnumName
.size() < 40)
156 OS
.indent(40 - Ints
[i
].EnumName
.size());
157 OS
<< " // " << Ints
[i
].Name
<< "\n";
160 // Emit num_intrinsics into the target neutral enum.
161 if (IntrinsicPrefix
.empty()) {
162 OS
<< " num_intrinsics = " << (Ints
.size() + 1) << "\n";
165 OS
<< "}; // enum\n";
166 OS
<< "} // namespace Intrinsic\n";
167 OS
<< "} // namespace llvm\n\n";
172 void IntrinsicEmitter::EmitArgKind(raw_ostream
&OS
) {
173 if (!IntrinsicPrefix
.empty())
175 OS
<< "// llvm::Intrinsic::IITDescriptor::ArgKind\n";
176 OS
<< "#ifdef GET_INTRINSIC_ARGKIND\n";
177 if (auto RecArgKind
= Records
.getDef("ArgKind")) {
178 for (auto &RV
: RecArgKind
->getValues())
179 OS
<< " AK_" << RV
.getName() << " = " << *RV
.getValue() << ",\n";
181 OS
<< "#error \"ArgKind is not defined\"\n";
186 void IntrinsicEmitter::EmitIITInfo(raw_ostream
&OS
) {
187 OS
<< "#ifdef GET_INTRINSIC_IITINFO\n";
188 std::array
<StringRef
, 256> RecsByNumber
;
189 auto IIT_Base
= Records
.getAllDerivedDefinitionsIfDefined("IIT_Base");
190 for (auto Rec
: IIT_Base
) {
191 auto Number
= Rec
->getValueAsInt("Number");
192 assert(0 <= Number
&& Number
< (int)RecsByNumber
.size() &&
193 "IIT_Info.Number should be uint8_t");
194 assert(RecsByNumber
[Number
].empty() && "Duplicate IIT_Info.Number");
195 RecsByNumber
[Number
] = Rec
->getName();
197 if (IIT_Base
.size() > 0) {
198 for (unsigned I
= 0, E
= RecsByNumber
.size(); I
< E
; ++I
)
199 if (!RecsByNumber
[I
].empty())
200 OS
<< " " << RecsByNumber
[I
] << " = " << I
<< ",\n";
202 OS
<< "#error \"class IIT_Base is not defined\"\n";
207 void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable
&Ints
,
209 OS
<< "// Target mapping\n";
210 OS
<< "#ifdef GET_INTRINSIC_TARGET_DATA\n";
211 OS
<< "struct IntrinsicTargetInfo {\n"
212 << " llvm::StringLiteral Name;\n"
213 << " size_t Offset;\n"
214 << " size_t Count;\n"
216 OS
<< "static constexpr IntrinsicTargetInfo TargetInfos[] = {\n";
217 for (const auto &Target
: Ints
.Targets
)
218 OS
<< " {llvm::StringLiteral(\"" << Target
.Name
<< "\"), " << Target
.Offset
219 << ", " << Target
.Count
<< "},\n";
224 void IntrinsicEmitter::EmitIntrinsicToNameTable(
225 const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
) {
226 OS
<< "// Intrinsic ID to name table\n";
227 OS
<< "#ifdef GET_INTRINSIC_NAME_TABLE\n";
228 OS
<< " // Note that entry #0 is the invalid intrinsic!\n";
229 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
)
230 OS
<< " \"" << Ints
[i
].Name
<< "\",\n";
234 void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
235 const CodeGenIntrinsicTable
&Ints
, raw_ostream
&OS
) {
236 OS
<< "// Intrinsic ID to overload bitset\n";
237 OS
<< "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
238 OS
<< "static const uint8_t OTable[] = {\n";
240 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
241 // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
244 if (Ints
[i
].isOverloaded
)
245 OS
<< " | (1<<" << (i
+1)%8 << ')';
248 // OTable contains a true bit at the position if the intrinsic is overloaded.
249 OS
<< "return (OTable[id/8] & (1 << (id%8))) != 0;\n";
253 /// ComputeFixedEncoding - If we can encode the type signature for this
254 /// intrinsic into 32 bits, return it. If not, return ~0U.
255 static void ComputeFixedEncoding(const CodeGenIntrinsic
&Int
,
256 std::vector
<unsigned char> &TypeSig
) {
257 if (auto *R
= Int
.TheDef
->getValue("TypeSig")) {
258 for (auto &a
: cast
<ListInit
>(R
->getValue())->getValues()) {
259 for (auto &b
: cast
<ListInit
>(a
)->getValues())
260 TypeSig
.push_back(cast
<IntInit
>(b
)->getValue());
265 static void printIITEntry(raw_ostream
&OS
, unsigned char X
) {
269 void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable
&Ints
,
271 // If we can compute a 32-bit fixed encoding for this intrinsic, do so and
272 // capture it in this vector, otherwise store a ~0U.
273 std::vector
<unsigned> FixedEncodings
;
275 SequenceToOffsetTable
<std::vector
<unsigned char> > LongEncodingTable
;
277 std::vector
<unsigned char> TypeSig
;
279 // Compute the unique argument type info.
280 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
281 // Get the signature for the intrinsic.
283 ComputeFixedEncoding(Ints
[i
], TypeSig
);
285 // Check to see if we can encode it into a 32-bit word. We can only encode
286 // 8 nibbles into a 32-bit word.
287 if (TypeSig
.size() <= 8) {
290 for (unsigned i
= 0, e
= TypeSig
.size(); i
!= e
; ++i
) {
291 // If we had an unencodable argument, bail out.
292 if (TypeSig
[i
] > 15) {
296 Result
= (Result
<< 4) | TypeSig
[e
-i
-1];
299 // If this could be encoded into a 31-bit word, return it.
300 if (!Failed
&& (Result
>> 31) == 0) {
301 FixedEncodings
.push_back(Result
);
306 // Otherwise, we're going to unique the sequence into the
307 // LongEncodingTable, and use its offset in the 32-bit table instead.
308 LongEncodingTable
.add(TypeSig
);
310 // This is a placehold that we'll replace after the table is laid out.
311 FixedEncodings
.push_back(~0U);
314 LongEncodingTable
.layout();
316 OS
<< "// Global intrinsic function declaration type table.\n";
317 OS
<< "#ifdef GET_INTRINSIC_GENERATOR_GLOBAL\n";
319 OS
<< "static const unsigned IIT_Table[] = {\n ";
321 for (unsigned i
= 0, e
= FixedEncodings
.size(); i
!= e
; ++i
) {
325 // If the entry fit in the table, just emit it.
326 if (FixedEncodings
[i
] != ~0U) {
327 OS
<< "0x" << Twine::utohexstr(FixedEncodings
[i
]) << ", ";
332 ComputeFixedEncoding(Ints
[i
], TypeSig
);
335 // Otherwise, emit the offset into the long encoding table. We emit it this
336 // way so that it is easier to read the offset in the .def file.
337 OS
<< "(1U<<31) | " << LongEncodingTable
.get(TypeSig
) << ", ";
342 // Emit the shared table of register lists.
343 OS
<< "static const unsigned char IIT_LongEncodingTable[] = {\n";
344 if (!LongEncodingTable
.empty())
345 LongEncodingTable
.emit(OS
, printIITEntry
);
346 OS
<< " 255\n};\n\n";
348 OS
<< "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
352 std::optional
<bool> compareFnAttributes(const CodeGenIntrinsic
*L
,
353 const CodeGenIntrinsic
*R
) {
354 // Sort throwing intrinsics after non-throwing intrinsics.
355 if (L
->canThrow
!= R
->canThrow
)
358 if (L
->isNoDuplicate
!= R
->isNoDuplicate
)
359 return R
->isNoDuplicate
;
361 if (L
->isNoMerge
!= R
->isNoMerge
)
364 if (L
->isNoReturn
!= R
->isNoReturn
)
365 return R
->isNoReturn
;
367 if (L
->isNoCallback
!= R
->isNoCallback
)
368 return R
->isNoCallback
;
370 if (L
->isNoSync
!= R
->isNoSync
)
373 if (L
->isNoFree
!= R
->isNoFree
)
376 if (L
->isWillReturn
!= R
->isWillReturn
)
377 return R
->isWillReturn
;
379 if (L
->isCold
!= R
->isCold
)
382 if (L
->isConvergent
!= R
->isConvergent
)
383 return R
->isConvergent
;
385 if (L
->isSpeculatable
!= R
->isSpeculatable
)
386 return R
->isSpeculatable
;
388 if (L
->hasSideEffects
!= R
->hasSideEffects
)
389 return R
->hasSideEffects
;
391 if (L
->isStrictFP
!= R
->isStrictFP
)
392 return R
->isStrictFP
;
394 // Try to order by readonly/readnone attribute.
395 uint32_t LK
= L
->ME
.toIntValue();
396 uint32_t RK
= R
->ME
.toIntValue();
397 if (LK
!= RK
) return (LK
> RK
);
402 struct FnAttributeComparator
{
403 bool operator()(const CodeGenIntrinsic
*L
, const CodeGenIntrinsic
*R
) const {
404 return compareFnAttributes(L
, R
).value_or(false);
408 struct AttributeComparator
{
409 bool operator()(const CodeGenIntrinsic
*L
, const CodeGenIntrinsic
*R
) const {
410 if (std::optional
<bool> Res
= compareFnAttributes(L
, R
))
413 // Order by argument attributes.
414 // This is reliable because each side is already sorted internally.
415 return (L
->ArgumentAttributes
< R
->ArgumentAttributes
);
418 } // End anonymous namespace
420 /// EmitAttributes - This emits the Intrinsic::getAttributes method.
421 void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable
&Ints
,
423 OS
<< "// Add parameter attributes that are not common to all intrinsics.\n";
424 OS
<< "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
426 // Compute unique argument attribute sets.
427 std::map
<SmallVector
<CodeGenIntrinsic::ArgAttribute
, 0>, unsigned>
429 OS
<< "static AttributeSet getIntrinsicArgAttributeSet("
430 << "LLVMContext &C, unsigned ID) {\n"
431 << " switch (ID) {\n"
432 << " default: llvm_unreachable(\"Invalid attribute set number\");\n";
433 for (const CodeGenIntrinsic
&Int
: Ints
) {
434 for (auto &Attrs
: Int
.ArgumentAttributes
) {
438 unsigned ID
= UniqArgAttributes
.size();
439 if (!UniqArgAttributes
.try_emplace(Attrs
, ID
).second
)
442 assert(is_sorted(Attrs
) &&
443 "Argument attributes are not sorted");
445 OS
<< " case " << ID
<< ":\n";
446 OS
<< " return AttributeSet::get(C, {\n";
447 for (const CodeGenIntrinsic::ArgAttribute
&Attr
: Attrs
) {
449 case CodeGenIntrinsic::NoCapture
:
450 OS
<< " Attribute::get(C, Attribute::NoCapture),\n";
452 case CodeGenIntrinsic::NoAlias
:
453 OS
<< " Attribute::get(C, Attribute::NoAlias),\n";
455 case CodeGenIntrinsic::NoUndef
:
456 OS
<< " Attribute::get(C, Attribute::NoUndef),\n";
458 case CodeGenIntrinsic::NonNull
:
459 OS
<< " Attribute::get(C, Attribute::NonNull),\n";
461 case CodeGenIntrinsic::Returned
:
462 OS
<< " Attribute::get(C, Attribute::Returned),\n";
464 case CodeGenIntrinsic::ReadOnly
:
465 OS
<< " Attribute::get(C, Attribute::ReadOnly),\n";
467 case CodeGenIntrinsic::WriteOnly
:
468 OS
<< " Attribute::get(C, Attribute::WriteOnly),\n";
470 case CodeGenIntrinsic::ReadNone
:
471 OS
<< " Attribute::get(C, Attribute::ReadNone),\n";
473 case CodeGenIntrinsic::ImmArg
:
474 OS
<< " Attribute::get(C, Attribute::ImmArg),\n";
476 case CodeGenIntrinsic::Alignment
:
477 OS
<< " Attribute::get(C, Attribute::Alignment, "
478 << Attr
.Value
<< "),\n";
480 case CodeGenIntrinsic::Dereferenceable
:
481 OS
<< " Attribute::get(C, Attribute::Dereferenceable, "
482 << Attr
.Value
<< "),\n";
492 // Compute unique function attribute sets.
493 std::map
<const CodeGenIntrinsic
*, unsigned, FnAttributeComparator
>
495 OS
<< "static AttributeSet getIntrinsicFnAttributeSet("
496 << "LLVMContext &C, unsigned ID) {\n"
497 << " switch (ID) {\n"
498 << " default: llvm_unreachable(\"Invalid attribute set number\");\n";
499 for (const CodeGenIntrinsic
&Intrinsic
: Ints
) {
500 unsigned ID
= UniqFnAttributes
.size();
501 if (!UniqFnAttributes
.try_emplace(&Intrinsic
, ID
).second
)
504 OS
<< " case " << ID
<< ":\n"
505 << " return AttributeSet::get(C, {\n";
506 if (!Intrinsic
.canThrow
)
507 OS
<< " Attribute::get(C, Attribute::NoUnwind),\n";
508 if (Intrinsic
.isNoReturn
)
509 OS
<< " Attribute::get(C, Attribute::NoReturn),\n";
510 if (Intrinsic
.isNoCallback
)
511 OS
<< " Attribute::get(C, Attribute::NoCallback),\n";
512 if (Intrinsic
.isNoSync
)
513 OS
<< " Attribute::get(C, Attribute::NoSync),\n";
514 if (Intrinsic
.isNoFree
)
515 OS
<< " Attribute::get(C, Attribute::NoFree),\n";
516 if (Intrinsic
.isWillReturn
)
517 OS
<< " Attribute::get(C, Attribute::WillReturn),\n";
518 if (Intrinsic
.isCold
)
519 OS
<< " Attribute::get(C, Attribute::Cold),\n";
520 if (Intrinsic
.isNoDuplicate
)
521 OS
<< " Attribute::get(C, Attribute::NoDuplicate),\n";
522 if (Intrinsic
.isNoMerge
)
523 OS
<< " Attribute::get(C, Attribute::NoMerge),\n";
524 if (Intrinsic
.isConvergent
)
525 OS
<< " Attribute::get(C, Attribute::Convergent),\n";
526 if (Intrinsic
.isSpeculatable
)
527 OS
<< " Attribute::get(C, Attribute::Speculatable),\n";
528 if (Intrinsic
.isStrictFP
)
529 OS
<< " Attribute::get(C, Attribute::StrictFP),\n";
531 MemoryEffects ME
= Intrinsic
.ME
;
532 // TODO: IntrHasSideEffects should affect not only readnone intrinsics.
533 if (ME
.doesNotAccessMemory() && Intrinsic
.hasSideEffects
)
534 ME
= MemoryEffects::unknown();
535 if (ME
!= MemoryEffects::unknown()) {
536 OS
<< " Attribute::getWithMemoryEffects(C, "
537 << "MemoryEffects::createFromIntValue(" << ME
.toIntValue() << ")),\n";
543 OS
<< "AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {\n";
545 // Compute the maximum number of attribute arguments and the map
546 typedef std::map
<const CodeGenIntrinsic
*, unsigned,
547 AttributeComparator
> UniqAttrMapTy
;
548 UniqAttrMapTy UniqAttributes
;
549 unsigned maxArgAttrs
= 0;
550 unsigned AttrNum
= 0;
551 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
552 const CodeGenIntrinsic
&intrinsic
= Ints
[i
];
554 std::max(maxArgAttrs
, unsigned(intrinsic
.ArgumentAttributes
.size()));
555 unsigned &N
= UniqAttributes
[&intrinsic
];
558 assert(N
< 65536 && "Too many unique attributes for table!");
561 // Emit an array of AttributeList. Most intrinsics will have at least one
562 // entry, for the function itself (index ~1), which is usually nounwind.
563 OS
<< " static const uint16_t IntrinsicsToAttributesMap[] = {\n";
565 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
566 const CodeGenIntrinsic
&intrinsic
= Ints
[i
];
568 OS
<< " " << UniqAttributes
[&intrinsic
] << ", // "
569 << intrinsic
.Name
<< "\n";
573 OS
<< " std::pair<unsigned, AttributeSet> AS[" << maxArgAttrs
+ 1 << "];\n";
574 OS
<< " unsigned NumAttrs = 0;\n";
575 OS
<< " if (id != 0) {\n";
576 OS
<< " switch(IntrinsicsToAttributesMap[id - 1]) {\n";
577 OS
<< " default: llvm_unreachable(\"Invalid attribute number\");\n";
578 for (auto UniqAttribute
: UniqAttributes
) {
579 OS
<< " case " << UniqAttribute
.second
<< ": {\n";
581 const CodeGenIntrinsic
&Intrinsic
= *(UniqAttribute
.first
);
583 // Keep track of the number of attributes we're writing out.
584 unsigned numAttrs
= 0;
586 for (const auto &[AttrIdx
, Attrs
] :
587 enumerate(Intrinsic
.ArgumentAttributes
)) {
591 unsigned ID
= UniqArgAttributes
.find(Attrs
)->second
;
592 OS
<< " AS[" << numAttrs
++ << "] = {" << AttrIdx
593 << ", getIntrinsicArgAttributeSet(C, " << ID
<< ")};\n";
596 if (!Intrinsic
.canThrow
||
597 (Intrinsic
.ME
!= MemoryEffects::unknown() &&
598 !Intrinsic
.hasSideEffects
) ||
599 Intrinsic
.isNoReturn
|| Intrinsic
.isNoCallback
|| Intrinsic
.isNoSync
||
600 Intrinsic
.isNoFree
|| Intrinsic
.isWillReturn
|| Intrinsic
.isCold
||
601 Intrinsic
.isNoDuplicate
|| Intrinsic
.isNoMerge
||
602 Intrinsic
.isConvergent
|| Intrinsic
.isSpeculatable
||
603 Intrinsic
.isStrictFP
) {
604 unsigned ID
= UniqFnAttributes
.find(&Intrinsic
)->second
;
605 OS
<< " AS[" << numAttrs
++ << "] = {AttributeList::FunctionIndex, "
606 << "getIntrinsicFnAttributeSet(C, " << ID
<< ")};\n";
610 OS
<< " NumAttrs = " << numAttrs
<< ";\n";
614 OS
<< " return AttributeList();\n";
621 OS
<< " return AttributeList::get(C, ArrayRef(AS, NumAttrs));\n";
623 OS
<< "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
626 void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
627 const CodeGenIntrinsicTable
&Ints
, bool IsClang
, raw_ostream
&OS
) {
628 StringRef CompilerName
= (IsClang
? "Clang" : "MS");
629 StringRef UpperCompilerName
= (IsClang
? "CLANG" : "MS");
630 typedef std::map
<std::string
, std::map
<std::string
, std::string
>> BIMTy
;
632 StringToOffsetTable Table
;
633 for (unsigned i
= 0, e
= Ints
.size(); i
!= e
; ++i
) {
634 const std::string
&BuiltinName
=
635 IsClang
? Ints
[i
].ClangBuiltinName
: Ints
[i
].MSBuiltinName
;
636 if (!BuiltinName
.empty()) {
637 // Get the map for this target prefix.
638 std::map
<std::string
, std::string
> &BIM
=
639 BuiltinMap
[Ints
[i
].TargetPrefix
];
641 if (!BIM
.insert(std::make_pair(BuiltinName
, Ints
[i
].EnumName
)).second
)
642 PrintFatalError(Ints
[i
].TheDef
->getLoc(),
643 "Intrinsic '" + Ints
[i
].TheDef
->getName() +
644 "': duplicate " + CompilerName
+ " builtin name!");
645 Table
.GetOrAddStringOffset(BuiltinName
);
649 OS
<< "// Get the LLVM intrinsic that corresponds to a builtin.\n";
650 OS
<< "// This is used by the C front-end. The builtin name is passed\n";
651 OS
<< "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
652 OS
<< "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
653 OS
<< "#ifdef GET_LLVM_INTRINSIC_FOR_" << UpperCompilerName
<< "_BUILTIN\n";
655 OS
<< "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName
656 << "Builtin(const char "
657 << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n";
660 OS
<< " return Intrinsic::not_intrinsic;\n";
666 OS
<< " static const char BuiltinNames[] = {\n";
667 Table
.EmitCharArray(OS
);
670 OS
<< " struct BuiltinEntry {\n";
671 OS
<< " Intrinsic::ID IntrinID;\n";
672 OS
<< " unsigned StrTabOffset;\n";
673 OS
<< " const char *getName() const {\n";
674 OS
<< " return &BuiltinNames[StrTabOffset];\n";
676 OS
<< " bool operator<(StringRef RHS) const {\n";
677 OS
<< " return strncmp(getName(), RHS.data(), RHS.size()) < 0;\n";
681 OS
<< " StringRef TargetPrefix(TargetPrefixStr);\n\n";
683 // Note: this could emit significantly better code if we cared.
684 for (auto &I
: BuiltinMap
) {
686 if (!I
.first
.empty())
687 OS
<< "if (TargetPrefix == \"" << I
.first
<< "\") ";
689 OS
<< "/* Target Independent Builtins */ ";
692 // Emit the comparisons for this target prefix.
693 OS
<< " static const BuiltinEntry " << I
.first
<< "Names[] = {\n";
694 for (const auto &P
: I
.second
) {
695 OS
<< " {Intrinsic::" << P
.second
<< ", "
696 << Table
.GetOrAddStringOffset(P
.first
) << "}, // " << P
.first
<< "\n";
699 OS
<< " auto I = std::lower_bound(std::begin(" << I
.first
<< "Names),\n";
700 OS
<< " std::end(" << I
.first
<< "Names),\n";
701 OS
<< " BuiltinNameStr);\n";
702 OS
<< " if (I != std::end(" << I
.first
<< "Names) &&\n";
703 OS
<< " I->getName() == BuiltinNameStr)\n";
704 OS
<< " return I->IntrinID;\n";
708 OS
<< "Intrinsic::not_intrinsic;\n";
713 static void EmitIntrinsicEnums(RecordKeeper
&RK
, raw_ostream
&OS
) {
714 IntrinsicEmitter(RK
).run(OS
, /*Enums=*/true);
717 static TableGen::Emitter::Opt
X("gen-intrinsic-enums", EmitIntrinsicEnums
,
718 "Generate intrinsic enums");
720 static void EmitIntrinsicImpl(RecordKeeper
&RK
, raw_ostream
&OS
) {
721 IntrinsicEmitter(RK
).run(OS
, /*Enums=*/false);
724 static TableGen::Emitter::Opt
Y("gen-intrinsic-impl", EmitIntrinsicImpl
,
725 "Generate intrinsic information");