1 //===- SveEmitter.cpp - Generate arm_sve.h for use with clang -*- C++ -*-===// 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 is responsible for emitting arm_sve.h, which includes 10 // a declaration and definition of each function specified by the ARM C/C++ 11 // Language Extensions (ACLE). 12 // 13 // For details, visit: 14 // https://developer.arm.com/architectures/system-architectures/software-standards/acle 15 // 16 // Each SVE instruction is implemented in terms of 1 or more functions which 17 // are suffixed with the element type of the input vectors. Functions may be 18 // implemented in terms of generic vector operations such as +, *, -, etc. or 19 // by calling a __builtin_-prefixed function which will be handled by clang's 20 // CodeGen library. 21 // 22 // See also the documentation in include/clang/Basic/arm_sve.td. 23 // 24 //===----------------------------------------------------------------------===// 25 26 #include "llvm/ADT/ArrayRef.h" 27 #include "llvm/ADT/STLExtras.h" 28 #include "llvm/ADT/StringExtras.h" 29 #include "llvm/ADT/StringMap.h" 30 #include "llvm/TableGen/Error.h" 31 #include "llvm/TableGen/Record.h" 32 #include <array> 33 #include <cctype> 34 #include <set> 35 #include <sstream> 36 #include <string> 37 #include <tuple> 38 39 using namespace llvm; 40 41 enum ClassKind { 42 ClassNone, 43 ClassS, // signed/unsigned, e.g., "_s8", "_u8" suffix 44 ClassG, // Overloaded name without type suffix 45 }; 46 47 enum class ACLEKind { SVE, SME }; 48 49 using TypeSpec = std::string; 50 51 namespace { 52 53 class ImmCheck { 54 unsigned Arg; 55 unsigned Kind; 56 unsigned ElementSizeInBits; 57 58 public: 59 ImmCheck(unsigned Arg, unsigned Kind, unsigned ElementSizeInBits = 0) 60 : Arg(Arg), Kind(Kind), ElementSizeInBits(ElementSizeInBits) {} 61 ImmCheck(const ImmCheck &Other) = default; 62 ~ImmCheck() = default; 63 64 unsigned getArg() const { return Arg; } 65 unsigned getKind() const { return Kind; } 66 unsigned getElementSizeInBits() const { return ElementSizeInBits; } 67 }; 68 69 class SVEType { 70 bool Float, Signed, Immediate, Void, Constant, Pointer, BFloat; 71 bool DefaultType, IsScalable, Predicate, PredicatePattern, PrefetchOp, 72 Svcount; 73 unsigned Bitwidth, ElementBitwidth, NumVectors; 74 75 public: 76 SVEType() : SVEType("", 'v') {} 77 78 SVEType(StringRef TS, char CharMod, unsigned NumVectors = 1) 79 : Float(false), Signed(true), Immediate(false), Void(false), 80 Constant(false), Pointer(false), BFloat(false), DefaultType(false), 81 IsScalable(true), Predicate(false), PredicatePattern(false), 82 PrefetchOp(false), Svcount(false), Bitwidth(128), ElementBitwidth(~0U), 83 NumVectors(NumVectors) { 84 if (!TS.empty()) 85 applyTypespec(TS); 86 applyModifier(CharMod); 87 } 88 89 SVEType(const SVEType &Base, unsigned NumV) : SVEType(Base) { 90 NumVectors = NumV; 91 } 92 93 bool isPointer() const { return Pointer; } 94 bool isVoidPointer() const { return Pointer && Void; } 95 bool isSigned() const { return Signed; } 96 bool isImmediate() const { return Immediate; } 97 bool isScalar() const { return NumVectors == 0; } 98 bool isVector() const { return NumVectors > 0; } 99 bool isScalableVector() const { return isVector() && IsScalable; } 100 bool isFixedLengthVector() const { return isVector() && !IsScalable; } 101 bool isChar() const { return ElementBitwidth == 8; } 102 bool isVoid() const { return Void && !Pointer; } 103 bool isDefault() const { return DefaultType; } 104 bool isFloat() const { return Float && !BFloat; } 105 bool isBFloat() const { return BFloat && !Float; } 106 bool isFloatingPoint() const { return Float || BFloat; } 107 bool isInteger() const { 108 return !isFloatingPoint() && !Predicate && !Svcount; 109 } 110 bool isScalarPredicate() const { 111 return !isFloatingPoint() && Predicate && NumVectors == 0; 112 } 113 bool isPredicateVector() const { return Predicate; } 114 bool isPredicatePattern() const { return PredicatePattern; } 115 bool isPrefetchOp() const { return PrefetchOp; } 116 bool isSvcount() const { return Svcount; } 117 bool isConstant() const { return Constant; } 118 unsigned getElementSizeInBits() const { return ElementBitwidth; } 119 unsigned getNumVectors() const { return NumVectors; } 120 121 unsigned getNumElements() const { 122 assert(ElementBitwidth != ~0U); 123 return Bitwidth / ElementBitwidth; 124 } 125 unsigned getSizeInBits() const { 126 return Bitwidth; 127 } 128 129 /// Return the string representation of a type, which is an encoded 130 /// string for passing to the BUILTIN() macro in Builtins.def. 131 std::string builtin_str() const; 132 133 /// Return the C/C++ string representation of a type for use in the 134 /// arm_sve.h header file. 135 std::string str() const; 136 137 private: 138 /// Creates the type based on the typespec string in TS. 139 void applyTypespec(StringRef TS); 140 141 /// Applies a prototype modifier to the type. 142 void applyModifier(char Mod); 143 }; 144 145 class SVEEmitter; 146 147 /// The main grunt class. This represents an instantiation of an intrinsic with 148 /// a particular typespec and prototype. 149 class Intrinsic { 150 /// The unmangled name. 151 std::string Name; 152 153 /// The name of the corresponding LLVM IR intrinsic. 154 std::string LLVMName; 155 156 /// Intrinsic prototype. 157 std::string Proto; 158 159 /// The base type spec for this intrinsic. 160 TypeSpec BaseTypeSpec; 161 162 /// The base class kind. Most intrinsics use ClassS, which has full type 163 /// info for integers (_s32/_u32), or ClassG which is used for overloaded 164 /// intrinsics. 165 ClassKind Class; 166 167 /// The architectural #ifdef guard. 168 std::string SVEGuard, SMEGuard; 169 170 // The merge suffix such as _m, _x or _z. 171 std::string MergeSuffix; 172 173 /// The types of return value [0] and parameters [1..]. 174 std::vector<SVEType> Types; 175 176 /// The "base type", which is VarType('d', BaseTypeSpec). 177 SVEType BaseType; 178 179 uint64_t Flags; 180 181 SmallVector<ImmCheck, 2> ImmChecks; 182 183 public: 184 Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy, 185 StringRef MergeSuffix, uint64_t MemoryElementTy, StringRef LLVMName, 186 uint64_t Flags, ArrayRef<ImmCheck> ImmChecks, TypeSpec BT, 187 ClassKind Class, SVEEmitter &Emitter, StringRef SVEGuard, 188 StringRef SMEGuard); 189 190 ~Intrinsic()=default; 191 192 std::string getName() const { return Name; } 193 std::string getLLVMName() const { return LLVMName; } 194 std::string getProto() const { return Proto; } 195 TypeSpec getBaseTypeSpec() const { return BaseTypeSpec; } 196 SVEType getBaseType() const { return BaseType; } 197 198 StringRef getSVEGuard() const { return SVEGuard; } 199 StringRef getSMEGuard() const { return SMEGuard; } 200 void printGuard(raw_ostream &OS) const { 201 if (!SVEGuard.empty() && SMEGuard.empty()) 202 OS << SVEGuard; 203 else if (SVEGuard.empty() && !SMEGuard.empty()) 204 OS << SMEGuard; 205 else { 206 if (SVEGuard.find(",") != std::string::npos || 207 SVEGuard.find("|") != std::string::npos) 208 OS << "(" << SVEGuard << ")"; 209 else 210 OS << SVEGuard; 211 OS << "|"; 212 if (SMEGuard.find(",") != std::string::npos || 213 SMEGuard.find("|") != std::string::npos) 214 OS << "(" << SMEGuard << ")"; 215 else 216 OS << SMEGuard; 217 } 218 } 219 ClassKind getClassKind() const { return Class; } 220 221 SVEType getReturnType() const { return Types[0]; } 222 ArrayRef<SVEType> getTypes() const { return Types; } 223 SVEType getParamType(unsigned I) const { return Types[I + 1]; } 224 unsigned getNumParams() const { 225 return Proto.size() - (2 * llvm::count(Proto, '.')) - 1; 226 } 227 228 uint64_t getFlags() const { return Flags; } 229 bool isFlagSet(uint64_t Flag) const { return Flags & Flag;} 230 231 ArrayRef<ImmCheck> getImmChecks() const { return ImmChecks; } 232 233 /// Return the type string for a BUILTIN() macro in Builtins.def. 234 std::string getBuiltinTypeStr(); 235 236 /// Return the name, mangled with type information. The name is mangled for 237 /// ClassS, so will add type suffixes such as _u32/_s32. 238 std::string getMangledName() const { return mangleName(ClassS); } 239 240 /// As above, but mangles the LLVM name instead. 241 std::string getMangledLLVMName() const { return mangleLLVMName(); } 242 243 /// Returns true if the intrinsic is overloaded, in that it should also generate 244 /// a short form without the type-specifiers, e.g. 'svld1(..)' instead of 245 /// 'svld1_u32(..)'. 246 static bool isOverloadedIntrinsic(StringRef Name) { 247 auto BrOpen = Name.find('['); 248 auto BrClose = Name.find(']'); 249 return BrOpen != std::string::npos && BrClose != std::string::npos; 250 } 251 252 /// Return true if the intrinsic takes a splat operand. 253 bool hasSplat() const { 254 // These prototype modifiers are described in arm_sve.td. 255 return Proto.find_first_of("ajfrKLR@") != std::string::npos; 256 } 257 258 /// Return the parameter index of the splat operand. 259 unsigned getSplatIdx() const { 260 unsigned I = 1, Param = 0; 261 for (; I < Proto.size(); ++I, ++Param) { 262 if (Proto[I] == 'a' || Proto[I] == 'j' || Proto[I] == 'f' || 263 Proto[I] == 'r' || Proto[I] == 'K' || Proto[I] == 'L' || 264 Proto[I] == 'R' || Proto[I] == '@') 265 break; 266 267 // Multivector modifier can be skipped 268 if (Proto[I] == '.') 269 I += 2; 270 } 271 assert(I != Proto.size() && "Prototype has no splat operand"); 272 return Param; 273 } 274 275 /// Emits the intrinsic declaration to the ostream. 276 void emitIntrinsic(raw_ostream &OS, SVEEmitter &Emitter, ACLEKind Kind) const; 277 278 private: 279 std::string getMergeSuffix() const { return MergeSuffix; } 280 std::string mangleName(ClassKind LocalCK) const; 281 std::string mangleLLVMName() const; 282 std::string replaceTemplatedArgs(std::string Name, TypeSpec TS, 283 std::string Proto) const; 284 }; 285 286 class SVEEmitter { 287 private: 288 // The reinterpret builtins are generated separately because they 289 // need the cross product of all types (121 functions in total), 290 // which is inconvenient to specify in the arm_sve.td file or 291 // generate in CGBuiltin.cpp. 292 struct ReinterpretTypeInfo { 293 SVEType BaseType; 294 const char *Suffix; 295 }; 296 297 static const std::array<ReinterpretTypeInfo, 12> Reinterprets; 298 299 RecordKeeper &Records; 300 llvm::StringMap<uint64_t> EltTypes; 301 llvm::StringMap<uint64_t> MemEltTypes; 302 llvm::StringMap<uint64_t> FlagTypes; 303 llvm::StringMap<uint64_t> MergeTypes; 304 llvm::StringMap<uint64_t> ImmCheckTypes; 305 306 public: 307 SVEEmitter(RecordKeeper &R) : Records(R) { 308 for (auto *RV : Records.getAllDerivedDefinitions("EltType")) 309 EltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value"); 310 for (auto *RV : Records.getAllDerivedDefinitions("MemEltType")) 311 MemEltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value"); 312 for (auto *RV : Records.getAllDerivedDefinitions("FlagType")) 313 FlagTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value"); 314 for (auto *RV : Records.getAllDerivedDefinitions("MergeType")) 315 MergeTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value"); 316 for (auto *RV : Records.getAllDerivedDefinitions("ImmCheckType")) 317 ImmCheckTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value"); 318 } 319 320 /// Returns the enum value for the immcheck type 321 unsigned getEnumValueForImmCheck(StringRef C) const { 322 auto It = ImmCheckTypes.find(C); 323 if (It != ImmCheckTypes.end()) 324 return It->getValue(); 325 llvm_unreachable("Unsupported imm check"); 326 } 327 328 /// Returns the enum value for the flag type 329 uint64_t getEnumValueForFlag(StringRef C) const { 330 auto Res = FlagTypes.find(C); 331 if (Res != FlagTypes.end()) 332 return Res->getValue(); 333 llvm_unreachable("Unsupported flag"); 334 } 335 336 // Returns the SVETypeFlags for a given value and mask. 337 uint64_t encodeFlag(uint64_t V, StringRef MaskName) const { 338 auto It = FlagTypes.find(MaskName); 339 if (It != FlagTypes.end()) { 340 uint64_t Mask = It->getValue(); 341 unsigned Shift = llvm::countr_zero(Mask); 342 assert(Shift < 64 && "Mask value produced an invalid shift value"); 343 return (V << Shift) & Mask; 344 } 345 llvm_unreachable("Unsupported flag"); 346 } 347 348 // Returns the SVETypeFlags for the given element type. 349 uint64_t encodeEltType(StringRef EltName) { 350 auto It = EltTypes.find(EltName); 351 if (It != EltTypes.end()) 352 return encodeFlag(It->getValue(), "EltTypeMask"); 353 llvm_unreachable("Unsupported EltType"); 354 } 355 356 // Returns the SVETypeFlags for the given memory element type. 357 uint64_t encodeMemoryElementType(uint64_t MT) { 358 return encodeFlag(MT, "MemEltTypeMask"); 359 } 360 361 // Returns the SVETypeFlags for the given merge type. 362 uint64_t encodeMergeType(uint64_t MT) { 363 return encodeFlag(MT, "MergeTypeMask"); 364 } 365 366 // Returns the SVETypeFlags for the given splat operand. 367 unsigned encodeSplatOperand(unsigned SplatIdx) { 368 assert(SplatIdx < 7 && "SplatIdx out of encodable range"); 369 return encodeFlag(SplatIdx + 1, "SplatOperandMask"); 370 } 371 372 // Returns the SVETypeFlags value for the given SVEType. 373 uint64_t encodeTypeFlags(const SVEType &T); 374 375 /// Emit arm_sve.h. 376 void createHeader(raw_ostream &o); 377 378 // Emits core intrinsics in both arm_sme.h and arm_sve.h 379 void createCoreHeaderIntrinsics(raw_ostream &o, SVEEmitter &Emitter, 380 ACLEKind Kind); 381 382 /// Emit all the __builtin prototypes and code needed by Sema. 383 void createBuiltins(raw_ostream &o); 384 385 /// Emit all the information needed to map builtin -> LLVM IR intrinsic. 386 void createCodeGenMap(raw_ostream &o); 387 388 /// Emit all the range checks for the immediates. 389 void createRangeChecks(raw_ostream &o); 390 391 /// Create the SVETypeFlags used in CGBuiltins 392 void createTypeFlags(raw_ostream &o); 393 394 /// Emit arm_sme.h. 395 void createSMEHeader(raw_ostream &o); 396 397 /// Emit all the SME __builtin prototypes and code needed by Sema. 398 void createSMEBuiltins(raw_ostream &o); 399 400 /// Emit all the information needed to map builtin -> LLVM IR intrinsic. 401 void createSMECodeGenMap(raw_ostream &o); 402 403 /// Create a table for a builtin's requirement for PSTATE.SM. 404 void createStreamingAttrs(raw_ostream &o, ACLEKind Kind); 405 406 /// Emit all the range checks for the immediates. 407 void createSMERangeChecks(raw_ostream &o); 408 409 /// Create a table for a builtin's requirement for PSTATE.ZA. 410 void createBuiltinZAState(raw_ostream &OS); 411 412 /// Create intrinsic and add it to \p Out 413 void createIntrinsic(Record *R, 414 SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out); 415 }; 416 417 const std::array<SVEEmitter::ReinterpretTypeInfo, 12> SVEEmitter::Reinterprets = 418 {{{SVEType("c", 'd'), "s8"}, 419 {SVEType("Uc", 'd'), "u8"}, 420 {SVEType("s", 'd'), "s16"}, 421 {SVEType("Us", 'd'), "u16"}, 422 {SVEType("i", 'd'), "s32"}, 423 {SVEType("Ui", 'd'), "u32"}, 424 {SVEType("l", 'd'), "s64"}, 425 {SVEType("Ul", 'd'), "u64"}, 426 {SVEType("h", 'd'), "f16"}, 427 {SVEType("b", 'd'), "bf16"}, 428 {SVEType("f", 'd'), "f32"}, 429 {SVEType("d", 'd'), "f64"}}}; 430 431 } // end anonymous namespace 432 433 434 //===----------------------------------------------------------------------===// 435 // Type implementation 436 //===----------------------------------------------------------------------===// 437 438 std::string SVEType::builtin_str() const { 439 std::string S; 440 if (isVoid()) 441 return "v"; 442 443 if (isScalarPredicate()) 444 return "b"; 445 446 if (isSvcount()) 447 return "Qa"; 448 449 if (isVoidPointer()) 450 S += "v"; 451 else if (!isFloatingPoint()) 452 switch (ElementBitwidth) { 453 case 1: S += "b"; break; 454 case 8: S += "c"; break; 455 case 16: S += "s"; break; 456 case 32: S += "i"; break; 457 case 64: S += "Wi"; break; 458 case 128: S += "LLLi"; break; 459 default: llvm_unreachable("Unhandled case!"); 460 } 461 else if (isFloat()) 462 switch (ElementBitwidth) { 463 case 16: S += "h"; break; 464 case 32: S += "f"; break; 465 case 64: S += "d"; break; 466 default: llvm_unreachable("Unhandled case!"); 467 } 468 else if (isBFloat()) { 469 assert(ElementBitwidth == 16 && "Not a valid BFloat."); 470 S += "y"; 471 } 472 473 if (!isFloatingPoint()) { 474 if ((isChar() || isPointer()) && !isVoidPointer()) { 475 // Make chars and typed pointers explicitly signed. 476 if (Signed) 477 S = "S" + S; 478 else if (!Signed) 479 S = "U" + S; 480 } else if (!isVoidPointer() && !Signed) { 481 S = "U" + S; 482 } 483 } 484 485 // Constant indices are "int", but have the "constant expression" modifier. 486 if (isImmediate()) { 487 assert(!isFloat() && "fp immediates are not supported"); 488 S = "I" + S; 489 } 490 491 if (isScalar()) { 492 if (Constant) S += "C"; 493 if (Pointer) S += "*"; 494 return S; 495 } 496 497 if (isFixedLengthVector()) 498 return "V" + utostr(getNumElements() * NumVectors) + S; 499 return "q" + utostr(getNumElements() * NumVectors) + S; 500 } 501 502 std::string SVEType::str() const { 503 if (isPredicatePattern()) 504 return "enum svpattern"; 505 506 if (isPrefetchOp()) 507 return "enum svprfop"; 508 509 std::string S; 510 if (Void) 511 S += "void"; 512 else { 513 if (isScalableVector() || isSvcount()) 514 S += "sv"; 515 if (!Signed && !isFloatingPoint()) 516 S += "u"; 517 518 if (Float) 519 S += "float"; 520 else if (isSvcount()) 521 S += "count"; 522 else if (isScalarPredicate() || isPredicateVector()) 523 S += "bool"; 524 else if (isBFloat()) 525 S += "bfloat"; 526 else 527 S += "int"; 528 529 if (!isScalarPredicate() && !isPredicateVector() && !isSvcount()) 530 S += utostr(ElementBitwidth); 531 if (isFixedLengthVector()) 532 S += "x" + utostr(getNumElements()); 533 if (NumVectors > 1) 534 S += "x" + utostr(NumVectors); 535 if (!isScalarPredicate()) 536 S += "_t"; 537 } 538 539 if (Constant) 540 S += " const"; 541 if (Pointer) 542 S += " *"; 543 544 return S; 545 } 546 547 void SVEType::applyTypespec(StringRef TS) { 548 for (char I : TS) { 549 switch (I) { 550 case 'Q': 551 Svcount = true; 552 break; 553 case 'P': 554 Predicate = true; 555 break; 556 case 'U': 557 Signed = false; 558 break; 559 case 'c': 560 ElementBitwidth = 8; 561 break; 562 case 's': 563 ElementBitwidth = 16; 564 break; 565 case 'i': 566 ElementBitwidth = 32; 567 break; 568 case 'l': 569 ElementBitwidth = 64; 570 break; 571 case 'q': 572 ElementBitwidth = 128; 573 break; 574 case 'h': 575 Float = true; 576 ElementBitwidth = 16; 577 break; 578 case 'f': 579 Float = true; 580 ElementBitwidth = 32; 581 break; 582 case 'd': 583 Float = true; 584 ElementBitwidth = 64; 585 break; 586 case 'b': 587 BFloat = true; 588 Float = false; 589 ElementBitwidth = 16; 590 break; 591 default: 592 llvm_unreachable("Unhandled type code!"); 593 } 594 } 595 assert(ElementBitwidth != ~0U && "Bad element bitwidth!"); 596 } 597 598 void SVEType::applyModifier(char Mod) { 599 switch (Mod) { 600 case 'v': 601 Void = true; 602 break; 603 case 'd': 604 DefaultType = true; 605 break; 606 case 'c': 607 Constant = true; 608 [[fallthrough]]; 609 case 'p': 610 Pointer = true; 611 Bitwidth = ElementBitwidth; 612 NumVectors = 0; 613 break; 614 case 'e': 615 Signed = false; 616 ElementBitwidth /= 2; 617 break; 618 case 'h': 619 ElementBitwidth /= 2; 620 break; 621 case 'q': 622 ElementBitwidth /= 4; 623 break; 624 case 'b': 625 Signed = false; 626 Float = false; 627 BFloat = false; 628 ElementBitwidth /= 4; 629 break; 630 case 'o': 631 ElementBitwidth *= 4; 632 break; 633 case 'P': 634 Signed = true; 635 Float = false; 636 BFloat = false; 637 Predicate = true; 638 Svcount = false; 639 Bitwidth = 16; 640 ElementBitwidth = 1; 641 break; 642 case '{': 643 IsScalable = false; 644 Bitwidth = 128; 645 NumVectors = 1; 646 break; 647 case 's': 648 case 'a': 649 Bitwidth = ElementBitwidth; 650 NumVectors = 0; 651 break; 652 case 'R': 653 ElementBitwidth /= 2; 654 NumVectors = 0; 655 break; 656 case 'r': 657 ElementBitwidth /= 4; 658 NumVectors = 0; 659 break; 660 case '@': 661 Signed = false; 662 Float = false; 663 BFloat = false; 664 ElementBitwidth /= 4; 665 NumVectors = 0; 666 break; 667 case 'K': 668 Signed = true; 669 Float = false; 670 BFloat = false; 671 Bitwidth = ElementBitwidth; 672 NumVectors = 0; 673 break; 674 case 'L': 675 Signed = false; 676 Float = false; 677 BFloat = false; 678 Bitwidth = ElementBitwidth; 679 NumVectors = 0; 680 break; 681 case 'u': 682 Predicate = false; 683 Svcount = false; 684 Signed = false; 685 Float = false; 686 BFloat = false; 687 break; 688 case 'x': 689 Predicate = false; 690 Svcount = false; 691 Signed = true; 692 Float = false; 693 BFloat = false; 694 break; 695 case 'i': 696 Predicate = false; 697 Svcount = false; 698 Float = false; 699 BFloat = false; 700 ElementBitwidth = Bitwidth = 64; 701 NumVectors = 0; 702 Signed = false; 703 Immediate = true; 704 break; 705 case 'I': 706 Predicate = false; 707 Svcount = false; 708 Float = false; 709 BFloat = false; 710 ElementBitwidth = Bitwidth = 32; 711 NumVectors = 0; 712 Signed = true; 713 Immediate = true; 714 PredicatePattern = true; 715 break; 716 case 'J': 717 Predicate = false; 718 Svcount = false; 719 Float = false; 720 BFloat = false; 721 ElementBitwidth = Bitwidth = 32; 722 NumVectors = 0; 723 Signed = true; 724 Immediate = true; 725 PrefetchOp = true; 726 break; 727 case 'k': 728 Predicate = false; 729 Svcount = false; 730 Signed = true; 731 Float = false; 732 BFloat = false; 733 ElementBitwidth = Bitwidth = 32; 734 NumVectors = 0; 735 break; 736 case 'l': 737 Predicate = false; 738 Svcount = false; 739 Signed = true; 740 Float = false; 741 BFloat = false; 742 ElementBitwidth = Bitwidth = 64; 743 NumVectors = 0; 744 break; 745 case 'm': 746 Predicate = false; 747 Svcount = false; 748 Signed = false; 749 Float = false; 750 BFloat = false; 751 ElementBitwidth = Bitwidth = 32; 752 NumVectors = 0; 753 break; 754 case 'n': 755 Predicate = false; 756 Svcount = false; 757 Signed = false; 758 Float = false; 759 BFloat = false; 760 ElementBitwidth = Bitwidth = 64; 761 NumVectors = 0; 762 break; 763 case 'w': 764 ElementBitwidth = 64; 765 break; 766 case 'j': 767 ElementBitwidth = Bitwidth = 64; 768 NumVectors = 0; 769 break; 770 case 'f': 771 Signed = false; 772 ElementBitwidth = Bitwidth = 64; 773 NumVectors = 0; 774 break; 775 case 'g': 776 Signed = false; 777 Float = false; 778 BFloat = false; 779 ElementBitwidth = 64; 780 break; 781 case '[': 782 Signed = false; 783 Float = false; 784 BFloat = false; 785 ElementBitwidth = 8; 786 break; 787 case 't': 788 Signed = true; 789 Float = false; 790 BFloat = false; 791 ElementBitwidth = 32; 792 break; 793 case 'z': 794 Signed = false; 795 Float = false; 796 BFloat = false; 797 ElementBitwidth = 32; 798 break; 799 case 'O': 800 Predicate = false; 801 Svcount = false; 802 Float = true; 803 ElementBitwidth = 16; 804 break; 805 case 'M': 806 Predicate = false; 807 Svcount = false; 808 Float = true; 809 BFloat = false; 810 ElementBitwidth = 32; 811 break; 812 case 'N': 813 Predicate = false; 814 Svcount = false; 815 Float = true; 816 ElementBitwidth = 64; 817 break; 818 case 'Q': 819 Constant = true; 820 Pointer = true; 821 Void = true; 822 NumVectors = 0; 823 break; 824 case 'S': 825 Constant = true; 826 Pointer = true; 827 ElementBitwidth = Bitwidth = 8; 828 NumVectors = 0; 829 Signed = true; 830 break; 831 case 'W': 832 Constant = true; 833 Pointer = true; 834 ElementBitwidth = Bitwidth = 8; 835 NumVectors = 0; 836 Signed = false; 837 break; 838 case 'T': 839 Constant = true; 840 Pointer = true; 841 ElementBitwidth = Bitwidth = 16; 842 NumVectors = 0; 843 Signed = true; 844 break; 845 case 'X': 846 Constant = true; 847 Pointer = true; 848 ElementBitwidth = Bitwidth = 16; 849 NumVectors = 0; 850 Signed = false; 851 break; 852 case 'Y': 853 Constant = true; 854 Pointer = true; 855 ElementBitwidth = Bitwidth = 32; 856 NumVectors = 0; 857 Signed = false; 858 break; 859 case 'U': 860 Constant = true; 861 Pointer = true; 862 ElementBitwidth = Bitwidth = 32; 863 NumVectors = 0; 864 Signed = true; 865 break; 866 case '%': 867 Pointer = true; 868 Void = true; 869 NumVectors = 0; 870 break; 871 case 'A': 872 Pointer = true; 873 ElementBitwidth = Bitwidth = 8; 874 NumVectors = 0; 875 Signed = true; 876 break; 877 case 'B': 878 Pointer = true; 879 ElementBitwidth = Bitwidth = 16; 880 NumVectors = 0; 881 Signed = true; 882 break; 883 case 'C': 884 Pointer = true; 885 ElementBitwidth = Bitwidth = 32; 886 NumVectors = 0; 887 Signed = true; 888 break; 889 case 'D': 890 Pointer = true; 891 ElementBitwidth = Bitwidth = 64; 892 NumVectors = 0; 893 Signed = true; 894 break; 895 case 'E': 896 Pointer = true; 897 ElementBitwidth = Bitwidth = 8; 898 NumVectors = 0; 899 Signed = false; 900 break; 901 case 'F': 902 Pointer = true; 903 ElementBitwidth = Bitwidth = 16; 904 NumVectors = 0; 905 Signed = false; 906 break; 907 case 'G': 908 Pointer = true; 909 ElementBitwidth = Bitwidth = 32; 910 NumVectors = 0; 911 Signed = false; 912 break; 913 case '$': 914 Predicate = false; 915 Svcount = false; 916 Float = false; 917 BFloat = true; 918 ElementBitwidth = 16; 919 break; 920 case '}': 921 Predicate = false; 922 Signed = true; 923 Svcount = true; 924 NumVectors = 0; 925 Float = false; 926 BFloat = false; 927 break; 928 case '.': 929 llvm_unreachable(". is never a type in itself"); 930 break; 931 default: 932 llvm_unreachable("Unhandled character!"); 933 } 934 } 935 936 /// Returns the modifier and number of vectors for the given operand \p Op. 937 std::pair<char, unsigned> getProtoModifier(StringRef Proto, unsigned Op) { 938 for (unsigned P = 0; !Proto.empty(); ++P) { 939 unsigned NumVectors = 1; 940 unsigned CharsToSkip = 1; 941 char Mod = Proto[0]; 942 if (Mod == '2' || Mod == '3' || Mod == '4') { 943 NumVectors = Mod - '0'; 944 Mod = 'd'; 945 if (Proto.size() > 1 && Proto[1] == '.') { 946 Mod = Proto[2]; 947 CharsToSkip = 3; 948 } 949 } 950 951 if (P == Op) 952 return {Mod, NumVectors}; 953 954 Proto = Proto.drop_front(CharsToSkip); 955 } 956 llvm_unreachable("Unexpected Op"); 957 } 958 959 //===----------------------------------------------------------------------===// 960 // Intrinsic implementation 961 //===----------------------------------------------------------------------===// 962 963 Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy, 964 StringRef MergeSuffix, uint64_t MemoryElementTy, 965 StringRef LLVMName, uint64_t Flags, 966 ArrayRef<ImmCheck> Checks, TypeSpec BT, ClassKind Class, 967 SVEEmitter &Emitter, StringRef SVEGuard, 968 StringRef SMEGuard) 969 : Name(Name.str()), LLVMName(LLVMName), Proto(Proto.str()), 970 BaseTypeSpec(BT), Class(Class), SVEGuard(SVEGuard.str()), 971 SMEGuard(SMEGuard.str()), MergeSuffix(MergeSuffix.str()), 972 BaseType(BT, 'd'), Flags(Flags), ImmChecks(Checks.begin(), Checks.end()) { 973 // Types[0] is the return value. 974 for (unsigned I = 0; I < (getNumParams() + 1); ++I) { 975 char Mod; 976 unsigned NumVectors; 977 std::tie(Mod, NumVectors) = getProtoModifier(Proto, I); 978 SVEType T(BaseTypeSpec, Mod, NumVectors); 979 Types.push_back(T); 980 981 // Add range checks for immediates 982 if (I > 0) { 983 if (T.isPredicatePattern()) 984 ImmChecks.emplace_back( 985 I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_31")); 986 else if (T.isPrefetchOp()) 987 ImmChecks.emplace_back( 988 I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_13")); 989 } 990 } 991 992 // Set flags based on properties 993 this->Flags |= Emitter.encodeTypeFlags(BaseType); 994 this->Flags |= Emitter.encodeMemoryElementType(MemoryElementTy); 995 this->Flags |= Emitter.encodeMergeType(MergeTy); 996 if (hasSplat()) 997 this->Flags |= Emitter.encodeSplatOperand(getSplatIdx()); 998 } 999 1000 std::string Intrinsic::getBuiltinTypeStr() { 1001 std::string S = getReturnType().builtin_str(); 1002 for (unsigned I = 0; I < getNumParams(); ++I) 1003 S += getParamType(I).builtin_str(); 1004 1005 return S; 1006 } 1007 1008 std::string Intrinsic::replaceTemplatedArgs(std::string Name, TypeSpec TS, 1009 std::string Proto) const { 1010 std::string Ret = Name; 1011 while (Ret.find('{') != std::string::npos) { 1012 size_t Pos = Ret.find('{'); 1013 size_t End = Ret.find('}'); 1014 unsigned NumChars = End - Pos + 1; 1015 assert(NumChars == 3 && "Unexpected template argument"); 1016 1017 SVEType T; 1018 char C = Ret[Pos+1]; 1019 switch(C) { 1020 default: 1021 llvm_unreachable("Unknown predication specifier"); 1022 case 'd': 1023 T = SVEType(TS, 'd'); 1024 break; 1025 case '0': 1026 case '1': 1027 case '2': 1028 case '3': 1029 T = SVEType(TS, Proto[C - '0']); 1030 break; 1031 } 1032 1033 // Replace templated arg with the right suffix (e.g. u32) 1034 std::string TypeCode; 1035 if (T.isInteger()) 1036 TypeCode = T.isSigned() ? 's' : 'u'; 1037 else if (T.isSvcount()) 1038 TypeCode = 'c'; 1039 else if (T.isPredicateVector()) 1040 TypeCode = 'b'; 1041 else if (T.isBFloat()) 1042 TypeCode = "bf"; 1043 else 1044 TypeCode = 'f'; 1045 Ret.replace(Pos, NumChars, TypeCode + utostr(T.getElementSizeInBits())); 1046 } 1047 1048 return Ret; 1049 } 1050 1051 std::string Intrinsic::mangleLLVMName() const { 1052 std::string S = getLLVMName(); 1053 1054 // Replace all {d} like expressions with e.g. 'u32' 1055 return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto()); 1056 } 1057 1058 std::string Intrinsic::mangleName(ClassKind LocalCK) const { 1059 std::string S = getName(); 1060 1061 if (LocalCK == ClassG) { 1062 // Remove the square brackets and everything in between. 1063 while (S.find('[') != std::string::npos) { 1064 auto Start = S.find('['); 1065 auto End = S.find(']'); 1066 S.erase(Start, (End-Start)+1); 1067 } 1068 } else { 1069 // Remove the square brackets. 1070 while (S.find('[') != std::string::npos) { 1071 auto BrPos = S.find('['); 1072 if (BrPos != std::string::npos) 1073 S.erase(BrPos, 1); 1074 BrPos = S.find(']'); 1075 if (BrPos != std::string::npos) 1076 S.erase(BrPos, 1); 1077 } 1078 } 1079 1080 // Replace all {d} like expressions with e.g. 'u32' 1081 return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto()) + 1082 getMergeSuffix(); 1083 } 1084 1085 void Intrinsic::emitIntrinsic(raw_ostream &OS, SVEEmitter &Emitter, 1086 ACLEKind Kind) const { 1087 bool IsOverloaded = getClassKind() == ClassG && getProto().size() > 1; 1088 1089 std::string FullName = mangleName(ClassS); 1090 std::string ProtoName = mangleName(getClassKind()); 1091 OS << (IsOverloaded ? "__aio " : "__ai ") 1092 << "__attribute__((__clang_arm_builtin_alias("; 1093 1094 switch (Kind) { 1095 case ACLEKind::SME: 1096 OS << "__builtin_sme_" << FullName << ")"; 1097 break; 1098 case ACLEKind::SVE: 1099 OS << "__builtin_sve_" << FullName << ")"; 1100 break; 1101 } 1102 1103 OS << "))\n"; 1104 1105 OS << getTypes()[0].str() << " " << ProtoName << "("; 1106 for (unsigned I = 0; I < getTypes().size() - 1; ++I) { 1107 if (I != 0) 1108 OS << ", "; 1109 OS << getTypes()[I + 1].str(); 1110 } 1111 OS << ");\n"; 1112 } 1113 1114 //===----------------------------------------------------------------------===// 1115 // SVEEmitter implementation 1116 //===----------------------------------------------------------------------===// 1117 uint64_t SVEEmitter::encodeTypeFlags(const SVEType &T) { 1118 if (T.isFloat()) { 1119 switch (T.getElementSizeInBits()) { 1120 case 16: 1121 return encodeEltType("EltTyFloat16"); 1122 case 32: 1123 return encodeEltType("EltTyFloat32"); 1124 case 64: 1125 return encodeEltType("EltTyFloat64"); 1126 default: 1127 llvm_unreachable("Unhandled float element bitwidth!"); 1128 } 1129 } 1130 1131 if (T.isBFloat()) { 1132 assert(T.getElementSizeInBits() == 16 && "Not a valid BFloat."); 1133 return encodeEltType("EltTyBFloat16"); 1134 } 1135 1136 if (T.isPredicateVector() || T.isSvcount()) { 1137 switch (T.getElementSizeInBits()) { 1138 case 8: 1139 return encodeEltType("EltTyBool8"); 1140 case 16: 1141 return encodeEltType("EltTyBool16"); 1142 case 32: 1143 return encodeEltType("EltTyBool32"); 1144 case 64: 1145 return encodeEltType("EltTyBool64"); 1146 default: 1147 llvm_unreachable("Unhandled predicate element bitwidth!"); 1148 } 1149 } 1150 1151 switch (T.getElementSizeInBits()) { 1152 case 8: 1153 return encodeEltType("EltTyInt8"); 1154 case 16: 1155 return encodeEltType("EltTyInt16"); 1156 case 32: 1157 return encodeEltType("EltTyInt32"); 1158 case 64: 1159 return encodeEltType("EltTyInt64"); 1160 case 128: 1161 return encodeEltType("EltTyInt128"); 1162 default: 1163 llvm_unreachable("Unhandled integer element bitwidth!"); 1164 } 1165 } 1166 1167 void SVEEmitter::createIntrinsic( 1168 Record *R, SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out) { 1169 StringRef Name = R->getValueAsString("Name"); 1170 StringRef Proto = R->getValueAsString("Prototype"); 1171 StringRef Types = R->getValueAsString("Types"); 1172 StringRef SVEGuard = R->getValueAsString("SVETargetGuard"); 1173 StringRef SMEGuard = R->getValueAsString("SMETargetGuard"); 1174 StringRef LLVMName = R->getValueAsString("LLVMIntrinsic"); 1175 uint64_t Merge = R->getValueAsInt("Merge"); 1176 StringRef MergeSuffix = R->getValueAsString("MergeSuffix"); 1177 uint64_t MemEltType = R->getValueAsInt("MemEltType"); 1178 std::vector<Record*> FlagsList = R->getValueAsListOfDefs("Flags"); 1179 std::vector<Record*> ImmCheckList = R->getValueAsListOfDefs("ImmChecks"); 1180 1181 int64_t Flags = 0; 1182 for (auto FlagRec : FlagsList) 1183 Flags |= FlagRec->getValueAsInt("Value"); 1184 1185 // Create a dummy TypeSpec for non-overloaded builtins. 1186 if (Types.empty()) { 1187 assert((Flags & getEnumValueForFlag("IsOverloadNone")) && 1188 "Expect TypeSpec for overloaded builtin!"); 1189 Types = "i"; 1190 } 1191 1192 // Extract type specs from string 1193 SmallVector<TypeSpec, 8> TypeSpecs; 1194 TypeSpec Acc; 1195 for (char I : Types) { 1196 Acc.push_back(I); 1197 if (islower(I)) { 1198 TypeSpecs.push_back(TypeSpec(Acc)); 1199 Acc.clear(); 1200 } 1201 } 1202 1203 // Remove duplicate type specs. 1204 llvm::sort(TypeSpecs); 1205 TypeSpecs.erase(std::unique(TypeSpecs.begin(), TypeSpecs.end()), 1206 TypeSpecs.end()); 1207 1208 // Create an Intrinsic for each type spec. 1209 for (auto TS : TypeSpecs) { 1210 // Collate a list of range/option checks for the immediates. 1211 SmallVector<ImmCheck, 2> ImmChecks; 1212 for (auto *R : ImmCheckList) { 1213 int64_t Arg = R->getValueAsInt("Arg"); 1214 int64_t EltSizeArg = R->getValueAsInt("EltSizeArg"); 1215 int64_t Kind = R->getValueAsDef("Kind")->getValueAsInt("Value"); 1216 assert(Arg >= 0 && Kind >= 0 && "Arg and Kind must be nonnegative"); 1217 1218 unsigned ElementSizeInBits = 0; 1219 char Mod; 1220 unsigned NumVectors; 1221 std::tie(Mod, NumVectors) = getProtoModifier(Proto, EltSizeArg + 1); 1222 if (EltSizeArg >= 0) 1223 ElementSizeInBits = SVEType(TS, Mod, NumVectors).getElementSizeInBits(); 1224 ImmChecks.push_back(ImmCheck(Arg, Kind, ElementSizeInBits)); 1225 } 1226 1227 Out.push_back(std::make_unique<Intrinsic>( 1228 Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags, ImmChecks, 1229 TS, ClassS, *this, SVEGuard, SMEGuard)); 1230 1231 // Also generate the short-form (e.g. svadd_m) for the given type-spec. 1232 if (Intrinsic::isOverloadedIntrinsic(Name)) 1233 Out.push_back(std::make_unique<Intrinsic>( 1234 Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags, 1235 ImmChecks, TS, ClassG, *this, SVEGuard, SMEGuard)); 1236 } 1237 } 1238 1239 void SVEEmitter::createCoreHeaderIntrinsics(raw_ostream &OS, 1240 SVEEmitter &Emitter, 1241 ACLEKind Kind) { 1242 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1243 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1244 for (auto *R : RV) 1245 createIntrinsic(R, Defs); 1246 1247 // Sort intrinsics in header file by following order/priority: 1248 // - Architectural guard (i.e. does it require SVE2 or SVE2_AES) 1249 // - Class (is intrinsic overloaded or not) 1250 // - Intrinsic name 1251 std::stable_sort(Defs.begin(), Defs.end(), 1252 [](const std::unique_ptr<Intrinsic> &A, 1253 const std::unique_ptr<Intrinsic> &B) { 1254 auto ToTuple = [](const std::unique_ptr<Intrinsic> &I) { 1255 return std::make_tuple( 1256 I->getSVEGuard().str() + I->getSMEGuard().str(), 1257 (unsigned)I->getClassKind(), I->getName()); 1258 }; 1259 return ToTuple(A) < ToTuple(B); 1260 }); 1261 1262 // Actually emit the intrinsic declarations. 1263 for (auto &I : Defs) 1264 I->emitIntrinsic(OS, Emitter, Kind); 1265 } 1266 1267 void SVEEmitter::createHeader(raw_ostream &OS) { 1268 OS << "/*===---- arm_sve.h - ARM SVE intrinsics " 1269 "-----------------------------------===\n" 1270 " *\n" 1271 " *\n" 1272 " * Part of the LLVM Project, under the Apache License v2.0 with LLVM " 1273 "Exceptions.\n" 1274 " * See https://llvm.org/LICENSE.txt for license information.\n" 1275 " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n" 1276 " *\n" 1277 " *===-----------------------------------------------------------------" 1278 "------===\n" 1279 " */\n\n"; 1280 1281 OS << "#ifndef __ARM_SVE_H\n"; 1282 OS << "#define __ARM_SVE_H\n\n"; 1283 1284 OS << "#if !defined(__LITTLE_ENDIAN__)\n"; 1285 OS << "#error \"Big endian is currently not supported for arm_sve.h\"\n"; 1286 OS << "#endif\n"; 1287 1288 OS << "#include <stdint.h>\n\n"; 1289 OS << "#ifdef __cplusplus\n"; 1290 OS << "extern \"C\" {\n"; 1291 OS << "#else\n"; 1292 OS << "#include <stdbool.h>\n"; 1293 OS << "#endif\n\n"; 1294 1295 OS << "typedef __fp16 float16_t;\n"; 1296 OS << "typedef float float32_t;\n"; 1297 OS << "typedef double float64_t;\n"; 1298 1299 OS << "typedef __SVInt8_t svint8_t;\n"; 1300 OS << "typedef __SVInt16_t svint16_t;\n"; 1301 OS << "typedef __SVInt32_t svint32_t;\n"; 1302 OS << "typedef __SVInt64_t svint64_t;\n"; 1303 OS << "typedef __SVUint8_t svuint8_t;\n"; 1304 OS << "typedef __SVUint16_t svuint16_t;\n"; 1305 OS << "typedef __SVUint32_t svuint32_t;\n"; 1306 OS << "typedef __SVUint64_t svuint64_t;\n"; 1307 OS << "typedef __SVFloat16_t svfloat16_t;\n\n"; 1308 1309 OS << "typedef __SVBfloat16_t svbfloat16_t;\n"; 1310 1311 OS << "#include <arm_bf16.h>\n"; 1312 OS << "#include <arm_vector_types.h>\n"; 1313 1314 OS << "typedef __SVFloat32_t svfloat32_t;\n"; 1315 OS << "typedef __SVFloat64_t svfloat64_t;\n"; 1316 OS << "typedef __clang_svint8x2_t svint8x2_t;\n"; 1317 OS << "typedef __clang_svint16x2_t svint16x2_t;\n"; 1318 OS << "typedef __clang_svint32x2_t svint32x2_t;\n"; 1319 OS << "typedef __clang_svint64x2_t svint64x2_t;\n"; 1320 OS << "typedef __clang_svuint8x2_t svuint8x2_t;\n"; 1321 OS << "typedef __clang_svuint16x2_t svuint16x2_t;\n"; 1322 OS << "typedef __clang_svuint32x2_t svuint32x2_t;\n"; 1323 OS << "typedef __clang_svuint64x2_t svuint64x2_t;\n"; 1324 OS << "typedef __clang_svfloat16x2_t svfloat16x2_t;\n"; 1325 OS << "typedef __clang_svfloat32x2_t svfloat32x2_t;\n"; 1326 OS << "typedef __clang_svfloat64x2_t svfloat64x2_t;\n"; 1327 OS << "typedef __clang_svint8x3_t svint8x3_t;\n"; 1328 OS << "typedef __clang_svint16x3_t svint16x3_t;\n"; 1329 OS << "typedef __clang_svint32x3_t svint32x3_t;\n"; 1330 OS << "typedef __clang_svint64x3_t svint64x3_t;\n"; 1331 OS << "typedef __clang_svuint8x3_t svuint8x3_t;\n"; 1332 OS << "typedef __clang_svuint16x3_t svuint16x3_t;\n"; 1333 OS << "typedef __clang_svuint32x3_t svuint32x3_t;\n"; 1334 OS << "typedef __clang_svuint64x3_t svuint64x3_t;\n"; 1335 OS << "typedef __clang_svfloat16x3_t svfloat16x3_t;\n"; 1336 OS << "typedef __clang_svfloat32x3_t svfloat32x3_t;\n"; 1337 OS << "typedef __clang_svfloat64x3_t svfloat64x3_t;\n"; 1338 OS << "typedef __clang_svint8x4_t svint8x4_t;\n"; 1339 OS << "typedef __clang_svint16x4_t svint16x4_t;\n"; 1340 OS << "typedef __clang_svint32x4_t svint32x4_t;\n"; 1341 OS << "typedef __clang_svint64x4_t svint64x4_t;\n"; 1342 OS << "typedef __clang_svuint8x4_t svuint8x4_t;\n"; 1343 OS << "typedef __clang_svuint16x4_t svuint16x4_t;\n"; 1344 OS << "typedef __clang_svuint32x4_t svuint32x4_t;\n"; 1345 OS << "typedef __clang_svuint64x4_t svuint64x4_t;\n"; 1346 OS << "typedef __clang_svfloat16x4_t svfloat16x4_t;\n"; 1347 OS << "typedef __clang_svfloat32x4_t svfloat32x4_t;\n"; 1348 OS << "typedef __clang_svfloat64x4_t svfloat64x4_t;\n"; 1349 OS << "typedef __SVBool_t svbool_t;\n"; 1350 OS << "typedef __clang_svboolx2_t svboolx2_t;\n"; 1351 OS << "typedef __clang_svboolx4_t svboolx4_t;\n\n"; 1352 1353 OS << "typedef __clang_svbfloat16x2_t svbfloat16x2_t;\n"; 1354 OS << "typedef __clang_svbfloat16x3_t svbfloat16x3_t;\n"; 1355 OS << "typedef __clang_svbfloat16x4_t svbfloat16x4_t;\n"; 1356 1357 OS << "typedef __SVCount_t svcount_t;\n\n"; 1358 1359 OS << "enum svpattern\n"; 1360 OS << "{\n"; 1361 OS << " SV_POW2 = 0,\n"; 1362 OS << " SV_VL1 = 1,\n"; 1363 OS << " SV_VL2 = 2,\n"; 1364 OS << " SV_VL3 = 3,\n"; 1365 OS << " SV_VL4 = 4,\n"; 1366 OS << " SV_VL5 = 5,\n"; 1367 OS << " SV_VL6 = 6,\n"; 1368 OS << " SV_VL7 = 7,\n"; 1369 OS << " SV_VL8 = 8,\n"; 1370 OS << " SV_VL16 = 9,\n"; 1371 OS << " SV_VL32 = 10,\n"; 1372 OS << " SV_VL64 = 11,\n"; 1373 OS << " SV_VL128 = 12,\n"; 1374 OS << " SV_VL256 = 13,\n"; 1375 OS << " SV_MUL4 = 29,\n"; 1376 OS << " SV_MUL3 = 30,\n"; 1377 OS << " SV_ALL = 31\n"; 1378 OS << "};\n\n"; 1379 1380 OS << "enum svprfop\n"; 1381 OS << "{\n"; 1382 OS << " SV_PLDL1KEEP = 0,\n"; 1383 OS << " SV_PLDL1STRM = 1,\n"; 1384 OS << " SV_PLDL2KEEP = 2,\n"; 1385 OS << " SV_PLDL2STRM = 3,\n"; 1386 OS << " SV_PLDL3KEEP = 4,\n"; 1387 OS << " SV_PLDL3STRM = 5,\n"; 1388 OS << " SV_PSTL1KEEP = 8,\n"; 1389 OS << " SV_PSTL1STRM = 9,\n"; 1390 OS << " SV_PSTL2KEEP = 10,\n"; 1391 OS << " SV_PSTL2STRM = 11,\n"; 1392 OS << " SV_PSTL3KEEP = 12,\n"; 1393 OS << " SV_PSTL3STRM = 13\n"; 1394 OS << "};\n\n"; 1395 1396 OS << "/* Function attributes */\n"; 1397 OS << "#define __ai static __inline__ __attribute__((__always_inline__, " 1398 "__nodebug__))\n\n"; 1399 OS << "#define __aio static __inline__ __attribute__((__always_inline__, " 1400 "__nodebug__, __overloadable__))\n\n"; 1401 1402 // Add reinterpret functions. 1403 for (auto [N, Suffix] : 1404 std::initializer_list<std::pair<unsigned, const char *>>{ 1405 {1, ""}, {2, "_x2"}, {3, "_x3"}, {4, "_x4"}}) { 1406 for (auto ShortForm : {false, true}) 1407 for (const ReinterpretTypeInfo &To : Reinterprets) { 1408 SVEType ToV(To.BaseType, N); 1409 for (const ReinterpretTypeInfo &From : Reinterprets) { 1410 SVEType FromV(From.BaseType, N); 1411 OS << "__aio " 1412 "__attribute__((__clang_arm_builtin_alias(__builtin_sve_" 1413 "reinterpret_" 1414 << To.Suffix << "_" << From.Suffix << Suffix << ")))\n" 1415 << ToV.str() << " svreinterpret_" << To.Suffix; 1416 if (!ShortForm) 1417 OS << "_" << From.Suffix << Suffix; 1418 OS << "(" << FromV.str() << " op);\n"; 1419 } 1420 } 1421 } 1422 1423 createCoreHeaderIntrinsics(OS, *this, ACLEKind::SVE); 1424 1425 OS << "#define svcvtnt_bf16_x svcvtnt_bf16_m\n"; 1426 OS << "#define svcvtnt_bf16_f32_x svcvtnt_bf16_f32_m\n"; 1427 1428 OS << "#define svcvtnt_f16_x svcvtnt_f16_m\n"; 1429 OS << "#define svcvtnt_f16_f32_x svcvtnt_f16_f32_m\n"; 1430 OS << "#define svcvtnt_f32_x svcvtnt_f32_m\n"; 1431 OS << "#define svcvtnt_f32_f64_x svcvtnt_f32_f64_m\n\n"; 1432 1433 OS << "#define svcvtxnt_f32_x svcvtxnt_f32_m\n"; 1434 OS << "#define svcvtxnt_f32_f64_x svcvtxnt_f32_f64_m\n\n"; 1435 1436 OS << "#ifdef __cplusplus\n"; 1437 OS << "} // extern \"C\"\n"; 1438 OS << "#endif\n\n"; 1439 OS << "#undef __ai\n\n"; 1440 OS << "#undef __aio\n\n"; 1441 OS << "#endif /* __ARM_SVE_H */\n"; 1442 } 1443 1444 void SVEEmitter::createBuiltins(raw_ostream &OS) { 1445 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1446 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1447 for (auto *R : RV) 1448 createIntrinsic(R, Defs); 1449 1450 // The mappings must be sorted based on BuiltinID. 1451 llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A, 1452 const std::unique_ptr<Intrinsic> &B) { 1453 return A->getMangledName() < B->getMangledName(); 1454 }); 1455 1456 OS << "#ifdef GET_SVE_BUILTINS\n"; 1457 for (auto &Def : Defs) { 1458 // Only create BUILTINs for non-overloaded intrinsics, as overloaded 1459 // declarations only live in the header file. 1460 if (Def->getClassKind() != ClassG) { 1461 OS << "TARGET_BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \"" 1462 << Def->getBuiltinTypeStr() << "\", \"n\", \""; 1463 Def->printGuard(OS); 1464 OS << "\")\n"; 1465 } 1466 } 1467 1468 // Add reinterpret functions. 1469 for (auto [N, Suffix] : 1470 std::initializer_list<std::pair<unsigned, const char *>>{ 1471 {1, ""}, {2, "_x2"}, {3, "_x3"}, {4, "_x4"}}) { 1472 for (const ReinterpretTypeInfo &To : Reinterprets) { 1473 SVEType ToV(To.BaseType, N); 1474 for (const ReinterpretTypeInfo &From : Reinterprets) { 1475 SVEType FromV(From.BaseType, N); 1476 OS << "TARGET_BUILTIN(__builtin_sve_reinterpret_" << To.Suffix << "_" 1477 << From.Suffix << Suffix << +", \"" << ToV.builtin_str() 1478 << FromV.builtin_str() << "\", \"n\", \"sme|sve\")\n"; 1479 } 1480 } 1481 } 1482 1483 OS << "#endif\n\n"; 1484 } 1485 1486 void SVEEmitter::createCodeGenMap(raw_ostream &OS) { 1487 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1488 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1489 for (auto *R : RV) 1490 createIntrinsic(R, Defs); 1491 1492 // The mappings must be sorted based on BuiltinID. 1493 llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A, 1494 const std::unique_ptr<Intrinsic> &B) { 1495 return A->getMangledName() < B->getMangledName(); 1496 }); 1497 1498 OS << "#ifdef GET_SVE_LLVM_INTRINSIC_MAP\n"; 1499 for (auto &Def : Defs) { 1500 // Builtins only exist for non-overloaded intrinsics, overloaded 1501 // declarations only live in the header file. 1502 if (Def->getClassKind() == ClassG) 1503 continue; 1504 1505 uint64_t Flags = Def->getFlags(); 1506 auto FlagString = std::to_string(Flags); 1507 1508 std::string LLVMName = Def->getMangledLLVMName(); 1509 std::string Builtin = Def->getMangledName(); 1510 if (!LLVMName.empty()) 1511 OS << "SVEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString 1512 << "),\n"; 1513 else 1514 OS << "SVEMAP2(" << Builtin << ", " << FlagString << "),\n"; 1515 } 1516 OS << "#endif\n\n"; 1517 } 1518 1519 void SVEEmitter::createRangeChecks(raw_ostream &OS) { 1520 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1521 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1522 for (auto *R : RV) 1523 createIntrinsic(R, Defs); 1524 1525 // The mappings must be sorted based on BuiltinID. 1526 llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A, 1527 const std::unique_ptr<Intrinsic> &B) { 1528 return A->getMangledName() < B->getMangledName(); 1529 }); 1530 1531 1532 OS << "#ifdef GET_SVE_IMMEDIATE_CHECK\n"; 1533 1534 // Ensure these are only emitted once. 1535 std::set<std::string> Emitted; 1536 1537 for (auto &Def : Defs) { 1538 if (Emitted.find(Def->getMangledName()) != Emitted.end() || 1539 Def->getImmChecks().empty()) 1540 continue; 1541 1542 OS << "case SVE::BI__builtin_sve_" << Def->getMangledName() << ":\n"; 1543 for (auto &Check : Def->getImmChecks()) 1544 OS << "ImmChecks.push_back(std::make_tuple(" << Check.getArg() << ", " 1545 << Check.getKind() << ", " << Check.getElementSizeInBits() << "));\n"; 1546 OS << " break;\n"; 1547 1548 Emitted.insert(Def->getMangledName()); 1549 } 1550 1551 OS << "#endif\n\n"; 1552 } 1553 1554 /// Create the SVETypeFlags used in CGBuiltins 1555 void SVEEmitter::createTypeFlags(raw_ostream &OS) { 1556 OS << "#ifdef LLVM_GET_SVE_TYPEFLAGS\n"; 1557 for (auto &KV : FlagTypes) 1558 OS << "const uint64_t " << KV.getKey() << " = " << KV.getValue() << ";\n"; 1559 OS << "#endif\n\n"; 1560 1561 OS << "#ifdef LLVM_GET_SVE_ELTTYPES\n"; 1562 for (auto &KV : EltTypes) 1563 OS << " " << KV.getKey() << " = " << KV.getValue() << ",\n"; 1564 OS << "#endif\n\n"; 1565 1566 OS << "#ifdef LLVM_GET_SVE_MEMELTTYPES\n"; 1567 for (auto &KV : MemEltTypes) 1568 OS << " " << KV.getKey() << " = " << KV.getValue() << ",\n"; 1569 OS << "#endif\n\n"; 1570 1571 OS << "#ifdef LLVM_GET_SVE_MERGETYPES\n"; 1572 for (auto &KV : MergeTypes) 1573 OS << " " << KV.getKey() << " = " << KV.getValue() << ",\n"; 1574 OS << "#endif\n\n"; 1575 1576 OS << "#ifdef LLVM_GET_SVE_IMMCHECKTYPES\n"; 1577 for (auto &KV : ImmCheckTypes) 1578 OS << " " << KV.getKey() << " = " << KV.getValue() << ",\n"; 1579 OS << "#endif\n\n"; 1580 } 1581 1582 void SVEEmitter::createSMEHeader(raw_ostream &OS) { 1583 OS << "/*===---- arm_sme.h - ARM SME intrinsics " 1584 "------===\n" 1585 " *\n" 1586 " *\n" 1587 " * Part of the LLVM Project, under the Apache License v2.0 with LLVM " 1588 "Exceptions.\n" 1589 " * See https://llvm.org/LICENSE.txt for license information.\n" 1590 " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n" 1591 " *\n" 1592 " *===-----------------------------------------------------------------" 1593 "------===\n" 1594 " */\n\n"; 1595 1596 OS << "#ifndef __ARM_SME_H\n"; 1597 OS << "#define __ARM_SME_H\n\n"; 1598 1599 OS << "#if !defined(__LITTLE_ENDIAN__)\n"; 1600 OS << "#error \"Big endian is currently not supported for arm_sme.h\"\n"; 1601 OS << "#endif\n"; 1602 1603 OS << "#include <arm_sve.h>\n\n"; 1604 OS << "#include <stddef.h>\n\n"; 1605 1606 OS << "/* Function attributes */\n"; 1607 OS << "#define __ai static __inline__ __attribute__((__always_inline__, " 1608 "__nodebug__))\n\n"; 1609 OS << "#define __aio static __inline__ __attribute__((__always_inline__, " 1610 "__nodebug__, __overloadable__))\n\n"; 1611 1612 OS << "#ifdef __cplusplus\n"; 1613 OS << "extern \"C\" {\n"; 1614 OS << "#endif\n\n"; 1615 1616 OS << "void __arm_za_disable(void) __arm_streaming_compatible;\n\n"; 1617 1618 OS << "__ai bool __arm_has_sme(void) __arm_streaming_compatible {\n"; 1619 OS << " uint64_t x0, x1;\n"; 1620 OS << " __builtin_arm_get_sme_state(&x0, &x1);\n"; 1621 OS << " return x0 & (1ULL << 63);\n"; 1622 OS << "}\n\n"; 1623 1624 OS << "__ai bool __arm_in_streaming_mode(void) __arm_streaming_compatible " 1625 "{\n"; 1626 OS << " uint64_t x0, x1;\n"; 1627 OS << " __builtin_arm_get_sme_state(&x0, &x1);\n"; 1628 OS << " return x0 & 1;\n"; 1629 OS << "}\n\n"; 1630 1631 OS << "void *__arm_sc_memcpy(void *dest, const void *src, size_t n) __arm_streaming_compatible;\n"; 1632 OS << "void *__arm_sc_memmove(void *dest, const void *src, size_t n) __arm_streaming_compatible;\n"; 1633 OS << "void *__arm_sc_memset(void *s, int c, size_t n) __arm_streaming_compatible;\n"; 1634 OS << "void *__arm_sc_memchr(void *s, int c, size_t n) __arm_streaming_compatible;\n\n"; 1635 1636 OS << "__ai __attribute__((target(\"sme\"))) void svundef_za(void) " 1637 "__arm_streaming_compatible __arm_out(\"za\") " 1638 "{ }\n\n"; 1639 1640 createCoreHeaderIntrinsics(OS, *this, ACLEKind::SME); 1641 1642 OS << "#ifdef __cplusplus\n"; 1643 OS << "} // extern \"C\"\n"; 1644 OS << "#endif\n\n"; 1645 OS << "#undef __ai\n\n"; 1646 OS << "#endif /* __ARM_SME_H */\n"; 1647 } 1648 1649 void SVEEmitter::createSMEBuiltins(raw_ostream &OS) { 1650 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1651 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1652 for (auto *R : RV) { 1653 createIntrinsic(R, Defs); 1654 } 1655 1656 // The mappings must be sorted based on BuiltinID. 1657 llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A, 1658 const std::unique_ptr<Intrinsic> &B) { 1659 return A->getMangledName() < B->getMangledName(); 1660 }); 1661 1662 OS << "#ifdef GET_SME_BUILTINS\n"; 1663 for (auto &Def : Defs) { 1664 // Only create BUILTINs for non-overloaded intrinsics, as overloaded 1665 // declarations only live in the header file. 1666 if (Def->getClassKind() != ClassG) { 1667 OS << "TARGET_BUILTIN(__builtin_sme_" << Def->getMangledName() << ", \"" 1668 << Def->getBuiltinTypeStr() << "\", \"n\", \""; 1669 Def->printGuard(OS); 1670 OS << "\")\n"; 1671 } 1672 } 1673 1674 OS << "#endif\n\n"; 1675 } 1676 1677 void SVEEmitter::createSMECodeGenMap(raw_ostream &OS) { 1678 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1679 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1680 for (auto *R : RV) { 1681 createIntrinsic(R, Defs); 1682 } 1683 1684 // The mappings must be sorted based on BuiltinID. 1685 llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A, 1686 const std::unique_ptr<Intrinsic> &B) { 1687 return A->getMangledName() < B->getMangledName(); 1688 }); 1689 1690 OS << "#ifdef GET_SME_LLVM_INTRINSIC_MAP\n"; 1691 for (auto &Def : Defs) { 1692 // Builtins only exist for non-overloaded intrinsics, overloaded 1693 // declarations only live in the header file. 1694 if (Def->getClassKind() == ClassG) 1695 continue; 1696 1697 uint64_t Flags = Def->getFlags(); 1698 auto FlagString = std::to_string(Flags); 1699 1700 std::string LLVMName = Def->getLLVMName(); 1701 std::string Builtin = Def->getMangledName(); 1702 if (!LLVMName.empty()) 1703 OS << "SMEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString 1704 << "),\n"; 1705 else 1706 OS << "SMEMAP2(" << Builtin << ", " << FlagString << "),\n"; 1707 } 1708 OS << "#endif\n\n"; 1709 } 1710 1711 void SVEEmitter::createSMERangeChecks(raw_ostream &OS) { 1712 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1713 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1714 for (auto *R : RV) { 1715 createIntrinsic(R, Defs); 1716 } 1717 1718 // The mappings must be sorted based on BuiltinID. 1719 llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A, 1720 const std::unique_ptr<Intrinsic> &B) { 1721 return A->getMangledName() < B->getMangledName(); 1722 }); 1723 1724 1725 OS << "#ifdef GET_SME_IMMEDIATE_CHECK\n"; 1726 1727 // Ensure these are only emitted once. 1728 std::set<std::string> Emitted; 1729 1730 for (auto &Def : Defs) { 1731 if (Emitted.find(Def->getMangledName()) != Emitted.end() || 1732 Def->getImmChecks().empty()) 1733 continue; 1734 1735 OS << "case SME::BI__builtin_sme_" << Def->getMangledName() << ":\n"; 1736 for (auto &Check : Def->getImmChecks()) 1737 OS << "ImmChecks.push_back(std::make_tuple(" << Check.getArg() << ", " 1738 << Check.getKind() << ", " << Check.getElementSizeInBits() << "));\n"; 1739 OS << " break;\n"; 1740 1741 Emitted.insert(Def->getMangledName()); 1742 } 1743 1744 OS << "#endif\n\n"; 1745 } 1746 1747 void SVEEmitter::createBuiltinZAState(raw_ostream &OS) { 1748 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1749 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1750 for (auto *R : RV) 1751 createIntrinsic(R, Defs); 1752 1753 std::map<std::string, std::set<std::string>> IntrinsicsPerState; 1754 for (auto &Def : Defs) { 1755 std::string Key; 1756 auto AddToKey = [&Key](const std::string &S) -> void { 1757 Key = Key.empty() ? S : (Key + " | " + S); 1758 }; 1759 1760 if (Def->isFlagSet(getEnumValueForFlag("IsInZA"))) 1761 AddToKey("ArmInZA"); 1762 else if (Def->isFlagSet(getEnumValueForFlag("IsOutZA"))) 1763 AddToKey("ArmOutZA"); 1764 else if (Def->isFlagSet(getEnumValueForFlag("IsInOutZA"))) 1765 AddToKey("ArmInOutZA"); 1766 1767 if (Def->isFlagSet(getEnumValueForFlag("IsInZT0"))) 1768 AddToKey("ArmInZT0"); 1769 else if (Def->isFlagSet(getEnumValueForFlag("IsOutZT0"))) 1770 AddToKey("ArmOutZT0"); 1771 else if (Def->isFlagSet(getEnumValueForFlag("IsInOutZT0"))) 1772 AddToKey("ArmInOutZT0"); 1773 1774 if (!Key.empty()) 1775 IntrinsicsPerState[Key].insert(Def->getMangledName()); 1776 } 1777 1778 OS << "#ifdef GET_SME_BUILTIN_GET_STATE\n"; 1779 for (auto &KV : IntrinsicsPerState) { 1780 for (StringRef Name : KV.second) 1781 OS << "case SME::BI__builtin_sme_" << Name << ":\n"; 1782 OS << " return " << KV.first << ";\n"; 1783 } 1784 OS << "#endif\n\n"; 1785 } 1786 1787 void SVEEmitter::createStreamingAttrs(raw_ostream &OS, ACLEKind Kind) { 1788 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 1789 SmallVector<std::unique_ptr<Intrinsic>, 128> Defs; 1790 for (auto *R : RV) 1791 createIntrinsic(R, Defs); 1792 1793 StringRef ExtensionKind; 1794 switch (Kind) { 1795 case ACLEKind::SME: 1796 ExtensionKind = "SME"; 1797 break; 1798 case ACLEKind::SVE: 1799 ExtensionKind = "SVE"; 1800 break; 1801 } 1802 1803 OS << "#ifdef GET_" << ExtensionKind << "_STREAMING_ATTRS\n"; 1804 1805 llvm::StringMap<std::set<std::string>> StreamingMap; 1806 1807 uint64_t IsStreamingFlag = getEnumValueForFlag("IsStreaming"); 1808 uint64_t VerifyRuntimeMode = getEnumValueForFlag("VerifyRuntimeMode"); 1809 uint64_t IsStreamingCompatibleFlag = 1810 getEnumValueForFlag("IsStreamingCompatible"); 1811 1812 for (auto &Def : Defs) { 1813 if (!Def->isFlagSet(VerifyRuntimeMode) && !Def->getSVEGuard().empty() && 1814 !Def->getSMEGuard().empty()) 1815 report_fatal_error("Missing VerifyRuntimeMode flag"); 1816 1817 if (Def->isFlagSet(IsStreamingFlag)) 1818 StreamingMap["ArmStreaming"].insert(Def->getMangledName()); 1819 else if (Def->isFlagSet(VerifyRuntimeMode)) 1820 StreamingMap["VerifyRuntimeMode"].insert(Def->getMangledName()); 1821 else if (Def->isFlagSet(IsStreamingCompatibleFlag)) 1822 StreamingMap["ArmStreamingCompatible"].insert(Def->getMangledName()); 1823 else 1824 StreamingMap["ArmNonStreaming"].insert(Def->getMangledName()); 1825 } 1826 1827 for (auto BuiltinType : StreamingMap.keys()) { 1828 for (auto Name : StreamingMap[BuiltinType]) { 1829 OS << "case " << ExtensionKind << "::BI__builtin_" 1830 << ExtensionKind.lower() << "_"; 1831 OS << Name << ":\n"; 1832 } 1833 OS << " BuiltinType = " << BuiltinType << ";\n"; 1834 OS << " break;\n"; 1835 } 1836 1837 OS << "#endif\n\n"; 1838 } 1839 1840 namespace clang { 1841 void EmitSveHeader(RecordKeeper &Records, raw_ostream &OS) { 1842 SVEEmitter(Records).createHeader(OS); 1843 } 1844 1845 void EmitSveBuiltins(RecordKeeper &Records, raw_ostream &OS) { 1846 SVEEmitter(Records).createBuiltins(OS); 1847 } 1848 1849 void EmitSveBuiltinCG(RecordKeeper &Records, raw_ostream &OS) { 1850 SVEEmitter(Records).createCodeGenMap(OS); 1851 } 1852 1853 void EmitSveRangeChecks(RecordKeeper &Records, raw_ostream &OS) { 1854 SVEEmitter(Records).createRangeChecks(OS); 1855 } 1856 1857 void EmitSveTypeFlags(RecordKeeper &Records, raw_ostream &OS) { 1858 SVEEmitter(Records).createTypeFlags(OS); 1859 } 1860 1861 void EmitSveStreamingAttrs(RecordKeeper &Records, raw_ostream &OS) { 1862 SVEEmitter(Records).createStreamingAttrs(OS, ACLEKind::SVE); 1863 } 1864 1865 void EmitSmeHeader(RecordKeeper &Records, raw_ostream &OS) { 1866 SVEEmitter(Records).createSMEHeader(OS); 1867 } 1868 1869 void EmitSmeBuiltins(RecordKeeper &Records, raw_ostream &OS) { 1870 SVEEmitter(Records).createSMEBuiltins(OS); 1871 } 1872 1873 void EmitSmeBuiltinCG(RecordKeeper &Records, raw_ostream &OS) { 1874 SVEEmitter(Records).createSMECodeGenMap(OS); 1875 } 1876 1877 void EmitSmeRangeChecks(RecordKeeper &Records, raw_ostream &OS) { 1878 SVEEmitter(Records).createSMERangeChecks(OS); 1879 } 1880 1881 void EmitSmeStreamingAttrs(RecordKeeper &Records, raw_ostream &OS) { 1882 SVEEmitter(Records).createStreamingAttrs(OS, ACLEKind::SME); 1883 } 1884 1885 void EmitSmeBuiltinZAState(RecordKeeper &Records, raw_ostream &OS) { 1886 SVEEmitter(Records).createBuiltinZAState(OS); 1887 } 1888 } // End namespace clang 1889