1 //===- NeonEmitter.cpp - Generate arm_neon.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_neon.h, which includes 10 // a declaration and definition of each function specified by the ARM NEON 11 // compiler interface. See ARM document DUI0348B. 12 // 13 // Each NEON instruction is implemented in terms of 1 or more functions which 14 // are suffixed with the element type of the input vectors. Functions may be 15 // implemented in terms of generic vector operations such as +, *, -, etc. or 16 // by calling a __builtin_-prefixed function which will be handled by clang's 17 // CodeGen library. 18 // 19 // Additional validation code can be generated by this file when runHeader() is 20 // called, rather than the normal run() entry point. 21 // 22 // See also the documentation in include/clang/Basic/arm_neon.td. 23 // 24 //===----------------------------------------------------------------------===// 25 26 #include "TableGenBackends.h" 27 #include "llvm/ADT/ArrayRef.h" 28 #include "llvm/ADT/DenseMap.h" 29 #include "llvm/ADT/None.h" 30 #include "llvm/ADT/SmallVector.h" 31 #include "llvm/ADT/STLExtras.h" 32 #include "llvm/ADT/StringExtras.h" 33 #include "llvm/ADT/StringRef.h" 34 #include "llvm/Support/Casting.h" 35 #include "llvm/Support/ErrorHandling.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include "llvm/TableGen/Error.h" 38 #include "llvm/TableGen/Record.h" 39 #include "llvm/TableGen/SetTheory.h" 40 #include <algorithm> 41 #include <cassert> 42 #include <cctype> 43 #include <cstddef> 44 #include <cstdint> 45 #include <deque> 46 #include <map> 47 #include <set> 48 #include <sstream> 49 #include <string> 50 #include <utility> 51 #include <vector> 52 53 using namespace llvm; 54 55 namespace { 56 57 // While globals are generally bad, this one allows us to perform assertions 58 // liberally and somehow still trace them back to the def they indirectly 59 // came from. 60 static Record *CurrentRecord = nullptr; 61 static void assert_with_loc(bool Assertion, const std::string &Str) { 62 if (!Assertion) { 63 if (CurrentRecord) 64 PrintFatalError(CurrentRecord->getLoc(), Str); 65 else 66 PrintFatalError(Str); 67 } 68 } 69 70 enum ClassKind { 71 ClassNone, 72 ClassI, // generic integer instruction, e.g., "i8" suffix 73 ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix 74 ClassW, // width-specific instruction, e.g., "8" suffix 75 ClassB, // bitcast arguments with enum argument to specify type 76 ClassL, // Logical instructions which are op instructions 77 // but we need to not emit any suffix for in our 78 // tests. 79 ClassNoTest // Instructions which we do not test since they are 80 // not TRUE instructions. 81 }; 82 83 /// NeonTypeFlags - Flags to identify the types for overloaded Neon 84 /// builtins. These must be kept in sync with the flags in 85 /// include/clang/Basic/TargetBuiltins.h. 86 namespace NeonTypeFlags { 87 88 enum { EltTypeMask = 0xf, UnsignedFlag = 0x10, QuadFlag = 0x20 }; 89 90 enum EltType { 91 Int8, 92 Int16, 93 Int32, 94 Int64, 95 Poly8, 96 Poly16, 97 Poly64, 98 Poly128, 99 Float16, 100 Float32, 101 Float64 102 }; 103 104 } // end namespace NeonTypeFlags 105 106 class NeonEmitter; 107 108 //===----------------------------------------------------------------------===// 109 // TypeSpec 110 //===----------------------------------------------------------------------===// 111 112 /// A TypeSpec is just a simple wrapper around a string, but gets its own type 113 /// for strong typing purposes. 114 /// 115 /// A TypeSpec can be used to create a type. 116 class TypeSpec : public std::string { 117 public: 118 static std::vector<TypeSpec> fromTypeSpecs(StringRef Str) { 119 std::vector<TypeSpec> Ret; 120 TypeSpec Acc; 121 for (char I : Str.str()) { 122 if (islower(I)) { 123 Acc.push_back(I); 124 Ret.push_back(TypeSpec(Acc)); 125 Acc.clear(); 126 } else { 127 Acc.push_back(I); 128 } 129 } 130 return Ret; 131 } 132 }; 133 134 //===----------------------------------------------------------------------===// 135 // Type 136 //===----------------------------------------------------------------------===// 137 138 /// A Type. Not much more to say here. 139 class Type { 140 private: 141 TypeSpec TS; 142 143 enum TypeKind { 144 Void, 145 Float, 146 SInt, 147 UInt, 148 Poly, 149 }; 150 TypeKind Kind; 151 bool Immediate, Constant, Pointer; 152 // ScalarForMangling and NoManglingQ are really not suited to live here as 153 // they are not related to the type. But they live in the TypeSpec (not the 154 // prototype), so this is really the only place to store them. 155 bool ScalarForMangling, NoManglingQ; 156 unsigned Bitwidth, ElementBitwidth, NumVectors; 157 158 public: 159 Type() 160 : Kind(Void), Immediate(false), Constant(false), 161 Pointer(false), ScalarForMangling(false), NoManglingQ(false), 162 Bitwidth(0), ElementBitwidth(0), NumVectors(0) {} 163 164 Type(TypeSpec TS, char CharMod) 165 : TS(std::move(TS)), Kind(Void), Immediate(false), 166 Constant(false), Pointer(false), ScalarForMangling(false), 167 NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) { 168 applyModifier(CharMod); 169 } 170 171 /// Returns a type representing "void". 172 static Type getVoid() { return Type(); } 173 174 bool operator==(const Type &Other) const { return str() == Other.str(); } 175 bool operator!=(const Type &Other) const { return !operator==(Other); } 176 177 // 178 // Query functions 179 // 180 bool isScalarForMangling() const { return ScalarForMangling; } 181 bool noManglingQ() const { return NoManglingQ; } 182 183 bool isPointer() const { return Pointer; } 184 bool isFloating() const { return Kind == Float; } 185 bool isInteger() const { return Kind == SInt || Kind == UInt; } 186 bool isPoly() const { return Kind == Poly; } 187 bool isSigned() const { return Kind == SInt; } 188 bool isImmediate() const { return Immediate; } 189 bool isScalar() const { return NumVectors == 0; } 190 bool isVector() const { return NumVectors > 0; } 191 bool isFloat() const { return isFloating() && ElementBitwidth == 32; } 192 bool isDouble() const { return isFloating() && ElementBitwidth == 64; } 193 bool isHalf() const { return isFloating() && ElementBitwidth == 16; } 194 bool isChar() const { return ElementBitwidth == 8; } 195 bool isShort() const { return isInteger() && ElementBitwidth == 16; } 196 bool isInt() const { return isInteger() && ElementBitwidth == 32; } 197 bool isLong() const { return isInteger() && ElementBitwidth == 64; } 198 bool isVoid() const { return Kind == Void; } 199 unsigned getNumElements() const { return Bitwidth / ElementBitwidth; } 200 unsigned getSizeInBits() const { return Bitwidth; } 201 unsigned getElementSizeInBits() const { return ElementBitwidth; } 202 unsigned getNumVectors() const { return NumVectors; } 203 204 // 205 // Mutator functions 206 // 207 void makeUnsigned() { 208 assert(isInteger() && "not a potentially signed type"); 209 Kind = UInt; 210 } 211 void makeSigned() { 212 assert(isInteger() && "not a potentially signed type"); 213 Kind = SInt; 214 } 215 216 void makeInteger(unsigned ElemWidth, bool Sign) { 217 assert(!isVoid() && "converting void to int probably not useful"); 218 Kind = Sign ? SInt : UInt; 219 Immediate = false; 220 ElementBitwidth = ElemWidth; 221 } 222 223 void makeImmediate(unsigned ElemWidth) { 224 Kind = SInt; 225 Immediate = true; 226 ElementBitwidth = ElemWidth; 227 } 228 229 void makeScalar() { 230 Bitwidth = ElementBitwidth; 231 NumVectors = 0; 232 } 233 234 void makeOneVector() { 235 assert(isVector()); 236 NumVectors = 1; 237 } 238 239 void doubleLanes() { 240 assert_with_loc(Bitwidth != 128, "Can't get bigger than 128!"); 241 Bitwidth = 128; 242 } 243 244 void halveLanes() { 245 assert_with_loc(Bitwidth != 64, "Can't get smaller than 64!"); 246 Bitwidth = 64; 247 } 248 249 /// Return the C string representation of a type, which is the typename 250 /// defined in stdint.h or arm_neon.h. 251 std::string str() const; 252 253 /// Return the string representation of a type, which is an encoded 254 /// string for passing to the BUILTIN() macro in Builtins.def. 255 std::string builtin_str() const; 256 257 /// Return the value in NeonTypeFlags for this type. 258 unsigned getNeonEnum() const; 259 260 /// Parse a type from a stdint.h or arm_neon.h typedef name, 261 /// for example uint32x2_t or int64_t. 262 static Type fromTypedefName(StringRef Name); 263 264 private: 265 /// Creates the type based on the typespec string in TS. 266 /// Sets "Quad" to true if the "Q" or "H" modifiers were 267 /// seen. This is needed by applyModifier as some modifiers 268 /// only take effect if the type size was changed by "Q" or "H". 269 void applyTypespec(bool &Quad); 270 /// Applies a prototype modifiers to the type. 271 void applyModifier(char Mod); 272 }; 273 274 //===----------------------------------------------------------------------===// 275 // Variable 276 //===----------------------------------------------------------------------===// 277 278 /// A variable is a simple class that just has a type and a name. 279 class Variable { 280 Type T; 281 std::string N; 282 283 public: 284 Variable() : T(Type::getVoid()), N("") {} 285 Variable(Type T, std::string N) : T(std::move(T)), N(std::move(N)) {} 286 287 Type getType() const { return T; } 288 std::string getName() const { return "__" + N; } 289 }; 290 291 //===----------------------------------------------------------------------===// 292 // Intrinsic 293 //===----------------------------------------------------------------------===// 294 295 /// The main grunt class. This represents an instantiation of an intrinsic with 296 /// a particular typespec and prototype. 297 class Intrinsic { 298 friend class DagEmitter; 299 300 /// The Record this intrinsic was created from. 301 Record *R; 302 /// The unmangled name and prototype. 303 std::string Name, Proto; 304 /// The input and output typespecs. InTS == OutTS except when 305 /// CartesianProductOfTypes is 1 - this is the case for vreinterpret. 306 TypeSpec OutTS, InTS; 307 /// The base class kind. Most intrinsics use ClassS, which has full type 308 /// info for integers (s32/u32). Some use ClassI, which doesn't care about 309 /// signedness (i32), while some (ClassB) have no type at all, only a width 310 /// (32). 311 ClassKind CK; 312 /// The list of DAGs for the body. May be empty, in which case we should 313 /// emit a builtin call. 314 ListInit *Body; 315 /// The architectural #ifdef guard. 316 std::string Guard; 317 /// Set if the Unavailable bit is 1. This means we don't generate a body, 318 /// just an "unavailable" attribute on a declaration. 319 bool IsUnavailable; 320 /// Is this intrinsic safe for big-endian? or does it need its arguments 321 /// reversing? 322 bool BigEndianSafe; 323 324 /// The types of return value [0] and parameters [1..]. 325 std::vector<Type> Types; 326 /// The local variables defined. 327 std::map<std::string, Variable> Variables; 328 /// NeededEarly - set if any other intrinsic depends on this intrinsic. 329 bool NeededEarly; 330 /// UseMacro - set if we should implement using a macro or unset for a 331 /// function. 332 bool UseMacro; 333 /// The set of intrinsics that this intrinsic uses/requires. 334 std::set<Intrinsic *> Dependencies; 335 /// The "base type", which is Type('d', OutTS). InBaseType is only 336 /// different if CartesianProductOfTypes = 1 (for vreinterpret). 337 Type BaseType, InBaseType; 338 /// The return variable. 339 Variable RetVar; 340 /// A postfix to apply to every variable. Defaults to "". 341 std::string VariablePostfix; 342 343 NeonEmitter &Emitter; 344 std::stringstream OS; 345 346 bool isBigEndianSafe() const { 347 if (BigEndianSafe) 348 return true; 349 350 for (const auto &T : Types){ 351 if (T.isVector() && T.getNumElements() > 1) 352 return false; 353 } 354 return true; 355 } 356 357 public: 358 Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS, 359 TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter, 360 StringRef Guard, bool IsUnavailable, bool BigEndianSafe) 361 : R(R), Name(Name.str()), Proto(Proto.str()), OutTS(OutTS), InTS(InTS), 362 CK(CK), Body(Body), Guard(Guard.str()), IsUnavailable(IsUnavailable), 363 BigEndianSafe(BigEndianSafe), NeededEarly(false), UseMacro(false), 364 BaseType(OutTS, 'd'), InBaseType(InTS, 'd'), Emitter(Emitter) { 365 // If this builtin takes an immediate argument, we need to #define it rather 366 // than use a standard declaration, so that SemaChecking can range check 367 // the immediate passed by the user. 368 if (Proto.find('i') != std::string::npos) 369 UseMacro = true; 370 371 // Pointer arguments need to use macros to avoid hiding aligned attributes 372 // from the pointer type. 373 if (Proto.find('p') != std::string::npos || 374 Proto.find('c') != std::string::npos) 375 UseMacro = true; 376 377 // It is not permitted to pass or return an __fp16 by value, so intrinsics 378 // taking a scalar float16_t must be implemented as macros. 379 if (OutTS.find('h') != std::string::npos && 380 Proto.find('s') != std::string::npos) 381 UseMacro = true; 382 383 // Modify the TypeSpec per-argument to get a concrete Type, and create 384 // known variables for each. 385 // Types[0] is the return value. 386 Types.emplace_back(OutTS, Proto[0]); 387 for (unsigned I = 1; I < Proto.size(); ++I) 388 Types.emplace_back(InTS, Proto[I]); 389 } 390 391 /// Get the Record that this intrinsic is based off. 392 Record *getRecord() const { return R; } 393 /// Get the set of Intrinsics that this intrinsic calls. 394 /// this is the set of immediate dependencies, NOT the 395 /// transitive closure. 396 const std::set<Intrinsic *> &getDependencies() const { return Dependencies; } 397 /// Get the architectural guard string (#ifdef). 398 std::string getGuard() const { return Guard; } 399 /// Get the non-mangled name. 400 std::string getName() const { return Name; } 401 402 /// Return true if the intrinsic takes an immediate operand. 403 bool hasImmediate() const { 404 return Proto.find('i') != std::string::npos; 405 } 406 407 /// Return the parameter index of the immediate operand. 408 unsigned getImmediateIdx() const { 409 assert(hasImmediate()); 410 unsigned Idx = Proto.find('i'); 411 assert(Idx > 0 && "Can't return an immediate!"); 412 return Idx - 1; 413 } 414 415 unsigned getNumParams() const { return Proto.size() - 1; } 416 Type getReturnType() const { return Types[0]; } 417 Type getParamType(unsigned I) const { return Types[I + 1]; } 418 Type getBaseType() const { return BaseType; } 419 /// Return the raw prototype string. 420 std::string getProto() const { return Proto; } 421 422 /// Return true if the prototype has a scalar argument. 423 bool protoHasScalar() const; 424 425 /// Return the index that parameter PIndex will sit at 426 /// in a generated function call. This is often just PIndex, 427 /// but may not be as things such as multiple-vector operands 428 /// and sret parameters need to be taken into accont. 429 unsigned getGeneratedParamIdx(unsigned PIndex) { 430 unsigned Idx = 0; 431 if (getReturnType().getNumVectors() > 1) 432 // Multiple vectors are passed as sret. 433 ++Idx; 434 435 for (unsigned I = 0; I < PIndex; ++I) 436 Idx += std::max(1U, getParamType(I).getNumVectors()); 437 438 return Idx; 439 } 440 441 bool hasBody() const { return Body && !Body->getValues().empty(); } 442 443 void setNeededEarly() { NeededEarly = true; } 444 445 bool operator<(const Intrinsic &Other) const { 446 // Sort lexicographically on a two-tuple (Guard, Name) 447 if (Guard != Other.Guard) 448 return Guard < Other.Guard; 449 return Name < Other.Name; 450 } 451 452 ClassKind getClassKind(bool UseClassBIfScalar = false) { 453 if (UseClassBIfScalar && !protoHasScalar()) 454 return ClassB; 455 return CK; 456 } 457 458 /// Return the name, mangled with type information. 459 /// If ForceClassS is true, use ClassS (u32/s32) instead 460 /// of the intrinsic's own type class. 461 std::string getMangledName(bool ForceClassS = false) const; 462 /// Return the type code for a builtin function call. 463 std::string getInstTypeCode(Type T, ClassKind CK) const; 464 /// Return the type string for a BUILTIN() macro in Builtins.def. 465 std::string getBuiltinTypeStr(); 466 467 /// Generate the intrinsic, returning code. 468 std::string generate(); 469 /// Perform type checking and populate the dependency graph, but 470 /// don't generate code yet. 471 void indexBody(); 472 473 private: 474 std::string mangleName(std::string Name, ClassKind CK) const; 475 476 void initVariables(); 477 std::string replaceParamsIn(std::string S); 478 479 void emitBodyAsBuiltinCall(); 480 481 void generateImpl(bool ReverseArguments, 482 StringRef NamePrefix, StringRef CallPrefix); 483 void emitReturn(); 484 void emitBody(StringRef CallPrefix); 485 void emitShadowedArgs(); 486 void emitArgumentReversal(); 487 void emitReturnReversal(); 488 void emitReverseVariable(Variable &Dest, Variable &Src); 489 void emitNewLine(); 490 void emitClosingBrace(); 491 void emitOpeningBrace(); 492 void emitPrototype(StringRef NamePrefix); 493 494 class DagEmitter { 495 Intrinsic &Intr; 496 StringRef CallPrefix; 497 498 public: 499 DagEmitter(Intrinsic &Intr, StringRef CallPrefix) : 500 Intr(Intr), CallPrefix(CallPrefix) { 501 } 502 std::pair<Type, std::string> emitDagArg(Init *Arg, std::string ArgName); 503 std::pair<Type, std::string> emitDagSaveTemp(DagInit *DI); 504 std::pair<Type, std::string> emitDagSplat(DagInit *DI); 505 std::pair<Type, std::string> emitDagDup(DagInit *DI); 506 std::pair<Type, std::string> emitDagDupTyped(DagInit *DI); 507 std::pair<Type, std::string> emitDagShuffle(DagInit *DI); 508 std::pair<Type, std::string> emitDagCast(DagInit *DI, bool IsBitCast); 509 std::pair<Type, std::string> emitDagCall(DagInit *DI); 510 std::pair<Type, std::string> emitDagNameReplace(DagInit *DI); 511 std::pair<Type, std::string> emitDagLiteral(DagInit *DI); 512 std::pair<Type, std::string> emitDagOp(DagInit *DI); 513 std::pair<Type, std::string> emitDag(DagInit *DI); 514 }; 515 }; 516 517 //===----------------------------------------------------------------------===// 518 // NeonEmitter 519 //===----------------------------------------------------------------------===// 520 521 class NeonEmitter { 522 RecordKeeper &Records; 523 DenseMap<Record *, ClassKind> ClassMap; 524 std::map<std::string, std::deque<Intrinsic>> IntrinsicMap; 525 unsigned UniqueNumber; 526 527 void createIntrinsic(Record *R, SmallVectorImpl<Intrinsic *> &Out); 528 void genBuiltinsDef(raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs); 529 void genOverloadTypeCheckCode(raw_ostream &OS, 530 SmallVectorImpl<Intrinsic *> &Defs); 531 void genIntrinsicRangeCheckCode(raw_ostream &OS, 532 SmallVectorImpl<Intrinsic *> &Defs); 533 534 public: 535 /// Called by Intrinsic - this attempts to get an intrinsic that takes 536 /// the given types as arguments. 537 Intrinsic &getIntrinsic(StringRef Name, ArrayRef<Type> Types); 538 539 /// Called by Intrinsic - returns a globally-unique number. 540 unsigned getUniqueNumber() { return UniqueNumber++; } 541 542 NeonEmitter(RecordKeeper &R) : Records(R), UniqueNumber(0) { 543 Record *SI = R.getClass("SInst"); 544 Record *II = R.getClass("IInst"); 545 Record *WI = R.getClass("WInst"); 546 Record *SOpI = R.getClass("SOpInst"); 547 Record *IOpI = R.getClass("IOpInst"); 548 Record *WOpI = R.getClass("WOpInst"); 549 Record *LOpI = R.getClass("LOpInst"); 550 Record *NoTestOpI = R.getClass("NoTestOpInst"); 551 552 ClassMap[SI] = ClassS; 553 ClassMap[II] = ClassI; 554 ClassMap[WI] = ClassW; 555 ClassMap[SOpI] = ClassS; 556 ClassMap[IOpI] = ClassI; 557 ClassMap[WOpI] = ClassW; 558 ClassMap[LOpI] = ClassL; 559 ClassMap[NoTestOpI] = ClassNoTest; 560 } 561 562 // run - Emit arm_neon.h.inc 563 void run(raw_ostream &o); 564 565 // runFP16 - Emit arm_fp16.h.inc 566 void runFP16(raw_ostream &o); 567 568 // runHeader - Emit all the __builtin prototypes used in arm_neon.h 569 // and arm_fp16.h 570 void runHeader(raw_ostream &o); 571 572 // runTests - Emit tests for all the Neon intrinsics. 573 void runTests(raw_ostream &o); 574 }; 575 576 } // end anonymous namespace 577 578 //===----------------------------------------------------------------------===// 579 // Type implementation 580 //===----------------------------------------------------------------------===// 581 582 std::string Type::str() const { 583 if (isVoid()) 584 return "void"; 585 std::string S; 586 587 if (isInteger() && !isSigned()) 588 S += "u"; 589 590 if (isPoly()) 591 S += "poly"; 592 else if (isFloating()) 593 S += "float"; 594 else 595 S += "int"; 596 597 S += utostr(ElementBitwidth); 598 if (isVector()) 599 S += "x" + utostr(getNumElements()); 600 if (NumVectors > 1) 601 S += "x" + utostr(NumVectors); 602 S += "_t"; 603 604 if (Constant) 605 S += " const"; 606 if (Pointer) 607 S += " *"; 608 609 return S; 610 } 611 612 std::string Type::builtin_str() const { 613 std::string S; 614 if (isVoid()) 615 return "v"; 616 617 if (Pointer) 618 // All pointers are void pointers. 619 S += "v"; 620 else if (isInteger()) 621 switch (ElementBitwidth) { 622 case 8: S += "c"; break; 623 case 16: S += "s"; break; 624 case 32: S += "i"; break; 625 case 64: S += "Wi"; break; 626 case 128: S += "LLLi"; break; 627 default: llvm_unreachable("Unhandled case!"); 628 } 629 else 630 switch (ElementBitwidth) { 631 case 16: S += "h"; break; 632 case 32: S += "f"; break; 633 case 64: S += "d"; break; 634 default: llvm_unreachable("Unhandled case!"); 635 } 636 637 if (isChar() && !isPointer() && isSigned()) 638 // Make chars explicitly signed. 639 S = "S" + S; 640 else if (!isPointer() && isInteger() && !isSigned()) 641 S = "U" + S; 642 643 // Constant indices are "int", but have the "constant expression" modifier. 644 if (isImmediate()) { 645 assert(isInteger() && isSigned()); 646 S = "I" + S; 647 } 648 649 if (isScalar()) { 650 if (Constant) S += "C"; 651 if (Pointer) S += "*"; 652 return S; 653 } 654 655 std::string Ret; 656 for (unsigned I = 0; I < NumVectors; ++I) 657 Ret += "V" + utostr(getNumElements()) + S; 658 659 return Ret; 660 } 661 662 unsigned Type::getNeonEnum() const { 663 unsigned Addend; 664 switch (ElementBitwidth) { 665 case 8: Addend = 0; break; 666 case 16: Addend = 1; break; 667 case 32: Addend = 2; break; 668 case 64: Addend = 3; break; 669 case 128: Addend = 4; break; 670 default: llvm_unreachable("Unhandled element bitwidth!"); 671 } 672 673 unsigned Base = (unsigned)NeonTypeFlags::Int8 + Addend; 674 if (isPoly()) { 675 // Adjustment needed because Poly32 doesn't exist. 676 if (Addend >= 2) 677 --Addend; 678 Base = (unsigned)NeonTypeFlags::Poly8 + Addend; 679 } 680 if (isFloating()) { 681 assert(Addend != 0 && "Float8 doesn't exist!"); 682 Base = (unsigned)NeonTypeFlags::Float16 + (Addend - 1); 683 } 684 685 if (Bitwidth == 128) 686 Base |= (unsigned)NeonTypeFlags::QuadFlag; 687 if (isInteger() && !isSigned()) 688 Base |= (unsigned)NeonTypeFlags::UnsignedFlag; 689 690 return Base; 691 } 692 693 Type Type::fromTypedefName(StringRef Name) { 694 Type T; 695 T.Kind = SInt; 696 697 if (Name.front() == 'u') { 698 T.Kind = UInt; 699 Name = Name.drop_front(); 700 } 701 702 if (Name.startswith("float")) { 703 T.Kind = Float; 704 Name = Name.drop_front(5); 705 } else if (Name.startswith("poly")) { 706 T.Kind = Poly; 707 Name = Name.drop_front(4); 708 } else { 709 assert(Name.startswith("int")); 710 Name = Name.drop_front(3); 711 } 712 713 unsigned I = 0; 714 for (I = 0; I < Name.size(); ++I) { 715 if (!isdigit(Name[I])) 716 break; 717 } 718 Name.substr(0, I).getAsInteger(10, T.ElementBitwidth); 719 Name = Name.drop_front(I); 720 721 T.Bitwidth = T.ElementBitwidth; 722 T.NumVectors = 1; 723 724 if (Name.front() == 'x') { 725 Name = Name.drop_front(); 726 unsigned I = 0; 727 for (I = 0; I < Name.size(); ++I) { 728 if (!isdigit(Name[I])) 729 break; 730 } 731 unsigned NumLanes; 732 Name.substr(0, I).getAsInteger(10, NumLanes); 733 Name = Name.drop_front(I); 734 T.Bitwidth = T.ElementBitwidth * NumLanes; 735 } else { 736 // Was scalar. 737 T.NumVectors = 0; 738 } 739 if (Name.front() == 'x') { 740 Name = Name.drop_front(); 741 unsigned I = 0; 742 for (I = 0; I < Name.size(); ++I) { 743 if (!isdigit(Name[I])) 744 break; 745 } 746 Name.substr(0, I).getAsInteger(10, T.NumVectors); 747 Name = Name.drop_front(I); 748 } 749 750 assert(Name.startswith("_t") && "Malformed typedef!"); 751 return T; 752 } 753 754 void Type::applyTypespec(bool &Quad) { 755 std::string S = TS; 756 ScalarForMangling = false; 757 Kind = SInt; 758 ElementBitwidth = ~0U; 759 NumVectors = 1; 760 761 for (char I : S) { 762 switch (I) { 763 case 'S': 764 ScalarForMangling = true; 765 break; 766 case 'H': 767 NoManglingQ = true; 768 Quad = true; 769 break; 770 case 'Q': 771 Quad = true; 772 break; 773 case 'P': 774 Kind = Poly; 775 break; 776 case 'U': 777 Kind = UInt; 778 break; 779 case 'c': 780 ElementBitwidth = 8; 781 break; 782 case 'h': 783 Kind = Float; 784 LLVM_FALLTHROUGH; 785 case 's': 786 ElementBitwidth = 16; 787 break; 788 case 'f': 789 Kind = Float; 790 LLVM_FALLTHROUGH; 791 case 'i': 792 ElementBitwidth = 32; 793 break; 794 case 'd': 795 Kind = Float; 796 LLVM_FALLTHROUGH; 797 case 'l': 798 ElementBitwidth = 64; 799 break; 800 case 'k': 801 ElementBitwidth = 128; 802 // Poly doesn't have a 128x1 type. 803 if (isPoly()) 804 NumVectors = 0; 805 break; 806 default: 807 llvm_unreachable("Unhandled type code!"); 808 } 809 } 810 assert(ElementBitwidth != ~0U && "Bad element bitwidth!"); 811 812 Bitwidth = Quad ? 128 : 64; 813 } 814 815 void Type::applyModifier(char Mod) { 816 bool AppliedQuad = false; 817 applyTypespec(AppliedQuad); 818 819 switch (Mod) { 820 case 'v': 821 Kind = Void; 822 break; 823 case 't': 824 if (isPoly()) 825 Kind = UInt; 826 break; 827 case 'b': 828 Kind = UInt; 829 NumVectors = 0; 830 Bitwidth = ElementBitwidth; 831 break; 832 case '$': 833 Kind = SInt; 834 NumVectors = 0; 835 Bitwidth = ElementBitwidth; 836 break; 837 case 'u': 838 Kind = UInt; 839 break; 840 case 'x': 841 assert(!isPoly() && "'u' can't be used with poly types!"); 842 Kind = SInt; 843 break; 844 case 'o': 845 Bitwidth = ElementBitwidth = 64; 846 NumVectors = 0; 847 Kind = Float; 848 break; 849 case 'y': 850 Bitwidth = ElementBitwidth = 32; 851 NumVectors = 0; 852 Kind = Float; 853 break; 854 case 'Y': 855 Bitwidth = ElementBitwidth = 16; 856 NumVectors = 0; 857 Kind = Float; 858 break; 859 case 'I': 860 Bitwidth = ElementBitwidth = 32; 861 NumVectors = 0; 862 Kind = SInt; 863 break; 864 case 'L': 865 Bitwidth = ElementBitwidth = 64; 866 NumVectors = 0; 867 Kind = SInt; 868 break; 869 case 'U': 870 Bitwidth = ElementBitwidth = 32; 871 NumVectors = 0; 872 Kind = UInt; 873 break; 874 case 'O': 875 Bitwidth = ElementBitwidth = 64; 876 NumVectors = 0; 877 Kind = UInt; 878 break; 879 case 'f': 880 Kind = Float; 881 ElementBitwidth = 32; 882 break; 883 case 'F': 884 Kind = Float; 885 ElementBitwidth = 64; 886 break; 887 case 'H': 888 Kind = Float; 889 ElementBitwidth = 16; 890 break; 891 case '0': 892 Kind = Float; 893 if (AppliedQuad) 894 Bitwidth /= 2; 895 ElementBitwidth = 16; 896 break; 897 case '1': 898 Kind = Float; 899 if (!AppliedQuad) 900 Bitwidth *= 2; 901 ElementBitwidth = 16; 902 break; 903 case 'g': 904 if (AppliedQuad) 905 Bitwidth /= 2; 906 break; 907 case 'j': 908 if (!AppliedQuad) 909 Bitwidth *= 2; 910 break; 911 case 'w': 912 ElementBitwidth *= 2; 913 Bitwidth *= 2; 914 break; 915 case 'n': 916 ElementBitwidth *= 2; 917 break; 918 case 'i': 919 Kind = SInt; 920 ElementBitwidth = Bitwidth = 32; 921 NumVectors = 0; 922 Immediate = true; 923 break; 924 case 'l': 925 Kind = UInt; 926 ElementBitwidth = Bitwidth = 64; 927 NumVectors = 0; 928 Immediate = true; 929 break; 930 case 'z': 931 ElementBitwidth /= 2; 932 Bitwidth = ElementBitwidth; 933 NumVectors = 0; 934 break; 935 case 'r': 936 ElementBitwidth *= 2; 937 Bitwidth = ElementBitwidth; 938 NumVectors = 0; 939 break; 940 case 's': 941 Bitwidth = ElementBitwidth; 942 NumVectors = 0; 943 break; 944 case 'k': 945 Bitwidth *= 2; 946 break; 947 case 'c': 948 Constant = true; 949 LLVM_FALLTHROUGH; 950 case 'p': 951 Pointer = true; 952 Bitwidth = ElementBitwidth; 953 NumVectors = 0; 954 break; 955 case 'h': 956 ElementBitwidth /= 2; 957 break; 958 case 'q': 959 ElementBitwidth /= 2; 960 Bitwidth *= 2; 961 break; 962 case 'e': 963 ElementBitwidth /= 2; 964 Kind = UInt; 965 break; 966 case 'm': 967 ElementBitwidth /= 2; 968 Bitwidth /= 2; 969 break; 970 case 'd': 971 break; 972 case '2': 973 NumVectors = 2; 974 break; 975 case '3': 976 NumVectors = 3; 977 break; 978 case '4': 979 NumVectors = 4; 980 break; 981 case 'B': 982 NumVectors = 2; 983 if (!AppliedQuad) 984 Bitwidth *= 2; 985 break; 986 case 'C': 987 NumVectors = 3; 988 if (!AppliedQuad) 989 Bitwidth *= 2; 990 break; 991 case 'D': 992 NumVectors = 4; 993 if (!AppliedQuad) 994 Bitwidth *= 2; 995 break; 996 case '7': 997 if (AppliedQuad) 998 Bitwidth /= 2; 999 ElementBitwidth = 8; 1000 break; 1001 case '8': 1002 ElementBitwidth = 8; 1003 break; 1004 case '9': 1005 if (!AppliedQuad) 1006 Bitwidth *= 2; 1007 ElementBitwidth = 8; 1008 break; 1009 default: 1010 llvm_unreachable("Unhandled character!"); 1011 } 1012 } 1013 1014 //===----------------------------------------------------------------------===// 1015 // Intrinsic implementation 1016 //===----------------------------------------------------------------------===// 1017 1018 std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const { 1019 char typeCode = '\0'; 1020 bool printNumber = true; 1021 1022 if (CK == ClassB) 1023 return ""; 1024 1025 if (T.isPoly()) 1026 typeCode = 'p'; 1027 else if (T.isInteger()) 1028 typeCode = T.isSigned() ? 's' : 'u'; 1029 else 1030 typeCode = 'f'; 1031 1032 if (CK == ClassI) { 1033 switch (typeCode) { 1034 default: 1035 break; 1036 case 's': 1037 case 'u': 1038 case 'p': 1039 typeCode = 'i'; 1040 break; 1041 } 1042 } 1043 if (CK == ClassB) { 1044 typeCode = '\0'; 1045 } 1046 1047 std::string S; 1048 if (typeCode != '\0') 1049 S.push_back(typeCode); 1050 if (printNumber) 1051 S += utostr(T.getElementSizeInBits()); 1052 1053 return S; 1054 } 1055 1056 static bool isFloatingPointProtoModifier(char Mod) { 1057 return Mod == 'F' || Mod == 'f' || Mod == 'H' || Mod == 'Y' || Mod == 'I'; 1058 } 1059 1060 std::string Intrinsic::getBuiltinTypeStr() { 1061 ClassKind LocalCK = getClassKind(true); 1062 std::string S; 1063 1064 Type RetT = getReturnType(); 1065 if ((LocalCK == ClassI || LocalCK == ClassW) && RetT.isScalar() && 1066 !RetT.isFloating() && !RetT.isVoid()) 1067 RetT.makeInteger(RetT.getElementSizeInBits(), false); 1068 1069 // Since the return value must be one type, return a vector type of the 1070 // appropriate width which we will bitcast. An exception is made for 1071 // returning structs of 2, 3, or 4 vectors which are returned in a sret-like 1072 // fashion, storing them to a pointer arg. 1073 if (RetT.getNumVectors() > 1) { 1074 S += "vv*"; // void result with void* first argument 1075 } else { 1076 if (RetT.isPoly()) 1077 RetT.makeInteger(RetT.getElementSizeInBits(), false); 1078 if (!RetT.isScalar() && RetT.isInteger() && !RetT.isSigned()) 1079 RetT.makeSigned(); 1080 1081 bool ForcedVectorFloatingType = isFloatingPointProtoModifier(Proto[0]); 1082 if (LocalCK == ClassB && !RetT.isVoid() && !RetT.isScalar() && 1083 !ForcedVectorFloatingType) 1084 // Cast to vector of 8-bit elements. 1085 RetT.makeInteger(8, true); 1086 1087 S += RetT.builtin_str(); 1088 } 1089 1090 for (unsigned I = 0; I < getNumParams(); ++I) { 1091 Type T = getParamType(I); 1092 if (T.isPoly()) 1093 T.makeInteger(T.getElementSizeInBits(), false); 1094 1095 bool ForcedFloatingType = isFloatingPointProtoModifier(Proto[I + 1]); 1096 if (LocalCK == ClassB && !T.isScalar() && !ForcedFloatingType) 1097 T.makeInteger(8, true); 1098 // Halves always get converted to 8-bit elements. 1099 if (T.isHalf() && T.isVector() && !T.isScalarForMangling()) 1100 T.makeInteger(8, true); 1101 1102 if (LocalCK == ClassI && T.isInteger()) 1103 T.makeSigned(); 1104 1105 if (hasImmediate() && getImmediateIdx() == I) 1106 T.makeImmediate(32); 1107 1108 S += T.builtin_str(); 1109 } 1110 1111 // Extra constant integer to hold type class enum for this function, e.g. s8 1112 if (LocalCK == ClassB) 1113 S += "i"; 1114 1115 return S; 1116 } 1117 1118 std::string Intrinsic::getMangledName(bool ForceClassS) const { 1119 // Check if the prototype has a scalar operand with the type of the vector 1120 // elements. If not, bitcasting the args will take care of arg checking. 1121 // The actual signedness etc. will be taken care of with special enums. 1122 ClassKind LocalCK = CK; 1123 if (!protoHasScalar()) 1124 LocalCK = ClassB; 1125 1126 return mangleName(Name, ForceClassS ? ClassS : LocalCK); 1127 } 1128 1129 std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const { 1130 std::string typeCode = getInstTypeCode(BaseType, LocalCK); 1131 std::string S = Name; 1132 1133 if (Name == "vcvt_f16_f32" || Name == "vcvt_f32_f16" || 1134 Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32") 1135 return Name; 1136 1137 if (!typeCode.empty()) { 1138 // If the name ends with _xN (N = 2,3,4), insert the typeCode before _xN. 1139 if (Name.size() >= 3 && isdigit(Name.back()) && 1140 Name[Name.length() - 2] == 'x' && Name[Name.length() - 3] == '_') 1141 S.insert(S.length() - 3, "_" + typeCode); 1142 else 1143 S += "_" + typeCode; 1144 } 1145 1146 if (BaseType != InBaseType) { 1147 // A reinterpret - out the input base type at the end. 1148 S += "_" + getInstTypeCode(InBaseType, LocalCK); 1149 } 1150 1151 if (LocalCK == ClassB) 1152 S += "_v"; 1153 1154 // Insert a 'q' before the first '_' character so that it ends up before 1155 // _lane or _n on vector-scalar operations. 1156 if (BaseType.getSizeInBits() == 128 && !BaseType.noManglingQ()) { 1157 size_t Pos = S.find('_'); 1158 S.insert(Pos, "q"); 1159 } 1160 1161 char Suffix = '\0'; 1162 if (BaseType.isScalarForMangling()) { 1163 switch (BaseType.getElementSizeInBits()) { 1164 case 8: Suffix = 'b'; break; 1165 case 16: Suffix = 'h'; break; 1166 case 32: Suffix = 's'; break; 1167 case 64: Suffix = 'd'; break; 1168 default: llvm_unreachable("Bad suffix!"); 1169 } 1170 } 1171 if (Suffix != '\0') { 1172 size_t Pos = S.find('_'); 1173 S.insert(Pos, &Suffix, 1); 1174 } 1175 1176 return S; 1177 } 1178 1179 std::string Intrinsic::replaceParamsIn(std::string S) { 1180 while (S.find('$') != std::string::npos) { 1181 size_t Pos = S.find('$'); 1182 size_t End = Pos + 1; 1183 while (isalpha(S[End])) 1184 ++End; 1185 1186 std::string VarName = S.substr(Pos + 1, End - Pos - 1); 1187 assert_with_loc(Variables.find(VarName) != Variables.end(), 1188 "Variable not defined!"); 1189 S.replace(Pos, End - Pos, Variables.find(VarName)->second.getName()); 1190 } 1191 1192 return S; 1193 } 1194 1195 void Intrinsic::initVariables() { 1196 Variables.clear(); 1197 1198 // Modify the TypeSpec per-argument to get a concrete Type, and create 1199 // known variables for each. 1200 for (unsigned I = 1; I < Proto.size(); ++I) { 1201 char NameC = '0' + (I - 1); 1202 std::string Name = "p"; 1203 Name.push_back(NameC); 1204 1205 Variables[Name] = Variable(Types[I], Name + VariablePostfix); 1206 } 1207 RetVar = Variable(Types[0], "ret" + VariablePostfix); 1208 } 1209 1210 void Intrinsic::emitPrototype(StringRef NamePrefix) { 1211 if (UseMacro) 1212 OS << "#define "; 1213 else 1214 OS << "__ai " << Types[0].str() << " "; 1215 1216 OS << NamePrefix.str() << mangleName(Name, ClassS) << "("; 1217 1218 for (unsigned I = 0; I < getNumParams(); ++I) { 1219 if (I != 0) 1220 OS << ", "; 1221 1222 char NameC = '0' + I; 1223 std::string Name = "p"; 1224 Name.push_back(NameC); 1225 assert(Variables.find(Name) != Variables.end()); 1226 Variable &V = Variables[Name]; 1227 1228 if (!UseMacro) 1229 OS << V.getType().str() << " "; 1230 OS << V.getName(); 1231 } 1232 1233 OS << ")"; 1234 } 1235 1236 void Intrinsic::emitOpeningBrace() { 1237 if (UseMacro) 1238 OS << " __extension__ ({"; 1239 else 1240 OS << " {"; 1241 emitNewLine(); 1242 } 1243 1244 void Intrinsic::emitClosingBrace() { 1245 if (UseMacro) 1246 OS << "})"; 1247 else 1248 OS << "}"; 1249 } 1250 1251 void Intrinsic::emitNewLine() { 1252 if (UseMacro) 1253 OS << " \\\n"; 1254 else 1255 OS << "\n"; 1256 } 1257 1258 void Intrinsic::emitReverseVariable(Variable &Dest, Variable &Src) { 1259 if (Dest.getType().getNumVectors() > 1) { 1260 emitNewLine(); 1261 1262 for (unsigned K = 0; K < Dest.getType().getNumVectors(); ++K) { 1263 OS << " " << Dest.getName() << ".val[" << K << "] = " 1264 << "__builtin_shufflevector(" 1265 << Src.getName() << ".val[" << K << "], " 1266 << Src.getName() << ".val[" << K << "]"; 1267 for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J) 1268 OS << ", " << J; 1269 OS << ");"; 1270 emitNewLine(); 1271 } 1272 } else { 1273 OS << " " << Dest.getName() 1274 << " = __builtin_shufflevector(" << Src.getName() << ", " << Src.getName(); 1275 for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J) 1276 OS << ", " << J; 1277 OS << ");"; 1278 emitNewLine(); 1279 } 1280 } 1281 1282 void Intrinsic::emitArgumentReversal() { 1283 if (isBigEndianSafe()) 1284 return; 1285 1286 // Reverse all vector arguments. 1287 for (unsigned I = 0; I < getNumParams(); ++I) { 1288 std::string Name = "p" + utostr(I); 1289 std::string NewName = "rev" + utostr(I); 1290 1291 Variable &V = Variables[Name]; 1292 Variable NewV(V.getType(), NewName + VariablePostfix); 1293 1294 if (!NewV.getType().isVector() || NewV.getType().getNumElements() == 1) 1295 continue; 1296 1297 OS << " " << NewV.getType().str() << " " << NewV.getName() << ";"; 1298 emitReverseVariable(NewV, V); 1299 V = NewV; 1300 } 1301 } 1302 1303 void Intrinsic::emitReturnReversal() { 1304 if (isBigEndianSafe()) 1305 return; 1306 if (!getReturnType().isVector() || getReturnType().isVoid() || 1307 getReturnType().getNumElements() == 1) 1308 return; 1309 emitReverseVariable(RetVar, RetVar); 1310 } 1311 1312 void Intrinsic::emitShadowedArgs() { 1313 // Macro arguments are not type-checked like inline function arguments, 1314 // so assign them to local temporaries to get the right type checking. 1315 if (!UseMacro) 1316 return; 1317 1318 for (unsigned I = 0; I < getNumParams(); ++I) { 1319 // Do not create a temporary for an immediate argument. 1320 // That would defeat the whole point of using a macro! 1321 if (hasImmediate() && Proto[I+1] == 'i') 1322 continue; 1323 // Do not create a temporary for pointer arguments. The input 1324 // pointer may have an alignment hint. 1325 if (getParamType(I).isPointer()) 1326 continue; 1327 1328 std::string Name = "p" + utostr(I); 1329 1330 assert(Variables.find(Name) != Variables.end()); 1331 Variable &V = Variables[Name]; 1332 1333 std::string NewName = "s" + utostr(I); 1334 Variable V2(V.getType(), NewName + VariablePostfix); 1335 1336 OS << " " << V2.getType().str() << " " << V2.getName() << " = " 1337 << V.getName() << ";"; 1338 emitNewLine(); 1339 1340 V = V2; 1341 } 1342 } 1343 1344 bool Intrinsic::protoHasScalar() const { 1345 return (Proto.find('s') != std::string::npos || 1346 Proto.find('z') != std::string::npos || 1347 Proto.find('r') != std::string::npos || 1348 Proto.find('b') != std::string::npos || 1349 Proto.find('$') != std::string::npos || 1350 Proto.find('y') != std::string::npos || 1351 Proto.find('o') != std::string::npos); 1352 } 1353 1354 void Intrinsic::emitBodyAsBuiltinCall() { 1355 std::string S; 1356 1357 // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit 1358 // sret-like argument. 1359 bool SRet = getReturnType().getNumVectors() >= 2; 1360 1361 StringRef N = Name; 1362 ClassKind LocalCK = CK; 1363 if (!protoHasScalar()) 1364 LocalCK = ClassB; 1365 1366 if (!getReturnType().isVoid() && !SRet) 1367 S += "(" + RetVar.getType().str() + ") "; 1368 1369 S += "__builtin_neon_" + mangleName(N, LocalCK) + "("; 1370 1371 if (SRet) 1372 S += "&" + RetVar.getName() + ", "; 1373 1374 for (unsigned I = 0; I < getNumParams(); ++I) { 1375 Variable &V = Variables["p" + utostr(I)]; 1376 Type T = V.getType(); 1377 1378 // Handle multiple-vector values specially, emitting each subvector as an 1379 // argument to the builtin. 1380 if (T.getNumVectors() > 1) { 1381 // Check if an explicit cast is needed. 1382 std::string Cast; 1383 if (LocalCK == ClassB) { 1384 Type T2 = T; 1385 T2.makeOneVector(); 1386 T2.makeInteger(8, /*Signed=*/true); 1387 Cast = "(" + T2.str() + ")"; 1388 } 1389 1390 for (unsigned J = 0; J < T.getNumVectors(); ++J) 1391 S += Cast + V.getName() + ".val[" + utostr(J) + "], "; 1392 continue; 1393 } 1394 1395 std::string Arg = V.getName(); 1396 Type CastToType = T; 1397 1398 // Check if an explicit cast is needed. 1399 if (CastToType.isVector() && 1400 (LocalCK == ClassB || (T.isHalf() && !T.isScalarForMangling()))) { 1401 CastToType.makeInteger(8, true); 1402 Arg = "(" + CastToType.str() + ")" + Arg; 1403 } else if (CastToType.isVector() && LocalCK == ClassI) { 1404 if (CastToType.isInteger()) 1405 CastToType.makeSigned(); 1406 Arg = "(" + CastToType.str() + ")" + Arg; 1407 } 1408 1409 S += Arg + ", "; 1410 } 1411 1412 // Extra constant integer to hold type class enum for this function, e.g. s8 1413 if (getClassKind(true) == ClassB) { 1414 Type ThisTy = getReturnType(); 1415 if (Proto[0] == 'v' || isFloatingPointProtoModifier(Proto[0])) 1416 ThisTy = getParamType(0); 1417 if (ThisTy.isPointer()) 1418 ThisTy = getParamType(1); 1419 1420 S += utostr(ThisTy.getNeonEnum()); 1421 } else { 1422 // Remove extraneous ", ". 1423 S.pop_back(); 1424 S.pop_back(); 1425 } 1426 S += ");"; 1427 1428 std::string RetExpr; 1429 if (!SRet && !RetVar.getType().isVoid()) 1430 RetExpr = RetVar.getName() + " = "; 1431 1432 OS << " " << RetExpr << S; 1433 emitNewLine(); 1434 } 1435 1436 void Intrinsic::emitBody(StringRef CallPrefix) { 1437 std::vector<std::string> Lines; 1438 1439 assert(RetVar.getType() == Types[0]); 1440 // Create a return variable, if we're not void. 1441 if (!RetVar.getType().isVoid()) { 1442 OS << " " << RetVar.getType().str() << " " << RetVar.getName() << ";"; 1443 emitNewLine(); 1444 } 1445 1446 if (!Body || Body->getValues().empty()) { 1447 // Nothing specific to output - must output a builtin. 1448 emitBodyAsBuiltinCall(); 1449 return; 1450 } 1451 1452 // We have a list of "things to output". The last should be returned. 1453 for (auto *I : Body->getValues()) { 1454 if (StringInit *SI = dyn_cast<StringInit>(I)) { 1455 Lines.push_back(replaceParamsIn(SI->getAsString())); 1456 } else if (DagInit *DI = dyn_cast<DagInit>(I)) { 1457 DagEmitter DE(*this, CallPrefix); 1458 Lines.push_back(DE.emitDag(DI).second + ";"); 1459 } 1460 } 1461 1462 assert(!Lines.empty() && "Empty def?"); 1463 if (!RetVar.getType().isVoid()) 1464 Lines.back().insert(0, RetVar.getName() + " = "); 1465 1466 for (auto &L : Lines) { 1467 OS << " " << L; 1468 emitNewLine(); 1469 } 1470 } 1471 1472 void Intrinsic::emitReturn() { 1473 if (RetVar.getType().isVoid()) 1474 return; 1475 if (UseMacro) 1476 OS << " " << RetVar.getName() << ";"; 1477 else 1478 OS << " return " << RetVar.getName() << ";"; 1479 emitNewLine(); 1480 } 1481 1482 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDag(DagInit *DI) { 1483 // At this point we should only be seeing a def. 1484 DefInit *DefI = cast<DefInit>(DI->getOperator()); 1485 std::string Op = DefI->getAsString(); 1486 1487 if (Op == "cast" || Op == "bitcast") 1488 return emitDagCast(DI, Op == "bitcast"); 1489 if (Op == "shuffle") 1490 return emitDagShuffle(DI); 1491 if (Op == "dup") 1492 return emitDagDup(DI); 1493 if (Op == "dup_typed") 1494 return emitDagDupTyped(DI); 1495 if (Op == "splat") 1496 return emitDagSplat(DI); 1497 if (Op == "save_temp") 1498 return emitDagSaveTemp(DI); 1499 if (Op == "op") 1500 return emitDagOp(DI); 1501 if (Op == "call") 1502 return emitDagCall(DI); 1503 if (Op == "name_replace") 1504 return emitDagNameReplace(DI); 1505 if (Op == "literal") 1506 return emitDagLiteral(DI); 1507 assert_with_loc(false, "Unknown operation!"); 1508 return std::make_pair(Type::getVoid(), ""); 1509 } 1510 1511 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagOp(DagInit *DI) { 1512 std::string Op = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1513 if (DI->getNumArgs() == 2) { 1514 // Unary op. 1515 std::pair<Type, std::string> R = 1516 emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); 1517 return std::make_pair(R.first, Op + R.second); 1518 } else { 1519 assert(DI->getNumArgs() == 3 && "Can only handle unary and binary ops!"); 1520 std::pair<Type, std::string> R1 = 1521 emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); 1522 std::pair<Type, std::string> R2 = 1523 emitDagArg(DI->getArg(2), DI->getArgNameStr(2)); 1524 assert_with_loc(R1.first == R2.first, "Argument type mismatch!"); 1525 return std::make_pair(R1.first, R1.second + " " + Op + " " + R2.second); 1526 } 1527 } 1528 1529 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) { 1530 std::vector<Type> Types; 1531 std::vector<std::string> Values; 1532 for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { 1533 std::pair<Type, std::string> R = 1534 emitDagArg(DI->getArg(I + 1), DI->getArgNameStr(I + 1)); 1535 Types.push_back(R.first); 1536 Values.push_back(R.second); 1537 } 1538 1539 // Look up the called intrinsic. 1540 std::string N; 1541 if (StringInit *SI = dyn_cast<StringInit>(DI->getArg(0))) 1542 N = SI->getAsUnquotedString(); 1543 else 1544 N = emitDagArg(DI->getArg(0), "").second; 1545 Intrinsic &Callee = Intr.Emitter.getIntrinsic(N, Types); 1546 1547 // Make sure the callee is known as an early def. 1548 Callee.setNeededEarly(); 1549 Intr.Dependencies.insert(&Callee); 1550 1551 // Now create the call itself. 1552 std::string S = ""; 1553 if (!Callee.isBigEndianSafe()) 1554 S += CallPrefix.str(); 1555 S += Callee.getMangledName(true) + "("; 1556 for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { 1557 if (I != 0) 1558 S += ", "; 1559 S += Values[I]; 1560 } 1561 S += ")"; 1562 1563 return std::make_pair(Callee.getReturnType(), S); 1564 } 1565 1566 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI, 1567 bool IsBitCast){ 1568 // (cast MOD* VAL) -> cast VAL to type given by MOD. 1569 std::pair<Type, std::string> R = emitDagArg( 1570 DI->getArg(DI->getNumArgs() - 1), 1571 DI->getArgNameStr(DI->getNumArgs() - 1)); 1572 Type castToType = R.first; 1573 for (unsigned ArgIdx = 0; ArgIdx < DI->getNumArgs() - 1; ++ArgIdx) { 1574 1575 // MOD can take several forms: 1576 // 1. $X - take the type of parameter / variable X. 1577 // 2. The value "R" - take the type of the return type. 1578 // 3. a type string 1579 // 4. The value "U" or "S" to switch the signedness. 1580 // 5. The value "H" or "D" to half or double the bitwidth. 1581 // 6. The value "8" to convert to 8-bit (signed) integer lanes. 1582 if (!DI->getArgNameStr(ArgIdx).empty()) { 1583 assert_with_loc(Intr.Variables.find(DI->getArgNameStr(ArgIdx)) != 1584 Intr.Variables.end(), 1585 "Variable not found"); 1586 castToType = Intr.Variables[DI->getArgNameStr(ArgIdx)].getType(); 1587 } else { 1588 StringInit *SI = dyn_cast<StringInit>(DI->getArg(ArgIdx)); 1589 assert_with_loc(SI, "Expected string type or $Name for cast type"); 1590 1591 if (SI->getAsUnquotedString() == "R") { 1592 castToType = Intr.getReturnType(); 1593 } else if (SI->getAsUnquotedString() == "U") { 1594 castToType.makeUnsigned(); 1595 } else if (SI->getAsUnquotedString() == "S") { 1596 castToType.makeSigned(); 1597 } else if (SI->getAsUnquotedString() == "H") { 1598 castToType.halveLanes(); 1599 } else if (SI->getAsUnquotedString() == "D") { 1600 castToType.doubleLanes(); 1601 } else if (SI->getAsUnquotedString() == "8") { 1602 castToType.makeInteger(8, true); 1603 } else { 1604 castToType = Type::fromTypedefName(SI->getAsUnquotedString()); 1605 assert_with_loc(!castToType.isVoid(), "Unknown typedef"); 1606 } 1607 } 1608 } 1609 1610 std::string S; 1611 if (IsBitCast) { 1612 // Emit a reinterpret cast. The second operand must be an lvalue, so create 1613 // a temporary. 1614 std::string N = "reint"; 1615 unsigned I = 0; 1616 while (Intr.Variables.find(N) != Intr.Variables.end()) 1617 N = "reint" + utostr(++I); 1618 Intr.Variables[N] = Variable(R.first, N + Intr.VariablePostfix); 1619 1620 Intr.OS << R.first.str() << " " << Intr.Variables[N].getName() << " = " 1621 << R.second << ";"; 1622 Intr.emitNewLine(); 1623 1624 S = "*(" + castToType.str() + " *) &" + Intr.Variables[N].getName() + ""; 1625 } else { 1626 // Emit a normal (static) cast. 1627 S = "(" + castToType.str() + ")(" + R.second + ")"; 1628 } 1629 1630 return std::make_pair(castToType, S); 1631 } 1632 1633 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ 1634 // See the documentation in arm_neon.td for a description of these operators. 1635 class LowHalf : public SetTheory::Operator { 1636 public: 1637 void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 1638 ArrayRef<SMLoc> Loc) override { 1639 SetTheory::RecSet Elts2; 1640 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc); 1641 Elts.insert(Elts2.begin(), Elts2.begin() + (Elts2.size() / 2)); 1642 } 1643 }; 1644 1645 class HighHalf : public SetTheory::Operator { 1646 public: 1647 void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 1648 ArrayRef<SMLoc> Loc) override { 1649 SetTheory::RecSet Elts2; 1650 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc); 1651 Elts.insert(Elts2.begin() + (Elts2.size() / 2), Elts2.end()); 1652 } 1653 }; 1654 1655 class Rev : public SetTheory::Operator { 1656 unsigned ElementSize; 1657 1658 public: 1659 Rev(unsigned ElementSize) : ElementSize(ElementSize) {} 1660 1661 void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 1662 ArrayRef<SMLoc> Loc) override { 1663 SetTheory::RecSet Elts2; 1664 ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Elts2, Loc); 1665 1666 int64_t VectorSize = cast<IntInit>(Expr->getArg(0))->getValue(); 1667 VectorSize /= ElementSize; 1668 1669 std::vector<Record *> Revved; 1670 for (unsigned VI = 0; VI < Elts2.size(); VI += VectorSize) { 1671 for (int LI = VectorSize - 1; LI >= 0; --LI) { 1672 Revved.push_back(Elts2[VI + LI]); 1673 } 1674 } 1675 1676 Elts.insert(Revved.begin(), Revved.end()); 1677 } 1678 }; 1679 1680 class MaskExpander : public SetTheory::Expander { 1681 unsigned N; 1682 1683 public: 1684 MaskExpander(unsigned N) : N(N) {} 1685 1686 void expand(SetTheory &ST, Record *R, SetTheory::RecSet &Elts) override { 1687 unsigned Addend = 0; 1688 if (R->getName() == "mask0") 1689 Addend = 0; 1690 else if (R->getName() == "mask1") 1691 Addend = N; 1692 else 1693 return; 1694 for (unsigned I = 0; I < N; ++I) 1695 Elts.insert(R->getRecords().getDef("sv" + utostr(I + Addend))); 1696 } 1697 }; 1698 1699 // (shuffle arg1, arg2, sequence) 1700 std::pair<Type, std::string> Arg1 = 1701 emitDagArg(DI->getArg(0), DI->getArgNameStr(0)); 1702 std::pair<Type, std::string> Arg2 = 1703 emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); 1704 assert_with_loc(Arg1.first == Arg2.first, 1705 "Different types in arguments to shuffle!"); 1706 1707 SetTheory ST; 1708 SetTheory::RecSet Elts; 1709 ST.addOperator("lowhalf", std::make_unique<LowHalf>()); 1710 ST.addOperator("highhalf", std::make_unique<HighHalf>()); 1711 ST.addOperator("rev", 1712 std::make_unique<Rev>(Arg1.first.getElementSizeInBits())); 1713 ST.addExpander("MaskExpand", 1714 std::make_unique<MaskExpander>(Arg1.first.getNumElements())); 1715 ST.evaluate(DI->getArg(2), Elts, None); 1716 1717 std::string S = "__builtin_shufflevector(" + Arg1.second + ", " + Arg2.second; 1718 for (auto &E : Elts) { 1719 StringRef Name = E->getName(); 1720 assert_with_loc(Name.startswith("sv"), 1721 "Incorrect element kind in shuffle mask!"); 1722 S += ", " + Name.drop_front(2).str(); 1723 } 1724 S += ")"; 1725 1726 // Recalculate the return type - the shuffle may have halved or doubled it. 1727 Type T(Arg1.first); 1728 if (Elts.size() > T.getNumElements()) { 1729 assert_with_loc( 1730 Elts.size() == T.getNumElements() * 2, 1731 "Can only double or half the number of elements in a shuffle!"); 1732 T.doubleLanes(); 1733 } else if (Elts.size() < T.getNumElements()) { 1734 assert_with_loc( 1735 Elts.size() == T.getNumElements() / 2, 1736 "Can only double or half the number of elements in a shuffle!"); 1737 T.halveLanes(); 1738 } 1739 1740 return std::make_pair(T, S); 1741 } 1742 1743 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) { 1744 assert_with_loc(DI->getNumArgs() == 1, "dup() expects one argument"); 1745 std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), 1746 DI->getArgNameStr(0)); 1747 assert_with_loc(A.first.isScalar(), "dup() expects a scalar argument"); 1748 1749 Type T = Intr.getBaseType(); 1750 assert_with_loc(T.isVector(), "dup() used but default type is scalar!"); 1751 std::string S = "(" + T.str() + ") {"; 1752 for (unsigned I = 0; I < T.getNumElements(); ++I) { 1753 if (I != 0) 1754 S += ", "; 1755 S += A.second; 1756 } 1757 S += "}"; 1758 1759 return std::make_pair(T, S); 1760 } 1761 1762 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDupTyped(DagInit *DI) { 1763 assert_with_loc(DI->getNumArgs() == 2, "dup_typed() expects two arguments"); 1764 std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), 1765 DI->getArgNameStr(0)); 1766 std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), 1767 DI->getArgNameStr(1)); 1768 assert_with_loc(B.first.isScalar(), 1769 "dup_typed() requires a scalar as the second argument"); 1770 1771 Type T = A.first; 1772 assert_with_loc(T.isVector(), "dup_typed() used but target type is scalar!"); 1773 std::string S = "(" + T.str() + ") {"; 1774 for (unsigned I = 0; I < T.getNumElements(); ++I) { 1775 if (I != 0) 1776 S += ", "; 1777 S += B.second; 1778 } 1779 S += "}"; 1780 1781 return std::make_pair(T, S); 1782 } 1783 1784 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) { 1785 assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments"); 1786 std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), 1787 DI->getArgNameStr(0)); 1788 std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), 1789 DI->getArgNameStr(1)); 1790 1791 assert_with_loc(B.first.isScalar(), 1792 "splat() requires a scalar int as the second argument"); 1793 1794 std::string S = "__builtin_shufflevector(" + A.second + ", " + A.second; 1795 for (unsigned I = 0; I < Intr.getBaseType().getNumElements(); ++I) { 1796 S += ", " + B.second; 1797 } 1798 S += ")"; 1799 1800 return std::make_pair(Intr.getBaseType(), S); 1801 } 1802 1803 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSaveTemp(DagInit *DI) { 1804 assert_with_loc(DI->getNumArgs() == 2, "save_temp() expects two arguments"); 1805 std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), 1806 DI->getArgNameStr(1)); 1807 1808 assert_with_loc(!A.first.isVoid(), 1809 "Argument to save_temp() must have non-void type!"); 1810 1811 std::string N = DI->getArgNameStr(0); 1812 assert_with_loc(!N.empty(), 1813 "save_temp() expects a name as the first argument"); 1814 1815 assert_with_loc(Intr.Variables.find(N) == Intr.Variables.end(), 1816 "Variable already defined!"); 1817 Intr.Variables[N] = Variable(A.first, N + Intr.VariablePostfix); 1818 1819 std::string S = 1820 A.first.str() + " " + Intr.Variables[N].getName() + " = " + A.second; 1821 1822 return std::make_pair(Type::getVoid(), S); 1823 } 1824 1825 std::pair<Type, std::string> 1826 Intrinsic::DagEmitter::emitDagNameReplace(DagInit *DI) { 1827 std::string S = Intr.Name; 1828 1829 assert_with_loc(DI->getNumArgs() == 2, "name_replace requires 2 arguments!"); 1830 std::string ToReplace = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1831 std::string ReplaceWith = cast<StringInit>(DI->getArg(1))->getAsUnquotedString(); 1832 1833 size_t Idx = S.find(ToReplace); 1834 1835 assert_with_loc(Idx != std::string::npos, "name should contain '" + ToReplace + "'!"); 1836 S.replace(Idx, ToReplace.size(), ReplaceWith); 1837 1838 return std::make_pair(Type::getVoid(), S); 1839 } 1840 1841 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagLiteral(DagInit *DI){ 1842 std::string Ty = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1843 std::string Value = cast<StringInit>(DI->getArg(1))->getAsUnquotedString(); 1844 return std::make_pair(Type::fromTypedefName(Ty), Value); 1845 } 1846 1847 std::pair<Type, std::string> 1848 Intrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) { 1849 if (!ArgName.empty()) { 1850 assert_with_loc(!Arg->isComplete(), 1851 "Arguments must either be DAGs or names, not both!"); 1852 assert_with_loc(Intr.Variables.find(ArgName) != Intr.Variables.end(), 1853 "Variable not defined!"); 1854 Variable &V = Intr.Variables[ArgName]; 1855 return std::make_pair(V.getType(), V.getName()); 1856 } 1857 1858 assert(Arg && "Neither ArgName nor Arg?!"); 1859 DagInit *DI = dyn_cast<DagInit>(Arg); 1860 assert_with_loc(DI, "Arguments must either be DAGs or names!"); 1861 1862 return emitDag(DI); 1863 } 1864 1865 std::string Intrinsic::generate() { 1866 // Avoid duplicated code for big and little endian 1867 if (isBigEndianSafe()) { 1868 generateImpl(false, "", ""); 1869 return OS.str(); 1870 } 1871 // Little endian intrinsics are simple and don't require any argument 1872 // swapping. 1873 OS << "#ifdef __LITTLE_ENDIAN__\n"; 1874 1875 generateImpl(false, "", ""); 1876 1877 OS << "#else\n"; 1878 1879 // Big endian intrinsics are more complex. The user intended these 1880 // intrinsics to operate on a vector "as-if" loaded by (V)LDR, 1881 // but we load as-if (V)LD1. So we should swap all arguments and 1882 // swap the return value too. 1883 // 1884 // If we call sub-intrinsics, we should call a version that does 1885 // not re-swap the arguments! 1886 generateImpl(true, "", "__noswap_"); 1887 1888 // If we're needed early, create a non-swapping variant for 1889 // big-endian. 1890 if (NeededEarly) { 1891 generateImpl(false, "__noswap_", "__noswap_"); 1892 } 1893 OS << "#endif\n\n"; 1894 1895 return OS.str(); 1896 } 1897 1898 void Intrinsic::generateImpl(bool ReverseArguments, 1899 StringRef NamePrefix, StringRef CallPrefix) { 1900 CurrentRecord = R; 1901 1902 // If we call a macro, our local variables may be corrupted due to 1903 // lack of proper lexical scoping. So, add a globally unique postfix 1904 // to every variable. 1905 // 1906 // indexBody() should have set up the Dependencies set by now. 1907 for (auto *I : Dependencies) 1908 if (I->UseMacro) { 1909 VariablePostfix = "_" + utostr(Emitter.getUniqueNumber()); 1910 break; 1911 } 1912 1913 initVariables(); 1914 1915 emitPrototype(NamePrefix); 1916 1917 if (IsUnavailable) { 1918 OS << " __attribute__((unavailable));"; 1919 } else { 1920 emitOpeningBrace(); 1921 emitShadowedArgs(); 1922 if (ReverseArguments) 1923 emitArgumentReversal(); 1924 emitBody(CallPrefix); 1925 if (ReverseArguments) 1926 emitReturnReversal(); 1927 emitReturn(); 1928 emitClosingBrace(); 1929 } 1930 OS << "\n"; 1931 1932 CurrentRecord = nullptr; 1933 } 1934 1935 void Intrinsic::indexBody() { 1936 CurrentRecord = R; 1937 1938 initVariables(); 1939 emitBody(""); 1940 OS.str(""); 1941 1942 CurrentRecord = nullptr; 1943 } 1944 1945 //===----------------------------------------------------------------------===// 1946 // NeonEmitter implementation 1947 //===----------------------------------------------------------------------===// 1948 1949 Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) { 1950 // First, look up the name in the intrinsic map. 1951 assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(), 1952 ("Intrinsic '" + Name + "' not found!").str()); 1953 auto &V = IntrinsicMap.find(Name.str())->second; 1954 std::vector<Intrinsic *> GoodVec; 1955 1956 // Create a string to print if we end up failing. 1957 std::string ErrMsg = "looking up intrinsic '" + Name.str() + "("; 1958 for (unsigned I = 0; I < Types.size(); ++I) { 1959 if (I != 0) 1960 ErrMsg += ", "; 1961 ErrMsg += Types[I].str(); 1962 } 1963 ErrMsg += ")'\n"; 1964 ErrMsg += "Available overloads:\n"; 1965 1966 // Now, look through each intrinsic implementation and see if the types are 1967 // compatible. 1968 for (auto &I : V) { 1969 ErrMsg += " - " + I.getReturnType().str() + " " + I.getMangledName(); 1970 ErrMsg += "("; 1971 for (unsigned A = 0; A < I.getNumParams(); ++A) { 1972 if (A != 0) 1973 ErrMsg += ", "; 1974 ErrMsg += I.getParamType(A).str(); 1975 } 1976 ErrMsg += ")\n"; 1977 1978 if (I.getNumParams() != Types.size()) 1979 continue; 1980 1981 bool Good = true; 1982 for (unsigned Arg = 0; Arg < Types.size(); ++Arg) { 1983 if (I.getParamType(Arg) != Types[Arg]) { 1984 Good = false; 1985 break; 1986 } 1987 } 1988 if (Good) 1989 GoodVec.push_back(&I); 1990 } 1991 1992 assert_with_loc(!GoodVec.empty(), 1993 "No compatible intrinsic found - " + ErrMsg); 1994 assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg); 1995 1996 return *GoodVec.front(); 1997 } 1998 1999 void NeonEmitter::createIntrinsic(Record *R, 2000 SmallVectorImpl<Intrinsic *> &Out) { 2001 std::string Name = R->getValueAsString("Name"); 2002 std::string Proto = R->getValueAsString("Prototype"); 2003 std::string Types = R->getValueAsString("Types"); 2004 Record *OperationRec = R->getValueAsDef("Operation"); 2005 bool CartesianProductOfTypes = R->getValueAsBit("CartesianProductOfTypes"); 2006 bool BigEndianSafe = R->getValueAsBit("BigEndianSafe"); 2007 std::string Guard = R->getValueAsString("ArchGuard"); 2008 bool IsUnavailable = OperationRec->getValueAsBit("Unavailable"); 2009 2010 // Set the global current record. This allows assert_with_loc to produce 2011 // decent location information even when highly nested. 2012 CurrentRecord = R; 2013 2014 ListInit *Body = OperationRec->getValueAsListInit("Ops"); 2015 2016 std::vector<TypeSpec> TypeSpecs = TypeSpec::fromTypeSpecs(Types); 2017 2018 ClassKind CK = ClassNone; 2019 if (R->getSuperClasses().size() >= 2) 2020 CK = ClassMap[R->getSuperClasses()[1].first]; 2021 2022 std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs; 2023 for (auto TS : TypeSpecs) { 2024 if (CartesianProductOfTypes) { 2025 Type DefaultT(TS, 'd'); 2026 for (auto SrcTS : TypeSpecs) { 2027 Type DefaultSrcT(SrcTS, 'd'); 2028 if (TS == SrcTS || 2029 DefaultSrcT.getSizeInBits() != DefaultT.getSizeInBits()) 2030 continue; 2031 NewTypeSpecs.push_back(std::make_pair(TS, SrcTS)); 2032 } 2033 } else { 2034 NewTypeSpecs.push_back(std::make_pair(TS, TS)); 2035 } 2036 } 2037 2038 llvm::sort(NewTypeSpecs); 2039 NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()), 2040 NewTypeSpecs.end()); 2041 auto &Entry = IntrinsicMap[Name]; 2042 2043 for (auto &I : NewTypeSpecs) { 2044 Entry.emplace_back(R, Name, Proto, I.first, I.second, CK, Body, *this, 2045 Guard, IsUnavailable, BigEndianSafe); 2046 Out.push_back(&Entry.back()); 2047 } 2048 2049 CurrentRecord = nullptr; 2050 } 2051 2052 /// genBuiltinsDef: Generate the BuiltinsARM.def and BuiltinsAArch64.def 2053 /// declaration of builtins, checking for unique builtin declarations. 2054 void NeonEmitter::genBuiltinsDef(raw_ostream &OS, 2055 SmallVectorImpl<Intrinsic *> &Defs) { 2056 OS << "#ifdef GET_NEON_BUILTINS\n"; 2057 2058 // We only want to emit a builtin once, and we want to emit them in 2059 // alphabetical order, so use a std::set. 2060 std::set<std::string> Builtins; 2061 2062 for (auto *Def : Defs) { 2063 if (Def->hasBody()) 2064 continue; 2065 2066 std::string S = "BUILTIN(__builtin_neon_" + Def->getMangledName() + ", \""; 2067 2068 S += Def->getBuiltinTypeStr(); 2069 S += "\", \"n\")"; 2070 2071 Builtins.insert(S); 2072 } 2073 2074 for (auto &S : Builtins) 2075 OS << S << "\n"; 2076 OS << "#endif\n\n"; 2077 } 2078 2079 /// Generate the ARM and AArch64 overloaded type checking code for 2080 /// SemaChecking.cpp, checking for unique builtin declarations. 2081 void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS, 2082 SmallVectorImpl<Intrinsic *> &Defs) { 2083 OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n"; 2084 2085 // We record each overload check line before emitting because subsequent Inst 2086 // definitions may extend the number of permitted types (i.e. augment the 2087 // Mask). Use std::map to avoid sorting the table by hash number. 2088 struct OverloadInfo { 2089 uint64_t Mask; 2090 int PtrArgNum; 2091 bool HasConstPtr; 2092 OverloadInfo() : Mask(0ULL), PtrArgNum(0), HasConstPtr(false) {} 2093 }; 2094 std::map<std::string, OverloadInfo> OverloadMap; 2095 2096 for (auto *Def : Defs) { 2097 // If the def has a body (that is, it has Operation DAGs), it won't call 2098 // __builtin_neon_* so we don't need to generate a definition for it. 2099 if (Def->hasBody()) 2100 continue; 2101 // Functions which have a scalar argument cannot be overloaded, no need to 2102 // check them if we are emitting the type checking code. 2103 if (Def->protoHasScalar()) 2104 continue; 2105 2106 uint64_t Mask = 0ULL; 2107 Type Ty = Def->getReturnType(); 2108 if (Def->getProto()[0] == 'v' || 2109 isFloatingPointProtoModifier(Def->getProto()[0])) 2110 Ty = Def->getParamType(0); 2111 if (Ty.isPointer()) 2112 Ty = Def->getParamType(1); 2113 2114 Mask |= 1ULL << Ty.getNeonEnum(); 2115 2116 // Check if the function has a pointer or const pointer argument. 2117 std::string Proto = Def->getProto(); 2118 int PtrArgNum = -1; 2119 bool HasConstPtr = false; 2120 for (unsigned I = 0; I < Def->getNumParams(); ++I) { 2121 char ArgType = Proto[I + 1]; 2122 if (ArgType == 'c') { 2123 HasConstPtr = true; 2124 PtrArgNum = I; 2125 break; 2126 } 2127 if (ArgType == 'p') { 2128 PtrArgNum = I; 2129 break; 2130 } 2131 } 2132 // For sret builtins, adjust the pointer argument index. 2133 if (PtrArgNum >= 0 && Def->getReturnType().getNumVectors() > 1) 2134 PtrArgNum += 1; 2135 2136 std::string Name = Def->getName(); 2137 // Omit type checking for the pointer arguments of vld1_lane, vld1_dup, 2138 // and vst1_lane intrinsics. Using a pointer to the vector element 2139 // type with one of those operations causes codegen to select an aligned 2140 // load/store instruction. If you want an unaligned operation, 2141 // the pointer argument needs to have less alignment than element type, 2142 // so just accept any pointer type. 2143 if (Name == "vld1_lane" || Name == "vld1_dup" || Name == "vst1_lane") { 2144 PtrArgNum = -1; 2145 HasConstPtr = false; 2146 } 2147 2148 if (Mask) { 2149 std::string Name = Def->getMangledName(); 2150 OverloadMap.insert(std::make_pair(Name, OverloadInfo())); 2151 OverloadInfo &OI = OverloadMap[Name]; 2152 OI.Mask |= Mask; 2153 OI.PtrArgNum |= PtrArgNum; 2154 OI.HasConstPtr = HasConstPtr; 2155 } 2156 } 2157 2158 for (auto &I : OverloadMap) { 2159 OverloadInfo &OI = I.second; 2160 2161 OS << "case NEON::BI__builtin_neon_" << I.first << ": "; 2162 OS << "mask = 0x" << Twine::utohexstr(OI.Mask) << "ULL"; 2163 if (OI.PtrArgNum >= 0) 2164 OS << "; PtrArgNum = " << OI.PtrArgNum; 2165 if (OI.HasConstPtr) 2166 OS << "; HasConstPtr = true"; 2167 OS << "; break;\n"; 2168 } 2169 OS << "#endif\n\n"; 2170 } 2171 2172 void NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, 2173 SmallVectorImpl<Intrinsic *> &Defs) { 2174 OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n"; 2175 2176 std::set<std::string> Emitted; 2177 2178 for (auto *Def : Defs) { 2179 if (Def->hasBody()) 2180 continue; 2181 // Functions which do not have an immediate do not need to have range 2182 // checking code emitted. 2183 if (!Def->hasImmediate()) 2184 continue; 2185 if (Emitted.find(Def->getMangledName()) != Emitted.end()) 2186 continue; 2187 2188 std::string LowerBound, UpperBound; 2189 2190 Record *R = Def->getRecord(); 2191 if (R->getValueAsBit("isVCVT_N")) { 2192 // VCVT between floating- and fixed-point values takes an immediate 2193 // in the range [1, 32) for f32 or [1, 64) for f64 or [1, 16) for f16. 2194 LowerBound = "1"; 2195 if (Def->getBaseType().getElementSizeInBits() == 16 || 2196 Def->getName().find('h') != std::string::npos) 2197 // VCVTh operating on FP16 intrinsics in range [1, 16) 2198 UpperBound = "15"; 2199 else if (Def->getBaseType().getElementSizeInBits() == 32) 2200 UpperBound = "31"; 2201 else 2202 UpperBound = "63"; 2203 } else if (R->getValueAsBit("isScalarShift")) { 2204 // Right shifts have an 'r' in the name, left shifts do not. Convert 2205 // instructions have the same bounds and right shifts. 2206 if (Def->getName().find('r') != std::string::npos || 2207 Def->getName().find("cvt") != std::string::npos) 2208 LowerBound = "1"; 2209 2210 UpperBound = utostr(Def->getReturnType().getElementSizeInBits() - 1); 2211 } else if (R->getValueAsBit("isShift")) { 2212 // Builtins which are overloaded by type will need to have their upper 2213 // bound computed at Sema time based on the type constant. 2214 2215 // Right shifts have an 'r' in the name, left shifts do not. 2216 if (Def->getName().find('r') != std::string::npos) 2217 LowerBound = "1"; 2218 UpperBound = "RFT(TV, true)"; 2219 } else if (Def->getClassKind(true) == ClassB) { 2220 // ClassB intrinsics have a type (and hence lane number) that is only 2221 // known at runtime. 2222 if (R->getValueAsBit("isLaneQ")) 2223 UpperBound = "RFT(TV, false, true)"; 2224 else 2225 UpperBound = "RFT(TV, false, false)"; 2226 } else { 2227 // The immediate generally refers to a lane in the preceding argument. 2228 assert(Def->getImmediateIdx() > 0); 2229 Type T = Def->getParamType(Def->getImmediateIdx() - 1); 2230 UpperBound = utostr(T.getNumElements() - 1); 2231 } 2232 2233 // Calculate the index of the immediate that should be range checked. 2234 unsigned Idx = Def->getNumParams(); 2235 if (Def->hasImmediate()) 2236 Idx = Def->getGeneratedParamIdx(Def->getImmediateIdx()); 2237 2238 OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ": " 2239 << "i = " << Idx << ";"; 2240 if (!LowerBound.empty()) 2241 OS << " l = " << LowerBound << ";"; 2242 if (!UpperBound.empty()) 2243 OS << " u = " << UpperBound << ";"; 2244 OS << " break;\n"; 2245 2246 Emitted.insert(Def->getMangledName()); 2247 } 2248 2249 OS << "#endif\n\n"; 2250 } 2251 2252 /// runHeader - Emit a file with sections defining: 2253 /// 1. the NEON section of BuiltinsARM.def and BuiltinsAArch64.def. 2254 /// 2. the SemaChecking code for the type overload checking. 2255 /// 3. the SemaChecking code for validation of intrinsic immediate arguments. 2256 void NeonEmitter::runHeader(raw_ostream &OS) { 2257 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2258 2259 SmallVector<Intrinsic *, 128> Defs; 2260 for (auto *R : RV) 2261 createIntrinsic(R, Defs); 2262 2263 // Generate shared BuiltinsXXX.def 2264 genBuiltinsDef(OS, Defs); 2265 2266 // Generate ARM overloaded type checking code for SemaChecking.cpp 2267 genOverloadTypeCheckCode(OS, Defs); 2268 2269 // Generate ARM range checking code for shift/lane immediates. 2270 genIntrinsicRangeCheckCode(OS, Defs); 2271 } 2272 2273 /// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h 2274 /// is comprised of type definitions and function declarations. 2275 void NeonEmitter::run(raw_ostream &OS) { 2276 OS << "/*===---- arm_neon.h - ARM Neon intrinsics " 2277 "------------------------------" 2278 "---===\n" 2279 " *\n" 2280 " * Permission is hereby granted, free of charge, to any person " 2281 "obtaining " 2282 "a copy\n" 2283 " * of this software and associated documentation files (the " 2284 "\"Software\")," 2285 " to deal\n" 2286 " * in the Software without restriction, including without limitation " 2287 "the " 2288 "rights\n" 2289 " * to use, copy, modify, merge, publish, distribute, sublicense, " 2290 "and/or sell\n" 2291 " * copies of the Software, and to permit persons to whom the Software " 2292 "is\n" 2293 " * furnished to do so, subject to the following conditions:\n" 2294 " *\n" 2295 " * The above copyright notice and this permission notice shall be " 2296 "included in\n" 2297 " * all copies or substantial portions of the Software.\n" 2298 " *\n" 2299 " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, " 2300 "EXPRESS OR\n" 2301 " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " 2302 "MERCHANTABILITY,\n" 2303 " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT " 2304 "SHALL THE\n" 2305 " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR " 2306 "OTHER\n" 2307 " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, " 2308 "ARISING FROM,\n" 2309 " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER " 2310 "DEALINGS IN\n" 2311 " * THE SOFTWARE.\n" 2312 " *\n" 2313 " *===-----------------------------------------------------------------" 2314 "---" 2315 "---===\n" 2316 " */\n\n"; 2317 2318 OS << "#ifndef __ARM_NEON_H\n"; 2319 OS << "#define __ARM_NEON_H\n\n"; 2320 2321 OS << "#if !defined(__ARM_NEON)\n"; 2322 OS << "#error \"NEON support not enabled\"\n"; 2323 OS << "#endif\n\n"; 2324 2325 OS << "#include <stdint.h>\n\n"; 2326 2327 // Emit NEON-specific scalar typedefs. 2328 OS << "typedef float float32_t;\n"; 2329 OS << "typedef __fp16 float16_t;\n"; 2330 2331 OS << "#ifdef __aarch64__\n"; 2332 OS << "typedef double float64_t;\n"; 2333 OS << "#endif\n\n"; 2334 2335 // For now, signedness of polynomial types depends on target 2336 OS << "#ifdef __aarch64__\n"; 2337 OS << "typedef uint8_t poly8_t;\n"; 2338 OS << "typedef uint16_t poly16_t;\n"; 2339 OS << "typedef uint64_t poly64_t;\n"; 2340 OS << "typedef __uint128_t poly128_t;\n"; 2341 OS << "#else\n"; 2342 OS << "typedef int8_t poly8_t;\n"; 2343 OS << "typedef int16_t poly16_t;\n"; 2344 OS << "#endif\n"; 2345 2346 // Emit Neon vector typedefs. 2347 std::string TypedefTypes( 2348 "cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPsPlQPl"); 2349 std::vector<TypeSpec> TDTypeVec = TypeSpec::fromTypeSpecs(TypedefTypes); 2350 2351 // Emit vector typedefs. 2352 bool InIfdef = false; 2353 for (auto &TS : TDTypeVec) { 2354 bool IsA64 = false; 2355 Type T(TS, 'd'); 2356 if (T.isDouble() || (T.isPoly() && T.getElementSizeInBits() == 64)) 2357 IsA64 = true; 2358 2359 if (InIfdef && !IsA64) { 2360 OS << "#endif\n"; 2361 InIfdef = false; 2362 } 2363 if (!InIfdef && IsA64) { 2364 OS << "#ifdef __aarch64__\n"; 2365 InIfdef = true; 2366 } 2367 2368 if (T.isPoly()) 2369 OS << "typedef __attribute__((neon_polyvector_type("; 2370 else 2371 OS << "typedef __attribute__((neon_vector_type("; 2372 2373 Type T2 = T; 2374 T2.makeScalar(); 2375 OS << T.getNumElements() << "))) "; 2376 OS << T2.str(); 2377 OS << " " << T.str() << ";\n"; 2378 } 2379 if (InIfdef) 2380 OS << "#endif\n"; 2381 OS << "\n"; 2382 2383 // Emit struct typedefs. 2384 InIfdef = false; 2385 for (unsigned NumMembers = 2; NumMembers <= 4; ++NumMembers) { 2386 for (auto &TS : TDTypeVec) { 2387 bool IsA64 = false; 2388 Type T(TS, 'd'); 2389 if (T.isDouble() || (T.isPoly() && T.getElementSizeInBits() == 64)) 2390 IsA64 = true; 2391 2392 if (InIfdef && !IsA64) { 2393 OS << "#endif\n"; 2394 InIfdef = false; 2395 } 2396 if (!InIfdef && IsA64) { 2397 OS << "#ifdef __aarch64__\n"; 2398 InIfdef = true; 2399 } 2400 2401 char M = '2' + (NumMembers - 2); 2402 Type VT(TS, M); 2403 OS << "typedef struct " << VT.str() << " {\n"; 2404 OS << " " << T.str() << " val"; 2405 OS << "[" << NumMembers << "]"; 2406 OS << ";\n} "; 2407 OS << VT.str() << ";\n"; 2408 OS << "\n"; 2409 } 2410 } 2411 if (InIfdef) 2412 OS << "#endif\n"; 2413 OS << "\n"; 2414 2415 OS << "#define __ai static __inline__ __attribute__((__always_inline__, " 2416 "__nodebug__))\n\n"; 2417 2418 SmallVector<Intrinsic *, 128> Defs; 2419 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2420 for (auto *R : RV) 2421 createIntrinsic(R, Defs); 2422 2423 for (auto *I : Defs) 2424 I->indexBody(); 2425 2426 llvm::stable_sort(Defs, llvm::deref<std::less<>>()); 2427 2428 // Only emit a def when its requirements have been met. 2429 // FIXME: This loop could be made faster, but it's fast enough for now. 2430 bool MadeProgress = true; 2431 std::string InGuard; 2432 while (!Defs.empty() && MadeProgress) { 2433 MadeProgress = false; 2434 2435 for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin(); 2436 I != Defs.end(); /*No step*/) { 2437 bool DependenciesSatisfied = true; 2438 for (auto *II : (*I)->getDependencies()) { 2439 if (llvm::is_contained(Defs, II)) 2440 DependenciesSatisfied = false; 2441 } 2442 if (!DependenciesSatisfied) { 2443 // Try the next one. 2444 ++I; 2445 continue; 2446 } 2447 2448 // Emit #endif/#if pair if needed. 2449 if ((*I)->getGuard() != InGuard) { 2450 if (!InGuard.empty()) 2451 OS << "#endif\n"; 2452 InGuard = (*I)->getGuard(); 2453 if (!InGuard.empty()) 2454 OS << "#if " << InGuard << "\n"; 2455 } 2456 2457 // Actually generate the intrinsic code. 2458 OS << (*I)->generate(); 2459 2460 MadeProgress = true; 2461 I = Defs.erase(I); 2462 } 2463 } 2464 assert(Defs.empty() && "Some requirements were not satisfied!"); 2465 if (!InGuard.empty()) 2466 OS << "#endif\n"; 2467 2468 OS << "\n"; 2469 OS << "#undef __ai\n\n"; 2470 OS << "#endif /* __ARM_NEON_H */\n"; 2471 } 2472 2473 /// run - Read the records in arm_fp16.td and output arm_fp16.h. arm_fp16.h 2474 /// is comprised of type definitions and function declarations. 2475 void NeonEmitter::runFP16(raw_ostream &OS) { 2476 OS << "/*===---- arm_fp16.h - ARM FP16 intrinsics " 2477 "------------------------------" 2478 "---===\n" 2479 " *\n" 2480 " * Permission is hereby granted, free of charge, to any person " 2481 "obtaining a copy\n" 2482 " * of this software and associated documentation files (the " 2483 "\"Software\"), to deal\n" 2484 " * in the Software without restriction, including without limitation " 2485 "the rights\n" 2486 " * to use, copy, modify, merge, publish, distribute, sublicense, " 2487 "and/or sell\n" 2488 " * copies of the Software, and to permit persons to whom the Software " 2489 "is\n" 2490 " * furnished to do so, subject to the following conditions:\n" 2491 " *\n" 2492 " * The above copyright notice and this permission notice shall be " 2493 "included in\n" 2494 " * all copies or substantial portions of the Software.\n" 2495 " *\n" 2496 " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, " 2497 "EXPRESS OR\n" 2498 " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " 2499 "MERCHANTABILITY,\n" 2500 " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT " 2501 "SHALL THE\n" 2502 " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR " 2503 "OTHER\n" 2504 " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, " 2505 "ARISING FROM,\n" 2506 " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER " 2507 "DEALINGS IN\n" 2508 " * THE SOFTWARE.\n" 2509 " *\n" 2510 " *===-----------------------------------------------------------------" 2511 "---" 2512 "---===\n" 2513 " */\n\n"; 2514 2515 OS << "#ifndef __ARM_FP16_H\n"; 2516 OS << "#define __ARM_FP16_H\n\n"; 2517 2518 OS << "#include <stdint.h>\n\n"; 2519 2520 OS << "typedef __fp16 float16_t;\n"; 2521 2522 OS << "#define __ai static __inline__ __attribute__((__always_inline__, " 2523 "__nodebug__))\n\n"; 2524 2525 SmallVector<Intrinsic *, 128> Defs; 2526 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2527 for (auto *R : RV) 2528 createIntrinsic(R, Defs); 2529 2530 for (auto *I : Defs) 2531 I->indexBody(); 2532 2533 llvm::stable_sort(Defs, llvm::deref<std::less<>>()); 2534 2535 // Only emit a def when its requirements have been met. 2536 // FIXME: This loop could be made faster, but it's fast enough for now. 2537 bool MadeProgress = true; 2538 std::string InGuard; 2539 while (!Defs.empty() && MadeProgress) { 2540 MadeProgress = false; 2541 2542 for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin(); 2543 I != Defs.end(); /*No step*/) { 2544 bool DependenciesSatisfied = true; 2545 for (auto *II : (*I)->getDependencies()) { 2546 if (llvm::is_contained(Defs, II)) 2547 DependenciesSatisfied = false; 2548 } 2549 if (!DependenciesSatisfied) { 2550 // Try the next one. 2551 ++I; 2552 continue; 2553 } 2554 2555 // Emit #endif/#if pair if needed. 2556 if ((*I)->getGuard() != InGuard) { 2557 if (!InGuard.empty()) 2558 OS << "#endif\n"; 2559 InGuard = (*I)->getGuard(); 2560 if (!InGuard.empty()) 2561 OS << "#if " << InGuard << "\n"; 2562 } 2563 2564 // Actually generate the intrinsic code. 2565 OS << (*I)->generate(); 2566 2567 MadeProgress = true; 2568 I = Defs.erase(I); 2569 } 2570 } 2571 assert(Defs.empty() && "Some requirements were not satisfied!"); 2572 if (!InGuard.empty()) 2573 OS << "#endif\n"; 2574 2575 OS << "\n"; 2576 OS << "#undef __ai\n\n"; 2577 OS << "#endif /* __ARM_FP16_H */\n"; 2578 } 2579 2580 void clang::EmitNeon(RecordKeeper &Records, raw_ostream &OS) { 2581 NeonEmitter(Records).run(OS); 2582 } 2583 2584 void clang::EmitFP16(RecordKeeper &Records, raw_ostream &OS) { 2585 NeonEmitter(Records).runFP16(OS); 2586 } 2587 2588 void clang::EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { 2589 NeonEmitter(Records).runHeader(OS); 2590 } 2591 2592 void clang::EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { 2593 llvm_unreachable("Neon test generation no longer implemented!"); 2594 } 2595