forked from OSchip/llvm-project
BuiltinsARM.def emitter, still needs a substantial bit of tweaking to lighten the load on clang.
llvm-svn: 105456
This commit is contained in:
parent
4e5e6a8973
commit
1ca8dba557
|
@ -14,46 +14,13 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "NeonEmitter.h"
|
#include "NeonEmitter.h"
|
||||||
#include "Record.h"
|
|
||||||
#include "llvm/ADT/DenseMap.h"
|
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
enum OpKind {
|
|
||||||
OpNone,
|
|
||||||
OpAdd,
|
|
||||||
OpSub,
|
|
||||||
OpMul,
|
|
||||||
OpMla,
|
|
||||||
OpMls,
|
|
||||||
OpEq,
|
|
||||||
OpGe,
|
|
||||||
OpLe,
|
|
||||||
OpGt,
|
|
||||||
OpLt,
|
|
||||||
OpNeg,
|
|
||||||
OpNot,
|
|
||||||
OpAnd,
|
|
||||||
OpOr,
|
|
||||||
OpXor,
|
|
||||||
OpAndNot,
|
|
||||||
OpOrNot,
|
|
||||||
OpCast
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ClassKind {
|
|
||||||
ClassNone,
|
|
||||||
ClassI,
|
|
||||||
ClassS,
|
|
||||||
ClassW,
|
|
||||||
ClassB
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ParseTypes(Record *r, std::string &s,
|
static void ParseTypes(Record *r, std::string &s,
|
||||||
SmallVectorImpl<StringRef> &TV) {
|
SmallVectorImpl<StringRef> &TV) {
|
||||||
const char *data = s.data();
|
const char *data = s.data();
|
||||||
|
@ -483,6 +450,20 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string GenBuiltinDef(const std::string &name,
|
||||||
|
const std::string &proto,
|
||||||
|
StringRef typestr, ClassKind ck) {
|
||||||
|
std::string s("BUILTIN(__builtin_neon_");
|
||||||
|
s += MangleName(name, typestr, ck);
|
||||||
|
s += ", \"";
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = proto.size(); i != e; ++i) {
|
||||||
|
}
|
||||||
|
|
||||||
|
s += "\", \"n\")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void NeonEmitter::run(raw_ostream &OS) {
|
void NeonEmitter::run(raw_ostream &OS) {
|
||||||
EmitSourceFileHeader("ARM NEON Header", OS);
|
EmitSourceFileHeader("ARM NEON Header", OS);
|
||||||
|
|
||||||
|
@ -539,37 +520,6 @@ void NeonEmitter::run(raw_ostream &OS) {
|
||||||
|
|
||||||
std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
|
std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
|
||||||
|
|
||||||
StringMap<OpKind> OpMap;
|
|
||||||
OpMap["OP_NONE"] = OpNone;
|
|
||||||
OpMap["OP_ADD"] = OpAdd;
|
|
||||||
OpMap["OP_SUB"] = OpSub;
|
|
||||||
OpMap["OP_MUL"] = OpMul;
|
|
||||||
OpMap["OP_MLA"] = OpMla;
|
|
||||||
OpMap["OP_MLS"] = OpMls;
|
|
||||||
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;
|
|
||||||
|
|
||||||
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.
|
// Unique the return+pattern types, and assign them.
|
||||||
for (unsigned i = 0, e = RV.size(); i != e; ++i) {
|
for (unsigned i = 0, e = RV.size(); i != e; ++i) {
|
||||||
Record *R = RV[i];
|
Record *R = RV[i];
|
||||||
|
@ -614,14 +564,41 @@ void NeonEmitter::run(raw_ostream &OS) {
|
||||||
}
|
}
|
||||||
OS << "\n";
|
OS << "\n";
|
||||||
}
|
}
|
||||||
|
OS << "#undef __ai\n\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 << "#endif /* __ARM_NEON_H */\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void NeonEmitter::runHeader(raw_ostream &OS) {
|
void NeonEmitter::runHeader(raw_ostream &OS) {
|
||||||
|
std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
|
||||||
|
|
||||||
|
StringMap<OpKind> EmittedMap;
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = RV.size(); i != e; ++i) {
|
||||||
|
Record *R = RV[i];
|
||||||
|
|
||||||
|
OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
|
||||||
|
if (k != OpNone)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string name = LowercaseString(R->getName());
|
||||||
|
std::string Proto = R->getValueAsString("Prototype");
|
||||||
|
std::string Types = R->getValueAsString("Types");
|
||||||
|
|
||||||
|
SmallVector<StringRef, 16> TypeVec;
|
||||||
|
ParseTypes(R, Types, TypeVec);
|
||||||
|
|
||||||
|
if (R->getSuperClasses().size() < 2)
|
||||||
|
throw TGError(R->getLoc(), "Builtin has no class kind");
|
||||||
|
|
||||||
|
ClassKind ck = ClassMap[R->getSuperClasses()[1]];
|
||||||
|
|
||||||
|
for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
|
||||||
|
std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
|
||||||
|
if (EmittedMap.count(bd))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
EmittedMap[bd] = OpNone;
|
||||||
|
OS << bd << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,79 @@
|
||||||
#ifndef NEON_EMITTER_H
|
#ifndef NEON_EMITTER_H
|
||||||
#define NEON_EMITTER_H
|
#define NEON_EMITTER_H
|
||||||
|
|
||||||
|
#include "Record.h"
|
||||||
#include "TableGenBackend.h"
|
#include "TableGenBackend.h"
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/StringMap.h"
|
||||||
|
|
||||||
|
enum OpKind {
|
||||||
|
OpNone,
|
||||||
|
OpAdd,
|
||||||
|
OpSub,
|
||||||
|
OpMul,
|
||||||
|
OpMla,
|
||||||
|
OpMls,
|
||||||
|
OpEq,
|
||||||
|
OpGe,
|
||||||
|
OpLe,
|
||||||
|
OpGt,
|
||||||
|
OpLt,
|
||||||
|
OpNeg,
|
||||||
|
OpNot,
|
||||||
|
OpAnd,
|
||||||
|
OpOr,
|
||||||
|
OpXor,
|
||||||
|
OpAndNot,
|
||||||
|
OpOrNot,
|
||||||
|
OpCast
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ClassKind {
|
||||||
|
ClassNone,
|
||||||
|
ClassI,
|
||||||
|
ClassS,
|
||||||
|
ClassW,
|
||||||
|
ClassB
|
||||||
|
};
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class NeonEmitter : public TableGenBackend {
|
class NeonEmitter : public TableGenBackend {
|
||||||
RecordKeeper &Records;
|
RecordKeeper &Records;
|
||||||
|
StringMap<OpKind> OpMap;
|
||||||
|
DenseMap<Record*, ClassKind> ClassMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NeonEmitter(RecordKeeper &R) : Records(R) {}
|
NeonEmitter(RecordKeeper &R) : Records(R) {
|
||||||
|
OpMap["OP_NONE"] = OpNone;
|
||||||
|
OpMap["OP_ADD"] = OpAdd;
|
||||||
|
OpMap["OP_SUB"] = OpSub;
|
||||||
|
OpMap["OP_MUL"] = OpMul;
|
||||||
|
OpMap["OP_MLA"] = OpMla;
|
||||||
|
OpMap["OP_MLS"] = OpMls;
|
||||||
|
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;
|
||||||
|
|
||||||
|
Record *SI = R.getClass("SInst");
|
||||||
|
Record *II = R.getClass("IInst");
|
||||||
|
Record *WI = R.getClass("WInst");
|
||||||
|
Record *BI = R.getClass("BInst");
|
||||||
|
ClassMap[SI] = ClassS;
|
||||||
|
ClassMap[II] = ClassI;
|
||||||
|
ClassMap[WI] = ClassW;
|
||||||
|
ClassMap[BI] = ClassB;
|
||||||
|
}
|
||||||
|
|
||||||
// run - Emit arm_neon.h.inc
|
// run - Emit arm_neon.h.inc
|
||||||
void run(raw_ostream &o);
|
void run(raw_ostream &o);
|
||||||
|
|
|
@ -66,6 +66,7 @@ enum ActionType {
|
||||||
GenLLVMCConf,
|
GenLLVMCConf,
|
||||||
GenEDHeader, GenEDInfo,
|
GenEDHeader, GenEDInfo,
|
||||||
GenNeonHeader,
|
GenNeonHeader,
|
||||||
|
GenNeonBuiltinsDef,
|
||||||
PrintEnums
|
PrintEnums
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,6 +127,8 @@ namespace {
|
||||||
"Generate enhanced disassembly info"),
|
"Generate enhanced disassembly info"),
|
||||||
clEnumValN(GenNeonHeader, "gen-arm-neon-header",
|
clEnumValN(GenNeonHeader, "gen-arm-neon-header",
|
||||||
"Generate arm_neon.h for clang"),
|
"Generate arm_neon.h for clang"),
|
||||||
|
clEnumValN(GenNeonBuiltinsDef, "gen-arm-neon-builtins-def",
|
||||||
|
"Generate NEON BuiltinsARM.def for clang"),
|
||||||
clEnumValN(PrintEnums, "print-enums",
|
clEnumValN(PrintEnums, "print-enums",
|
||||||
"Print enum values for a class"),
|
"Print enum values for a class"),
|
||||||
clEnumValEnd));
|
clEnumValEnd));
|
||||||
|
@ -294,6 +297,9 @@ int main(int argc, char **argv) {
|
||||||
case GenNeonHeader:
|
case GenNeonHeader:
|
||||||
NeonEmitter(Records).run(Out);
|
NeonEmitter(Records).run(Out);
|
||||||
break;
|
break;
|
||||||
|
case GenNeonBuiltinsDef:
|
||||||
|
NeonEmitter(Records).runHeader(Out);
|
||||||
|
break;
|
||||||
case PrintEnums:
|
case PrintEnums:
|
||||||
{
|
{
|
||||||
std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
|
std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
|
||||||
|
|
Loading…
Reference in New Issue