diff --git a/llvm/utils/TableGen/NeonEmitter.cpp b/llvm/utils/TableGen/NeonEmitter.cpp index ce754a78188d..eeb0bcc15047 100644 --- a/llvm/utils/TableGen/NeonEmitter.cpp +++ b/llvm/utils/TableGen/NeonEmitter.cpp @@ -15,12 +15,219 @@ #include "NeonEmitter.h" #include "Record.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include using namespace llvm; +static void ParseTypes(Record *r, std::string &s, + SmallVectorImpl &TV) { + const char *data = s.data(); + int len = 0; + + for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) { + if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U') + continue; + + switch (data[len]) { + case 'c': + case 's': + case 'i': + case 'l': + case 'h': + case 'f': + break; + default: + throw TGError(r->getLoc(), + "Unexpected letter: " + std::string(data + len, 1)); + break; + } + TV.push_back(StringRef(data, len + 1)); + data += len + 1; + len = -1; + } +} + +static const char Widen(const char t) { + switch (t) { + case 'c': + return 's'; + case 's': + return 'i'; + case 'i': + return 'l'; + default: throw "unhandled type in widen!"; + } + return '\0'; +} + +static std::string TypeString(const char mod, StringRef typestr) { + unsigned off = 0; + + bool quad = false; + bool poly = false; + bool usgn = false; + bool scal = false; + bool cnst = false; + bool pntr = false; + + // remember quad. + if (typestr[off] == 'Q') { + quad = true; + ++off; + } + + // remember poly. + if (typestr[off] == 'P') { + poly = true; + ++off; + } + + // remember unsigned. + if (typestr[off] == 'U') { + usgn = true; + ++off; + } + + // base type to get the type string for. + char type = typestr[off]; + + // Based on the modifying character, change the type and width if necessary. + switch (mod) { + case 'v': + type = 'v'; + scal = true; + usgn = false; + break; + case 't': + if (poly) { + poly = false; + usgn = true; + } + break; + case 'x': + usgn = true; + if (type == 'f') + type = 'i'; + break; + case 'f': + type = 'f'; + break; + case 'w': + type = Widen(type); + quad = true; + break; + case 'n': + type = Widen(type); + break; + case 'i': + type = 'i'; + scal = true; + usgn = false; + break; + case 'l': + type = 'l'; + scal = true; + usgn = true; + break; + case 's': + scal = true; + break; + case 'k': + quad = true; + break; + case 'c': + cnst = true; + case 'p': + pntr = true; + scal = true; + break; + default: + break; + } + + SmallString<128> s; + + if (usgn) + s.push_back('u'); + + switch (type) { + case 'c': + s += poly ? "poly8" : "int8"; + if (scal) + break; + s += quad ? "x16" : "x8"; + break; + case 's': + s += poly ? "poly16" : "int16"; + if (scal) + break; + s += quad ? "x8" : "x4"; + break; + case 'i': + s += "int32"; + if (scal) + break; + s += quad ? "x4" : "x2"; + break; + case 'l': + s += "int64"; + if (scal) + break; + s += quad ? "x2" : "x1"; + break; + case 'h': + s += "float16"; + if (scal) + break; + s += quad ? "x8" : "x4"; + break; + case 'f': + s += "float32"; + if (scal) + break; + s += quad ? "x4" : "x2"; + break; + case 'v': + s += "void"; + break; + default: + throw "unhandled type!"; + break; + } + + if (mod == '2') + s += "x2"; + if (mod == '3') + s += "x3"; + if (mod == '4') + s += "x4"; + + // Append _t, finishing the type string typedef type. + s += "_t"; + + if (cnst) + s += " const"; + + if (pntr) + s += " *"; + + return s.str(); +} + +// Turn "vst2_lane" into "vst2q_lane_f32", etc. +static std::string MangleName(const std::string &name, StringRef typestr) { + return ""; +} + +// +static std::string GenArgs(const std::string &proto, StringRef typestr) { + return ""; +} + void NeonEmitter::run(raw_ostream &OS) { EmitSourceFileHeader("ARM NEON Header", OS); @@ -37,25 +244,46 @@ void NeonEmitter::run(raw_ostream &OS) { // EmitTypedefs(OS); - // Process Records - std::vector RV = Records.getAllDerivedDefinitions("Inst"); - // Unique the pattern types, and assign them - - // emit #define directives for uniq'd prototypes - - // emit record directives + // Initialize Type Map + // Unique the return+pattern types, and assign them. for (unsigned i = 0, e = RV.size(); i != e; ++i) { Record *R = RV[i]; - - OS << LowercaseString(R->getName()) << "\n"; - + std::string name = LowercaseString(R->getName()); + std::string Proto = R->getValueAsString("Prototype"); std::string Types = R->getValueAsString("Types"); - //std::string Pattern = R->getValueAsString("Pattern"); - //OS << Types << "\n" << Pattern << "\n\n"; + + SmallVector TypeVec; + ParseTypes(R, Types, TypeVec); + + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { + assert(!Proto.empty() && ""); + + SmallString<128> Prototype; + Prototype += TypeString(Proto[0], TypeVec[ti]); + Prototype += " "; + Prototype += MangleName(name, TypeVec[ti]); + Prototype += GenArgs(Proto, TypeVec[ti]); + + OS << Prototype << ";\n"; + + // gen definition + + // if (opcode) + + // gen opstring + + // gen builtin (args) + } + OS << "\n"; } + + // TODO: + // Unique the return+pattern types, and assign them to each record + // Emit a #define for each unique "type" of intrinsic declaring all variants. + // Emit a #define for each intrinsic mapping it to a particular type. - OS << "#endif /* __ARM_NEON_H */\n"; + OS << "\n#endif /* __ARM_NEON_H */\n"; }