From f8c4c27d845d97463cbd56852e6e6964d7acc8ec Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Thu, 17 Jun 2010 04:15:13 +0000 Subject: 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 --- utils/TableGen/NeonEmitter.cpp | 210 +++++++++++++++++++++++++---------------- utils/TableGen/TableGen.cpp | 14 +-- 2 files changed, 135 insertions(+), 89 deletions(-) (limited to 'utils') diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 6343513b23..689db653cb 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 RV = Records.getAllDerivedDefinitions("Inst"); StringMap 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 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 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 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 49a40c172f..7a4f74ff6a 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: -- cgit v1.2.3