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