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/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" 28 #include <algorithm> 29 #include <array> 30 #include <cassert> 31 #include <cctype> 32 #include <map> 33 #include <optional> 34 #include <string> 35 #include <utility> 36 #include <vector> 37 using namespace llvm; 38 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)); 44 45 namespace { 46 class IntrinsicEmitter { 47 const RecordKeeper &Records; 48 49 public: 50 IntrinsicEmitter(const RecordKeeper &R) : Records(R) {} 51 52 void run(raw_ostream &OS, bool Enums); 53 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, 59 raw_ostream &OS); 60 void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints, 61 raw_ostream &OS); 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); 66 }; 67 68 // Helper class to use with `TableGen::Emitter::OptClass`. 69 template <bool Enums> class IntrinsicEmitterOpt : public IntrinsicEmitter { 70 public: 71 IntrinsicEmitterOpt(const RecordKeeper &R) : IntrinsicEmitter(R) {} 72 void run(raw_ostream &OS) { IntrinsicEmitter::run(OS, Enums); } 73 }; 74 75 } // End anonymous namespace 76 77 //===----------------------------------------------------------------------===// 78 // IntrinsicEmitter Implementation 79 //===----------------------------------------------------------------------===// 80 81 void IntrinsicEmitter::run(raw_ostream &OS, bool Enums) { 82 emitSourceFileHeader("Intrinsic Function Source Fragment", OS); 83 84 CodeGenIntrinsicTable Ints(Records); 85 86 if (Enums) { 87 // Emit the enum information. 88 EmitEnumInfo(Ints, OS); 89 90 // Emit ArgKind for Intrinsics.h. 91 EmitArgKind(OS); 92 } else { 93 // Emit IIT_Info constants. 94 EmitIITInfo(OS); 95 96 // Emit the target metadata. 97 EmitTargetInfo(Ints, OS); 98 99 // Emit the intrinsic ID -> name table. 100 EmitIntrinsicToNameTable(Ints, OS); 101 102 // Emit the intrinsic ID -> overload table. 103 EmitIntrinsicToOverloadTable(Ints, OS); 104 105 // Emit the intrinsic declaration generator. 106 EmitGenerator(Ints, OS); 107 108 // Emit the intrinsic parameter attributes. 109 EmitAttributes(Ints, OS); 110 111 // Emit code to translate Clang builtins into LLVM intrinsics. 112 EmitIntrinsicToBuiltinMap(Ints, true, OS); 113 114 // Emit code to translate MS builtins into LLVM intrinsics. 115 EmitIntrinsicToBuiltinMap(Ints, false, OS); 116 } 117 } 118 119 void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints, 120 raw_ostream &OS) { 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) { 128 Set = &Target; 129 break; 130 } 131 } 132 if (!Set) { 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; }); 140 OS << '\n'; 141 }); 142 } 143 144 // Generate a complete header for target specific intrinsics. 145 if (IntrinsicPrefix.empty()) { 146 OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n"; 147 } else { 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); 153 } 154 155 OS << "// Enum values for intrinsics.\n"; 156 bool First = true; 157 for (const auto &Int : Ints[*Set]) { 158 OS << " " << Int.EnumName; 159 160 // Assign a value to the first intrinsic in this target set so that all 161 // intrinsic ids are distinct. 162 if (First) { 163 OS << " = " << Set->Offset + 1; 164 First = false; 165 } 166 167 OS << ", "; 168 if (Int.EnumName.size() < 40) 169 OS.indent(40 - Int.EnumName.size()); 170 OS << formatv(" // {}\n", Int.Name); 171 } 172 173 // Emit num_intrinsics into the target neutral enum. 174 if (IntrinsicPrefix.empty()) { 175 OS << formatv(" num_intrinsics = {}\n", Ints.size() + 1); 176 OS << "#endif\n\n"; 177 } else { 178 OS << R"(}; // enum 179 } // namespace llvm::Intrinsic 180 #endif 181 182 )"; 183 } 184 } 185 186 void IntrinsicEmitter::EmitArgKind(raw_ostream &OS) { 187 if (!IntrinsicPrefix.empty()) 188 return; 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"; 194 } else { 195 OS << "#error \"ArgKind is not defined\"\n"; 196 } 197 OS << "#endif\n\n"; 198 } 199 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(); 210 } 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"; 215 } else { 216 OS << "#error \"class IIT_Base is not defined\"\n"; 217 } 218 OS << "#endif\n\n"; 219 } 220 221 void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints, 222 raw_ostream &OS) { 223 OS << R"(// Target mapping. 224 #ifdef GET_INTRINSIC_TARGET_DATA 225 struct IntrinsicTargetInfo { 226 StringLiteral Name; 227 size_t Offset; 228 size_t Count; 229 }; 230 static constexpr IntrinsicTargetInfo TargetInfos[] = { 231 )"; 232 for (const auto [Name, Offset, Count] : Ints.getTargets()) 233 OS << formatv(" {{\"{}\", {}, {}},\n", Name, Offset, Count); 234 OS << R"(}; 235 #endif 236 237 )"; 238 } 239 240 void IntrinsicEmitter::EmitIntrinsicToNameTable( 241 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) { 242 // Built up a table of the intrinsic names. 243 constexpr StringLiteral NotIntrinsic = "not_intrinsic"; 244 StringToOffsetTable Table; 245 Table.GetOrAddStringOffset(NotIntrinsic); 246 for (const auto &Int : Ints) 247 Table.GetOrAddStringOffset(Int.Name); 248 249 OS << R"(// Intrinsic ID to name table. 250 #ifdef GET_INTRINSIC_NAME_TABLE 251 // Note that entry #0 is the invalid intrinsic! 252 253 )"; 254 255 Table.EmitStringTableDef(OS, "IntrinsicNameTable", /*Indent=*/""); 256 257 OS << R"( 258 static constexpr unsigned IntrinsicNameOffsetTable[] = { 259 )"; 260 261 OS << formatv(" {}, // {}\n", Table.GetStringOffset(NotIntrinsic), 262 NotIntrinsic); 263 for (const auto &Int : Ints) 264 OS << formatv(" {}, // {}\n", Table.GetStringOffset(Int.Name), Int.Name); 265 266 OS << R"( 267 }; // IntrinsicNameOffsetTable 268 269 #endif 270 271 )"; 272 } 273 274 void IntrinsicEmitter::EmitIntrinsicToOverloadTable( 275 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) { 276 OS << R"(// Intrinsic ID to overload bitset. 277 #ifdef GET_INTRINSIC_OVERLOAD_TABLE 278 static constexpr uint8_t OTable[] = { 279 0 280 )"; 281 for (auto [I, Int] : enumerate(Ints)) { 282 // Add one to the index so we emit a null bit for the invalid #0 intrinsic. 283 size_t Idx = I + 1; 284 285 if (Idx % 8 == 0) 286 OS << ",\n 0"; 287 if (Int.isOverloaded) 288 OS << " | (1<<" << Idx % 8 << ')'; 289 } 290 OS << "\n};\n\n"; 291 // OTable contains a true bit at the position if the intrinsic is overloaded. 292 OS << "return (OTable[id/8] & (1 << (id%8))) != 0;\n"; 293 OS << "#endif\n\n"; 294 } 295 296 using TypeSigTy = SmallVector<unsigned char>; 297 298 /// Computes type signature of the intrinsic \p Int. 299 static TypeSigTy ComputeTypeSignature(const CodeGenIntrinsic &Int) { 300 TypeSigTy TypeSig; 301 const Record *TypeInfo = Int.TheDef->getValueAsDef("TypeInfo"); 302 const ListInit *TypeList = TypeInfo->getValueAsListInit("TypeSig"); 303 304 for (const auto *TypeListEntry : TypeList->getValues()) 305 TypeSig.emplace_back(cast<IntInit>(TypeListEntry)->getValue()); 306 return TypeSig; 307 } 308 309 // Pack the type signature into 32-bit fixed encoding word. 310 static std::optional<uint32_t> encodePacked(const TypeSigTy &TypeSig) { 311 if (TypeSig.size() > 8) 312 return std::nullopt; 313 314 uint32_t Result = 0; 315 for (unsigned char C : reverse(TypeSig)) { 316 if (C > 15) 317 return std::nullopt; 318 Result = (Result << 4) | C; 319 } 320 return Result; 321 } 322 323 void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints, 324 raw_ostream &OS) { 325 // Note: the code below can be switched to use 32-bit fixed encoding by 326 // flipping the flag below. 327 constexpr bool Use16BitFixedEncoding = true; 328 using FixedEncodingTy = 329 std::conditional_t<Use16BitFixedEncoding, uint16_t, uint32_t>; 330 constexpr unsigned FixedEncodingBits = sizeof(FixedEncodingTy) * CHAR_BIT; 331 // Mask with all bits 1 except the most significant bit. 332 const unsigned Mask = (1U << (FixedEncodingBits - 1)) - 1; 333 const unsigned MSBPostion = FixedEncodingBits - 1; 334 StringRef FixedEncodingTypeName = 335 Use16BitFixedEncoding ? "uint16_t" : "uint32_t"; 336 337 // If we can compute a 16/32-bit fixed encoding for this intrinsic, do so and 338 // capture it in this vector, otherwise store a ~0U. 339 std::vector<FixedEncodingTy> FixedEncodings; 340 SequenceToOffsetTable<TypeSigTy> LongEncodingTable; 341 342 FixedEncodings.reserve(Ints.size()); 343 344 // Compute the unique argument type info. 345 for (const CodeGenIntrinsic &Int : Ints) { 346 // Get the signature for the intrinsic. 347 TypeSigTy TypeSig = ComputeTypeSignature(Int); 348 349 // Check to see if we can encode it into a 16/32 bit word. 350 std::optional<uint32_t> Result = encodePacked(TypeSig); 351 if (Result && (*Result & Mask) == Result) { 352 FixedEncodings.push_back(static_cast<FixedEncodingTy>(*Result)); 353 continue; 354 } 355 356 LongEncodingTable.add(TypeSig); 357 358 // This is a placehold that we'll replace after the table is laid out. 359 FixedEncodings.push_back(static_cast<FixedEncodingTy>(~0U)); 360 } 361 362 LongEncodingTable.layout(); 363 364 OS << formatv(R"(// Global intrinsic function declaration type table. 365 #ifdef GET_INTRINSIC_GENERATOR_GLOBAL 366 static constexpr {} IIT_Table[] = {{ 367 )", 368 FixedEncodingTypeName); 369 370 unsigned MaxOffset = 0; 371 for (auto [Idx, FixedEncoding, Int] : enumerate(FixedEncodings, Ints)) { 372 if ((Idx & 7) == 7) 373 OS << "\n "; 374 375 // If the entry fit in the table, just emit it. 376 if ((FixedEncoding & Mask) == FixedEncoding) { 377 OS << "0x" << Twine::utohexstr(FixedEncoding) << ", "; 378 continue; 379 } 380 381 TypeSigTy TypeSig = ComputeTypeSignature(Int); 382 unsigned Offset = LongEncodingTable.get(TypeSig); 383 MaxOffset = std::max(MaxOffset, Offset); 384 385 // Otherwise, emit the offset into the long encoding table. We emit it this 386 // way so that it is easier to read the offset in the .def file. 387 OS << formatv("(1U<<{}) | {}, ", MSBPostion, Offset); 388 } 389 390 OS << "0\n};\n\n"; 391 392 // verify that all offsets will fit in 16/32 bits. 393 if ((MaxOffset & Mask) != MaxOffset) 394 PrintFatalError("Offset of long encoding table exceeds encoding bits"); 395 396 // Emit the shared table of register lists. 397 OS << "static constexpr unsigned char IIT_LongEncodingTable[] = {\n"; 398 if (!LongEncodingTable.empty()) 399 LongEncodingTable.emit( 400 OS, [](raw_ostream &OS, unsigned char C) { OS << (unsigned)C; }); 401 OS << " 255\n};\n"; 402 OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL 403 } 404 405 /// Returns the effective MemoryEffects for intrinsic \p Int. 406 static MemoryEffects getEffectiveME(const CodeGenIntrinsic &Int) { 407 MemoryEffects ME = Int.ME; 408 // TODO: IntrHasSideEffects should affect not only readnone intrinsics. 409 if (ME.doesNotAccessMemory() && Int.hasSideEffects) 410 ME = MemoryEffects::unknown(); 411 return ME; 412 } 413 414 static bool compareFnAttributes(const CodeGenIntrinsic *L, 415 const CodeGenIntrinsic *R) { 416 auto TieBoolAttributes = [](const CodeGenIntrinsic *I) -> auto { 417 // Sort throwing intrinsics after non-throwing intrinsics. 418 return std::tie(I->canThrow, I->isNoDuplicate, I->isNoMerge, I->isNoReturn, 419 I->isNoCallback, I->isNoSync, I->isNoFree, I->isWillReturn, 420 I->isCold, I->isConvergent, I->isSpeculatable, 421 I->hasSideEffects, I->isStrictFP); 422 }; 423 424 auto TieL = TieBoolAttributes(L); 425 auto TieR = TieBoolAttributes(R); 426 427 if (TieL != TieR) 428 return TieL < TieR; 429 430 // Try to order by readonly/readnone attribute. 431 uint32_t LME = getEffectiveME(*L).toIntValue(); 432 uint32_t RME = getEffectiveME(*R).toIntValue(); 433 if (LME != RME) 434 return LME > RME; 435 436 return false; 437 } 438 439 /// Returns true if \p Int has a non-empty set of function attributes. Note that 440 /// NoUnwind = !canThrow, so we need to negate it's sense to test if the 441 // intrinsic has NoUnwind attribute. 442 static bool hasFnAttributes(const CodeGenIntrinsic &Int) { 443 return !Int.canThrow || Int.isNoReturn || Int.isNoCallback || Int.isNoSync || 444 Int.isNoFree || Int.isWillReturn || Int.isCold || Int.isNoDuplicate || 445 Int.isNoMerge || Int.isConvergent || Int.isSpeculatable || 446 Int.isStrictFP || getEffectiveME(Int) != MemoryEffects::unknown(); 447 } 448 449 namespace { 450 struct FnAttributeComparator { 451 bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { 452 return compareFnAttributes(L, R); 453 } 454 }; 455 456 struct AttributeComparator { 457 bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { 458 // Order all intrinsics with no functiona attributes before all intrinsics 459 // with function attributes. 460 bool HasFnAttrLHS = hasFnAttributes(*L); 461 bool HasFnAttrRHS = hasFnAttributes(*R); 462 463 // Order by argument attributes if function `hasFnAttributes` is equal. 464 // This is reliable because each side is already sorted internally. 465 return std::tie(HasFnAttrLHS, L->ArgumentAttributes) < 466 std::tie(HasFnAttrRHS, R->ArgumentAttributes); 467 } 468 }; 469 } // End anonymous namespace 470 471 /// Returns the name of the IR enum for argument attribute kind \p Kind. 472 static StringRef getArgAttrEnumName(CodeGenIntrinsic::ArgAttrKind Kind) { 473 switch (Kind) { 474 case CodeGenIntrinsic::NoCapture: 475 llvm_unreachable("Handled separately"); 476 case CodeGenIntrinsic::NoAlias: 477 return "NoAlias"; 478 case CodeGenIntrinsic::NoUndef: 479 return "NoUndef"; 480 case CodeGenIntrinsic::NonNull: 481 return "NonNull"; 482 case CodeGenIntrinsic::Returned: 483 return "Returned"; 484 case CodeGenIntrinsic::ReadOnly: 485 return "ReadOnly"; 486 case CodeGenIntrinsic::WriteOnly: 487 return "WriteOnly"; 488 case CodeGenIntrinsic::ReadNone: 489 return "ReadNone"; 490 case CodeGenIntrinsic::ImmArg: 491 return "ImmArg"; 492 case CodeGenIntrinsic::Alignment: 493 return "Alignment"; 494 case CodeGenIntrinsic::Dereferenceable: 495 return "Dereferenceable"; 496 } 497 llvm_unreachable("Unknown CodeGenIntrinsic::ArgAttrKind enum"); 498 } 499 500 /// EmitAttributes - This emits the Intrinsic::getAttributes method. 501 void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, 502 raw_ostream &OS) { 503 OS << R"(// Add parameter attributes that are not common to all intrinsics. 504 #ifdef GET_INTRINSIC_ATTRIBUTES 505 static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) { 506 switch (ID) { 507 default: llvm_unreachable("Invalid attribute set number");)"; 508 // Compute unique argument attribute sets. 509 std::map<SmallVector<CodeGenIntrinsic::ArgAttribute, 0>, unsigned> 510 UniqArgAttributes; 511 for (const CodeGenIntrinsic &Int : Ints) { 512 for (auto &Attrs : Int.ArgumentAttributes) { 513 if (Attrs.empty()) 514 continue; 515 516 unsigned ID = UniqArgAttributes.size(); 517 if (!UniqArgAttributes.try_emplace(Attrs, ID).second) 518 continue; 519 520 assert(is_sorted(Attrs) && "Argument attributes are not sorted"); 521 522 OS << formatv(R"( 523 case {}: 524 return AttributeSet::get(C, {{ 525 )", 526 ID); 527 for (const CodeGenIntrinsic::ArgAttribute &Attr : Attrs) { 528 if (Attr.Kind == CodeGenIntrinsic::NoCapture) { 529 OS << " Attribute::getWithCaptureInfo(C, " 530 "CaptureInfo::none()),\n"; 531 continue; 532 } 533 StringRef AttrName = getArgAttrEnumName(Attr.Kind); 534 if (Attr.Kind == CodeGenIntrinsic::Alignment || 535 Attr.Kind == CodeGenIntrinsic::Dereferenceable) 536 OS << formatv(" Attribute::get(C, Attribute::{}, {}),\n", 537 AttrName, Attr.Value); 538 else 539 OS << formatv(" Attribute::get(C, Attribute::{}),\n", AttrName); 540 } 541 OS << " });"; 542 } 543 } 544 OS << R"( 545 } 546 } // getIntrinsicArgAttributeSet 547 )"; 548 549 // Compute unique function attribute sets. 550 std::map<const CodeGenIntrinsic *, unsigned, FnAttributeComparator> 551 UniqFnAttributes; 552 OS << R"( 553 static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) { 554 switch (ID) { 555 default: llvm_unreachable("Invalid attribute set number");)"; 556 557 for (const CodeGenIntrinsic &Int : Ints) { 558 if (!hasFnAttributes(Int)) 559 continue; 560 unsigned ID = UniqFnAttributes.size(); 561 if (!UniqFnAttributes.try_emplace(&Int, ID).second) 562 continue; 563 OS << formatv(R"( 564 case {}: 565 return AttributeSet::get(C, {{ 566 )", 567 ID); 568 auto addAttribute = [&OS](StringRef Attr) { 569 OS << formatv(" Attribute::get(C, Attribute::{}),\n", Attr); 570 }; 571 if (!Int.canThrow) 572 addAttribute("NoUnwind"); 573 if (Int.isNoReturn) 574 addAttribute("NoReturn"); 575 if (Int.isNoCallback) 576 addAttribute("NoCallback"); 577 if (Int.isNoSync) 578 addAttribute("NoSync"); 579 if (Int.isNoFree) 580 addAttribute("NoFree"); 581 if (Int.isWillReturn) 582 addAttribute("WillReturn"); 583 if (Int.isCold) 584 addAttribute("Cold"); 585 if (Int.isNoDuplicate) 586 addAttribute("NoDuplicate"); 587 if (Int.isNoMerge) 588 addAttribute("NoMerge"); 589 if (Int.isConvergent) 590 addAttribute("Convergent"); 591 if (Int.isSpeculatable) 592 addAttribute("Speculatable"); 593 if (Int.isStrictFP) 594 addAttribute("StrictFP"); 595 596 const MemoryEffects ME = getEffectiveME(Int); 597 if (ME != MemoryEffects::unknown()) { 598 OS << formatv(" // {}\n", ME); 599 OS << formatv(" Attribute::getWithMemoryEffects(C, " 600 "MemoryEffects::createFromIntValue({})),\n", 601 ME.toIntValue()); 602 } 603 OS << " });"; 604 } 605 OS << R"( 606 } 607 } // getIntrinsicFnAttributeSet 608 609 AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) { 610 )"; 611 612 // Compute the maximum number of attribute arguments and the map. For function 613 // attributes, we only consider whether the intrinsics has any function 614 // arguments or not. 615 std::map<const CodeGenIntrinsic *, unsigned, AttributeComparator> 616 UniqAttributes; 617 for (const CodeGenIntrinsic &Int : Ints) { 618 unsigned ID = UniqAttributes.size(); 619 UniqAttributes.try_emplace(&Int, ID); 620 } 621 622 // Assign a 16-bit packed ID for each intrinsic. The lower 8-bits will be its 623 // "argument attribute ID" (index in UniqAttributes) and upper 8 bits will be 624 // its "function attribute ID" (index in UniqFnAttributes). 625 if (UniqAttributes.size() > 256) 626 PrintFatalError("Too many unique argument attributes for table!"); 627 if (UniqFnAttributes.size() > 256) 628 PrintFatalError("Too many unique function attributes for table!"); 629 630 // Emit an array of AttributeList. Most intrinsics will have at least one 631 // entry, for the function itself (index ~1), which is usually nounwind. 632 OS << " static constexpr uint16_t IntrinsicsToAttributesMap[] = {"; 633 for (const CodeGenIntrinsic &Int : Ints) { 634 uint16_t FnAttrIndex = hasFnAttributes(Int) ? UniqFnAttributes[&Int] : 0; 635 OS << formatv("\n {} << 8 | {}, // {}", FnAttrIndex, 636 UniqAttributes[&Int], Int.Name); 637 } 638 639 OS << formatv(R"( 640 }; 641 if (id == 0) 642 return AttributeList(); 643 644 uint16_t PackedID = IntrinsicsToAttributesMap[id - 1]; 645 uint8_t FnAttrID = PackedID >> 8; 646 switch(PackedID & 0xFF) {{ 647 default: llvm_unreachable("Invalid attribute number"); 648 )"); 649 650 for (const auto [IntPtr, UniqueID] : UniqAttributes) { 651 OS << formatv(" case {}:\n", UniqueID); 652 const CodeGenIntrinsic &Int = *IntPtr; 653 654 // Keep track of the number of attributes we're writing out. 655 unsigned NumAttrs = 656 llvm::count_if(Int.ArgumentAttributes, 657 [](const auto &Attrs) { return !Attrs.empty(); }); 658 NumAttrs += hasFnAttributes(Int); 659 if (NumAttrs == 0) { 660 OS << " return AttributeList();\n"; 661 continue; 662 } 663 664 OS << " return AttributeList::get(C, {\n"; 665 ListSeparator LS(",\n"); 666 for (const auto &[AttrIdx, Attrs] : enumerate(Int.ArgumentAttributes)) { 667 if (Attrs.empty()) 668 continue; 669 670 unsigned ArgAttrID = UniqArgAttributes.find(Attrs)->second; 671 OS << LS 672 << formatv(" {{{}, getIntrinsicArgAttributeSet(C, {})}", AttrIdx, 673 ArgAttrID); 674 } 675 676 if (hasFnAttributes(Int)) { 677 OS << LS 678 << " {AttributeList::FunctionIndex, " 679 "getIntrinsicFnAttributeSet(C, FnAttrID)}"; 680 } 681 OS << "\n });\n"; 682 } 683 684 OS << R"( } 685 } 686 #endif // GET_INTRINSIC_ATTRIBUTES 687 688 )"; 689 } 690 691 void IntrinsicEmitter::EmitIntrinsicToBuiltinMap( 692 const CodeGenIntrinsicTable &Ints, bool IsClang, raw_ostream &OS) { 693 StringRef CompilerName = IsClang ? "Clang" : "MS"; 694 StringRef UpperCompilerName = IsClang ? "CLANG" : "MS"; 695 696 // map<TargetPrefix, pair<map<BuiltinName, EnumName>, CommonPrefix>. 697 // Note that we iterate over both the maps in the code below and both 698 // iterations need to iterate in sorted key order. For the inner map, entries 699 // need to be emitted in the sorted order of `BuiltinName` with `CommonPrefix` 700 // rempved, because we use std::lower_bound to search these entries. For the 701 // outer map as well, entries need to be emitted in sorter order of 702 // `TargetPrefix` as we use std::lower_bound to search these entries. 703 using BIMEntryTy = 704 std::pair<std::map<StringRef, StringRef>, std::optional<StringRef>>; 705 std::map<StringRef, BIMEntryTy> BuiltinMap; 706 707 for (const CodeGenIntrinsic &Int : Ints) { 708 StringRef BuiltinName = IsClang ? Int.ClangBuiltinName : Int.MSBuiltinName; 709 if (BuiltinName.empty()) 710 continue; 711 // Get the map for this target prefix. 712 auto &[Map, CommonPrefix] = BuiltinMap[Int.TargetPrefix]; 713 714 if (!Map.insert({BuiltinName, Int.EnumName}).second) 715 PrintFatalError(Int.TheDef->getLoc(), 716 "Intrinsic '" + Int.TheDef->getName() + "': duplicate " + 717 CompilerName + " builtin name!"); 718 719 // Update common prefix. 720 if (!CommonPrefix) { 721 // For the first builtin for this target, initialize the common prefix. 722 CommonPrefix = BuiltinName; 723 continue; 724 } 725 726 // Update the common prefix. Note that this assumes that `take_front` will 727 // never set the `Data` pointer in CommonPrefix to nullptr. 728 const char *Mismatch = mismatch(*CommonPrefix, BuiltinName).first; 729 *CommonPrefix = CommonPrefix->take_front(Mismatch - CommonPrefix->begin()); 730 } 731 732 // Populate the string table with the names of all the builtins after 733 // removing this common prefix. 734 StringToOffsetTable Table; 735 for (const auto &[TargetPrefix, Entry] : BuiltinMap) { 736 auto &[Map, CommonPrefix] = Entry; 737 for (auto &[BuiltinName, EnumName] : Map) { 738 StringRef Suffix = BuiltinName.substr(CommonPrefix->size()); 739 Table.GetOrAddStringOffset(Suffix); 740 } 741 } 742 743 OS << formatv(R"( 744 // Get the LLVM intrinsic that corresponds to a builtin. This is used by the 745 // C front-end. The builtin name is passed in as BuiltinName, and a target 746 // prefix (e.g. 'ppc') is passed in as TargetPrefix. 747 #ifdef GET_LLVM_INTRINSIC_FOR_{}_BUILTIN 748 Intrinsic::ID 749 Intrinsic::getIntrinsicFor{}Builtin(StringRef TargetPrefix, 750 StringRef BuiltinName) {{ 751 using namespace Intrinsic; 752 )", 753 UpperCompilerName, CompilerName); 754 755 if (BuiltinMap.empty()) { 756 OS << formatv(R"( 757 return not_intrinsic; 758 } 759 #endif // GET_LLVM_INTRINSIC_FOR_{}_BUILTIN 760 )", 761 UpperCompilerName); 762 return; 763 } 764 765 if (!Table.empty()) { 766 Table.EmitStringTableDef(OS, "BuiltinNames"); 767 768 OS << R"( 769 struct BuiltinEntry { 770 ID IntrinsicID; 771 unsigned StrTabOffset; 772 const char *getName() const { return BuiltinNames[StrTabOffset].data(); } 773 bool operator<(StringRef RHS) const { 774 return strncmp(getName(), RHS.data(), RHS.size()) < 0; 775 } 776 }; 777 778 )"; 779 } 780 781 // Emit a per target table of bultin names. 782 bool HasTargetIndependentBuiltins = false; 783 StringRef TargetIndepndentCommonPrefix; 784 for (const auto &[TargetPrefix, Entry] : BuiltinMap) { 785 const auto &[Map, CommonPrefix] = Entry; 786 if (!TargetPrefix.empty()) { 787 OS << formatv(" // Builtins for {0}.\n", TargetPrefix); 788 } else { 789 OS << " // Target independent builtins.\n"; 790 HasTargetIndependentBuiltins = true; 791 TargetIndepndentCommonPrefix = *CommonPrefix; 792 } 793 794 // Emit the builtin table for this target prefix. 795 OS << formatv(" static constexpr BuiltinEntry {}Names[] = {{\n", 796 TargetPrefix); 797 for (const auto &[BuiltinName, EnumName] : Map) { 798 StringRef Suffix = BuiltinName.substr(CommonPrefix->size()); 799 OS << formatv(" {{{}, {}}, // {}\n", EnumName, 800 *Table.GetStringOffset(Suffix), BuiltinName); 801 } 802 OS << formatv(" }; // {}Names\n\n", TargetPrefix); 803 } 804 805 // After emitting the builtin tables for all targets, emit a lookup table for 806 // all targets. We will use binary search, similar to the table for builtin 807 // names to lookup into this table. 808 OS << R"( 809 struct TargetEntry { 810 StringLiteral TargetPrefix; 811 ArrayRef<BuiltinEntry> Names; 812 StringLiteral CommonPrefix; 813 bool operator<(StringRef RHS) const { 814 return TargetPrefix < RHS; 815 }; 816 }; 817 static constexpr TargetEntry TargetTable[] = { 818 )"; 819 820 for (const auto &[TargetPrefix, Entry] : BuiltinMap) { 821 const auto &[Map, CommonPrefix] = Entry; 822 if (TargetPrefix.empty()) 823 continue; 824 OS << formatv(R"( {{"{0}", {0}Names, "{1}"},)", TargetPrefix, 825 CommonPrefix) 826 << "\n"; 827 } 828 OS << " };\n"; 829 830 // Now for the actual lookup, first check the target independent table if 831 // we emitted one. 832 if (HasTargetIndependentBuiltins) { 833 OS << formatv(R"( 834 // Check if it's a target independent builtin. 835 // Copy the builtin name so we can use it in consume_front without clobbering 836 // if for the lookup in the target specific table. 837 StringRef Suffix = BuiltinName; 838 if (Suffix.consume_front("{}")) {{ 839 auto II = lower_bound(Names, Suffix); 840 if (II != std::end(Names) && II->getName() == Suffix) 841 return II->IntrinsicID; 842 } 843 )", 844 TargetIndepndentCommonPrefix); 845 } 846 847 // If a target independent builtin was not found, lookup the target specific. 848 OS << formatv(R"( 849 auto TI = lower_bound(TargetTable, TargetPrefix); 850 if (TI == std::end(TargetTable) || TI->TargetPrefix != TargetPrefix) 851 return not_intrinsic; 852 // This is the last use of BuiltinName, so no need to copy before using it in 853 // consume_front. 854 if (!BuiltinName.consume_front(TI->CommonPrefix)) 855 return not_intrinsic; 856 auto II = lower_bound(TI->Names, BuiltinName); 857 if (II == std::end(TI->Names) || II->getName() != BuiltinName) 858 return not_intrinsic; 859 return II->IntrinsicID; 860 } 861 #endif // GET_LLVM_INTRINSIC_FOR_{}_BUILTIN 862 863 )", 864 UpperCompilerName); 865 } 866 867 static TableGen::Emitter::OptClass<IntrinsicEmitterOpt</*Enums=*/true>> 868 X("gen-intrinsic-enums", "Generate intrinsic enums"); 869 870 static TableGen::Emitter::OptClass<IntrinsicEmitterOpt</*Enums=*/false>> 871 Y("gen-intrinsic-impl", "Generate intrinsic implementation code"); 872