summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp')
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp233
1 files changed, 219 insertions, 14 deletions
diff --git a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
index e6f2e53..6837306 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
@@ -23,16 +23,206 @@
//
//===----------------------------------------------------------------------===//
-#include "NeonEmitter.h"
-#include "llvm/TableGen/Error.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <string>
-
using namespace llvm;
+enum OpKind {
+ OpNone,
+ OpUnavailable,
+ OpAdd,
+ OpAddl,
+ OpAddw,
+ OpSub,
+ OpSubl,
+ OpSubw,
+ OpMul,
+ OpMla,
+ OpMlal,
+ OpMls,
+ OpMlsl,
+ OpMulN,
+ OpMlaN,
+ OpMlsN,
+ OpMlalN,
+ OpMlslN,
+ OpMulLane,
+ OpMullLane,
+ OpMlaLane,
+ OpMlsLane,
+ OpMlalLane,
+ OpMlslLane,
+ OpQDMullLane,
+ OpQDMlalLane,
+ OpQDMlslLane,
+ OpQDMulhLane,
+ OpQRDMulhLane,
+ OpEq,
+ OpGe,
+ OpLe,
+ OpGt,
+ OpLt,
+ OpNeg,
+ OpNot,
+ OpAnd,
+ OpOr,
+ OpXor,
+ OpAndNot,
+ OpOrNot,
+ OpCast,
+ OpConcat,
+ OpDup,
+ OpDupLane,
+ OpHi,
+ OpLo,
+ OpSelect,
+ OpRev16,
+ OpRev32,
+ OpRev64,
+ OpReinterpret,
+ OpAbdl,
+ OpAba,
+ OpAbal
+};
+
+enum ClassKind {
+ ClassNone,
+ ClassI, // generic integer instruction, e.g., "i8" suffix
+ ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
+ ClassW, // width-specific instruction, e.g., "8" suffix
+ ClassB // bitcast arguments with enum argument to specify type
+};
+
+/// NeonTypeFlags - Flags to identify the types for overloaded Neon
+/// builtins. These must be kept in sync with the flags in
+/// include/clang/Basic/TargetBuiltins.h.
+namespace {
+class NeonTypeFlags {
+ enum {
+ EltTypeMask = 0xf,
+ UnsignedFlag = 0x10,
+ QuadFlag = 0x20
+ };
+ uint32_t Flags;
+
+public:
+ enum EltType {
+ Int8,
+ Int16,
+ Int32,
+ Int64,
+ Poly8,
+ Poly16,
+ Float16,
+ Float32
+ };
+
+ NeonTypeFlags(unsigned F) : Flags(F) {}
+ NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
+ if (IsUnsigned)
+ Flags |= UnsignedFlag;
+ if (IsQuad)
+ Flags |= QuadFlag;
+ }
+
+ uint32_t getFlags() const { return Flags; }
+};
+} // end anonymous namespace
+
+namespace {
+class NeonEmitter {
+ RecordKeeper &Records;
+ StringMap<OpKind> OpMap;
+ DenseMap<Record*, ClassKind> ClassMap;
+
+public:
+ NeonEmitter(RecordKeeper &R) : Records(R) {
+ OpMap["OP_NONE"] = OpNone;
+ OpMap["OP_UNAVAILABLE"] = OpUnavailable;
+ OpMap["OP_ADD"] = OpAdd;
+ OpMap["OP_ADDL"] = OpAddl;
+ OpMap["OP_ADDW"] = OpAddw;
+ OpMap["OP_SUB"] = OpSub;
+ OpMap["OP_SUBL"] = OpSubl;
+ OpMap["OP_SUBW"] = OpSubw;
+ OpMap["OP_MUL"] = OpMul;
+ OpMap["OP_MLA"] = OpMla;
+ OpMap["OP_MLAL"] = OpMlal;
+ OpMap["OP_MLS"] = OpMls;
+ OpMap["OP_MLSL"] = OpMlsl;
+ OpMap["OP_MUL_N"] = OpMulN;
+ OpMap["OP_MLA_N"] = OpMlaN;
+ OpMap["OP_MLS_N"] = OpMlsN;
+ OpMap["OP_MLAL_N"] = OpMlalN;
+ OpMap["OP_MLSL_N"] = OpMlslN;
+ OpMap["OP_MUL_LN"]= OpMulLane;
+ OpMap["OP_MULL_LN"] = OpMullLane;
+ OpMap["OP_MLA_LN"]= OpMlaLane;
+ OpMap["OP_MLS_LN"]= OpMlsLane;
+ OpMap["OP_MLAL_LN"] = OpMlalLane;
+ OpMap["OP_MLSL_LN"] = OpMlslLane;
+ OpMap["OP_QDMULL_LN"] = OpQDMullLane;
+ OpMap["OP_QDMLAL_LN"] = OpQDMlalLane;
+ OpMap["OP_QDMLSL_LN"] = OpQDMlslLane;
+ OpMap["OP_QDMULH_LN"] = OpQDMulhLane;
+ OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane;
+ OpMap["OP_EQ"] = OpEq;
+ OpMap["OP_GE"] = OpGe;
+ OpMap["OP_LE"] = OpLe;
+ OpMap["OP_GT"] = OpGt;
+ OpMap["OP_LT"] = OpLt;
+ OpMap["OP_NEG"] = OpNeg;
+ OpMap["OP_NOT"] = OpNot;
+ OpMap["OP_AND"] = OpAnd;
+ OpMap["OP_OR"] = OpOr;
+ OpMap["OP_XOR"] = OpXor;
+ OpMap["OP_ANDN"] = OpAndNot;
+ OpMap["OP_ORN"] = OpOrNot;
+ OpMap["OP_CAST"] = OpCast;
+ OpMap["OP_CONC"] = OpConcat;
+ OpMap["OP_HI"] = OpHi;
+ OpMap["OP_LO"] = OpLo;
+ OpMap["OP_DUP"] = OpDup;
+ OpMap["OP_DUP_LN"] = OpDupLane;
+ OpMap["OP_SEL"] = OpSelect;
+ OpMap["OP_REV16"] = OpRev16;
+ OpMap["OP_REV32"] = OpRev32;
+ OpMap["OP_REV64"] = OpRev64;
+ OpMap["OP_REINT"] = OpReinterpret;
+ OpMap["OP_ABDL"] = OpAbdl;
+ OpMap["OP_ABA"] = OpAba;
+ OpMap["OP_ABAL"] = OpAbal;
+
+ Record *SI = R.getClass("SInst");
+ Record *II = R.getClass("IInst");
+ Record *WI = R.getClass("WInst");
+ ClassMap[SI] = ClassS;
+ ClassMap[II] = ClassI;
+ ClassMap[WI] = ClassW;
+ }
+
+ // run - Emit arm_neon.h.inc
+ void run(raw_ostream &o);
+
+ // runHeader - Emit all the __builtin prototypes used in arm_neon.h
+ void runHeader(raw_ostream &o);
+
+ // runTests - Emit tests for all the Neon intrinsics.
+ void runTests(raw_ostream &o);
+
+private:
+ void emitIntrinsic(raw_ostream &OS, Record *R);
+};
+} // end anonymous namespace
+
/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
/// which each StringRef representing a single type declared in the string.
/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
@@ -1012,7 +1202,7 @@ static std::string GenIntrinsic(const std::string &name,
StringRef outTypeStr, StringRef inTypeStr,
OpKind kind, ClassKind classKind) {
assert(!proto.empty() && "");
- bool define = UseMacro(proto);
+ bool define = UseMacro(proto) && kind != OpUnavailable;
std::string s;
// static always inline + return type
@@ -1040,9 +1230,11 @@ static std::string GenIntrinsic(const std::string &name,
if (define) {
s += " __extension__ ({ \\\n ";
s += GenMacroLocals(proto, inTypeStr);
- } else {
- s += " { \\\n ";
- }
+ } else if (kind == OpUnavailable) {
+ s += " __attribute__((unavailable));\n";
+ return s;
+ } else
+ s += " {\n ";
if (kind != OpNone)
s += GenOpString(kind, proto, outTypeStr);
@@ -1238,7 +1430,7 @@ static unsigned RangeFromType(const char mod, StringRef typestr) {
/// runHeader - Emit a file with sections defining:
/// 1. the NEON section of BuiltinsARM.def.
/// 2. the SemaChecking code for the type overload checking.
-/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
+/// 3. the SemaChecking code for validation of intrinsic immediate arguments.
void NeonEmitter::runHeader(raw_ostream &OS) {
std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
@@ -1312,7 +1504,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
throw TGError(R->getLoc(), "Builtin has no class kind");
int si = -1, qi = -1;
- unsigned mask = 0, qmask = 0;
+ uint64_t mask = 0, qmask = 0;
for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
// Generate the switch case(s) for this builtin for the type validation.
bool quad = false, poly = false, usgn = false;
@@ -1320,10 +1512,10 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
if (quad) {
qi = ti;
- qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ qmask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
} else {
si = ti;
- mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ mask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]);
}
}
@@ -1360,7 +1552,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
if (mask) {
OS << "case ARM::BI__builtin_neon_"
<< MangleName(name, TypeVec[si], ClassB)
- << ": mask = " << "0x" << utohexstr(mask);
+ << ": mask = " << "0x" << utohexstr(mask) << "ULL";
if (PtrArgNum >= 0)
OS << "; PtrArgNum = " << PtrArgNum;
if (HasConstPtr)
@@ -1370,7 +1562,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
if (qmask) {
OS << "case ARM::BI__builtin_neon_"
<< MangleName(name, TypeVec[qi], ClassB)
- << ": mask = " << "0x" << utohexstr(qmask);
+ << ": mask = " << "0x" << utohexstr(qmask) << "ULL";
if (PtrArgNum >= 0)
OS << "; PtrArgNum = " << PtrArgNum;
if (HasConstPtr)
@@ -1505,7 +1697,7 @@ static std::string GenTest(const std::string &name,
s.push_back(arg);
comma = ", ";
}
- s += ") { \\\n ";
+ s += ") {\n ";
if (proto[0] != 'v')
s += "return ";
@@ -1551,6 +1743,8 @@ void NeonEmitter::runTests(raw_ostream &OS) {
ParseTypes(R, Types, TypeVec);
OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
+ if (kind == OpUnavailable)
+ continue;
for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
if (kind == OpReinterpret) {
bool outQuad = false;
@@ -1572,3 +1766,14 @@ void NeonEmitter::runTests(raw_ostream &OS) {
}
}
+namespace clang {
+void EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
+ NeonEmitter(Records).run(OS);
+}
+void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
+ NeonEmitter(Records).runHeader(OS);
+}
+void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
+ NeonEmitter(Records).runTests(OS);
+}
+} // End namespace clang
OpenPOWER on IntegriCloud