xref: /freebsd/contrib/llvm-project/clang/utils/TableGen/SveEmitter.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===- SveEmitter.cpp - Generate arm_sve.h for use with clang -*- C++ -*-===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric //  Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric //  See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric //  SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric //
95ffd83dbSDimitry Andric // This tablegen backend is responsible for emitting arm_sve.h, which includes
105ffd83dbSDimitry Andric // a declaration and definition of each function specified by the ARM C/C++
115ffd83dbSDimitry Andric // Language Extensions (ACLE).
125ffd83dbSDimitry Andric //
135ffd83dbSDimitry Andric // For details, visit:
145ffd83dbSDimitry Andric //  https://developer.arm.com/architectures/system-architectures/software-standards/acle
155ffd83dbSDimitry Andric //
165ffd83dbSDimitry Andric // Each SVE instruction is implemented in terms of 1 or more functions which
175ffd83dbSDimitry Andric // are suffixed with the element type of the input vectors.  Functions may be
185ffd83dbSDimitry Andric // implemented in terms of generic vector operations such as +, *, -, etc. or
195ffd83dbSDimitry Andric // by calling a __builtin_-prefixed function which will be handled by clang's
205ffd83dbSDimitry Andric // CodeGen library.
215ffd83dbSDimitry Andric //
225ffd83dbSDimitry Andric // See also the documentation in include/clang/Basic/arm_sve.td.
235ffd83dbSDimitry Andric //
245ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
255ffd83dbSDimitry Andric 
265ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
275ffd83dbSDimitry Andric #include "llvm/ADT/StringMap.h"
285ffd83dbSDimitry Andric #include "llvm/ADT/ArrayRef.h"
295ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h"
305ffd83dbSDimitry Andric #include "llvm/TableGen/Record.h"
315ffd83dbSDimitry Andric #include "llvm/TableGen/Error.h"
325ffd83dbSDimitry Andric #include <string>
335ffd83dbSDimitry Andric #include <sstream>
345ffd83dbSDimitry Andric #include <set>
355ffd83dbSDimitry Andric #include <cctype>
365ffd83dbSDimitry Andric #include <tuple>
375ffd83dbSDimitry Andric 
385ffd83dbSDimitry Andric using namespace llvm;
395ffd83dbSDimitry Andric 
405ffd83dbSDimitry Andric enum ClassKind {
415ffd83dbSDimitry Andric   ClassNone,
425ffd83dbSDimitry Andric   ClassS,     // signed/unsigned, e.g., "_s8", "_u8" suffix
435ffd83dbSDimitry Andric   ClassG,     // Overloaded name without type suffix
445ffd83dbSDimitry Andric };
455ffd83dbSDimitry Andric 
465ffd83dbSDimitry Andric using TypeSpec = std::string;
475ffd83dbSDimitry Andric 
485ffd83dbSDimitry Andric namespace {
495ffd83dbSDimitry Andric 
505ffd83dbSDimitry Andric class ImmCheck {
515ffd83dbSDimitry Andric   unsigned Arg;
525ffd83dbSDimitry Andric   unsigned Kind;
535ffd83dbSDimitry Andric   unsigned ElementSizeInBits;
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric public:
565ffd83dbSDimitry Andric   ImmCheck(unsigned Arg, unsigned Kind, unsigned ElementSizeInBits = 0)
575ffd83dbSDimitry Andric       : Arg(Arg), Kind(Kind), ElementSizeInBits(ElementSizeInBits) {}
585ffd83dbSDimitry Andric   ImmCheck(const ImmCheck &Other) = default;
595ffd83dbSDimitry Andric   ~ImmCheck() = default;
605ffd83dbSDimitry Andric 
615ffd83dbSDimitry Andric   unsigned getArg() const { return Arg; }
625ffd83dbSDimitry Andric   unsigned getKind() const { return Kind; }
635ffd83dbSDimitry Andric   unsigned getElementSizeInBits() const { return ElementSizeInBits; }
645ffd83dbSDimitry Andric };
655ffd83dbSDimitry Andric 
665ffd83dbSDimitry Andric class SVEType {
675ffd83dbSDimitry Andric   TypeSpec TS;
685ffd83dbSDimitry Andric   bool Float, Signed, Immediate, Void, Constant, Pointer, BFloat;
69*06c3fb27SDimitry Andric   bool DefaultType, IsScalable, Predicate, PredicatePattern, PrefetchOp,
70*06c3fb27SDimitry Andric       Svcount;
715ffd83dbSDimitry Andric   unsigned Bitwidth, ElementBitwidth, NumVectors;
725ffd83dbSDimitry Andric 
735ffd83dbSDimitry Andric public:
745ffd83dbSDimitry Andric   SVEType() : SVEType(TypeSpec(), 'v') {}
755ffd83dbSDimitry Andric 
765ffd83dbSDimitry Andric   SVEType(TypeSpec TS, char CharMod)
775ffd83dbSDimitry Andric       : TS(TS), Float(false), Signed(true), Immediate(false), Void(false),
785ffd83dbSDimitry Andric         Constant(false), Pointer(false), BFloat(false), DefaultType(false),
795ffd83dbSDimitry Andric         IsScalable(true), Predicate(false), PredicatePattern(false),
80*06c3fb27SDimitry Andric         PrefetchOp(false), Svcount(false), Bitwidth(128), ElementBitwidth(~0U),
81*06c3fb27SDimitry Andric         NumVectors(1) {
825ffd83dbSDimitry Andric     if (!TS.empty())
835ffd83dbSDimitry Andric       applyTypespec();
845ffd83dbSDimitry Andric     applyModifier(CharMod);
855ffd83dbSDimitry Andric   }
865ffd83dbSDimitry Andric 
875ffd83dbSDimitry Andric   bool isPointer() const { return Pointer; }
885ffd83dbSDimitry Andric   bool isVoidPointer() const { return Pointer && Void; }
895ffd83dbSDimitry Andric   bool isSigned() const { return Signed; }
905ffd83dbSDimitry Andric   bool isImmediate() const { return Immediate; }
915ffd83dbSDimitry Andric   bool isScalar() const { return NumVectors == 0; }
925ffd83dbSDimitry Andric   bool isVector() const { return NumVectors > 0; }
935ffd83dbSDimitry Andric   bool isScalableVector() const { return isVector() && IsScalable; }
945ffd83dbSDimitry Andric   bool isChar() const { return ElementBitwidth == 8; }
955ffd83dbSDimitry Andric   bool isVoid() const { return Void & !Pointer; }
965ffd83dbSDimitry Andric   bool isDefault() const { return DefaultType; }
975ffd83dbSDimitry Andric   bool isFloat() const { return Float && !BFloat; }
985ffd83dbSDimitry Andric   bool isBFloat() const { return BFloat && !Float; }
995ffd83dbSDimitry Andric   bool isFloatingPoint() const { return Float || BFloat; }
100*06c3fb27SDimitry Andric   bool isInteger() const {
101*06c3fb27SDimitry Andric     return !isFloatingPoint() && !Predicate && !Svcount;
102*06c3fb27SDimitry Andric   }
1035ffd83dbSDimitry Andric   bool isScalarPredicate() const {
1045ffd83dbSDimitry Andric     return !isFloatingPoint() && Predicate && NumVectors == 0;
1055ffd83dbSDimitry Andric   }
1065ffd83dbSDimitry Andric   bool isPredicateVector() const { return Predicate; }
1075ffd83dbSDimitry Andric   bool isPredicatePattern() const { return PredicatePattern; }
1085ffd83dbSDimitry Andric   bool isPrefetchOp() const { return PrefetchOp; }
109*06c3fb27SDimitry Andric   bool isSvcount() const { return Svcount; }
1105ffd83dbSDimitry Andric   bool isConstant() const { return Constant; }
1115ffd83dbSDimitry Andric   unsigned getElementSizeInBits() const { return ElementBitwidth; }
1125ffd83dbSDimitry Andric   unsigned getNumVectors() const { return NumVectors; }
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric   unsigned getNumElements() const {
1155ffd83dbSDimitry Andric     assert(ElementBitwidth != ~0U);
1165ffd83dbSDimitry Andric     return Bitwidth / ElementBitwidth;
1175ffd83dbSDimitry Andric   }
1185ffd83dbSDimitry Andric   unsigned getSizeInBits() const {
1195ffd83dbSDimitry Andric     return Bitwidth;
1205ffd83dbSDimitry Andric   }
1215ffd83dbSDimitry Andric 
1225ffd83dbSDimitry Andric   /// Return the string representation of a type, which is an encoded
1235ffd83dbSDimitry Andric   /// string for passing to the BUILTIN() macro in Builtins.def.
1245ffd83dbSDimitry Andric   std::string builtin_str() const;
1255ffd83dbSDimitry Andric 
1265ffd83dbSDimitry Andric   /// Return the C/C++ string representation of a type for use in the
1275ffd83dbSDimitry Andric   /// arm_sve.h header file.
1285ffd83dbSDimitry Andric   std::string str() const;
1295ffd83dbSDimitry Andric 
1305ffd83dbSDimitry Andric private:
1315ffd83dbSDimitry Andric   /// Creates the type based on the typespec string in TS.
1325ffd83dbSDimitry Andric   void applyTypespec();
1335ffd83dbSDimitry Andric 
1345ffd83dbSDimitry Andric   /// Applies a prototype modifier to the type.
1355ffd83dbSDimitry Andric   void applyModifier(char Mod);
1365ffd83dbSDimitry Andric };
1375ffd83dbSDimitry Andric 
1385ffd83dbSDimitry Andric 
1395ffd83dbSDimitry Andric class SVEEmitter;
1405ffd83dbSDimitry Andric 
1415ffd83dbSDimitry Andric /// The main grunt class. This represents an instantiation of an intrinsic with
1425ffd83dbSDimitry Andric /// a particular typespec and prototype.
1435ffd83dbSDimitry Andric class Intrinsic {
1445ffd83dbSDimitry Andric   /// The unmangled name.
1455ffd83dbSDimitry Andric   std::string Name;
1465ffd83dbSDimitry Andric 
1475ffd83dbSDimitry Andric   /// The name of the corresponding LLVM IR intrinsic.
1485ffd83dbSDimitry Andric   std::string LLVMName;
1495ffd83dbSDimitry Andric 
1505ffd83dbSDimitry Andric   /// Intrinsic prototype.
1515ffd83dbSDimitry Andric   std::string Proto;
1525ffd83dbSDimitry Andric 
1535ffd83dbSDimitry Andric   /// The base type spec for this intrinsic.
1545ffd83dbSDimitry Andric   TypeSpec BaseTypeSpec;
1555ffd83dbSDimitry Andric 
1565ffd83dbSDimitry Andric   /// The base class kind. Most intrinsics use ClassS, which has full type
1575ffd83dbSDimitry Andric   /// info for integers (_s32/_u32), or ClassG which is used for overloaded
1585ffd83dbSDimitry Andric   /// intrinsics.
1595ffd83dbSDimitry Andric   ClassKind Class;
1605ffd83dbSDimitry Andric 
1615ffd83dbSDimitry Andric   /// The architectural #ifdef guard.
1625ffd83dbSDimitry Andric   std::string Guard;
1635ffd83dbSDimitry Andric 
1645ffd83dbSDimitry Andric   // The merge suffix such as _m, _x or _z.
1655ffd83dbSDimitry Andric   std::string MergeSuffix;
1665ffd83dbSDimitry Andric 
1675ffd83dbSDimitry Andric   /// The types of return value [0] and parameters [1..].
1685ffd83dbSDimitry Andric   std::vector<SVEType> Types;
1695ffd83dbSDimitry Andric 
1705ffd83dbSDimitry Andric   /// The "base type", which is VarType('d', BaseTypeSpec).
1715ffd83dbSDimitry Andric   SVEType BaseType;
1725ffd83dbSDimitry Andric 
1735ffd83dbSDimitry Andric   uint64_t Flags;
1745ffd83dbSDimitry Andric 
1755ffd83dbSDimitry Andric   SmallVector<ImmCheck, 2> ImmChecks;
1765ffd83dbSDimitry Andric 
1775ffd83dbSDimitry Andric public:
1785ffd83dbSDimitry Andric   Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
1795ffd83dbSDimitry Andric             StringRef MergeSuffix, uint64_t MemoryElementTy, StringRef LLVMName,
1805ffd83dbSDimitry Andric             uint64_t Flags, ArrayRef<ImmCheck> ImmChecks, TypeSpec BT,
1815ffd83dbSDimitry Andric             ClassKind Class, SVEEmitter &Emitter, StringRef Guard);
1825ffd83dbSDimitry Andric 
1835ffd83dbSDimitry Andric   ~Intrinsic()=default;
1845ffd83dbSDimitry Andric 
1855ffd83dbSDimitry Andric   std::string getName() const { return Name; }
1865ffd83dbSDimitry Andric   std::string getLLVMName() const { return LLVMName; }
1875ffd83dbSDimitry Andric   std::string getProto() const { return Proto; }
1885ffd83dbSDimitry Andric   TypeSpec getBaseTypeSpec() const { return BaseTypeSpec; }
1895ffd83dbSDimitry Andric   SVEType getBaseType() const { return BaseType; }
1905ffd83dbSDimitry Andric 
1915ffd83dbSDimitry Andric   StringRef getGuard() const { return Guard; }
1925ffd83dbSDimitry Andric   ClassKind getClassKind() const { return Class; }
1935ffd83dbSDimitry Andric 
1945ffd83dbSDimitry Andric   SVEType getReturnType() const { return Types[0]; }
1955ffd83dbSDimitry Andric   ArrayRef<SVEType> getTypes() const { return Types; }
1965ffd83dbSDimitry Andric   SVEType getParamType(unsigned I) const { return Types[I + 1]; }
1975ffd83dbSDimitry Andric   unsigned getNumParams() const { return Proto.size() - 1; }
1985ffd83dbSDimitry Andric 
1995ffd83dbSDimitry Andric   uint64_t getFlags() const { return Flags; }
2005ffd83dbSDimitry Andric   bool isFlagSet(uint64_t Flag) const { return Flags & Flag;}
2015ffd83dbSDimitry Andric 
2025ffd83dbSDimitry Andric   ArrayRef<ImmCheck> getImmChecks() const { return ImmChecks; }
2035ffd83dbSDimitry Andric 
2045ffd83dbSDimitry Andric   /// Return the type string for a BUILTIN() macro in Builtins.def.
2055ffd83dbSDimitry Andric   std::string getBuiltinTypeStr();
2065ffd83dbSDimitry Andric 
2075ffd83dbSDimitry Andric   /// Return the name, mangled with type information. The name is mangled for
2085ffd83dbSDimitry Andric   /// ClassS, so will add type suffixes such as _u32/_s32.
2095ffd83dbSDimitry Andric   std::string getMangledName() const { return mangleName(ClassS); }
2105ffd83dbSDimitry Andric 
211*06c3fb27SDimitry Andric   /// As above, but mangles the LLVM name instead.
212*06c3fb27SDimitry Andric   std::string getMangledLLVMName() const { return mangleLLVMName(); }
213*06c3fb27SDimitry Andric 
2145ffd83dbSDimitry Andric   /// Returns true if the intrinsic is overloaded, in that it should also generate
2155ffd83dbSDimitry Andric   /// a short form without the type-specifiers, e.g. 'svld1(..)' instead of
2165ffd83dbSDimitry Andric   /// 'svld1_u32(..)'.
2175ffd83dbSDimitry Andric   static bool isOverloadedIntrinsic(StringRef Name) {
218e8d8bef9SDimitry Andric     auto BrOpen = Name.find('[');
2195ffd83dbSDimitry Andric     auto BrClose = Name.find(']');
2205ffd83dbSDimitry Andric     return BrOpen != std::string::npos && BrClose != std::string::npos;
2215ffd83dbSDimitry Andric   }
2225ffd83dbSDimitry Andric 
2235ffd83dbSDimitry Andric   /// Return true if the intrinsic takes a splat operand.
2245ffd83dbSDimitry Andric   bool hasSplat() const {
2255ffd83dbSDimitry Andric     // These prototype modifiers are described in arm_sve.td.
2265ffd83dbSDimitry Andric     return Proto.find_first_of("ajfrKLR@") != std::string::npos;
2275ffd83dbSDimitry Andric   }
2285ffd83dbSDimitry Andric 
2295ffd83dbSDimitry Andric   /// Return the parameter index of the splat operand.
2305ffd83dbSDimitry Andric   unsigned getSplatIdx() const {
2315ffd83dbSDimitry Andric     // These prototype modifiers are described in arm_sve.td.
2325ffd83dbSDimitry Andric     auto Idx = Proto.find_first_of("ajfrKLR@");
2335ffd83dbSDimitry Andric     assert(Idx != std::string::npos && Idx > 0 &&
2345ffd83dbSDimitry Andric            "Prototype has no splat operand");
2355ffd83dbSDimitry Andric     return Idx - 1;
2365ffd83dbSDimitry Andric   }
2375ffd83dbSDimitry Andric 
2385ffd83dbSDimitry Andric   /// Emits the intrinsic declaration to the ostream.
239*06c3fb27SDimitry Andric   void emitIntrinsic(raw_ostream &OS, SVEEmitter &Emitter) const;
2405ffd83dbSDimitry Andric 
2415ffd83dbSDimitry Andric private:
2425ffd83dbSDimitry Andric   std::string getMergeSuffix() const { return MergeSuffix; }
2435ffd83dbSDimitry Andric   std::string mangleName(ClassKind LocalCK) const;
244*06c3fb27SDimitry Andric   std::string mangleLLVMName() const;
2455ffd83dbSDimitry Andric   std::string replaceTemplatedArgs(std::string Name, TypeSpec TS,
2465ffd83dbSDimitry Andric                                    std::string Proto) const;
2475ffd83dbSDimitry Andric };
2485ffd83dbSDimitry Andric 
2495ffd83dbSDimitry Andric class SVEEmitter {
2505ffd83dbSDimitry Andric private:
2515ffd83dbSDimitry Andric   // The reinterpret builtins are generated separately because they
2525ffd83dbSDimitry Andric   // need the cross product of all types (121 functions in total),
2535ffd83dbSDimitry Andric   // which is inconvenient to specify in the arm_sve.td file or
2545ffd83dbSDimitry Andric   // generate in CGBuiltin.cpp.
2555ffd83dbSDimitry Andric   struct ReinterpretTypeInfo {
2565ffd83dbSDimitry Andric     const char *Suffix;
2575ffd83dbSDimitry Andric     const char *Type;
2585ffd83dbSDimitry Andric     const char *BuiltinType;
2595ffd83dbSDimitry Andric   };
2605ffd83dbSDimitry Andric   SmallVector<ReinterpretTypeInfo, 12> Reinterprets = {
2615ffd83dbSDimitry Andric       {"s8", "svint8_t", "q16Sc"},   {"s16", "svint16_t", "q8Ss"},
2625ffd83dbSDimitry Andric       {"s32", "svint32_t", "q4Si"},  {"s64", "svint64_t", "q2SWi"},
2635ffd83dbSDimitry Andric       {"u8", "svuint8_t", "q16Uc"},  {"u16", "svuint16_t", "q8Us"},
2645ffd83dbSDimitry Andric       {"u32", "svuint32_t", "q4Ui"}, {"u64", "svuint64_t", "q2UWi"},
2655ffd83dbSDimitry Andric       {"f16", "svfloat16_t", "q8h"}, {"bf16", "svbfloat16_t", "q8y"},
2665ffd83dbSDimitry Andric       {"f32", "svfloat32_t", "q4f"}, {"f64", "svfloat64_t", "q2d"}};
2675ffd83dbSDimitry Andric 
2685ffd83dbSDimitry Andric   RecordKeeper &Records;
2695ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> EltTypes;
2705ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> MemEltTypes;
2715ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> FlagTypes;
2725ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> MergeTypes;
2735ffd83dbSDimitry Andric   llvm::StringMap<uint64_t> ImmCheckTypes;
2745ffd83dbSDimitry Andric 
2755ffd83dbSDimitry Andric public:
2765ffd83dbSDimitry Andric   SVEEmitter(RecordKeeper &R) : Records(R) {
2775ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("EltType"))
2785ffd83dbSDimitry Andric       EltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
2795ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("MemEltType"))
2805ffd83dbSDimitry Andric       MemEltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
2815ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("FlagType"))
2825ffd83dbSDimitry Andric       FlagTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
2835ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("MergeType"))
2845ffd83dbSDimitry Andric       MergeTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
2855ffd83dbSDimitry Andric     for (auto *RV : Records.getAllDerivedDefinitions("ImmCheckType"))
2865ffd83dbSDimitry Andric       ImmCheckTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
2875ffd83dbSDimitry Andric   }
2885ffd83dbSDimitry Andric 
2895ffd83dbSDimitry Andric   /// Returns the enum value for the immcheck type
2905ffd83dbSDimitry Andric   unsigned getEnumValueForImmCheck(StringRef C) const {
2915ffd83dbSDimitry Andric     auto It = ImmCheckTypes.find(C);
2925ffd83dbSDimitry Andric     if (It != ImmCheckTypes.end())
2935ffd83dbSDimitry Andric       return It->getValue();
2945ffd83dbSDimitry Andric     llvm_unreachable("Unsupported imm check");
2955ffd83dbSDimitry Andric   }
2965ffd83dbSDimitry Andric 
2975ffd83dbSDimitry Andric   /// Returns the enum value for the flag type
2985ffd83dbSDimitry Andric   uint64_t getEnumValueForFlag(StringRef C) const {
2995ffd83dbSDimitry Andric     auto Res = FlagTypes.find(C);
3005ffd83dbSDimitry Andric     if (Res != FlagTypes.end())
3015ffd83dbSDimitry Andric       return Res->getValue();
3025ffd83dbSDimitry Andric     llvm_unreachable("Unsupported flag");
3035ffd83dbSDimitry Andric   }
3045ffd83dbSDimitry Andric 
3055ffd83dbSDimitry Andric   // Returns the SVETypeFlags for a given value and mask.
3065ffd83dbSDimitry Andric   uint64_t encodeFlag(uint64_t V, StringRef MaskName) const {
3075ffd83dbSDimitry Andric     auto It = FlagTypes.find(MaskName);
3085ffd83dbSDimitry Andric     if (It != FlagTypes.end()) {
3095ffd83dbSDimitry Andric       uint64_t Mask = It->getValue();
310*06c3fb27SDimitry Andric       unsigned Shift = llvm::countr_zero(Mask);
311*06c3fb27SDimitry Andric       assert(Shift < 64 && "Mask value produced an invalid shift value");
3125ffd83dbSDimitry Andric       return (V << Shift) & Mask;
3135ffd83dbSDimitry Andric     }
3145ffd83dbSDimitry Andric     llvm_unreachable("Unsupported flag");
3155ffd83dbSDimitry Andric   }
3165ffd83dbSDimitry Andric 
3175ffd83dbSDimitry Andric   // Returns the SVETypeFlags for the given element type.
3185ffd83dbSDimitry Andric   uint64_t encodeEltType(StringRef EltName) {
3195ffd83dbSDimitry Andric     auto It = EltTypes.find(EltName);
3205ffd83dbSDimitry Andric     if (It != EltTypes.end())
3215ffd83dbSDimitry Andric       return encodeFlag(It->getValue(), "EltTypeMask");
3225ffd83dbSDimitry Andric     llvm_unreachable("Unsupported EltType");
3235ffd83dbSDimitry Andric   }
3245ffd83dbSDimitry Andric 
3255ffd83dbSDimitry Andric   // Returns the SVETypeFlags for the given memory element type.
3265ffd83dbSDimitry Andric   uint64_t encodeMemoryElementType(uint64_t MT) {
3275ffd83dbSDimitry Andric     return encodeFlag(MT, "MemEltTypeMask");
3285ffd83dbSDimitry Andric   }
3295ffd83dbSDimitry Andric 
3305ffd83dbSDimitry Andric   // Returns the SVETypeFlags for the given merge type.
3315ffd83dbSDimitry Andric   uint64_t encodeMergeType(uint64_t MT) {
3325ffd83dbSDimitry Andric     return encodeFlag(MT, "MergeTypeMask");
3335ffd83dbSDimitry Andric   }
3345ffd83dbSDimitry Andric 
3355ffd83dbSDimitry Andric   // Returns the SVETypeFlags for the given splat operand.
3365ffd83dbSDimitry Andric   unsigned encodeSplatOperand(unsigned SplatIdx) {
3375ffd83dbSDimitry Andric     assert(SplatIdx < 7 && "SplatIdx out of encodable range");
3385ffd83dbSDimitry Andric     return encodeFlag(SplatIdx + 1, "SplatOperandMask");
3395ffd83dbSDimitry Andric   }
3405ffd83dbSDimitry Andric 
3415ffd83dbSDimitry Andric   // Returns the SVETypeFlags value for the given SVEType.
3425ffd83dbSDimitry Andric   uint64_t encodeTypeFlags(const SVEType &T);
3435ffd83dbSDimitry Andric 
3445ffd83dbSDimitry Andric   /// Emit arm_sve.h.
3455ffd83dbSDimitry Andric   void createHeader(raw_ostream &o);
3465ffd83dbSDimitry Andric 
3475ffd83dbSDimitry Andric   /// Emit all the __builtin prototypes and code needed by Sema.
3485ffd83dbSDimitry Andric   void createBuiltins(raw_ostream &o);
3495ffd83dbSDimitry Andric 
3505ffd83dbSDimitry Andric   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
3515ffd83dbSDimitry Andric   void createCodeGenMap(raw_ostream &o);
3525ffd83dbSDimitry Andric 
3535ffd83dbSDimitry Andric   /// Emit all the range checks for the immediates.
3545ffd83dbSDimitry Andric   void createRangeChecks(raw_ostream &o);
3555ffd83dbSDimitry Andric 
3565ffd83dbSDimitry Andric   /// Create the SVETypeFlags used in CGBuiltins
3575ffd83dbSDimitry Andric   void createTypeFlags(raw_ostream &o);
3585ffd83dbSDimitry Andric 
359*06c3fb27SDimitry Andric   /// Emit arm_sme.h.
360*06c3fb27SDimitry Andric   void createSMEHeader(raw_ostream &o);
361*06c3fb27SDimitry Andric 
362*06c3fb27SDimitry Andric   /// Emit all the SME __builtin prototypes and code needed by Sema.
363*06c3fb27SDimitry Andric   void createSMEBuiltins(raw_ostream &o);
364*06c3fb27SDimitry Andric 
365*06c3fb27SDimitry Andric   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
366*06c3fb27SDimitry Andric   void createSMECodeGenMap(raw_ostream &o);
367*06c3fb27SDimitry Andric 
368*06c3fb27SDimitry Andric   /// Emit all the range checks for the immediates.
369*06c3fb27SDimitry Andric   void createSMERangeChecks(raw_ostream &o);
370*06c3fb27SDimitry Andric 
3715ffd83dbSDimitry Andric   /// Create intrinsic and add it to \p Out
372*06c3fb27SDimitry Andric   void createIntrinsic(Record *R,
373*06c3fb27SDimitry Andric                        SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out);
3745ffd83dbSDimitry Andric };
3755ffd83dbSDimitry Andric 
3765ffd83dbSDimitry Andric } // end anonymous namespace
3775ffd83dbSDimitry Andric 
3785ffd83dbSDimitry Andric 
3795ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
3805ffd83dbSDimitry Andric // Type implementation
3815ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
3825ffd83dbSDimitry Andric 
3835ffd83dbSDimitry Andric std::string SVEType::builtin_str() const {
3845ffd83dbSDimitry Andric   std::string S;
3855ffd83dbSDimitry Andric   if (isVoid())
3865ffd83dbSDimitry Andric     return "v";
3875ffd83dbSDimitry Andric 
388fe6060f1SDimitry Andric   if (isScalarPredicate())
389fe6060f1SDimitry Andric     return "b";
390fe6060f1SDimitry Andric 
391*06c3fb27SDimitry Andric   if (isSvcount())
392*06c3fb27SDimitry Andric     return "Qa";
393*06c3fb27SDimitry Andric 
3945ffd83dbSDimitry Andric   if (isVoidPointer())
3955ffd83dbSDimitry Andric     S += "v";
3965ffd83dbSDimitry Andric   else if (!isFloatingPoint())
3975ffd83dbSDimitry Andric     switch (ElementBitwidth) {
3985ffd83dbSDimitry Andric     case 1: S += "b"; break;
3995ffd83dbSDimitry Andric     case 8: S += "c"; break;
4005ffd83dbSDimitry Andric     case 16: S += "s"; break;
4015ffd83dbSDimitry Andric     case 32: S += "i"; break;
4025ffd83dbSDimitry Andric     case 64: S += "Wi"; break;
4035ffd83dbSDimitry Andric     case 128: S += "LLLi"; break;
4045ffd83dbSDimitry Andric     default: llvm_unreachable("Unhandled case!");
4055ffd83dbSDimitry Andric     }
4065ffd83dbSDimitry Andric   else if (isFloat())
4075ffd83dbSDimitry Andric     switch (ElementBitwidth) {
4085ffd83dbSDimitry Andric     case 16: S += "h"; break;
4095ffd83dbSDimitry Andric     case 32: S += "f"; break;
4105ffd83dbSDimitry Andric     case 64: S += "d"; break;
4115ffd83dbSDimitry Andric     default: llvm_unreachable("Unhandled case!");
4125ffd83dbSDimitry Andric     }
4135ffd83dbSDimitry Andric   else if (isBFloat()) {
4145ffd83dbSDimitry Andric     assert(ElementBitwidth == 16 && "Not a valid BFloat.");
4155ffd83dbSDimitry Andric     S += "y";
4165ffd83dbSDimitry Andric   }
4175ffd83dbSDimitry Andric 
4185ffd83dbSDimitry Andric   if (!isFloatingPoint()) {
4195ffd83dbSDimitry Andric     if ((isChar() || isPointer()) && !isVoidPointer()) {
4205ffd83dbSDimitry Andric       // Make chars and typed pointers explicitly signed.
4215ffd83dbSDimitry Andric       if (Signed)
4225ffd83dbSDimitry Andric         S = "S" + S;
4235ffd83dbSDimitry Andric       else if (!Signed)
4245ffd83dbSDimitry Andric         S = "U" + S;
4255ffd83dbSDimitry Andric     } else if (!isVoidPointer() && !Signed) {
4265ffd83dbSDimitry Andric       S = "U" + S;
4275ffd83dbSDimitry Andric     }
4285ffd83dbSDimitry Andric   }
4295ffd83dbSDimitry Andric 
4305ffd83dbSDimitry Andric   // Constant indices are "int", but have the "constant expression" modifier.
4315ffd83dbSDimitry Andric   if (isImmediate()) {
4325ffd83dbSDimitry Andric     assert(!isFloat() && "fp immediates are not supported");
4335ffd83dbSDimitry Andric     S = "I" + S;
4345ffd83dbSDimitry Andric   }
4355ffd83dbSDimitry Andric 
4365ffd83dbSDimitry Andric   if (isScalar()) {
4375ffd83dbSDimitry Andric     if (Constant) S += "C";
4385ffd83dbSDimitry Andric     if (Pointer) S += "*";
4395ffd83dbSDimitry Andric     return S;
4405ffd83dbSDimitry Andric   }
4415ffd83dbSDimitry Andric 
4425ffd83dbSDimitry Andric   assert(isScalableVector() && "Unsupported type");
4435ffd83dbSDimitry Andric   return "q" + utostr(getNumElements() * NumVectors) + S;
4445ffd83dbSDimitry Andric }
4455ffd83dbSDimitry Andric 
4465ffd83dbSDimitry Andric std::string SVEType::str() const {
4475ffd83dbSDimitry Andric   if (isPredicatePattern())
448e8d8bef9SDimitry Andric     return "enum svpattern";
4495ffd83dbSDimitry Andric 
4505ffd83dbSDimitry Andric   if (isPrefetchOp())
451e8d8bef9SDimitry Andric     return "enum svprfop";
4525ffd83dbSDimitry Andric 
4535ffd83dbSDimitry Andric   std::string S;
4545ffd83dbSDimitry Andric   if (Void)
4555ffd83dbSDimitry Andric     S += "void";
4565ffd83dbSDimitry Andric   else {
457*06c3fb27SDimitry Andric     if (isScalableVector() || isSvcount())
4585ffd83dbSDimitry Andric       S += "sv";
4595ffd83dbSDimitry Andric     if (!Signed && !isFloatingPoint())
4605ffd83dbSDimitry Andric       S += "u";
4615ffd83dbSDimitry Andric 
4625ffd83dbSDimitry Andric     if (Float)
4635ffd83dbSDimitry Andric       S += "float";
464*06c3fb27SDimitry Andric     else if (isSvcount())
465*06c3fb27SDimitry Andric       S += "count";
4665ffd83dbSDimitry Andric     else if (isScalarPredicate() || isPredicateVector())
4675ffd83dbSDimitry Andric       S += "bool";
4685ffd83dbSDimitry Andric     else if (isBFloat())
4695ffd83dbSDimitry Andric       S += "bfloat";
4705ffd83dbSDimitry Andric     else
4715ffd83dbSDimitry Andric       S += "int";
4725ffd83dbSDimitry Andric 
473*06c3fb27SDimitry Andric     if (!isScalarPredicate() && !isPredicateVector() && !isSvcount())
4745ffd83dbSDimitry Andric       S += utostr(ElementBitwidth);
4755ffd83dbSDimitry Andric     if (!isScalableVector() && isVector())
4765ffd83dbSDimitry Andric       S += "x" + utostr(getNumElements());
4775ffd83dbSDimitry Andric     if (NumVectors > 1)
4785ffd83dbSDimitry Andric       S += "x" + utostr(NumVectors);
4795ffd83dbSDimitry Andric     if (!isScalarPredicate())
4805ffd83dbSDimitry Andric       S += "_t";
4815ffd83dbSDimitry Andric   }
4825ffd83dbSDimitry Andric 
4835ffd83dbSDimitry Andric   if (Constant)
4845ffd83dbSDimitry Andric     S += " const";
4855ffd83dbSDimitry Andric   if (Pointer)
4865ffd83dbSDimitry Andric     S += " *";
4875ffd83dbSDimitry Andric 
4885ffd83dbSDimitry Andric   return S;
4895ffd83dbSDimitry Andric }
4905ffd83dbSDimitry Andric void SVEType::applyTypespec() {
4915ffd83dbSDimitry Andric   for (char I : TS) {
4925ffd83dbSDimitry Andric     switch (I) {
493*06c3fb27SDimitry Andric     case 'Q':
494*06c3fb27SDimitry Andric       Svcount = true;
495*06c3fb27SDimitry Andric       break;
4965ffd83dbSDimitry Andric     case 'P':
4975ffd83dbSDimitry Andric       Predicate = true;
4985ffd83dbSDimitry Andric       break;
4995ffd83dbSDimitry Andric     case 'U':
5005ffd83dbSDimitry Andric       Signed = false;
5015ffd83dbSDimitry Andric       break;
5025ffd83dbSDimitry Andric     case 'c':
5035ffd83dbSDimitry Andric       ElementBitwidth = 8;
5045ffd83dbSDimitry Andric       break;
5055ffd83dbSDimitry Andric     case 's':
5065ffd83dbSDimitry Andric       ElementBitwidth = 16;
5075ffd83dbSDimitry Andric       break;
5085ffd83dbSDimitry Andric     case 'i':
5095ffd83dbSDimitry Andric       ElementBitwidth = 32;
5105ffd83dbSDimitry Andric       break;
5115ffd83dbSDimitry Andric     case 'l':
5125ffd83dbSDimitry Andric       ElementBitwidth = 64;
5135ffd83dbSDimitry Andric       break;
514*06c3fb27SDimitry Andric     case 'q':
515*06c3fb27SDimitry Andric       ElementBitwidth = 128;
516*06c3fb27SDimitry Andric       break;
5175ffd83dbSDimitry Andric     case 'h':
5185ffd83dbSDimitry Andric       Float = true;
5195ffd83dbSDimitry Andric       ElementBitwidth = 16;
5205ffd83dbSDimitry Andric       break;
5215ffd83dbSDimitry Andric     case 'f':
5225ffd83dbSDimitry Andric       Float = true;
5235ffd83dbSDimitry Andric       ElementBitwidth = 32;
5245ffd83dbSDimitry Andric       break;
5255ffd83dbSDimitry Andric     case 'd':
5265ffd83dbSDimitry Andric       Float = true;
5275ffd83dbSDimitry Andric       ElementBitwidth = 64;
5285ffd83dbSDimitry Andric       break;
5295ffd83dbSDimitry Andric     case 'b':
5305ffd83dbSDimitry Andric       BFloat = true;
5315ffd83dbSDimitry Andric       Float = false;
5325ffd83dbSDimitry Andric       ElementBitwidth = 16;
5335ffd83dbSDimitry Andric       break;
5345ffd83dbSDimitry Andric     default:
5355ffd83dbSDimitry Andric       llvm_unreachable("Unhandled type code!");
5365ffd83dbSDimitry Andric     }
5375ffd83dbSDimitry Andric   }
5385ffd83dbSDimitry Andric   assert(ElementBitwidth != ~0U && "Bad element bitwidth!");
5395ffd83dbSDimitry Andric }
5405ffd83dbSDimitry Andric 
5415ffd83dbSDimitry Andric void SVEType::applyModifier(char Mod) {
5425ffd83dbSDimitry Andric   switch (Mod) {
5435ffd83dbSDimitry Andric   case '2':
5445ffd83dbSDimitry Andric     NumVectors = 2;
5455ffd83dbSDimitry Andric     break;
5465ffd83dbSDimitry Andric   case '3':
5475ffd83dbSDimitry Andric     NumVectors = 3;
5485ffd83dbSDimitry Andric     break;
5495ffd83dbSDimitry Andric   case '4':
5505ffd83dbSDimitry Andric     NumVectors = 4;
5515ffd83dbSDimitry Andric     break;
5525ffd83dbSDimitry Andric   case 'v':
5535ffd83dbSDimitry Andric     Void = true;
5545ffd83dbSDimitry Andric     break;
5555ffd83dbSDimitry Andric   case 'd':
5565ffd83dbSDimitry Andric     DefaultType = true;
5575ffd83dbSDimitry Andric     break;
5585ffd83dbSDimitry Andric   case 'c':
5595ffd83dbSDimitry Andric     Constant = true;
560bdd1243dSDimitry Andric     [[fallthrough]];
5615ffd83dbSDimitry Andric   case 'p':
5625ffd83dbSDimitry Andric     Pointer = true;
5635ffd83dbSDimitry Andric     Bitwidth = ElementBitwidth;
5645ffd83dbSDimitry Andric     NumVectors = 0;
5655ffd83dbSDimitry Andric     break;
5665ffd83dbSDimitry Andric   case 'e':
5675ffd83dbSDimitry Andric     Signed = false;
5685ffd83dbSDimitry Andric     ElementBitwidth /= 2;
5695ffd83dbSDimitry Andric     break;
5705ffd83dbSDimitry Andric   case 'h':
5715ffd83dbSDimitry Andric     ElementBitwidth /= 2;
5725ffd83dbSDimitry Andric     break;
5735ffd83dbSDimitry Andric   case 'q':
5745ffd83dbSDimitry Andric     ElementBitwidth /= 4;
5755ffd83dbSDimitry Andric     break;
5765ffd83dbSDimitry Andric   case 'b':
5775ffd83dbSDimitry Andric     Signed = false;
5785ffd83dbSDimitry Andric     Float = false;
5795ffd83dbSDimitry Andric     BFloat = false;
5805ffd83dbSDimitry Andric     ElementBitwidth /= 4;
5815ffd83dbSDimitry Andric     break;
5825ffd83dbSDimitry Andric   case 'o':
5835ffd83dbSDimitry Andric     ElementBitwidth *= 4;
5845ffd83dbSDimitry Andric     break;
5855ffd83dbSDimitry Andric   case 'P':
5865ffd83dbSDimitry Andric     Signed = true;
5875ffd83dbSDimitry Andric     Float = false;
5885ffd83dbSDimitry Andric     BFloat = false;
5895ffd83dbSDimitry Andric     Predicate = true;
590*06c3fb27SDimitry Andric     Svcount = false;
5915ffd83dbSDimitry Andric     Bitwidth = 16;
5925ffd83dbSDimitry Andric     ElementBitwidth = 1;
5935ffd83dbSDimitry Andric     break;
5945ffd83dbSDimitry Andric   case 's':
5955ffd83dbSDimitry Andric   case 'a':
5965ffd83dbSDimitry Andric     Bitwidth = ElementBitwidth;
5975ffd83dbSDimitry Andric     NumVectors = 0;
5985ffd83dbSDimitry Andric     break;
5995ffd83dbSDimitry Andric   case 'R':
6005ffd83dbSDimitry Andric     ElementBitwidth /= 2;
6015ffd83dbSDimitry Andric     NumVectors = 0;
6025ffd83dbSDimitry Andric     break;
6035ffd83dbSDimitry Andric   case 'r':
6045ffd83dbSDimitry Andric     ElementBitwidth /= 4;
6055ffd83dbSDimitry Andric     NumVectors = 0;
6065ffd83dbSDimitry Andric     break;
6075ffd83dbSDimitry Andric   case '@':
6085ffd83dbSDimitry Andric     Signed = false;
6095ffd83dbSDimitry Andric     Float = false;
6105ffd83dbSDimitry Andric     BFloat = false;
6115ffd83dbSDimitry Andric     ElementBitwidth /= 4;
6125ffd83dbSDimitry Andric     NumVectors = 0;
6135ffd83dbSDimitry Andric     break;
6145ffd83dbSDimitry Andric   case 'K':
6155ffd83dbSDimitry Andric     Signed = true;
6165ffd83dbSDimitry Andric     Float = false;
6175ffd83dbSDimitry Andric     BFloat = false;
6185ffd83dbSDimitry Andric     Bitwidth = ElementBitwidth;
6195ffd83dbSDimitry Andric     NumVectors = 0;
6205ffd83dbSDimitry Andric     break;
6215ffd83dbSDimitry Andric   case 'L':
6225ffd83dbSDimitry Andric     Signed = false;
6235ffd83dbSDimitry Andric     Float = false;
6245ffd83dbSDimitry Andric     BFloat = false;
6255ffd83dbSDimitry Andric     Bitwidth = ElementBitwidth;
6265ffd83dbSDimitry Andric     NumVectors = 0;
6275ffd83dbSDimitry Andric     break;
6285ffd83dbSDimitry Andric   case 'u':
6295ffd83dbSDimitry Andric     Predicate = false;
630*06c3fb27SDimitry Andric     Svcount = false;
6315ffd83dbSDimitry Andric     Signed = false;
6325ffd83dbSDimitry Andric     Float = false;
6335ffd83dbSDimitry Andric     BFloat = false;
6345ffd83dbSDimitry Andric     break;
6355ffd83dbSDimitry Andric   case 'x':
6365ffd83dbSDimitry Andric     Predicate = false;
637*06c3fb27SDimitry Andric     Svcount = false;
6385ffd83dbSDimitry Andric     Signed = true;
6395ffd83dbSDimitry Andric     Float = false;
6405ffd83dbSDimitry Andric     BFloat = false;
6415ffd83dbSDimitry Andric     break;
6425ffd83dbSDimitry Andric   case 'i':
6435ffd83dbSDimitry Andric     Predicate = false;
644*06c3fb27SDimitry Andric     Svcount = false;
6455ffd83dbSDimitry Andric     Float = false;
6465ffd83dbSDimitry Andric     BFloat = false;
6475ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
6485ffd83dbSDimitry Andric     NumVectors = 0;
6495ffd83dbSDimitry Andric     Signed = false;
6505ffd83dbSDimitry Andric     Immediate = true;
6515ffd83dbSDimitry Andric     break;
6525ffd83dbSDimitry Andric   case 'I':
6535ffd83dbSDimitry Andric     Predicate = false;
654*06c3fb27SDimitry Andric     Svcount = false;
6555ffd83dbSDimitry Andric     Float = false;
6565ffd83dbSDimitry Andric     BFloat = false;
6575ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
6585ffd83dbSDimitry Andric     NumVectors = 0;
6595ffd83dbSDimitry Andric     Signed = true;
6605ffd83dbSDimitry Andric     Immediate = true;
6615ffd83dbSDimitry Andric     PredicatePattern = true;
6625ffd83dbSDimitry Andric     break;
6635ffd83dbSDimitry Andric   case 'J':
6645ffd83dbSDimitry Andric     Predicate = false;
665*06c3fb27SDimitry Andric     Svcount = false;
6665ffd83dbSDimitry Andric     Float = false;
6675ffd83dbSDimitry Andric     BFloat = false;
6685ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
6695ffd83dbSDimitry Andric     NumVectors = 0;
6705ffd83dbSDimitry Andric     Signed = true;
6715ffd83dbSDimitry Andric     Immediate = true;
6725ffd83dbSDimitry Andric     PrefetchOp = true;
6735ffd83dbSDimitry Andric     break;
6745ffd83dbSDimitry Andric   case 'k':
6755ffd83dbSDimitry Andric     Predicate = false;
676*06c3fb27SDimitry Andric     Svcount = false;
6775ffd83dbSDimitry Andric     Signed = true;
6785ffd83dbSDimitry Andric     Float = false;
6795ffd83dbSDimitry Andric     BFloat = false;
6805ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
6815ffd83dbSDimitry Andric     NumVectors = 0;
6825ffd83dbSDimitry Andric     break;
6835ffd83dbSDimitry Andric   case 'l':
6845ffd83dbSDimitry Andric     Predicate = false;
685*06c3fb27SDimitry Andric     Svcount = false;
6865ffd83dbSDimitry Andric     Signed = true;
6875ffd83dbSDimitry Andric     Float = false;
6885ffd83dbSDimitry Andric     BFloat = false;
6895ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
6905ffd83dbSDimitry Andric     NumVectors = 0;
6915ffd83dbSDimitry Andric     break;
6925ffd83dbSDimitry Andric   case 'm':
6935ffd83dbSDimitry Andric     Predicate = false;
694*06c3fb27SDimitry Andric     Svcount = false;
6955ffd83dbSDimitry Andric     Signed = false;
6965ffd83dbSDimitry Andric     Float = false;
6975ffd83dbSDimitry Andric     BFloat = false;
6985ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
6995ffd83dbSDimitry Andric     NumVectors = 0;
7005ffd83dbSDimitry Andric     break;
7015ffd83dbSDimitry Andric   case 'n':
7025ffd83dbSDimitry Andric     Predicate = false;
703*06c3fb27SDimitry Andric     Svcount = false;
7045ffd83dbSDimitry Andric     Signed = false;
7055ffd83dbSDimitry Andric     Float = false;
7065ffd83dbSDimitry Andric     BFloat = false;
7075ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
7085ffd83dbSDimitry Andric     NumVectors = 0;
7095ffd83dbSDimitry Andric     break;
7105ffd83dbSDimitry Andric   case 'w':
7115ffd83dbSDimitry Andric     ElementBitwidth = 64;
7125ffd83dbSDimitry Andric     break;
7135ffd83dbSDimitry Andric   case 'j':
7145ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
7155ffd83dbSDimitry Andric     NumVectors = 0;
7165ffd83dbSDimitry Andric     break;
7175ffd83dbSDimitry Andric   case 'f':
7185ffd83dbSDimitry Andric     Signed = false;
7195ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
7205ffd83dbSDimitry Andric     NumVectors = 0;
7215ffd83dbSDimitry Andric     break;
7225ffd83dbSDimitry Andric   case 'g':
7235ffd83dbSDimitry Andric     Signed = false;
7245ffd83dbSDimitry Andric     Float = false;
7255ffd83dbSDimitry Andric     BFloat = false;
7265ffd83dbSDimitry Andric     ElementBitwidth = 64;
7275ffd83dbSDimitry Andric     break;
7285ffd83dbSDimitry Andric   case 't':
7295ffd83dbSDimitry Andric     Signed = true;
7305ffd83dbSDimitry Andric     Float = false;
7315ffd83dbSDimitry Andric     BFloat = false;
7325ffd83dbSDimitry Andric     ElementBitwidth = 32;
7335ffd83dbSDimitry Andric     break;
7345ffd83dbSDimitry Andric   case 'z':
7355ffd83dbSDimitry Andric     Signed = false;
7365ffd83dbSDimitry Andric     Float = false;
7375ffd83dbSDimitry Andric     BFloat = false;
7385ffd83dbSDimitry Andric     ElementBitwidth = 32;
7395ffd83dbSDimitry Andric     break;
7405ffd83dbSDimitry Andric   case 'O':
7415ffd83dbSDimitry Andric     Predicate = false;
742*06c3fb27SDimitry Andric     Svcount = false;
7435ffd83dbSDimitry Andric     Float = true;
7445ffd83dbSDimitry Andric     ElementBitwidth = 16;
7455ffd83dbSDimitry Andric     break;
7465ffd83dbSDimitry Andric   case 'M':
7475ffd83dbSDimitry Andric     Predicate = false;
748*06c3fb27SDimitry Andric     Svcount = false;
7495ffd83dbSDimitry Andric     Float = true;
7505ffd83dbSDimitry Andric     BFloat = false;
7515ffd83dbSDimitry Andric     ElementBitwidth = 32;
7525ffd83dbSDimitry Andric     break;
7535ffd83dbSDimitry Andric   case 'N':
7545ffd83dbSDimitry Andric     Predicate = false;
755*06c3fb27SDimitry Andric     Svcount = false;
7565ffd83dbSDimitry Andric     Float = true;
7575ffd83dbSDimitry Andric     ElementBitwidth = 64;
7585ffd83dbSDimitry Andric     break;
7595ffd83dbSDimitry Andric   case 'Q':
7605ffd83dbSDimitry Andric     Constant = true;
7615ffd83dbSDimitry Andric     Pointer = true;
7625ffd83dbSDimitry Andric     Void = true;
7635ffd83dbSDimitry Andric     NumVectors = 0;
7645ffd83dbSDimitry Andric     break;
7655ffd83dbSDimitry Andric   case 'S':
7665ffd83dbSDimitry Andric     Constant = true;
7675ffd83dbSDimitry Andric     Pointer = true;
7685ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 8;
7695ffd83dbSDimitry Andric     NumVectors = 0;
7705ffd83dbSDimitry Andric     Signed = true;
7715ffd83dbSDimitry Andric     break;
7725ffd83dbSDimitry Andric   case 'W':
7735ffd83dbSDimitry Andric     Constant = true;
7745ffd83dbSDimitry Andric     Pointer = true;
7755ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 8;
7765ffd83dbSDimitry Andric     NumVectors = 0;
7775ffd83dbSDimitry Andric     Signed = false;
7785ffd83dbSDimitry Andric     break;
7795ffd83dbSDimitry Andric   case 'T':
7805ffd83dbSDimitry Andric     Constant = true;
7815ffd83dbSDimitry Andric     Pointer = true;
7825ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 16;
7835ffd83dbSDimitry Andric     NumVectors = 0;
7845ffd83dbSDimitry Andric     Signed = true;
7855ffd83dbSDimitry Andric     break;
7865ffd83dbSDimitry Andric   case 'X':
7875ffd83dbSDimitry Andric     Constant = true;
7885ffd83dbSDimitry Andric     Pointer = true;
7895ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 16;
7905ffd83dbSDimitry Andric     NumVectors = 0;
7915ffd83dbSDimitry Andric     Signed = false;
7925ffd83dbSDimitry Andric     break;
7935ffd83dbSDimitry Andric   case 'Y':
7945ffd83dbSDimitry Andric     Constant = true;
7955ffd83dbSDimitry Andric     Pointer = true;
7965ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
7975ffd83dbSDimitry Andric     NumVectors = 0;
7985ffd83dbSDimitry Andric     Signed = false;
7995ffd83dbSDimitry Andric     break;
8005ffd83dbSDimitry Andric   case 'U':
8015ffd83dbSDimitry Andric     Constant = true;
8025ffd83dbSDimitry Andric     Pointer = true;
8035ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
8045ffd83dbSDimitry Andric     NumVectors = 0;
8055ffd83dbSDimitry Andric     Signed = true;
8065ffd83dbSDimitry Andric     break;
807*06c3fb27SDimitry Andric   case '%':
808*06c3fb27SDimitry Andric     Pointer = true;
809*06c3fb27SDimitry Andric     Void = true;
810*06c3fb27SDimitry Andric     NumVectors = 0;
811*06c3fb27SDimitry Andric     break;
8125ffd83dbSDimitry Andric   case 'A':
8135ffd83dbSDimitry Andric     Pointer = true;
8145ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 8;
8155ffd83dbSDimitry Andric     NumVectors = 0;
8165ffd83dbSDimitry Andric     Signed = true;
8175ffd83dbSDimitry Andric     break;
8185ffd83dbSDimitry Andric   case 'B':
8195ffd83dbSDimitry Andric     Pointer = true;
8205ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 16;
8215ffd83dbSDimitry Andric     NumVectors = 0;
8225ffd83dbSDimitry Andric     Signed = true;
8235ffd83dbSDimitry Andric     break;
8245ffd83dbSDimitry Andric   case 'C':
8255ffd83dbSDimitry Andric     Pointer = true;
8265ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
8275ffd83dbSDimitry Andric     NumVectors = 0;
8285ffd83dbSDimitry Andric     Signed = true;
8295ffd83dbSDimitry Andric     break;
8305ffd83dbSDimitry Andric   case 'D':
8315ffd83dbSDimitry Andric     Pointer = true;
8325ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 64;
8335ffd83dbSDimitry Andric     NumVectors = 0;
8345ffd83dbSDimitry Andric     Signed = true;
8355ffd83dbSDimitry Andric     break;
8365ffd83dbSDimitry Andric   case 'E':
8375ffd83dbSDimitry Andric     Pointer = true;
8385ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 8;
8395ffd83dbSDimitry Andric     NumVectors = 0;
8405ffd83dbSDimitry Andric     Signed = false;
8415ffd83dbSDimitry Andric     break;
8425ffd83dbSDimitry Andric   case 'F':
8435ffd83dbSDimitry Andric     Pointer = true;
8445ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 16;
8455ffd83dbSDimitry Andric     NumVectors = 0;
8465ffd83dbSDimitry Andric     Signed = false;
8475ffd83dbSDimitry Andric     break;
8485ffd83dbSDimitry Andric   case 'G':
8495ffd83dbSDimitry Andric     Pointer = true;
8505ffd83dbSDimitry Andric     ElementBitwidth = Bitwidth = 32;
8515ffd83dbSDimitry Andric     NumVectors = 0;
8525ffd83dbSDimitry Andric     Signed = false;
8535ffd83dbSDimitry Andric     break;
854*06c3fb27SDimitry Andric   case '}':
855*06c3fb27SDimitry Andric     Predicate = false;
856*06c3fb27SDimitry Andric     Signed = true;
857*06c3fb27SDimitry Andric     Svcount = true;
858*06c3fb27SDimitry Andric     NumVectors = 0;
859*06c3fb27SDimitry Andric     Float = false;
860*06c3fb27SDimitry Andric     BFloat = false;
861*06c3fb27SDimitry Andric     break;
8625ffd83dbSDimitry Andric   default:
8635ffd83dbSDimitry Andric     llvm_unreachable("Unhandled character!");
8645ffd83dbSDimitry Andric   }
8655ffd83dbSDimitry Andric }
8665ffd83dbSDimitry Andric 
8675ffd83dbSDimitry Andric 
8685ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8695ffd83dbSDimitry Andric // Intrinsic implementation
8705ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8715ffd83dbSDimitry Andric 
8725ffd83dbSDimitry Andric Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
8735ffd83dbSDimitry Andric                      StringRef MergeSuffix, uint64_t MemoryElementTy,
8745ffd83dbSDimitry Andric                      StringRef LLVMName, uint64_t Flags,
8755ffd83dbSDimitry Andric                      ArrayRef<ImmCheck> Checks, TypeSpec BT, ClassKind Class,
8765ffd83dbSDimitry Andric                      SVEEmitter &Emitter, StringRef Guard)
8775ffd83dbSDimitry Andric     : Name(Name.str()), LLVMName(LLVMName), Proto(Proto.str()),
8785ffd83dbSDimitry Andric       BaseTypeSpec(BT), Class(Class), Guard(Guard.str()),
8795ffd83dbSDimitry Andric       MergeSuffix(MergeSuffix.str()), BaseType(BT, 'd'), Flags(Flags),
8805ffd83dbSDimitry Andric       ImmChecks(Checks.begin(), Checks.end()) {
8815ffd83dbSDimitry Andric   // Types[0] is the return value.
8825ffd83dbSDimitry Andric   for (unsigned I = 0; I < Proto.size(); ++I) {
8835ffd83dbSDimitry Andric     SVEType T(BaseTypeSpec, Proto[I]);
8845ffd83dbSDimitry Andric     Types.push_back(T);
8855ffd83dbSDimitry Andric 
8865ffd83dbSDimitry Andric     // Add range checks for immediates
8875ffd83dbSDimitry Andric     if (I > 0) {
8885ffd83dbSDimitry Andric       if (T.isPredicatePattern())
8895ffd83dbSDimitry Andric         ImmChecks.emplace_back(
8905ffd83dbSDimitry Andric             I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_31"));
8915ffd83dbSDimitry Andric       else if (T.isPrefetchOp())
8925ffd83dbSDimitry Andric         ImmChecks.emplace_back(
8935ffd83dbSDimitry Andric             I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_13"));
8945ffd83dbSDimitry Andric     }
8955ffd83dbSDimitry Andric   }
8965ffd83dbSDimitry Andric 
8975ffd83dbSDimitry Andric   // Set flags based on properties
8985ffd83dbSDimitry Andric   this->Flags |= Emitter.encodeTypeFlags(BaseType);
8995ffd83dbSDimitry Andric   this->Flags |= Emitter.encodeMemoryElementType(MemoryElementTy);
9005ffd83dbSDimitry Andric   this->Flags |= Emitter.encodeMergeType(MergeTy);
9015ffd83dbSDimitry Andric   if (hasSplat())
9025ffd83dbSDimitry Andric     this->Flags |= Emitter.encodeSplatOperand(getSplatIdx());
9035ffd83dbSDimitry Andric }
9045ffd83dbSDimitry Andric 
9055ffd83dbSDimitry Andric std::string Intrinsic::getBuiltinTypeStr() {
9065ffd83dbSDimitry Andric   std::string S = getReturnType().builtin_str();
9075ffd83dbSDimitry Andric   for (unsigned I = 0; I < getNumParams(); ++I)
9085ffd83dbSDimitry Andric     S += getParamType(I).builtin_str();
9095ffd83dbSDimitry Andric 
9105ffd83dbSDimitry Andric   return S;
9115ffd83dbSDimitry Andric }
9125ffd83dbSDimitry Andric 
9135ffd83dbSDimitry Andric std::string Intrinsic::replaceTemplatedArgs(std::string Name, TypeSpec TS,
9145ffd83dbSDimitry Andric                                             std::string Proto) const {
9155ffd83dbSDimitry Andric   std::string Ret = Name;
9165ffd83dbSDimitry Andric   while (Ret.find('{') != std::string::npos) {
9175ffd83dbSDimitry Andric     size_t Pos = Ret.find('{');
9185ffd83dbSDimitry Andric     size_t End = Ret.find('}');
9195ffd83dbSDimitry Andric     unsigned NumChars = End - Pos + 1;
9205ffd83dbSDimitry Andric     assert(NumChars == 3 && "Unexpected template argument");
9215ffd83dbSDimitry Andric 
9225ffd83dbSDimitry Andric     SVEType T;
9235ffd83dbSDimitry Andric     char C = Ret[Pos+1];
9245ffd83dbSDimitry Andric     switch(C) {
9255ffd83dbSDimitry Andric     default:
9265ffd83dbSDimitry Andric       llvm_unreachable("Unknown predication specifier");
9275ffd83dbSDimitry Andric     case 'd':
9285ffd83dbSDimitry Andric       T = SVEType(TS, 'd');
9295ffd83dbSDimitry Andric       break;
9305ffd83dbSDimitry Andric     case '0':
9315ffd83dbSDimitry Andric     case '1':
9325ffd83dbSDimitry Andric     case '2':
9335ffd83dbSDimitry Andric     case '3':
9345ffd83dbSDimitry Andric       T = SVEType(TS, Proto[C - '0']);
9355ffd83dbSDimitry Andric       break;
9365ffd83dbSDimitry Andric     }
9375ffd83dbSDimitry Andric 
9385ffd83dbSDimitry Andric     // Replace templated arg with the right suffix (e.g. u32)
9395ffd83dbSDimitry Andric     std::string TypeCode;
9405ffd83dbSDimitry Andric     if (T.isInteger())
9415ffd83dbSDimitry Andric       TypeCode = T.isSigned() ? 's' : 'u';
942*06c3fb27SDimitry Andric     else if (T.isSvcount())
943*06c3fb27SDimitry Andric       TypeCode = 'c';
9445ffd83dbSDimitry Andric     else if (T.isPredicateVector())
9455ffd83dbSDimitry Andric       TypeCode = 'b';
9465ffd83dbSDimitry Andric     else if (T.isBFloat())
9475ffd83dbSDimitry Andric       TypeCode = "bf";
9485ffd83dbSDimitry Andric     else
9495ffd83dbSDimitry Andric       TypeCode = 'f';
9505ffd83dbSDimitry Andric     Ret.replace(Pos, NumChars, TypeCode + utostr(T.getElementSizeInBits()));
9515ffd83dbSDimitry Andric   }
9525ffd83dbSDimitry Andric 
9535ffd83dbSDimitry Andric   return Ret;
9545ffd83dbSDimitry Andric }
9555ffd83dbSDimitry Andric 
956*06c3fb27SDimitry Andric std::string Intrinsic::mangleLLVMName() const {
957*06c3fb27SDimitry Andric   std::string S = getLLVMName();
958*06c3fb27SDimitry Andric 
959*06c3fb27SDimitry Andric   // Replace all {d} like expressions with e.g. 'u32'
960*06c3fb27SDimitry Andric   return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto());
961*06c3fb27SDimitry Andric }
962*06c3fb27SDimitry Andric 
9635ffd83dbSDimitry Andric std::string Intrinsic::mangleName(ClassKind LocalCK) const {
9645ffd83dbSDimitry Andric   std::string S = getName();
9655ffd83dbSDimitry Andric 
9665ffd83dbSDimitry Andric   if (LocalCK == ClassG) {
9675ffd83dbSDimitry Andric     // Remove the square brackets and everything in between.
968e8d8bef9SDimitry Andric     while (S.find('[') != std::string::npos) {
969e8d8bef9SDimitry Andric       auto Start = S.find('[');
9705ffd83dbSDimitry Andric       auto End = S.find(']');
9715ffd83dbSDimitry Andric       S.erase(Start, (End-Start)+1);
9725ffd83dbSDimitry Andric     }
9735ffd83dbSDimitry Andric   } else {
9745ffd83dbSDimitry Andric     // Remove the square brackets.
975e8d8bef9SDimitry Andric     while (S.find('[') != std::string::npos) {
9765ffd83dbSDimitry Andric       auto BrPos = S.find('[');
9775ffd83dbSDimitry Andric       if (BrPos != std::string::npos)
9785ffd83dbSDimitry Andric         S.erase(BrPos, 1);
9795ffd83dbSDimitry Andric       BrPos = S.find(']');
9805ffd83dbSDimitry Andric       if (BrPos != std::string::npos)
9815ffd83dbSDimitry Andric         S.erase(BrPos, 1);
9825ffd83dbSDimitry Andric     }
9835ffd83dbSDimitry Andric   }
9845ffd83dbSDimitry Andric 
9855ffd83dbSDimitry Andric   // Replace all {d} like expressions with e.g. 'u32'
9865ffd83dbSDimitry Andric   return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto()) +
9875ffd83dbSDimitry Andric          getMergeSuffix();
9885ffd83dbSDimitry Andric }
9895ffd83dbSDimitry Andric 
990*06c3fb27SDimitry Andric void Intrinsic::emitIntrinsic(raw_ostream &OS, SVEEmitter &Emitter) const {
991fe6060f1SDimitry Andric   bool IsOverloaded = getClassKind() == ClassG && getProto().size() > 1;
9925ffd83dbSDimitry Andric 
993fe6060f1SDimitry Andric   std::string FullName = mangleName(ClassS);
994fe6060f1SDimitry Andric   std::string ProtoName = mangleName(getClassKind());
995*06c3fb27SDimitry Andric   std::string SMEAttrs = "";
996*06c3fb27SDimitry Andric 
997*06c3fb27SDimitry Andric   if (Flags & Emitter.getEnumValueForFlag("IsStreaming"))
998*06c3fb27SDimitry Andric     SMEAttrs += ", arm_streaming";
999*06c3fb27SDimitry Andric   if (Flags & Emitter.getEnumValueForFlag("IsStreamingCompatible"))
1000*06c3fb27SDimitry Andric     SMEAttrs += ", arm_streaming_compatible";
1001*06c3fb27SDimitry Andric   if (Flags & Emitter.getEnumValueForFlag("IsSharedZA"))
1002*06c3fb27SDimitry Andric     SMEAttrs += ", arm_shared_za";
1003*06c3fb27SDimitry Andric   if (Flags & Emitter.getEnumValueForFlag("IsPreservesZA"))
1004*06c3fb27SDimitry Andric     SMEAttrs += ", arm_preserves_za";
1005fe6060f1SDimitry Andric 
1006fe6060f1SDimitry Andric   OS << (IsOverloaded ? "__aio " : "__ai ")
1007fe6060f1SDimitry Andric      << "__attribute__((__clang_arm_builtin_alias("
1008*06c3fb27SDimitry Andric      << (SMEAttrs.empty() ? "__builtin_sve_" : "__builtin_sme_")
1009*06c3fb27SDimitry Andric      << FullName << ")";
1010*06c3fb27SDimitry Andric   if (!SMEAttrs.empty())
1011*06c3fb27SDimitry Andric     OS << SMEAttrs;
1012*06c3fb27SDimitry Andric   OS << "))\n";
10135ffd83dbSDimitry Andric 
10145ffd83dbSDimitry Andric   OS << getTypes()[0].str() << " " << ProtoName << "(";
10155ffd83dbSDimitry Andric   for (unsigned I = 0; I < getTypes().size() - 1; ++I) {
10165ffd83dbSDimitry Andric     if (I != 0)
10175ffd83dbSDimitry Andric       OS << ", ";
10185ffd83dbSDimitry Andric     OS << getTypes()[I + 1].str();
10195ffd83dbSDimitry Andric   }
10205ffd83dbSDimitry Andric   OS << ");\n";
10215ffd83dbSDimitry Andric }
10225ffd83dbSDimitry Andric 
10235ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
10245ffd83dbSDimitry Andric // SVEEmitter implementation
10255ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
10265ffd83dbSDimitry Andric uint64_t SVEEmitter::encodeTypeFlags(const SVEType &T) {
10275ffd83dbSDimitry Andric   if (T.isFloat()) {
10285ffd83dbSDimitry Andric     switch (T.getElementSizeInBits()) {
10295ffd83dbSDimitry Andric     case 16:
10305ffd83dbSDimitry Andric       return encodeEltType("EltTyFloat16");
10315ffd83dbSDimitry Andric     case 32:
10325ffd83dbSDimitry Andric       return encodeEltType("EltTyFloat32");
10335ffd83dbSDimitry Andric     case 64:
10345ffd83dbSDimitry Andric       return encodeEltType("EltTyFloat64");
10355ffd83dbSDimitry Andric     default:
10365ffd83dbSDimitry Andric       llvm_unreachable("Unhandled float element bitwidth!");
10375ffd83dbSDimitry Andric     }
10385ffd83dbSDimitry Andric   }
10395ffd83dbSDimitry Andric 
10405ffd83dbSDimitry Andric   if (T.isBFloat()) {
10415ffd83dbSDimitry Andric     assert(T.getElementSizeInBits() == 16 && "Not a valid BFloat.");
10425ffd83dbSDimitry Andric     return encodeEltType("EltTyBFloat16");
10435ffd83dbSDimitry Andric   }
10445ffd83dbSDimitry Andric 
1045*06c3fb27SDimitry Andric   if (T.isPredicateVector() || T.isSvcount()) {
10465ffd83dbSDimitry Andric     switch (T.getElementSizeInBits()) {
10475ffd83dbSDimitry Andric     case 8:
10485ffd83dbSDimitry Andric       return encodeEltType("EltTyBool8");
10495ffd83dbSDimitry Andric     case 16:
10505ffd83dbSDimitry Andric       return encodeEltType("EltTyBool16");
10515ffd83dbSDimitry Andric     case 32:
10525ffd83dbSDimitry Andric       return encodeEltType("EltTyBool32");
10535ffd83dbSDimitry Andric     case 64:
10545ffd83dbSDimitry Andric       return encodeEltType("EltTyBool64");
10555ffd83dbSDimitry Andric     default:
10565ffd83dbSDimitry Andric       llvm_unreachable("Unhandled predicate element bitwidth!");
10575ffd83dbSDimitry Andric     }
10585ffd83dbSDimitry Andric   }
10595ffd83dbSDimitry Andric 
10605ffd83dbSDimitry Andric   switch (T.getElementSizeInBits()) {
10615ffd83dbSDimitry Andric   case 8:
10625ffd83dbSDimitry Andric     return encodeEltType("EltTyInt8");
10635ffd83dbSDimitry Andric   case 16:
10645ffd83dbSDimitry Andric     return encodeEltType("EltTyInt16");
10655ffd83dbSDimitry Andric   case 32:
10665ffd83dbSDimitry Andric     return encodeEltType("EltTyInt32");
10675ffd83dbSDimitry Andric   case 64:
10685ffd83dbSDimitry Andric     return encodeEltType("EltTyInt64");
1069*06c3fb27SDimitry Andric   case 128:
1070*06c3fb27SDimitry Andric     return encodeEltType("EltTyInt128");
10715ffd83dbSDimitry Andric   default:
10725ffd83dbSDimitry Andric     llvm_unreachable("Unhandled integer element bitwidth!");
10735ffd83dbSDimitry Andric   }
10745ffd83dbSDimitry Andric }
10755ffd83dbSDimitry Andric 
10765ffd83dbSDimitry Andric void SVEEmitter::createIntrinsic(
10775ffd83dbSDimitry Andric     Record *R, SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out) {
10785ffd83dbSDimitry Andric   StringRef Name = R->getValueAsString("Name");
10795ffd83dbSDimitry Andric   StringRef Proto = R->getValueAsString("Prototype");
10805ffd83dbSDimitry Andric   StringRef Types = R->getValueAsString("Types");
1081bdd1243dSDimitry Andric   StringRef Guard = R->getValueAsString("TargetGuard");
10825ffd83dbSDimitry Andric   StringRef LLVMName = R->getValueAsString("LLVMIntrinsic");
10835ffd83dbSDimitry Andric   uint64_t Merge = R->getValueAsInt("Merge");
10845ffd83dbSDimitry Andric   StringRef MergeSuffix = R->getValueAsString("MergeSuffix");
10855ffd83dbSDimitry Andric   uint64_t MemEltType = R->getValueAsInt("MemEltType");
10865ffd83dbSDimitry Andric   std::vector<Record*> FlagsList = R->getValueAsListOfDefs("Flags");
10875ffd83dbSDimitry Andric   std::vector<Record*> ImmCheckList = R->getValueAsListOfDefs("ImmChecks");
10885ffd83dbSDimitry Andric 
10895ffd83dbSDimitry Andric   int64_t Flags = 0;
10905ffd83dbSDimitry Andric   for (auto FlagRec : FlagsList)
10915ffd83dbSDimitry Andric     Flags |= FlagRec->getValueAsInt("Value");
10925ffd83dbSDimitry Andric 
10935ffd83dbSDimitry Andric   // Create a dummy TypeSpec for non-overloaded builtins.
10945ffd83dbSDimitry Andric   if (Types.empty()) {
10955ffd83dbSDimitry Andric     assert((Flags & getEnumValueForFlag("IsOverloadNone")) &&
10965ffd83dbSDimitry Andric            "Expect TypeSpec for overloaded builtin!");
10975ffd83dbSDimitry Andric     Types = "i";
10985ffd83dbSDimitry Andric   }
10995ffd83dbSDimitry Andric 
11005ffd83dbSDimitry Andric   // Extract type specs from string
11015ffd83dbSDimitry Andric   SmallVector<TypeSpec, 8> TypeSpecs;
11025ffd83dbSDimitry Andric   TypeSpec Acc;
11035ffd83dbSDimitry Andric   for (char I : Types) {
11045ffd83dbSDimitry Andric     Acc.push_back(I);
11055ffd83dbSDimitry Andric     if (islower(I)) {
11065ffd83dbSDimitry Andric       TypeSpecs.push_back(TypeSpec(Acc));
11075ffd83dbSDimitry Andric       Acc.clear();
11085ffd83dbSDimitry Andric     }
11095ffd83dbSDimitry Andric   }
11105ffd83dbSDimitry Andric 
11115ffd83dbSDimitry Andric   // Remove duplicate type specs.
11125ffd83dbSDimitry Andric   llvm::sort(TypeSpecs);
11135ffd83dbSDimitry Andric   TypeSpecs.erase(std::unique(TypeSpecs.begin(), TypeSpecs.end()),
11145ffd83dbSDimitry Andric                   TypeSpecs.end());
11155ffd83dbSDimitry Andric 
11165ffd83dbSDimitry Andric   // Create an Intrinsic for each type spec.
11175ffd83dbSDimitry Andric   for (auto TS : TypeSpecs) {
11185ffd83dbSDimitry Andric     // Collate a list of range/option checks for the immediates.
11195ffd83dbSDimitry Andric     SmallVector<ImmCheck, 2> ImmChecks;
11205ffd83dbSDimitry Andric     for (auto *R : ImmCheckList) {
11215ffd83dbSDimitry Andric       int64_t Arg = R->getValueAsInt("Arg");
11225ffd83dbSDimitry Andric       int64_t EltSizeArg = R->getValueAsInt("EltSizeArg");
11235ffd83dbSDimitry Andric       int64_t Kind = R->getValueAsDef("Kind")->getValueAsInt("Value");
11245ffd83dbSDimitry Andric       assert(Arg >= 0 && Kind >= 0 && "Arg and Kind must be nonnegative");
11255ffd83dbSDimitry Andric 
11265ffd83dbSDimitry Andric       unsigned ElementSizeInBits = 0;
11275ffd83dbSDimitry Andric       if (EltSizeArg >= 0)
11285ffd83dbSDimitry Andric         ElementSizeInBits =
11295ffd83dbSDimitry Andric             SVEType(TS, Proto[EltSizeArg + /* offset by return arg */ 1])
11305ffd83dbSDimitry Andric                 .getElementSizeInBits();
11315ffd83dbSDimitry Andric       ImmChecks.push_back(ImmCheck(Arg, Kind, ElementSizeInBits));
11325ffd83dbSDimitry Andric     }
11335ffd83dbSDimitry Andric 
11345ffd83dbSDimitry Andric     Out.push_back(std::make_unique<Intrinsic>(
11355ffd83dbSDimitry Andric         Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags, ImmChecks,
11365ffd83dbSDimitry Andric         TS, ClassS, *this, Guard));
11375ffd83dbSDimitry Andric 
11385ffd83dbSDimitry Andric     // Also generate the short-form (e.g. svadd_m) for the given type-spec.
11395ffd83dbSDimitry Andric     if (Intrinsic::isOverloadedIntrinsic(Name))
11405ffd83dbSDimitry Andric       Out.push_back(std::make_unique<Intrinsic>(
11415ffd83dbSDimitry Andric           Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags,
11425ffd83dbSDimitry Andric           ImmChecks, TS, ClassG, *this, Guard));
11435ffd83dbSDimitry Andric   }
11445ffd83dbSDimitry Andric }
11455ffd83dbSDimitry Andric 
11465ffd83dbSDimitry Andric void SVEEmitter::createHeader(raw_ostream &OS) {
11475ffd83dbSDimitry Andric   OS << "/*===---- arm_sve.h - ARM SVE intrinsics "
11485ffd83dbSDimitry Andric         "-----------------------------------===\n"
11495ffd83dbSDimitry Andric         " *\n"
11505ffd83dbSDimitry Andric         " *\n"
11515ffd83dbSDimitry Andric         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
11525ffd83dbSDimitry Andric         "Exceptions.\n"
11535ffd83dbSDimitry Andric         " * See https://llvm.org/LICENSE.txt for license information.\n"
11545ffd83dbSDimitry Andric         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
11555ffd83dbSDimitry Andric         " *\n"
11565ffd83dbSDimitry Andric         " *===-----------------------------------------------------------------"
11575ffd83dbSDimitry Andric         "------===\n"
11585ffd83dbSDimitry Andric         " */\n\n";
11595ffd83dbSDimitry Andric 
11605ffd83dbSDimitry Andric   OS << "#ifndef __ARM_SVE_H\n";
11615ffd83dbSDimitry Andric   OS << "#define __ARM_SVE_H\n\n";
11625ffd83dbSDimitry Andric 
11635ffd83dbSDimitry Andric   OS << "#if !defined(__LITTLE_ENDIAN__)\n";
11645ffd83dbSDimitry Andric   OS << "#error \"Big endian is currently not supported for arm_sve.h\"\n";
11655ffd83dbSDimitry Andric   OS << "#endif\n";
11665ffd83dbSDimitry Andric 
11675ffd83dbSDimitry Andric   OS << "#include <stdint.h>\n\n";
11685ffd83dbSDimitry Andric   OS << "#ifdef  __cplusplus\n";
11695ffd83dbSDimitry Andric   OS << "extern \"C\" {\n";
11705ffd83dbSDimitry Andric   OS << "#else\n";
11715ffd83dbSDimitry Andric   OS << "#include <stdbool.h>\n";
11725ffd83dbSDimitry Andric   OS << "#endif\n\n";
11735ffd83dbSDimitry Andric 
11745ffd83dbSDimitry Andric   OS << "typedef __fp16 float16_t;\n";
11755ffd83dbSDimitry Andric   OS << "typedef float float32_t;\n";
11765ffd83dbSDimitry Andric   OS << "typedef double float64_t;\n";
11775ffd83dbSDimitry Andric 
11785ffd83dbSDimitry Andric   OS << "typedef __SVInt8_t svint8_t;\n";
11795ffd83dbSDimitry Andric   OS << "typedef __SVInt16_t svint16_t;\n";
11805ffd83dbSDimitry Andric   OS << "typedef __SVInt32_t svint32_t;\n";
11815ffd83dbSDimitry Andric   OS << "typedef __SVInt64_t svint64_t;\n";
11825ffd83dbSDimitry Andric   OS << "typedef __SVUint8_t svuint8_t;\n";
11835ffd83dbSDimitry Andric   OS << "typedef __SVUint16_t svuint16_t;\n";
11845ffd83dbSDimitry Andric   OS << "typedef __SVUint32_t svuint32_t;\n";
11855ffd83dbSDimitry Andric   OS << "typedef __SVUint64_t svuint64_t;\n";
11865ffd83dbSDimitry Andric   OS << "typedef __SVFloat16_t svfloat16_t;\n\n";
11875ffd83dbSDimitry Andric 
11885ffd83dbSDimitry Andric   OS << "typedef __SVBFloat16_t svbfloat16_t;\n";
11895ffd83dbSDimitry Andric 
11905ffd83dbSDimitry Andric   OS << "#include <arm_bf16.h>\n";
11915ffd83dbSDimitry Andric 
11925ffd83dbSDimitry Andric   OS << "typedef __SVFloat32_t svfloat32_t;\n";
11935ffd83dbSDimitry Andric   OS << "typedef __SVFloat64_t svfloat64_t;\n";
11945ffd83dbSDimitry Andric   OS << "typedef __clang_svint8x2_t svint8x2_t;\n";
11955ffd83dbSDimitry Andric   OS << "typedef __clang_svint16x2_t svint16x2_t;\n";
11965ffd83dbSDimitry Andric   OS << "typedef __clang_svint32x2_t svint32x2_t;\n";
11975ffd83dbSDimitry Andric   OS << "typedef __clang_svint64x2_t svint64x2_t;\n";
11985ffd83dbSDimitry Andric   OS << "typedef __clang_svuint8x2_t svuint8x2_t;\n";
11995ffd83dbSDimitry Andric   OS << "typedef __clang_svuint16x2_t svuint16x2_t;\n";
12005ffd83dbSDimitry Andric   OS << "typedef __clang_svuint32x2_t svuint32x2_t;\n";
12015ffd83dbSDimitry Andric   OS << "typedef __clang_svuint64x2_t svuint64x2_t;\n";
12025ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat16x2_t svfloat16x2_t;\n";
12035ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat32x2_t svfloat32x2_t;\n";
12045ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat64x2_t svfloat64x2_t;\n";
12055ffd83dbSDimitry Andric   OS << "typedef __clang_svint8x3_t svint8x3_t;\n";
12065ffd83dbSDimitry Andric   OS << "typedef __clang_svint16x3_t svint16x3_t;\n";
12075ffd83dbSDimitry Andric   OS << "typedef __clang_svint32x3_t svint32x3_t;\n";
12085ffd83dbSDimitry Andric   OS << "typedef __clang_svint64x3_t svint64x3_t;\n";
12095ffd83dbSDimitry Andric   OS << "typedef __clang_svuint8x3_t svuint8x3_t;\n";
12105ffd83dbSDimitry Andric   OS << "typedef __clang_svuint16x3_t svuint16x3_t;\n";
12115ffd83dbSDimitry Andric   OS << "typedef __clang_svuint32x3_t svuint32x3_t;\n";
12125ffd83dbSDimitry Andric   OS << "typedef __clang_svuint64x3_t svuint64x3_t;\n";
12135ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat16x3_t svfloat16x3_t;\n";
12145ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat32x3_t svfloat32x3_t;\n";
12155ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat64x3_t svfloat64x3_t;\n";
12165ffd83dbSDimitry Andric   OS << "typedef __clang_svint8x4_t svint8x4_t;\n";
12175ffd83dbSDimitry Andric   OS << "typedef __clang_svint16x4_t svint16x4_t;\n";
12185ffd83dbSDimitry Andric   OS << "typedef __clang_svint32x4_t svint32x4_t;\n";
12195ffd83dbSDimitry Andric   OS << "typedef __clang_svint64x4_t svint64x4_t;\n";
12205ffd83dbSDimitry Andric   OS << "typedef __clang_svuint8x4_t svuint8x4_t;\n";
12215ffd83dbSDimitry Andric   OS << "typedef __clang_svuint16x4_t svuint16x4_t;\n";
12225ffd83dbSDimitry Andric   OS << "typedef __clang_svuint32x4_t svuint32x4_t;\n";
12235ffd83dbSDimitry Andric   OS << "typedef __clang_svuint64x4_t svuint64x4_t;\n";
12245ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat16x4_t svfloat16x4_t;\n";
12255ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat32x4_t svfloat32x4_t;\n";
12265ffd83dbSDimitry Andric   OS << "typedef __clang_svfloat64x4_t svfloat64x4_t;\n";
1227*06c3fb27SDimitry Andric   OS << "typedef __SVBool_t  svbool_t;\n";
1228*06c3fb27SDimitry Andric   OS << "typedef __clang_svboolx2_t  svboolx2_t;\n";
1229*06c3fb27SDimitry Andric   OS << "typedef __clang_svboolx4_t  svboolx4_t;\n\n";
12305ffd83dbSDimitry Andric 
12315ffd83dbSDimitry Andric   OS << "typedef __clang_svbfloat16x2_t svbfloat16x2_t;\n";
12325ffd83dbSDimitry Andric   OS << "typedef __clang_svbfloat16x3_t svbfloat16x3_t;\n";
12335ffd83dbSDimitry Andric   OS << "typedef __clang_svbfloat16x4_t svbfloat16x4_t;\n";
12345ffd83dbSDimitry Andric 
1235*06c3fb27SDimitry Andric   OS << "typedef __SVCount_t svcount_t;\n\n";
1236*06c3fb27SDimitry Andric 
1237e8d8bef9SDimitry Andric   OS << "enum svpattern\n";
12385ffd83dbSDimitry Andric   OS << "{\n";
12395ffd83dbSDimitry Andric   OS << "  SV_POW2 = 0,\n";
12405ffd83dbSDimitry Andric   OS << "  SV_VL1 = 1,\n";
12415ffd83dbSDimitry Andric   OS << "  SV_VL2 = 2,\n";
12425ffd83dbSDimitry Andric   OS << "  SV_VL3 = 3,\n";
12435ffd83dbSDimitry Andric   OS << "  SV_VL4 = 4,\n";
12445ffd83dbSDimitry Andric   OS << "  SV_VL5 = 5,\n";
12455ffd83dbSDimitry Andric   OS << "  SV_VL6 = 6,\n";
12465ffd83dbSDimitry Andric   OS << "  SV_VL7 = 7,\n";
12475ffd83dbSDimitry Andric   OS << "  SV_VL8 = 8,\n";
12485ffd83dbSDimitry Andric   OS << "  SV_VL16 = 9,\n";
12495ffd83dbSDimitry Andric   OS << "  SV_VL32 = 10,\n";
12505ffd83dbSDimitry Andric   OS << "  SV_VL64 = 11,\n";
12515ffd83dbSDimitry Andric   OS << "  SV_VL128 = 12,\n";
12525ffd83dbSDimitry Andric   OS << "  SV_VL256 = 13,\n";
12535ffd83dbSDimitry Andric   OS << "  SV_MUL4 = 29,\n";
12545ffd83dbSDimitry Andric   OS << "  SV_MUL3 = 30,\n";
12555ffd83dbSDimitry Andric   OS << "  SV_ALL = 31\n";
1256e8d8bef9SDimitry Andric   OS << "};\n\n";
12575ffd83dbSDimitry Andric 
1258e8d8bef9SDimitry Andric   OS << "enum svprfop\n";
12595ffd83dbSDimitry Andric   OS << "{\n";
12605ffd83dbSDimitry Andric   OS << "  SV_PLDL1KEEP = 0,\n";
12615ffd83dbSDimitry Andric   OS << "  SV_PLDL1STRM = 1,\n";
12625ffd83dbSDimitry Andric   OS << "  SV_PLDL2KEEP = 2,\n";
12635ffd83dbSDimitry Andric   OS << "  SV_PLDL2STRM = 3,\n";
12645ffd83dbSDimitry Andric   OS << "  SV_PLDL3KEEP = 4,\n";
12655ffd83dbSDimitry Andric   OS << "  SV_PLDL3STRM = 5,\n";
12665ffd83dbSDimitry Andric   OS << "  SV_PSTL1KEEP = 8,\n";
12675ffd83dbSDimitry Andric   OS << "  SV_PSTL1STRM = 9,\n";
12685ffd83dbSDimitry Andric   OS << "  SV_PSTL2KEEP = 10,\n";
12695ffd83dbSDimitry Andric   OS << "  SV_PSTL2STRM = 11,\n";
12705ffd83dbSDimitry Andric   OS << "  SV_PSTL3KEEP = 12,\n";
12715ffd83dbSDimitry Andric   OS << "  SV_PSTL3STRM = 13\n";
1272e8d8bef9SDimitry Andric   OS << "};\n\n";
12735ffd83dbSDimitry Andric 
12745ffd83dbSDimitry Andric   OS << "/* Function attributes */\n";
1275fe6060f1SDimitry Andric   OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
1276fe6060f1SDimitry Andric         "__nodebug__))\n\n";
1277fe6060f1SDimitry Andric   OS << "#define __aio static __inline__ __attribute__((__always_inline__, "
12785ffd83dbSDimitry Andric         "__nodebug__, __overloadable__))\n\n";
12795ffd83dbSDimitry Andric 
12805ffd83dbSDimitry Andric   // Add reinterpret functions.
12815ffd83dbSDimitry Andric   for (auto ShortForm : { false, true } )
12825ffd83dbSDimitry Andric     for (const ReinterpretTypeInfo &From : Reinterprets)
12835ffd83dbSDimitry Andric       for (const ReinterpretTypeInfo &To : Reinterprets) {
12845ffd83dbSDimitry Andric         if (ShortForm) {
1285bdd1243dSDimitry Andric           OS << "__aio __attribute__((target(\"sve\"))) " << From.Type
1286bdd1243dSDimitry Andric              << " svreinterpret_" << From.Suffix;
12875ffd83dbSDimitry Andric           OS << "(" << To.Type << " op) {\n";
12885ffd83dbSDimitry Andric           OS << "  return __builtin_sve_reinterpret_" << From.Suffix << "_"
12895ffd83dbSDimitry Andric              << To.Suffix << "(op);\n";
12905ffd83dbSDimitry Andric           OS << "}\n\n";
12915ffd83dbSDimitry Andric         } else
12925ffd83dbSDimitry Andric           OS << "#define svreinterpret_" << From.Suffix << "_" << To.Suffix
12935ffd83dbSDimitry Andric              << "(...) __builtin_sve_reinterpret_" << From.Suffix << "_"
12945ffd83dbSDimitry Andric              << To.Suffix << "(__VA_ARGS__)\n";
12955ffd83dbSDimitry Andric       }
12965ffd83dbSDimitry Andric 
12975ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
12985ffd83dbSDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
12995ffd83dbSDimitry Andric   for (auto *R : RV)
13005ffd83dbSDimitry Andric     createIntrinsic(R, Defs);
13015ffd83dbSDimitry Andric 
13025ffd83dbSDimitry Andric   // Sort intrinsics in header file by following order/priority:
13035ffd83dbSDimitry Andric   // - Architectural guard (i.e. does it require SVE2 or SVE2_AES)
13045ffd83dbSDimitry Andric   // - Class (is intrinsic overloaded or not)
13055ffd83dbSDimitry Andric   // - Intrinsic name
13065ffd83dbSDimitry Andric   std::stable_sort(
13075ffd83dbSDimitry Andric       Defs.begin(), Defs.end(), [](const std::unique_ptr<Intrinsic> &A,
13085ffd83dbSDimitry Andric                                    const std::unique_ptr<Intrinsic> &B) {
13095ffd83dbSDimitry Andric         auto ToTuple = [](const std::unique_ptr<Intrinsic> &I) {
13105ffd83dbSDimitry Andric           return std::make_tuple(I->getGuard(), (unsigned)I->getClassKind(), I->getName());
13115ffd83dbSDimitry Andric         };
13125ffd83dbSDimitry Andric         return ToTuple(A) < ToTuple(B);
13135ffd83dbSDimitry Andric       });
13145ffd83dbSDimitry Andric 
1315bdd1243dSDimitry Andric   // Actually emit the intrinsic declarations.
1316bdd1243dSDimitry Andric   for (auto &I : Defs)
1317*06c3fb27SDimitry Andric     I->emitIntrinsic(OS, *this);
13185ffd83dbSDimitry Andric 
13195ffd83dbSDimitry Andric   OS << "#define svcvtnt_bf16_x      svcvtnt_bf16_m\n";
13205ffd83dbSDimitry Andric   OS << "#define svcvtnt_bf16_f32_x  svcvtnt_bf16_f32_m\n";
13215ffd83dbSDimitry Andric 
13225ffd83dbSDimitry Andric   OS << "#define svcvtnt_f16_x      svcvtnt_f16_m\n";
13235ffd83dbSDimitry Andric   OS << "#define svcvtnt_f16_f32_x  svcvtnt_f16_f32_m\n";
13245ffd83dbSDimitry Andric   OS << "#define svcvtnt_f32_x      svcvtnt_f32_m\n";
13255ffd83dbSDimitry Andric   OS << "#define svcvtnt_f32_f64_x  svcvtnt_f32_f64_m\n\n";
13265ffd83dbSDimitry Andric 
13275ffd83dbSDimitry Andric   OS << "#define svcvtxnt_f32_x     svcvtxnt_f32_m\n";
13285ffd83dbSDimitry Andric   OS << "#define svcvtxnt_f32_f64_x svcvtxnt_f32_f64_m\n\n";
13295ffd83dbSDimitry Andric 
13305ffd83dbSDimitry Andric   OS << "#ifdef __cplusplus\n";
13315ffd83dbSDimitry Andric   OS << "} // extern \"C\"\n";
13325ffd83dbSDimitry Andric   OS << "#endif\n\n";
1333a4a491e2SDimitry Andric   OS << "#undef __ai\n\n";
1334a4a491e2SDimitry Andric   OS << "#undef __aio\n\n";
13355ffd83dbSDimitry Andric   OS << "#endif /* __ARM_SVE_H */\n";
13365ffd83dbSDimitry Andric }
13375ffd83dbSDimitry Andric 
13385ffd83dbSDimitry Andric void SVEEmitter::createBuiltins(raw_ostream &OS) {
13395ffd83dbSDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
13405ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
13415ffd83dbSDimitry Andric   for (auto *R : RV)
13425ffd83dbSDimitry Andric     createIntrinsic(R, Defs);
13435ffd83dbSDimitry Andric 
13445ffd83dbSDimitry Andric   // The mappings must be sorted based on BuiltinID.
13455ffd83dbSDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
13465ffd83dbSDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
13475ffd83dbSDimitry Andric     return A->getMangledName() < B->getMangledName();
13485ffd83dbSDimitry Andric   });
13495ffd83dbSDimitry Andric 
13505ffd83dbSDimitry Andric   OS << "#ifdef GET_SVE_BUILTINS\n";
13515ffd83dbSDimitry Andric   for (auto &Def : Defs) {
13525ffd83dbSDimitry Andric     // Only create BUILTINs for non-overloaded intrinsics, as overloaded
13535ffd83dbSDimitry Andric     // declarations only live in the header file.
13545ffd83dbSDimitry Andric     if (Def->getClassKind() != ClassG)
1355bdd1243dSDimitry Andric       OS << "TARGET_BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \""
1356bdd1243dSDimitry Andric          << Def->getBuiltinTypeStr() << "\", \"n\", \"" << Def->getGuard()
1357bdd1243dSDimitry Andric          << "\")\n";
13585ffd83dbSDimitry Andric   }
13595ffd83dbSDimitry Andric 
13605ffd83dbSDimitry Andric   // Add reinterpret builtins
13615ffd83dbSDimitry Andric   for (const ReinterpretTypeInfo &From : Reinterprets)
13625ffd83dbSDimitry Andric     for (const ReinterpretTypeInfo &To : Reinterprets)
1363bdd1243dSDimitry Andric       OS << "TARGET_BUILTIN(__builtin_sve_reinterpret_" << From.Suffix << "_"
13645ffd83dbSDimitry Andric          << To.Suffix << +", \"" << From.BuiltinType << To.BuiltinType
1365bdd1243dSDimitry Andric          << "\", \"n\", \"sve\")\n";
13665ffd83dbSDimitry Andric 
13675ffd83dbSDimitry Andric   OS << "#endif\n\n";
13685ffd83dbSDimitry Andric }
13695ffd83dbSDimitry Andric 
13705ffd83dbSDimitry Andric void SVEEmitter::createCodeGenMap(raw_ostream &OS) {
13715ffd83dbSDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
13725ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
13735ffd83dbSDimitry Andric   for (auto *R : RV)
13745ffd83dbSDimitry Andric     createIntrinsic(R, Defs);
13755ffd83dbSDimitry Andric 
13765ffd83dbSDimitry Andric   // The mappings must be sorted based on BuiltinID.
13775ffd83dbSDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
13785ffd83dbSDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
13795ffd83dbSDimitry Andric     return A->getMangledName() < B->getMangledName();
13805ffd83dbSDimitry Andric   });
13815ffd83dbSDimitry Andric 
13825ffd83dbSDimitry Andric   OS << "#ifdef GET_SVE_LLVM_INTRINSIC_MAP\n";
13835ffd83dbSDimitry Andric   for (auto &Def : Defs) {
13845ffd83dbSDimitry Andric     // Builtins only exist for non-overloaded intrinsics, overloaded
13855ffd83dbSDimitry Andric     // declarations only live in the header file.
13865ffd83dbSDimitry Andric     if (Def->getClassKind() == ClassG)
13875ffd83dbSDimitry Andric       continue;
13885ffd83dbSDimitry Andric 
13895ffd83dbSDimitry Andric     uint64_t Flags = Def->getFlags();
13905ffd83dbSDimitry Andric     auto FlagString = std::to_string(Flags);
13915ffd83dbSDimitry Andric 
1392*06c3fb27SDimitry Andric     std::string LLVMName = Def->getMangledLLVMName();
13935ffd83dbSDimitry Andric     std::string Builtin = Def->getMangledName();
13945ffd83dbSDimitry Andric     if (!LLVMName.empty())
13955ffd83dbSDimitry Andric       OS << "SVEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString
13965ffd83dbSDimitry Andric          << "),\n";
13975ffd83dbSDimitry Andric     else
13985ffd83dbSDimitry Andric       OS << "SVEMAP2(" << Builtin << ", " << FlagString << "),\n";
13995ffd83dbSDimitry Andric   }
14005ffd83dbSDimitry Andric   OS << "#endif\n\n";
14015ffd83dbSDimitry Andric }
14025ffd83dbSDimitry Andric 
14035ffd83dbSDimitry Andric void SVEEmitter::createRangeChecks(raw_ostream &OS) {
14045ffd83dbSDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
14055ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
14065ffd83dbSDimitry Andric   for (auto *R : RV)
14075ffd83dbSDimitry Andric     createIntrinsic(R, Defs);
14085ffd83dbSDimitry Andric 
14095ffd83dbSDimitry Andric   // The mappings must be sorted based on BuiltinID.
14105ffd83dbSDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
14115ffd83dbSDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
14125ffd83dbSDimitry Andric     return A->getMangledName() < B->getMangledName();
14135ffd83dbSDimitry Andric   });
14145ffd83dbSDimitry Andric 
14155ffd83dbSDimitry Andric 
14165ffd83dbSDimitry Andric   OS << "#ifdef GET_SVE_IMMEDIATE_CHECK\n";
14175ffd83dbSDimitry Andric 
14185ffd83dbSDimitry Andric   // Ensure these are only emitted once.
14195ffd83dbSDimitry Andric   std::set<std::string> Emitted;
14205ffd83dbSDimitry Andric 
14215ffd83dbSDimitry Andric   for (auto &Def : Defs) {
14225ffd83dbSDimitry Andric     if (Emitted.find(Def->getMangledName()) != Emitted.end() ||
14235ffd83dbSDimitry Andric         Def->getImmChecks().empty())
14245ffd83dbSDimitry Andric       continue;
14255ffd83dbSDimitry Andric 
14265ffd83dbSDimitry Andric     OS << "case SVE::BI__builtin_sve_" << Def->getMangledName() << ":\n";
14275ffd83dbSDimitry Andric     for (auto &Check : Def->getImmChecks())
14285ffd83dbSDimitry Andric       OS << "ImmChecks.push_back(std::make_tuple(" << Check.getArg() << ", "
14295ffd83dbSDimitry Andric          << Check.getKind() << ", " << Check.getElementSizeInBits() << "));\n";
14305ffd83dbSDimitry Andric     OS << "  break;\n";
14315ffd83dbSDimitry Andric 
14325ffd83dbSDimitry Andric     Emitted.insert(Def->getMangledName());
14335ffd83dbSDimitry Andric   }
14345ffd83dbSDimitry Andric 
14355ffd83dbSDimitry Andric   OS << "#endif\n\n";
14365ffd83dbSDimitry Andric }
14375ffd83dbSDimitry Andric 
14385ffd83dbSDimitry Andric /// Create the SVETypeFlags used in CGBuiltins
14395ffd83dbSDimitry Andric void SVEEmitter::createTypeFlags(raw_ostream &OS) {
14405ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_TYPEFLAGS\n";
14415ffd83dbSDimitry Andric   for (auto &KV : FlagTypes)
14425ffd83dbSDimitry Andric     OS << "const uint64_t " << KV.getKey() << " = " << KV.getValue() << ";\n";
14435ffd83dbSDimitry Andric   OS << "#endif\n\n";
14445ffd83dbSDimitry Andric 
14455ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_ELTTYPES\n";
14465ffd83dbSDimitry Andric   for (auto &KV : EltTypes)
14475ffd83dbSDimitry Andric     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
14485ffd83dbSDimitry Andric   OS << "#endif\n\n";
14495ffd83dbSDimitry Andric 
14505ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_MEMELTTYPES\n";
14515ffd83dbSDimitry Andric   for (auto &KV : MemEltTypes)
14525ffd83dbSDimitry Andric     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
14535ffd83dbSDimitry Andric   OS << "#endif\n\n";
14545ffd83dbSDimitry Andric 
14555ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_MERGETYPES\n";
14565ffd83dbSDimitry Andric   for (auto &KV : MergeTypes)
14575ffd83dbSDimitry Andric     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
14585ffd83dbSDimitry Andric   OS << "#endif\n\n";
14595ffd83dbSDimitry Andric 
14605ffd83dbSDimitry Andric   OS << "#ifdef LLVM_GET_SVE_IMMCHECKTYPES\n";
14615ffd83dbSDimitry Andric   for (auto &KV : ImmCheckTypes)
14625ffd83dbSDimitry Andric     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
14635ffd83dbSDimitry Andric   OS << "#endif\n\n";
14645ffd83dbSDimitry Andric }
14655ffd83dbSDimitry Andric 
1466*06c3fb27SDimitry Andric void SVEEmitter::createSMEHeader(raw_ostream &OS) {
1467*06c3fb27SDimitry Andric   OS << "/*===---- arm_sme_draft_spec_subject_to_change.h - ARM SME intrinsics "
1468*06c3fb27SDimitry Andric         "------===\n"
1469*06c3fb27SDimitry Andric         " *\n"
1470*06c3fb27SDimitry Andric         " *\n"
1471*06c3fb27SDimitry Andric         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
1472*06c3fb27SDimitry Andric         "Exceptions.\n"
1473*06c3fb27SDimitry Andric         " * See https://llvm.org/LICENSE.txt for license information.\n"
1474*06c3fb27SDimitry Andric         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
1475*06c3fb27SDimitry Andric         " *\n"
1476*06c3fb27SDimitry Andric         " *===-----------------------------------------------------------------"
1477*06c3fb27SDimitry Andric         "------===\n"
1478*06c3fb27SDimitry Andric         " */\n\n";
1479*06c3fb27SDimitry Andric 
1480*06c3fb27SDimitry Andric   OS << "#ifndef __ARM_SME_H\n";
1481*06c3fb27SDimitry Andric   OS << "#define __ARM_SME_H\n\n";
1482*06c3fb27SDimitry Andric 
1483*06c3fb27SDimitry Andric   OS << "#if !defined(__LITTLE_ENDIAN__)\n";
1484*06c3fb27SDimitry Andric   OS << "#error \"Big endian is currently not supported for arm_sme_draft_spec_subject_to_change.h\"\n";
1485*06c3fb27SDimitry Andric   OS << "#endif\n";
1486*06c3fb27SDimitry Andric 
1487*06c3fb27SDimitry Andric   OS << "#include <arm_sve.h> \n\n";
1488*06c3fb27SDimitry Andric 
1489*06c3fb27SDimitry Andric   OS << "/* Function attributes */\n";
1490*06c3fb27SDimitry Andric   OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
1491*06c3fb27SDimitry Andric         "__nodebug__))\n\n";
1492*06c3fb27SDimitry Andric   OS << "#define __aio static __inline__ __attribute__((__always_inline__, "
1493*06c3fb27SDimitry Andric         "__nodebug__, __overloadable__))\n\n";
1494*06c3fb27SDimitry Andric 
1495*06c3fb27SDimitry Andric   OS << "#ifdef  __cplusplus\n";
1496*06c3fb27SDimitry Andric   OS << "extern \"C\" {\n";
1497*06c3fb27SDimitry Andric   OS << "#endif\n\n";
1498*06c3fb27SDimitry Andric 
1499*06c3fb27SDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1500*06c3fb27SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1501*06c3fb27SDimitry Andric   for (auto *R : RV)
1502*06c3fb27SDimitry Andric     createIntrinsic(R, Defs);
1503*06c3fb27SDimitry Andric 
1504*06c3fb27SDimitry Andric   // Sort intrinsics in header file by following order/priority similar to SVE:
1505*06c3fb27SDimitry Andric   // - Architectural guard
1506*06c3fb27SDimitry Andric   // - Class (is intrinsic overloaded or not)
1507*06c3fb27SDimitry Andric   // - Intrinsic name
1508*06c3fb27SDimitry Andric   std::stable_sort(Defs.begin(), Defs.end(),
1509*06c3fb27SDimitry Andric                    [](const std::unique_ptr<Intrinsic> &A,
1510*06c3fb27SDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
1511*06c3fb27SDimitry Andric                      auto ToTuple = [](const std::unique_ptr<Intrinsic> &I) {
1512*06c3fb27SDimitry Andric                        return std::make_tuple(I->getGuard(),
1513*06c3fb27SDimitry Andric                                               (unsigned)I->getClassKind(),
1514*06c3fb27SDimitry Andric                                               I->getName());
1515*06c3fb27SDimitry Andric                      };
1516*06c3fb27SDimitry Andric                      return ToTuple(A) < ToTuple(B);
1517*06c3fb27SDimitry Andric                    });
1518*06c3fb27SDimitry Andric 
1519*06c3fb27SDimitry Andric   // Actually emit the intrinsic declaration.
1520*06c3fb27SDimitry Andric   for (auto &I : Defs) {
1521*06c3fb27SDimitry Andric     I->emitIntrinsic(OS, *this);
1522*06c3fb27SDimitry Andric   }
1523*06c3fb27SDimitry Andric 
1524*06c3fb27SDimitry Andric   OS << "#ifdef __cplusplus\n";
1525*06c3fb27SDimitry Andric   OS << "} // extern \"C\"\n";
1526*06c3fb27SDimitry Andric   OS << "#endif\n\n";
1527*06c3fb27SDimitry Andric   OS << "#undef __ai\n\n";
1528*06c3fb27SDimitry Andric   OS << "#endif /* __ARM_SME_H */\n";
1529*06c3fb27SDimitry Andric }
1530*06c3fb27SDimitry Andric 
1531*06c3fb27SDimitry Andric void SVEEmitter::createSMEBuiltins(raw_ostream &OS) {
1532*06c3fb27SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1533*06c3fb27SDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1534*06c3fb27SDimitry Andric   for (auto *R : RV) {
1535*06c3fb27SDimitry Andric     createIntrinsic(R, Defs);
1536*06c3fb27SDimitry Andric   }
1537*06c3fb27SDimitry Andric 
1538*06c3fb27SDimitry Andric   // The mappings must be sorted based on BuiltinID.
1539*06c3fb27SDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1540*06c3fb27SDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
1541*06c3fb27SDimitry Andric     return A->getMangledName() < B->getMangledName();
1542*06c3fb27SDimitry Andric   });
1543*06c3fb27SDimitry Andric 
1544*06c3fb27SDimitry Andric   OS << "#ifdef GET_SME_BUILTINS\n";
1545*06c3fb27SDimitry Andric   for (auto &Def : Defs) {
1546*06c3fb27SDimitry Andric     // Only create BUILTINs for non-overloaded intrinsics, as overloaded
1547*06c3fb27SDimitry Andric     // declarations only live in the header file.
1548*06c3fb27SDimitry Andric     if (Def->getClassKind() != ClassG)
1549*06c3fb27SDimitry Andric       OS << "TARGET_BUILTIN(__builtin_sme_" << Def->getMangledName() << ", \""
1550*06c3fb27SDimitry Andric          << Def->getBuiltinTypeStr() << "\", \"n\", \"" << Def->getGuard()
1551*06c3fb27SDimitry Andric          << "\")\n";
1552*06c3fb27SDimitry Andric   }
1553*06c3fb27SDimitry Andric 
1554*06c3fb27SDimitry Andric   OS << "#endif\n\n";
1555*06c3fb27SDimitry Andric }
1556*06c3fb27SDimitry Andric 
1557*06c3fb27SDimitry Andric void SVEEmitter::createSMECodeGenMap(raw_ostream &OS) {
1558*06c3fb27SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1559*06c3fb27SDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1560*06c3fb27SDimitry Andric   for (auto *R : RV) {
1561*06c3fb27SDimitry Andric     createIntrinsic(R, Defs);
1562*06c3fb27SDimitry Andric   }
1563*06c3fb27SDimitry Andric 
1564*06c3fb27SDimitry Andric   // The mappings must be sorted based on BuiltinID.
1565*06c3fb27SDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1566*06c3fb27SDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
1567*06c3fb27SDimitry Andric     return A->getMangledName() < B->getMangledName();
1568*06c3fb27SDimitry Andric   });
1569*06c3fb27SDimitry Andric 
1570*06c3fb27SDimitry Andric   OS << "#ifdef GET_SME_LLVM_INTRINSIC_MAP\n";
1571*06c3fb27SDimitry Andric   for (auto &Def : Defs) {
1572*06c3fb27SDimitry Andric     // Builtins only exist for non-overloaded intrinsics, overloaded
1573*06c3fb27SDimitry Andric     // declarations only live in the header file.
1574*06c3fb27SDimitry Andric     if (Def->getClassKind() == ClassG)
1575*06c3fb27SDimitry Andric       continue;
1576*06c3fb27SDimitry Andric 
1577*06c3fb27SDimitry Andric     uint64_t Flags = Def->getFlags();
1578*06c3fb27SDimitry Andric     auto FlagString = std::to_string(Flags);
1579*06c3fb27SDimitry Andric 
1580*06c3fb27SDimitry Andric     std::string LLVMName = Def->getLLVMName();
1581*06c3fb27SDimitry Andric     std::string Builtin = Def->getMangledName();
1582*06c3fb27SDimitry Andric     if (!LLVMName.empty())
1583*06c3fb27SDimitry Andric       OS << "SMEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString
1584*06c3fb27SDimitry Andric          << "),\n";
1585*06c3fb27SDimitry Andric     else
1586*06c3fb27SDimitry Andric       OS << "SMEMAP2(" << Builtin << ", " << FlagString << "),\n";
1587*06c3fb27SDimitry Andric   }
1588*06c3fb27SDimitry Andric   OS << "#endif\n\n";
1589*06c3fb27SDimitry Andric }
1590*06c3fb27SDimitry Andric 
1591*06c3fb27SDimitry Andric void SVEEmitter::createSMERangeChecks(raw_ostream &OS) {
1592*06c3fb27SDimitry Andric   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1593*06c3fb27SDimitry Andric   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1594*06c3fb27SDimitry Andric   for (auto *R : RV) {
1595*06c3fb27SDimitry Andric     createIntrinsic(R, Defs);
1596*06c3fb27SDimitry Andric   }
1597*06c3fb27SDimitry Andric 
1598*06c3fb27SDimitry Andric   // The mappings must be sorted based on BuiltinID.
1599*06c3fb27SDimitry Andric   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1600*06c3fb27SDimitry Andric                       const std::unique_ptr<Intrinsic> &B) {
1601*06c3fb27SDimitry Andric     return A->getMangledName() < B->getMangledName();
1602*06c3fb27SDimitry Andric   });
1603*06c3fb27SDimitry Andric 
1604*06c3fb27SDimitry Andric 
1605*06c3fb27SDimitry Andric   OS << "#ifdef GET_SME_IMMEDIATE_CHECK\n";
1606*06c3fb27SDimitry Andric 
1607*06c3fb27SDimitry Andric   // Ensure these are only emitted once.
1608*06c3fb27SDimitry Andric   std::set<std::string> Emitted;
1609*06c3fb27SDimitry Andric 
1610*06c3fb27SDimitry Andric   for (auto &Def : Defs) {
1611*06c3fb27SDimitry Andric     if (Emitted.find(Def->getMangledName()) != Emitted.end() ||
1612*06c3fb27SDimitry Andric         Def->getImmChecks().empty())
1613*06c3fb27SDimitry Andric       continue;
1614*06c3fb27SDimitry Andric 
1615*06c3fb27SDimitry Andric     OS << "case SME::BI__builtin_sme_" << Def->getMangledName() << ":\n";
1616*06c3fb27SDimitry Andric     for (auto &Check : Def->getImmChecks())
1617*06c3fb27SDimitry Andric       OS << "ImmChecks.push_back(std::make_tuple(" << Check.getArg() << ", "
1618*06c3fb27SDimitry Andric          << Check.getKind() << ", " << Check.getElementSizeInBits() << "));\n";
1619*06c3fb27SDimitry Andric     OS << "  break;\n";
1620*06c3fb27SDimitry Andric 
1621*06c3fb27SDimitry Andric     Emitted.insert(Def->getMangledName());
1622*06c3fb27SDimitry Andric   }
1623*06c3fb27SDimitry Andric 
1624*06c3fb27SDimitry Andric   OS << "#endif\n\n";
1625*06c3fb27SDimitry Andric }
1626*06c3fb27SDimitry Andric 
16275ffd83dbSDimitry Andric namespace clang {
16285ffd83dbSDimitry Andric void EmitSveHeader(RecordKeeper &Records, raw_ostream &OS) {
16295ffd83dbSDimitry Andric   SVEEmitter(Records).createHeader(OS);
16305ffd83dbSDimitry Andric }
16315ffd83dbSDimitry Andric 
16325ffd83dbSDimitry Andric void EmitSveBuiltins(RecordKeeper &Records, raw_ostream &OS) {
16335ffd83dbSDimitry Andric   SVEEmitter(Records).createBuiltins(OS);
16345ffd83dbSDimitry Andric }
16355ffd83dbSDimitry Andric 
16365ffd83dbSDimitry Andric void EmitSveBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
16375ffd83dbSDimitry Andric   SVEEmitter(Records).createCodeGenMap(OS);
16385ffd83dbSDimitry Andric }
16395ffd83dbSDimitry Andric 
16405ffd83dbSDimitry Andric void EmitSveRangeChecks(RecordKeeper &Records, raw_ostream &OS) {
16415ffd83dbSDimitry Andric   SVEEmitter(Records).createRangeChecks(OS);
16425ffd83dbSDimitry Andric }
16435ffd83dbSDimitry Andric 
16445ffd83dbSDimitry Andric void EmitSveTypeFlags(RecordKeeper &Records, raw_ostream &OS) {
16455ffd83dbSDimitry Andric   SVEEmitter(Records).createTypeFlags(OS);
16465ffd83dbSDimitry Andric }
16475ffd83dbSDimitry Andric 
1648*06c3fb27SDimitry Andric void EmitSmeHeader(RecordKeeper &Records, raw_ostream &OS) {
1649*06c3fb27SDimitry Andric   SVEEmitter(Records).createSMEHeader(OS);
1650*06c3fb27SDimitry Andric }
1651*06c3fb27SDimitry Andric 
1652*06c3fb27SDimitry Andric void EmitSmeBuiltins(RecordKeeper &Records, raw_ostream &OS) {
1653*06c3fb27SDimitry Andric   SVEEmitter(Records).createSMEBuiltins(OS);
1654*06c3fb27SDimitry Andric }
1655*06c3fb27SDimitry Andric 
1656*06c3fb27SDimitry Andric void EmitSmeBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
1657*06c3fb27SDimitry Andric   SVEEmitter(Records).createSMECodeGenMap(OS);
1658*06c3fb27SDimitry Andric }
1659*06c3fb27SDimitry Andric 
1660*06c3fb27SDimitry Andric void EmitSmeRangeChecks(RecordKeeper &Records, raw_ostream &OS) {
1661*06c3fb27SDimitry Andric   SVEEmitter(Records).createSMERangeChecks(OS);
1662*06c3fb27SDimitry Andric }
16635ffd83dbSDimitry Andric } // End namespace clang
1664