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