aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/utils/TableGen/NeonEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/utils/TableGen/NeonEmitter.cpp')
-rw-r--r--contrib/llvm-project/clang/utils/TableGen/NeonEmitter.cpp261
1 files changed, 169 insertions, 92 deletions
diff --git a/contrib/llvm-project/clang/utils/TableGen/NeonEmitter.cpp b/contrib/llvm-project/clang/utils/TableGen/NeonEmitter.cpp
index f0da1a7d2f4e..53334016c180 100644
--- a/contrib/llvm-project/clang/utils/TableGen/NeonEmitter.cpp
+++ b/contrib/llvm-project/clang/utils/TableGen/NeonEmitter.cpp
@@ -26,8 +26,6 @@
#include "TableGenBackends.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -45,6 +43,7 @@
#include <cstdint>
#include <deque>
#include <map>
+#include <optional>
#include <set>
#include <sstream>
#include <string>
@@ -292,7 +291,7 @@ class Variable {
std::string N;
public:
- Variable() : T(Type::getVoid()), N("") {}
+ Variable() : T(Type::getVoid()) {}
Variable(Type T, std::string N) : T(std::move(T)), N(std::move(N)) {}
Type getType() const { return T; }
@@ -321,8 +320,10 @@ class Intrinsic {
/// The list of DAGs for the body. May be empty, in which case we should
/// emit a builtin call.
ListInit *Body;
- /// The architectural #ifdef guard.
- std::string Guard;
+ /// The architectural ifdef guard.
+ std::string ArchGuard;
+ /// The architectural target() guard.
+ std::string TargetGuard;
/// Set if the Unavailable bit is 1. This means we don't generate a body,
/// just an "unavailable" attribute on a declaration.
bool IsUnavailable;
@@ -368,9 +369,9 @@ class Intrinsic {
public:
Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS,
TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter,
- StringRef Guard, bool IsUnavailable, bool BigEndianSafe)
+ StringRef ArchGuard, StringRef TargetGuard, bool IsUnavailable, bool BigEndianSafe)
: R(R), Name(Name.str()), OutTS(OutTS), InTS(InTS), CK(CK), Body(Body),
- Guard(Guard.str()), IsUnavailable(IsUnavailable),
+ ArchGuard(ArchGuard.str()), TargetGuard(TargetGuard.str()), IsUnavailable(IsUnavailable),
BigEndianSafe(BigEndianSafe), PolymorphicKeyType(0), NeededEarly(false),
UseMacro(false), BaseType(OutTS, "."), InBaseType(InTS, "."),
Emitter(Emitter) {
@@ -382,13 +383,13 @@ public:
StringRef Mods = getNextModifiers(Proto, Pos);
while (!Mods.empty()) {
Types.emplace_back(InTS, Mods);
- if (Mods.find('!') != StringRef::npos)
+ if (Mods.contains('!'))
PolymorphicKeyType = Types.size() - 1;
Mods = getNextModifiers(Proto, Pos);
}
- for (auto Type : Types) {
+ for (const auto &Type : Types) {
// If this builtin takes an immediate argument, we need to #define it rather
// than use a standard declaration, so that SemaChecking can range check
// the immediate passed by the user.
@@ -411,14 +412,14 @@ public:
/// transitive closure.
const std::set<Intrinsic *> &getDependencies() const { return Dependencies; }
/// Get the architectural guard string (#ifdef).
- std::string getGuard() const { return Guard; }
+ std::string getArchGuard() const { return ArchGuard; }
+ std::string getTargetGuard() const { return TargetGuard; }
/// Get the non-mangled name.
std::string getName() const { return Name; }
/// Return true if the intrinsic takes an immediate operand.
bool hasImmediate() const {
- return std::any_of(Types.begin(), Types.end(),
- [](const Type &T) { return T.isImmediate(); });
+ return llvm::any_of(Types, [](const Type &T) { return T.isImmediate(); });
}
/// Return the parameter index of the immediate operand.
@@ -442,7 +443,7 @@ public:
/// Return the index that parameter PIndex will sit at
/// in a generated function call. This is often just PIndex,
/// but may not be as things such as multiple-vector operands
- /// and sret parameters need to be taken into accont.
+ /// and sret parameters need to be taken into account.
unsigned getGeneratedParamIdx(unsigned PIndex) {
unsigned Idx = 0;
if (getReturnType().getNumVectors() > 1)
@@ -460,9 +461,11 @@ public:
void setNeededEarly() { NeededEarly = true; }
bool operator<(const Intrinsic &Other) const {
- // Sort lexicographically on a two-tuple (Guard, Name)
- if (Guard != Other.Guard)
- return Guard < Other.Guard;
+ // Sort lexicographically on a three-tuple (ArchGuard, TargetGuard, Name)
+ if (ArchGuard != Other.ArchGuard)
+ return ArchGuard < Other.ArchGuard;
+ if (TargetGuard != Other.TargetGuard)
+ return TargetGuard < Other.TargetGuard;
return Name < Other.Name;
}
@@ -503,6 +506,7 @@ private:
void emitBody(StringRef CallPrefix);
void emitShadowedArgs();
void emitArgumentReversal();
+ void emitReturnVarDecl();
void emitReturnReversal();
void emitReverseVariable(Variable &Dest, Variable &Src);
void emitNewLine();
@@ -546,6 +550,8 @@ class NeonEmitter {
void createIntrinsic(Record *R, SmallVectorImpl<Intrinsic *> &Out);
void genBuiltinsDef(raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs);
+ void genStreamingSVECompatibleList(raw_ostream &OS,
+ SmallVectorImpl<Intrinsic *> &Defs);
void genOverloadTypeCheckCode(raw_ostream &OS,
SmallVectorImpl<Intrinsic *> &Defs);
void genIntrinsicRangeCheckCode(raw_ostream &OS,
@@ -555,7 +561,7 @@ public:
/// Called by Intrinsic - this attempts to get an intrinsic that takes
/// the given types as arguments.
Intrinsic &getIntrinsic(StringRef Name, ArrayRef<Type> Types,
- Optional<std::string> MangledName);
+ std::optional<std::string> MangledName);
/// Called by Intrinsic - returns a globally-unique number.
unsigned getUniqueNumber() { return UniqueNumber++; }
@@ -589,6 +595,8 @@ public:
// Emit arm_bf16.h.inc
void runBF16(raw_ostream &o);
+ void runVectorTypes(raw_ostream &o);
+
// Emit all the __builtin prototypes used in arm_neon.h, arm_fp16.h and
// arm_bf16.h
void runHeader(raw_ostream &o);
@@ -732,17 +740,17 @@ Type Type::fromTypedefName(StringRef Name) {
Name = Name.drop_front();
}
- if (Name.startswith("float")) {
+ if (Name.starts_with("float")) {
T.Kind = Float;
Name = Name.drop_front(5);
- } else if (Name.startswith("poly")) {
+ } else if (Name.starts_with("poly")) {
T.Kind = Poly;
Name = Name.drop_front(4);
- } else if (Name.startswith("bfloat")) {
+ } else if (Name.starts_with("bfloat")) {
T.Kind = BFloat16;
Name = Name.drop_front(6);
} else {
- assert(Name.startswith("int"));
+ assert(Name.starts_with("int"));
Name = Name.drop_front(3);
}
@@ -783,7 +791,7 @@ Type Type::fromTypedefName(StringRef Name) {
Name = Name.drop_front(I);
}
- assert(Name.startswith("_t") && "Malformed typedef!");
+ assert(Name.starts_with("_t") && "Malformed typedef!");
return T;
}
@@ -817,19 +825,19 @@ void Type::applyTypespec(bool &Quad) {
break;
case 'h':
Kind = Float;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case 's':
ElementBitwidth = 16;
break;
case 'f':
Kind = Float;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case 'i':
ElementBitwidth = 32;
break;
case 'd':
Kind = Float;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case 'l':
ElementBitwidth = 64;
break;
@@ -951,7 +959,7 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const {
char typeCode = '\0';
bool printNumber = true;
- if (CK == ClassB)
+ if (CK == ClassB && TargetGuard == "")
return "";
if (T.isBFloat16())
@@ -975,7 +983,7 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const {
break;
}
}
- if (CK == ClassB) {
+ if (CK == ClassB && TargetGuard == "") {
typeCode = '\0';
}
@@ -1077,7 +1085,7 @@ std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const {
S += "_" + getInstTypeCode(InBaseType, LocalCK);
}
- if (LocalCK == ClassB)
+ if (LocalCK == ClassB && TargetGuard == "")
S += "_v";
// Insert a 'q' before the first '_' character so that it ends up before
@@ -1137,10 +1145,14 @@ void Intrinsic::initVariables() {
}
void Intrinsic::emitPrototype(StringRef NamePrefix) {
- if (UseMacro)
+ if (UseMacro) {
OS << "#define ";
- else
- OS << "__ai " << Types[0].str() << " ";
+ } else {
+ OS << "__ai ";
+ if (TargetGuard != "")
+ OS << "__attribute__((target(\"" << TargetGuard << "\"))) ";
+ OS << Types[0].str() << " ";
+ }
OS << NamePrefix.str() << mangleName(Name, ClassS) << "(";
@@ -1229,6 +1241,15 @@ void Intrinsic::emitArgumentReversal() {
}
}
+void Intrinsic::emitReturnVarDecl() {
+ assert(RetVar.getType() == Types[0]);
+ // Create a return variable, if we're not void.
+ if (!RetVar.getType().isVoid()) {
+ OS << " " << RetVar.getType().str() << " " << RetVar.getName() << ";";
+ emitNewLine();
+ }
+}
+
void Intrinsic::emitReturnReversal() {
if (isBigEndianSafe())
return;
@@ -1271,9 +1292,8 @@ void Intrinsic::emitShadowedArgs() {
}
bool Intrinsic::protoHasScalar() const {
- return std::any_of(Types.begin(), Types.end(), [](const Type &T) {
- return T.isScalar() && !T.isImmediate();
- });
+ return llvm::any_of(
+ Types, [](const Type &T) { return T.isScalar() && !T.isImmediate(); });
}
void Intrinsic::emitBodyAsBuiltinCall() {
@@ -1308,7 +1328,7 @@ void Intrinsic::emitBodyAsBuiltinCall() {
if (LocalCK == ClassB) {
Type T2 = T;
T2.makeOneVector();
- T2.makeInteger(8, /*Signed=*/true);
+ T2.makeInteger(8, /*Sign=*/true);
Cast = "(" + T2.str() + ")";
}
@@ -1355,13 +1375,6 @@ void Intrinsic::emitBodyAsBuiltinCall() {
void Intrinsic::emitBody(StringRef CallPrefix) {
std::vector<std::string> Lines;
- assert(RetVar.getType() == Types[0]);
- // Create a return variable, if we're not void.
- if (!RetVar.getType().isVoid()) {
- OS << " " << RetVar.getType().str() << " " << RetVar.getName() << ";";
- emitNewLine();
- }
-
if (!Body || Body->getValues().empty()) {
// Nothing specific to output - must output a builtin.
emitBodyAsBuiltinCall();
@@ -1462,7 +1475,7 @@ Intrinsic::DagEmitter::emitDagCall(DagInit *DI, bool MatchMangledName) {
N = SI->getAsUnquotedString();
else
N = emitDagArg(DI->getArg(0), "").second;
- Optional<std::string> MangledName;
+ std::optional<std::string> MangledName;
if (MatchMangledName) {
if (Intr.getRecord()->getValueAsBit("isLaneQ"))
N += "q";
@@ -1475,7 +1488,7 @@ Intrinsic::DagEmitter::emitDagCall(DagInit *DI, bool MatchMangledName) {
Intr.Dependencies.insert(&Callee);
// Now create the call itself.
- std::string S = "";
+ std::string S;
if (!Callee.isBigEndianSafe())
S += CallPrefix.str();
S += Callee.getMangledName(true) + "(";
@@ -1641,12 +1654,12 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){
std::make_unique<Rev>(Arg1.first.getElementSizeInBits()));
ST.addExpander("MaskExpand",
std::make_unique<MaskExpander>(Arg1.first.getNumElements()));
- ST.evaluate(DI->getArg(2), Elts, None);
+ ST.evaluate(DI->getArg(2), Elts, std::nullopt);
std::string S = "__builtin_shufflevector(" + Arg1.second + ", " + Arg2.second;
for (auto &E : Elts) {
StringRef Name = E->getName();
- assert_with_loc(Name.startswith("sv"),
+ assert_with_loc(Name.starts_with("sv"),
"Incorrect element kind in shuffle mask!");
S += ", " + Name.drop_front(2).str();
}
@@ -1851,6 +1864,9 @@ void Intrinsic::generateImpl(bool ReverseArguments,
OS << " __attribute__((unavailable));";
} else {
emitOpeningBrace();
+ // Emit return variable declaration first as to not trigger
+ // -Wdeclaration-after-statement.
+ emitReturnVarDecl();
emitShadowedArgs();
if (ReverseArguments)
emitArgumentReversal();
@@ -1869,6 +1885,9 @@ void Intrinsic::indexBody() {
CurrentRecord = R;
initVariables();
+ // Emit return variable declaration first as to not trigger
+ // -Wdeclaration-after-statement.
+ emitReturnVarDecl();
emitBody("");
OS.str("");
@@ -1880,7 +1899,7 @@ void Intrinsic::indexBody() {
//===----------------------------------------------------------------------===//
Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types,
- Optional<std::string> MangledName) {
+ std::optional<std::string> MangledName) {
// First, look up the name in the intrinsic map.
assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(),
("Intrinsic '" + Name + "' not found!").str());
@@ -1916,10 +1935,9 @@ Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types,
continue;
unsigned ArgNum = 0;
- bool MatchingArgumentTypes =
- std::all_of(Types.begin(), Types.end(), [&](const auto &Type) {
- return Type == I.getParamType(ArgNum++);
- });
+ bool MatchingArgumentTypes = llvm::all_of(Types, [&](const auto &Type) {
+ return Type == I.getParamType(ArgNum++);
+ });
if (MatchingArgumentTypes)
GoodVec.push_back(&I);
@@ -1939,7 +1957,8 @@ void NeonEmitter::createIntrinsic(Record *R,
std::string Types = std::string(R->getValueAsString("Types"));
Record *OperationRec = R->getValueAsDef("Operation");
bool BigEndianSafe = R->getValueAsBit("BigEndianSafe");
- std::string Guard = std::string(R->getValueAsString("ArchGuard"));
+ std::string ArchGuard = std::string(R->getValueAsString("ArchGuard"));
+ std::string TargetGuard = std::string(R->getValueAsString("TargetGuard"));
bool IsUnavailable = OperationRec->getValueAsBit("Unavailable");
std::string CartesianProductWith = std::string(R->getValueAsString("CartesianProductWith"));
@@ -1981,7 +2000,7 @@ void NeonEmitter::createIntrinsic(Record *R,
for (auto &I : NewTypeSpecs) {
Entry.emplace_back(R, Name, Proto, I.first, I.second, CK, Body, *this,
- Guard, IsUnavailable, BigEndianSafe);
+ ArchGuard, TargetGuard, IsUnavailable, BigEndianSafe);
Out.push_back(&Entry.back());
}
@@ -1996,22 +2015,55 @@ void NeonEmitter::genBuiltinsDef(raw_ostream &OS,
// We only want to emit a builtin once, and we want to emit them in
// alphabetical order, so use a std::set.
- std::set<std::string> Builtins;
+ std::set<std::pair<std::string, std::string>> Builtins;
for (auto *Def : Defs) {
if (Def->hasBody())
continue;
- std::string S = "BUILTIN(__builtin_neon_" + Def->getMangledName() + ", \"";
-
+ std::string S = "__builtin_neon_" + Def->getMangledName() + ", \"";
S += Def->getBuiltinTypeStr();
- S += "\", \"n\")";
+ S += "\", \"n\"";
- Builtins.insert(S);
+ Builtins.emplace(S, Def->getTargetGuard());
+ }
+
+ for (auto &S : Builtins) {
+ if (S.second == "")
+ OS << "BUILTIN(";
+ else
+ OS << "TARGET_BUILTIN(";
+ OS << S.first;
+ if (S.second == "")
+ OS << ")\n";
+ else
+ OS << ", \"" << S.second << "\")\n";
}
- for (auto &S : Builtins)
- OS << S << "\n";
+ OS << "#endif\n\n";
+}
+
+void NeonEmitter::genStreamingSVECompatibleList(
+ raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs) {
+ OS << "#ifdef GET_NEON_STREAMING_COMPAT_FLAG\n";
+
+ std::set<std::string> Emitted;
+ for (auto *Def : Defs) {
+ // If the def has a body (that is, it has Operation DAGs), it won't call
+ // __builtin_neon_* so we don't need to generate a definition for it.
+ if (Def->hasBody())
+ continue;
+
+ std::string Name = Def->getMangledName();
+ if (Emitted.find(Name) != Emitted.end())
+ continue;
+
+ // FIXME: We should make exceptions here for some NEON builtins that are
+ // permitted in streaming mode.
+ OS << "case NEON::BI__builtin_neon_" << Name
+ << ": BuiltinType = ArmNonStreaming; break;\n";
+ Emitted.insert(Name);
+ }
OS << "#endif\n\n";
}
@@ -2025,10 +2077,10 @@ void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
// definitions may extend the number of permitted types (i.e. augment the
// Mask). Use std::map to avoid sorting the table by hash number.
struct OverloadInfo {
- uint64_t Mask;
- int PtrArgNum;
- bool HasConstPtr;
- OverloadInfo() : Mask(0ULL), PtrArgNum(0), HasConstPtr(false) {}
+ uint64_t Mask = 0ULL;
+ int PtrArgNum = 0;
+ bool HasConstPtr = false;
+ OverloadInfo() = default;
};
std::map<std::string, OverloadInfo> OverloadMap;
@@ -2062,12 +2114,13 @@ void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
std::string Name = Def->getName();
// Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
- // and vst1_lane intrinsics. Using a pointer to the vector element
- // type with one of those operations causes codegen to select an aligned
- // load/store instruction. If you want an unaligned operation,
- // the pointer argument needs to have less alignment than element type,
- // so just accept any pointer type.
- if (Name == "vld1_lane" || Name == "vld1_dup" || Name == "vst1_lane") {
+ // vst1_lane, vldap1_lane, and vstl1_lane intrinsics. Using a pointer to
+ // the vector element type with one of those operations causes codegen to
+ // select an aligned load/store instruction. If you want an unaligned
+ // operation, the pointer argument needs to have less alignment than element
+ // type, so just accept any pointer type.
+ if (Name == "vld1_lane" || Name == "vld1_dup" || Name == "vst1_lane" ||
+ Name == "vldap1_lane" || Name == "vstl1_lane") {
PtrArgNum = -1;
HasConstPtr = false;
}
@@ -2197,6 +2250,8 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
// Generate ARM overloaded type checking code for SemaChecking.cpp
genOverloadTypeCheckCode(OS, Defs);
+ genStreamingSVECompatibleList(OS, Defs);
+
// Generate ARM range checking code for shift/lane immediates.
genIntrinsicRangeCheckCode(OS, Defs);
}
@@ -2328,18 +2383,9 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "#include <stdint.h>\n\n";
- OS << "#ifdef __ARM_FEATURE_BF16\n";
OS << "#include <arm_bf16.h>\n";
- OS << "typedef __bf16 bfloat16_t;\n";
- OS << "#endif\n\n";
- // Emit NEON-specific scalar typedefs.
- OS << "typedef float float32_t;\n";
- OS << "typedef __fp16 float16_t;\n";
-
- OS << "#ifdef __aarch64__\n";
- OS << "typedef double float64_t;\n";
- OS << "#endif\n\n";
+ OS << "#include <arm_vector_types.h>\n";
// For now, signedness of polynomial types depends on target
OS << "#ifdef __aarch64__\n";
@@ -2352,12 +2398,7 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "typedef int16_t poly16_t;\n";
OS << "typedef int64_t poly64_t;\n";
OS << "#endif\n";
-
- emitNeonTypeDefs("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPsPlQPl", OS);
-
- OS << "#ifdef __ARM_FEATURE_BF16\n";
- emitNeonTypeDefs("bQb", OS);
- OS << "#endif\n\n";
+ emitNeonTypeDefs("PcQPcPsQPsPlQPl", OS);
OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
"__nodebug__))\n\n";
@@ -2393,10 +2434,10 @@ void NeonEmitter::run(raw_ostream &OS) {
}
// Emit #endif/#if pair if needed.
- if ((*I)->getGuard() != InGuard) {
+ if ((*I)->getArchGuard() != InGuard) {
if (!InGuard.empty())
OS << "#endif\n";
- InGuard = (*I)->getGuard();
+ InGuard = (*I)->getArchGuard();
if (!InGuard.empty())
OS << "#if " << InGuard << "\n";
}
@@ -2502,10 +2543,10 @@ void NeonEmitter::runFP16(raw_ostream &OS) {
}
// Emit #endif/#if pair if needed.
- if ((*I)->getGuard() != InGuard) {
+ if ((*I)->getArchGuard() != InGuard) {
if (!InGuard.empty())
OS << "#endif\n";
- InGuard = (*I)->getGuard();
+ InGuard = (*I)->getArchGuard();
if (!InGuard.empty())
OS << "#if " << InGuard << "\n";
}
@@ -2526,6 +2567,38 @@ void NeonEmitter::runFP16(raw_ostream &OS) {
OS << "#endif /* __ARM_FP16_H */\n";
}
+void NeonEmitter::runVectorTypes(raw_ostream &OS) {
+ OS << "/*===---- arm_vector_types - ARM vector type "
+ "------===\n"
+ " *\n"
+ " *\n"
+ " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
+ "Exceptions.\n"
+ " * See https://llvm.org/LICENSE.txt for license information.\n"
+ " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
+ " *\n"
+ " *===-----------------------------------------------------------------"
+ "------===\n"
+ " */\n\n";
+ OS << "#if !defined(__ARM_NEON_H) && !defined(__ARM_SVE_H)\n";
+ OS << "#error \"This file should not be used standalone. Please include"
+ " arm_neon.h or arm_sve.h instead\"\n\n";
+ OS << "#endif\n";
+ OS << "#ifndef __ARM_NEON_TYPES_H\n";
+ OS << "#define __ARM_NEON_TYPES_H\n";
+ OS << "typedef float float32_t;\n";
+ OS << "typedef __fp16 float16_t;\n";
+
+ OS << "#ifdef __aarch64__\n";
+ OS << "typedef double float64_t;\n";
+ OS << "#endif\n\n";
+
+ emitNeonTypeDefs("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQd", OS);
+
+ emitNeonTypeDefs("bQb", OS);
+ OS << "#endif // __ARM_NEON_TYPES_H\n";
+}
+
void NeonEmitter::runBF16(raw_ostream &OS) {
OS << "/*===---- arm_bf16.h - ARM BF16 intrinsics "
"-----------------------------------===\n"
@@ -2579,10 +2652,10 @@ void NeonEmitter::runBF16(raw_ostream &OS) {
}
// Emit #endif/#if pair if needed.
- if ((*I)->getGuard() != InGuard) {
+ if ((*I)->getArchGuard() != InGuard) {
if (!InGuard.empty())
OS << "#endif\n";
- InGuard = (*I)->getGuard();
+ InGuard = (*I)->getArchGuard();
if (!InGuard.empty())
OS << "#if " << InGuard << "\n";
}
@@ -2620,6 +2693,10 @@ void clang::EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runHeader(OS);
}
+void clang::EmitVectorTypes(RecordKeeper &Records, raw_ostream &OS) {
+ NeonEmitter(Records).runVectorTypes(OS);
+}
+
void clang::EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
llvm_unreachable("Neon test generation no longer implemented!");
}