aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--utils/TableGen/NeonEmitter.cpp35
1 files changed, 31 insertions, 4 deletions
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 41c55fa..d45910e 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -481,6 +481,28 @@ static std::string GenArgs(const std::string &proto, StringRef typestr) {
return s;
}
+// Generate the local temporaries used to provide type checking for macro
+// arguments.
+static std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
+ char arg = 'a';
+ std::string s;
+
+ for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+ // Do not create a temporary for an immediate argument.
+ // That would defeat the whole point of using a macro!
+ if (proto[i] == 'i') continue;
+
+ s += TypeString(proto[i], typestr) + " __";
+ s.push_back(arg);
+ s += " = (";
+ s.push_back(arg);
+ s += "); ";
+ }
+
+ s += "\\\n ";
+ return s;
+}
+
static std::string Duplicate(unsigned nElts, StringRef typestr,
const std::string &a) {
std::string s;
@@ -706,7 +728,6 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
static std::string GenBuiltin(const std::string &name, const std::string &proto,
StringRef typestr, ClassKind ck) {
- char arg = 'a';
std::string s;
// If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
@@ -724,6 +745,11 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
if (proto.find('s') == std::string::npos)
ck = ClassB;
+ // Macro arguments are not type-checked like inline function arguments, so
+ // assign them to local temporaries to get the right type checking.
+ if (define)
+ s += GenMacroLocals(proto, typestr);
+
if (proto[0] != 'v') {
std::string ts = TypeString(proto[0], typestr);
@@ -756,12 +782,13 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
if (sret)
s += "&r, ";
+ char arg = 'a';
for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
std::string args = std::string(&arg, 1);
- // Wrap macro arguments in parenthesis.
- if (define)
- args = "(" + args + ")";
+ // For macros, use the local temporaries instead of the macro arguments.
+ if (define && proto[i] != 'i')
+ args = "__" + args;
bool argQuad = false;
bool argPoly = false;