1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

Add a helping of comments

Add code for generating bits of semachecking

llvm-svn: 105907
This commit is contained in:
Nate Begeman 2010-06-13 04:47:03 +00:00
parent 1f31d12e8f
commit 955d383e5b

View File

@ -11,6 +11,15 @@
// a declaration and definition of each function specified by the ARM NEON
// compiler interface. See ARM document DUI0348B.
//
// Each NEON instruction is implemented in terms of 1 or more functions which
// are suffixed with the element type of the input vectors. Functions may be
// implemented in terms of generic vector operations such as +, *, -, etc. or
// by calling a __builtin_-prefixed function which will be handled by clang's
// CodeGen library.
//
// Additional validation code can be generated by this file when runHeader() is
// called, rather than the normal run() entry point.
//
//===----------------------------------------------------------------------===//
#include "NeonEmitter.h"
@ -21,6 +30,10 @@
using namespace llvm;
/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
/// which each StringRef representing a single type declared in the string.
/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
/// 2xfloat and 4xfloat respectively.
static void ParseTypes(Record *r, std::string &s,
SmallVectorImpl<StringRef> &TV) {
const char *data = s.data();
@ -49,6 +62,8 @@ static void ParseTypes(Record *r, std::string &s,
}
}
/// Widen - Convert a type code into the next wider type. char -> short,
/// short -> int, etc.
static char Widen(const char t) {
switch (t) {
case 'c':
@ -62,6 +77,8 @@ static char Widen(const char t) {
return '\0';
}
/// Narrow - Convert a type code into the next smaller type. short -> char,
/// float -> half float, etc.
static char Narrow(const char t) {
switch (t) {
case 's':
@ -77,6 +94,8 @@ static char Narrow(const char t) {
return '\0';
}
/// For a particular StringRef, return the base type code, and whether it has
/// the quad-vector, polynomial, or unsigned modifiers set.
static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
unsigned off = 0;
@ -102,6 +121,8 @@ static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
return ty[off];
}
/// ModType - Transform a type code and its modifiers based on a mod code. The
/// mod code definitions may be found at the top of arm_neon.td.
static char ModType(const char mod, char type, bool &quad, bool &poly,
bool &usgn, bool &scal, bool &cnst, bool &pntr) {
switch (mod) {
@ -166,8 +187,11 @@ static char ModType(const char mod, char type, bool &quad, bool &poly,
return type;
}
/// TypeString - for a modifier and type, generate the name of the typedef for
/// that type. If generic is true, emit the generic vector type rather than
/// the public NEON type. QUc -> uint8x8t_t / __neon_uint8x8_t.
static std::string TypeString(const char mod, StringRef typestr,
bool ret = false) {
bool generic = false) {
bool quad = false;
bool poly = false;
bool usgn = false;
@ -188,7 +212,7 @@ static std::string TypeString(const char mod, StringRef typestr,
SmallString<128> s;
if (ret)
if (generic)
s += "__neon_";
if (usgn)
@ -255,6 +279,9 @@ static std::string TypeString(const char mod, StringRef typestr,
return s.str();
}
/// TypeString - for a modifier and type, generate the clang BuiltinsARM.def
/// prototype code for the function. See the top of clang's Builtins.def for
/// a description of the type strings.
static std::string BuiltinTypeString(const char mod, StringRef typestr,
ClassKind ck, bool ret) {
bool quad = false;
@ -343,7 +370,9 @@ static std::string BuiltinTypeString(const char mod, StringRef typestr,
return quad ? "V16c" : "V8c";
}
// Turn "vst2_lane" into "vst2q_lane_f32", etc.
/// MangleName - Append a type or width suffix to a base neon function name,
/// and insert a 'q' in the appropriate location if the operation works on
/// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
static std::string MangleName(const std::string &name, StringRef typestr,
ClassKind ck) {
if (name == "vcvt_f32_f16")
@ -623,8 +652,6 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
ret |= 0x08;
if (quad)
ret |= 0x10;
if (poly)
ret |= 0x20;
switch (type) {
case 'c':
@ -798,6 +825,8 @@ static std::string GenBuiltinDef(const std::string &name,
return s;
}
/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h
/// is comprised of type definitions and function declarations.
void NeonEmitter::run(raw_ostream &OS) {
EmitSourceFileHeader("ARM NEON Header", OS);
@ -813,7 +842,6 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "#include <stdint.h>\n\n";
// Emit NEON-specific scalar typedefs.
// FIXME: probably need to do something better for polynomial types.
OS << "typedef float float32_t;\n";
OS << "typedef uint8_t poly8_t;\n";
OS << "typedef uint16_t poly16_t;\n";
@ -918,11 +946,26 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "#endif /* __ARM_NEON_H */\n";
}
/// 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.
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;
for (unsigned i = 0, e = RV.size(); i != e; ++i) {
Record *R = RV[i];
@ -934,18 +977,60 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
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 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)
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)
continue;
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]];
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.
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]);
}
continue;
}
if (genSemaRange) {
if (Proto.find('s') == std::string::npos)
ck = ClassB;
OS << "case ARM::BI__builtin_neon_"
<< MangleName(name, TypeVec[ti], ck) << "\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;
@ -953,5 +1038,17 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
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;
}
}
}