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