aboutsummaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2010-06-17 04:15:13 +0000
committerNate Begeman <natebegeman@mac.com>2010-06-17 04:15:13 +0000
commitf8c4c27d845d97463cbd56852e6e6964d7acc8ec (patch)
tree3f6000f38342e5f5c9062c86c9b876d2cc039aa3 /utils
parent7072cf62a52787c461e3371ad36e1754e8a0dc97 (diff)
downloadexternal_llvm-f8c4c27d845d97463cbd56852e6e6964d7acc8ec.zip
external_llvm-f8c4c27d845d97463cbd56852e6e6964d7acc8ec.tar.gz
external_llvm-f8c4c27d845d97463cbd56852e6e6964d7acc8ec.tar.bz2
Modify tablegen to support generating all NEON code used by clang at once.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@106207 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/NeonEmitter.cpp210
-rw-r--r--utils/TableGen/TableGen.cpp14
2 files changed, 135 insertions, 89 deletions
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 6343513..689db65 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -968,37 +968,66 @@ static unsigned RangeFromType(StringRef typestr) {
}
}
-/// runHeader - generate one of three different tables which are used by clang
-/// to support ARM NEON codegen. By default, this will produce the contents of
-/// BuiltinsARM.def's NEON section. You may also enable the genSemaTypes or
-/// getSemaRange variables below to generate code that SemaChecking will use to
-/// validate the builtin function calls.
-///
-/// This is not used as part of the build system currently, but is run manually
-/// and the output placed in the appropriate file.
+/// 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.
void NeonEmitter::runHeader(raw_ostream &OS) {
std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
StringMap<OpKind> EmittedMap;
- // Set true to generate the overloaded type checking code for SemaChecking.cpp
- bool genSemaTypes = false;
-
- // Set true to generate the intrinsic range checking code for shift/lane
- // immediates for SemaChecking.cpp
- bool genSemaRange = true;
-
+ // Generate BuiltinsARM.def for NEON
+ OS << "#ifdef GET_NEON_BUILTINS\n";
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 Proto = R->getValueAsString("Prototype");
+
+ // Functions with 'a' (the splat code) in the type prototype should not get
+ // their own builtin as they use the non-splat variant.
+ if (Proto.find('a') != std::string::npos)
+ continue;
+
+ 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");
std::string name = LowercaseString(R->getName());
+ ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ // Generate the BuiltinsARM.def declaration for this builtin, ensuring
+ // that each unique BUILTIN() macro appears only once in the output
+ // stream.
+ std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
+ if (EmittedMap.count(bd))
+ continue;
+
+ EmittedMap[bd] = OpNone;
+ OS << bd << "\n";
+ }
+ }
+ OS << "#endif\n\n";
+
+ // Generate the overloaded type checking code for SemaChecking.cpp
+ OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
+ 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 Proto = R->getValueAsString("Prototype");
std::string Types = R->getValueAsString("Types");
-
+ std::string name = LowercaseString(R->getName());
+
// Functions with 'a' (the splat code) in the type prototype should not get
// their own builtin as they use the non-splat variant.
if (Proto.find('a') != std::string::npos)
@@ -1006,12 +1035,62 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
// Functions which have a scalar argument cannot be overloaded, no need to
// check them if we are emitting the type checking code.
- if (genSemaTypes && Proto.find('s') != std::string::npos)
+ if (Proto.find('s') != std::string::npos)
+ continue;
+
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ int si = -1, qi = -1;
+ unsigned 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;
+ (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
+
+ if (quad) {
+ qi = ti;
+ qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ } else {
+ si = ti;
+ mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ }
+ }
+ if (mask)
+ OS << "case ARM::BI__builtin_neon_"
+ << MangleName(name, TypeVec[si], ClassB)
+ << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
+ if (qmask)
+ OS << "case ARM::BI__builtin_neon_"
+ << MangleName(name, TypeVec[qi], ClassB)
+ << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
+ }
+ OS << "#endif\n\n";
+
+ // Generate the intrinsic range checking code for shift/lane immediates.
+ OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
+ 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");
+
+ // Functions with 'a' (the splat code) in the type prototype should not get
+ // their own builtin as they use the non-splat variant.
+ if (Proto.find('a') != std::string::npos)
continue;
// Functions which do not have an immediate do not need to have range
// checking code emitted.
- if (genSemaRange && Proto.find('i') == std::string::npos)
+ if (Proto.find('i') == std::string::npos)
continue;
SmallVector<StringRef, 16> TypeVec;
@@ -1022,76 +1101,43 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
ClassKind ck = ClassMap[R->getSuperClasses()[1]];
- int si = -1, qi = -1;
- unsigned mask = 0, qmask = 0;
for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ std::string namestr, shiftstr, rangestr;
- // Generate the switch case(s) for this builtin for the type validation.
- if (genSemaTypes) {
- bool quad = false, poly = false, usgn = false;
- (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
-
- if (quad) {
- qi = ti;
- qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
- } else {
- si = ti;
- mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ // Builtins which are overloaded by type will need to have their upper
+ // bound computed at Sema time based on the type constant.
+ if (Proto.find('s') == std::string::npos) {
+ ck = ClassB;
+ if (R->getValueAsBit("isShift")) {
+ shiftstr = ", true";
+
+ // Right shifts have an 'r' in the name, left shifts do not.
+ if (name.find('r') != std::string::npos)
+ rangestr = "l = 1; ";
}
- continue;
+ rangestr += "u = RFT(TV" + shiftstr + ")";
+ } else {
+ rangestr = "u = " + utostr(RangeFromType(TypeVec[ti]));
}
+ // Make sure cases appear only once.
+ namestr = MangleName(name, TypeVec[ti], ck);
+ if (EmittedMap.count(namestr))
+ continue;
+ EmittedMap[namestr] = OpNone;
- if (genSemaRange) {
- std::string namestr, shiftstr, rangestr;
-
- // Builtins which are overloaded by type will need to have their upper
- // bound computed at Sema time based on the type constant.
- if (Proto.find('s') == std::string::npos) {
- ck = ClassB;
- if (R->getValueAsBit("isShift")) {
- shiftstr = ", true";
-
- // Right shifts have an 'r' in the name, left shifts do not.
- if (name.find('r') != std::string::npos)
- rangestr = "l = 1; ";
- }
- rangestr += "u = RFT(TV" + shiftstr + ")";
- } else {
- rangestr = "u = " + utostr(RangeFromType(TypeVec[ti]));
+ unsigned immidx = 0;
+ for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
+ switch (Proto[ii]) {
+ default: immidx += 1; break;
+ case '2': immidx += 2; break;
+ case '3': immidx += 3; break;
+ case '4': immidx += 4; break;
+ case 'i': ie = ii + 1; break;
}
- // Make sure cases appear only once.
- namestr = MangleName(name, TypeVec[ti], ck);
- if (EmittedMap.count(namestr))
- continue;
- EmittedMap[namestr] = OpNone;
-
- OS << "case ARM::BI__builtin_neon_"
- << MangleName(name, TypeVec[ti], ck) << ": i = " << Proto.find('i')-1
- << "; " << rangestr << "; break;\n";
- continue;
}
-
- // Generate the BuiltinsARM.def declaration for this builtin, ensuring
- // that each unique BUILTIN() macro appears only once in the output
- // stream.
- std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
- if (EmittedMap.count(bd))
- continue;
-
- EmittedMap[bd] = OpNone;
- OS << bd << "\n";
- }
-
- if (genSemaTypes) {
- if (mask)
- OS << "case ARM::BI__builtin_neon_"
- << MangleName(name, TypeVec[si], ClassB)
- << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
- if (qmask)
- OS << "case ARM::BI__builtin_neon_"
- << MangleName(name, TypeVec[qi], ClassB)
- << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
- continue;
+ OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
+ << ": i = " << immidx << "; " << rangestr << "; break;\n";
}
}
+ OS << "#endif\n\n";
}
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index 49a40c1..7a4f74f 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -68,8 +68,8 @@ enum ActionType {
GenTgtIntrinsic,
GenLLVMCConf,
GenEDHeader, GenEDInfo,
- GenNeonHeader,
- GenNeonBuiltinsDef,
+ GenArmNeon,
+ GenArmNeonSema,
PrintEnums
};
@@ -132,10 +132,10 @@ namespace {
"Generate enhanced disassembly info header"),
clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
"Generate enhanced disassembly info"),
- clEnumValN(GenNeonHeader, "gen-arm-neon-header",
+ clEnumValN(GenArmNeon, "gen-arm-neon",
"Generate arm_neon.h for clang"),
- clEnumValN(GenNeonBuiltinsDef, "gen-arm-neon-builtins-def",
- "Generate NEON BuiltinsARM.def for clang"),
+ clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
+ "Generate ARM NEON sema support for clang"),
clEnumValN(PrintEnums, "print-enums",
"Print enum values for a class"),
clEnumValEnd));
@@ -307,10 +307,10 @@ int main(int argc, char **argv) {
case GenEDInfo:
EDEmitter(Records).run(Out);
break;
- case GenNeonHeader:
+ case GenArmNeon:
NeonEmitter(Records).run(Out);
break;
- case GenNeonBuiltinsDef:
+ case GenArmNeonSema:
NeonEmitter(Records).runHeader(Out);
break;
case PrintEnums: