#include "NeonEmitter.h"
#include "Record.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
OpCast
};
+enum ClassKind {
+ ClassNone,
+ ClassI,
+ ClassS,
+ ClassW,
+ ClassB
+};
+
static void ParseTypes(Record *r, std::string &s,
SmallVectorImpl<StringRef> &TV) {
const char *data = s.data();
}
// Turn "vst2_lane" into "vst2q_lane_f32", etc.
-static std::string MangleName(const std::string &name, StringRef typestr) {
+static std::string MangleName(const std::string &name, StringRef typestr,
+ ClassKind ck) {
bool quad = false;
bool poly = false;
bool usgn = false;
std::string s = name;
switch (type) {
- case 'c':
- s += poly ? "_p8" : usgn ? "_u8" : "_s8";
- break;
- case 's':
- s += poly ? "_p16" : usgn ? "_u16" : "_s16";
- break;
- case 'i':
- s += usgn ? "_u32" : "_s32";
- break;
- case 'l':
- s += usgn ? "_u64" : "_s64";
- break;
- case 'h':
- s += "_f16";
- break;
- case 'f':
- s += "_f32";
- break;
- default:
- throw "unhandled type!";
- break;
+ case 'c':
+ switch (ck) {
+ case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
+ case ClassI: s += "_i8"; break;
+ case ClassW: s += "_8"; break;
+ default: break;
+ }
+ break;
+ case 's':
+ switch (ck) {
+ case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
+ case ClassI: s += "_i16"; break;
+ case ClassW: s += "_16"; break;
+ default: break;
+ }
+ break;
+ case 'i':
+ switch (ck) {
+ case ClassS: s += usgn ? "_u32" : "_s32"; break;
+ case ClassI: s += "_i32"; break;
+ case ClassW: s += "_32"; break;
+ default: break;
+ }
+ break;
+ case 'l':
+ switch (ck) {
+ case ClassS: s += usgn ? "_u64" : "_s64"; break;
+ case ClassI: s += "_i64"; break;
+ case ClassW: s += "_64"; break;
+ default: break;
+ }
+ break;
+ case 'h':
+ switch (ck) {
+ case ClassS:
+ case ClassI: s += "_f16"; break;
+ case ClassW: s += "_16"; break;
+ default: break;
+ }
+ break;
+ case 'f':
+ switch (ck) {
+ case ClassS:
+ case ClassI: s += "_f32"; break;
+ case ClassW: s += "_32"; break;
+ default: break;
+ }
+ break;
+ default:
+ throw "unhandled type!";
+ break;
}
-
+ if (ck == ClassB)
+ return s += "_v";
+
// Insert a 'q' before the first '_' character so that it ends up before
// _lane or _n on vector-scalar operations.
if (quad) {
// If structTypes is true, the NEON types are structs of vector types rather
// than vector types, and the call becomes __builtin_neon_cls(a.val)
static std::string GenBuiltin(const std::string &name, const std::string &proto,
- StringRef typestr, bool structTypes = true) {
+ StringRef typestr, ClassKind ck,
+ bool structTypes = true) {
char arg = 'a';
std::string s;
}
s += "__builtin_neon_";
- s += name;
+ s += MangleName(name, typestr, ck);
s += "(";
for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
OpMap["OP_ORN"] = OpOrNot;
OpMap["OP_CAST"] = OpCast;
+ DenseMap<Record*, ClassKind> ClassMap;
+ Record *SI = Records.getClass("SInst");
+ Record *II = Records.getClass("IInst");
+ Record *WI = Records.getClass("WInst");
+ Record *BI = Records.getClass("BInst");
+ ClassMap[SI] = ClassS;
+ ClassMap[II] = ClassI;
+ ClassMap[WI] = ClassW;
+ ClassMap[BI] = ClassB;
+
// Unique the return+pattern types, and assign them.
for (unsigned i = 0, e = RV.size(); i != e; ++i) {
Record *R = RV[i];
OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
// Function name with type suffix
- OS << " " << MangleName(name, TypeVec[ti]);
+ OS << " " << MangleName(name, TypeVec[ti], ClassS);
// Function arguments
OS << GenArgs(Proto, TypeVec[ti]);
// Definition.
OS << " { ";
- if (k != OpNone)
+ if (k != OpNone) {
OS << GenOpString(k, Proto, TypeVec[ti]);
- else
- OS << GenBuiltin(name, Proto, TypeVec[ti]);
+ } else {
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+ if (ck == ClassNone)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+ OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
+ }
OS << " }\n";
}
OS << "#endif /* __ARM_NEON_H */\n";
}
+
+void NeonEmitter::runHeader(raw_ostream &OS) {
+}