OK, I've updated the diff to get the signedness of polynomials right (or 
rather, wrong in the appropriate places). I've also checked that 
-gen-arm-neon-test is unaffected at the moment.

  Does it look OK?

  Cheers.

  Tim.

http://llvm-reviews.chandlerc.com/D2738

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2738?vs=6984&id=7024#toc

Files:
  include/clang/Sema/Sema.h
  lib/Sema/SemaChecking.cpp
  utils/TableGen/NeonEmitter.cpp
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -7855,6 +7855,7 @@
 
   ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
 
+  bool CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
   bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall);
   bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
   bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -388,32 +388,29 @@
   llvm_unreachable("Invalid NeonTypeFlag!");
 }
 
-bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
-                                           CallExpr *TheCall) {
-
+bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
   llvm::APSInt Result;
-
   uint64_t mask = 0;
   unsigned TV = 0;
   int PtrArgNum = -1;
   bool HasConstPtr = false;
   switch (BuiltinID) {
-#define GET_NEON_AARCH64_OVERLOAD_CHECK
+#define GET_NEON_OVERLOAD_CHECK
 #include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_AARCH64_OVERLOAD_CHECK
+#undef GET_NEON_OVERLOAD_CHECK
   }
 
   // For NEON intrinsics which are overloaded on vector element type, validate
   // the immediate which specifies which variant to emit.
-  unsigned ImmArg = TheCall->getNumArgs() - 1;
+  unsigned ImmArg = TheCall->getNumArgs()-1;
   if (mask) {
     if (SemaBuiltinConstantArg(TheCall, ImmArg, Result))
       return true;
 
     TV = Result.getLimitedValue(64);
     if ((TV > 63) || (mask & (1ULL << TV)) == 0)
       return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
-             << TheCall->getArg(ImmArg)->getSourceRange();
+        << TheCall->getArg(ImmArg)->getSourceRange();
   }
 
   if (PtrArgNum >= 0) {
@@ -423,7 +420,10 @@
       Arg = ICE->getSubExpr();
     ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
     QualType RHSTy = RHS.get()->getType();
-    QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, true);
+
+    bool IsAArch64 =
+        Context.getTargetInfo().getTriple().getArch() == llvm::Triple::aarch64;
+    QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, IsAArch64);
     if (HasConstPtr)
       EltTy = EltTy.withConst();
     QualType LHSTy = Context.getPointerType(EltTy);
@@ -442,9 +442,9 @@
   switch (BuiltinID) {
   default:
     return false;
-#define GET_NEON_AARCH64_IMMEDIATE_CHECK
+#define GET_NEON_IMMEDIATE_CHECK
 #include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_AARCH64_IMMEDIATE_CHECK
+#undef GET_NEON_IMMEDIATE_CHECK
   }
   ;
 
@@ -466,6 +466,14 @@
   return false;
 }
 
+bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
+                                           CallExpr *TheCall) {
+  if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
+    return true;
+
+  return false;
+}
+
 bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) {
   assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
           BuiltinID == ARM::BI__builtin_arm_strex) &&
@@ -580,48 +588,8 @@
     return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall);
   }
 
-  uint64_t mask = 0;
-  unsigned TV = 0;
-  int PtrArgNum = -1;
-  bool HasConstPtr = false;
-  switch (BuiltinID) {
-#define GET_NEON_OVERLOAD_CHECK
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_OVERLOAD_CHECK
-  }
-  
-  // For NEON intrinsics which are overloaded on vector element type, validate
-  // the immediate which specifies which variant to emit.
-  unsigned ImmArg = TheCall->getNumArgs()-1;
-  if (mask) {
-    if (SemaBuiltinConstantArg(TheCall, ImmArg, Result))
-      return true;
-    
-    TV = Result.getLimitedValue(64);
-    if ((TV > 63) || (mask & (1ULL << TV)) == 0)
-      return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
-        << TheCall->getArg(ImmArg)->getSourceRange();
-  }
-
-  if (PtrArgNum >= 0) {
-    // Check that pointer arguments have the specified type.
-    Expr *Arg = TheCall->getArg(PtrArgNum);
-    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
-      Arg = ICE->getSubExpr();
-    ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
-    QualType RHSTy = RHS.get()->getType();
-    QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, false);
-    if (HasConstPtr)
-      EltTy = EltTy.withConst();
-    QualType LHSTy = Context.getPointerType(EltTy);
-    AssignConvertType ConvTy;
-    ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
-    if (RHS.isInvalid())
-      return true;
-    if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy,
-                                 RHS.get(), AA_Assigning))
-      return true;
-  }
+  if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
+    return true;
 
   // For NEON intrinsics which take an immediate value as part of the 
   // instruction, range check them here.
@@ -634,9 +602,6 @@
   case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
   case ARM::BI__builtin_arm_dmb:
   case ARM::BI__builtin_arm_dsb: l = 0; u = 15; break;
-#define GET_NEON_IMMEDIATE_CHECK
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_IMMEDIATE_CHECK
   };
 
   // We can't check the value of a dependent argument.
Index: utils/TableGen/NeonEmitter.cpp
===================================================================
--- utils/TableGen/NeonEmitter.cpp
+++ utils/TableGen/NeonEmitter.cpp
@@ -375,12 +375,8 @@
   void emitIntrinsic(raw_ostream &OS, Record *R,
                      StringMap<ClassKind> &EmittedMap);
   void genBuiltinsDef(raw_ostream &OS);
-  void genOverloadTypeCheckCode(raw_ostream &OS,
-                                StringMap<ClassKind> &A64IntrinsicMap,
-                                bool isA64TypeCheck);
-  void genIntrinsicRangeCheckCode(raw_ostream &OS,
-                                  StringMap<ClassKind> &A64IntrinsicMap,
-                                  bool isA64RangeCheck);
+  void genOverloadTypeCheckCode(raw_ostream &OS);
+  void genIntrinsicRangeCheckCode(raw_ostream &OS);
   void genTargetTest(raw_ostream &OS, StringMap<OpKind> &EmittedMap,
                      bool isA64TestGen);
 };
@@ -2911,17 +2907,12 @@
 /// Generate the ARM and AArch64 intrinsic range checking code for
 /// shift/lane immediates, checking for unique declarations.
 void
-NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
-                                        StringMap<ClassKind> &A64IntrinsicMap,
-                                        bool isA64RangeCheck) {
+NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS) {
   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
   StringMap<OpKind> EmittedMap;
 
   // Generate the intrinsic range checking code for shift/lane immediates.
-  if (isA64RangeCheck)
-    OS << "#ifdef GET_NEON_AARCH64_IMMEDIATE_CHECK\n";
-  else
-    OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
+  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
 
   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
     Record *R = RV[i];
@@ -2956,19 +2947,6 @@
     if (!ProtoHasScalar(Proto))
       ck = ClassB;
 
-    // Do not include AArch64 range checks if not generating code for AArch64.
-    bool isA64 = R->getValueAsBit("isA64");
-    if (!isA64RangeCheck && isA64)
-      continue;
-
-    // Include ARM range checks in AArch64 but only if ARM intrinsics are not
-    // redefined by AArch64 to handle new types.
-    if (isA64RangeCheck && !isA64 && A64IntrinsicMap.count(Rename)) {
-      ClassKind &A64CK = A64IntrinsicMap[Rename];
-      if (A64CK == ck && ck != ClassNone)
-        continue;
-    }
-
     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
       std::string namestr, shiftstr, rangestr;
 
@@ -3070,16 +3048,22 @@
 /// Generate the ARM and AArch64 overloaded type checking code for
 /// SemaChecking.cpp, checking for unique builtin declarations.
 void
-NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
-                                      StringMap<ClassKind> &A64IntrinsicMap,
-                                      bool isA64TypeCheck) {
+NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS) {
   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
 
   // Generate the overloaded type checking code for SemaChecking.cpp
-  if (isA64TypeCheck)
-    OS << "#ifdef GET_NEON_AARCH64_OVERLOAD_CHECK\n";
-  else
-    OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
+  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
+
+  // We record each overload check line before emitting because subsequent Inst
+  // definitions may extend the number of permitted types (i.e. augment the
+  // Mask). Use std::map to avoid sorting the table by hash number.
+  struct OverloadInfo {
+    uint64_t Mask;
+    int PtrArgNum;
+    bool HasConstPtr;
+  };
+  std::map<std::string, OverloadInfo> OverloadMap;
+  typedef std::map<std::string, OverloadInfo>::iterator OverloadIterator;
 
   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
     Record *R = RV[i];
@@ -3108,21 +3092,6 @@
     if (R->getSuperClasses().size() < 2)
       PrintFatalError(R->getLoc(), "Builtin has no class kind");
 
-    // Do not include AArch64 type checks if not generating code for AArch64.
-    bool isA64 = R->getValueAsBit("isA64");
-    if (!isA64TypeCheck && isA64)
-      continue;
-
-    // Include ARM  type check in AArch64 but only if ARM intrinsics
-    // are not redefined in AArch64 to handle new types, e.g. "vabd" is a SIntr
-    // redefined in AArch64 to handle an additional 2 x f64 type.
-    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
-    if (isA64TypeCheck && !isA64 && A64IntrinsicMap.count(Rename)) {
-      ClassKind &A64CK = A64IntrinsicMap[Rename];
-      if (A64CK == ck && ck != ClassNone)
-        continue;
-    }
-
     int si = -1, qi = -1;
     uint64_t mask = 0, qmask = 0;
     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
@@ -3170,26 +3139,41 @@
     }
 
     if (mask) {
-      OS << "case NEON::BI__builtin_neon_";
-      OS << MangleName(name, TypeVec[si], ClassB) << ": mask = "
-         << "0x" << utohexstr(mask) << "ULL";
-      if (PtrArgNum >= 0)
-        OS << "; PtrArgNum = " << PtrArgNum;
-      if (HasConstPtr)
-        OS << "; HasConstPtr = true";
-      OS << "; break;\n";
+      std::pair<OverloadIterator, bool> I = OverloadMap.insert(std::make_pair(
+          MangleName(name, TypeVec[si], ClassB), OverloadInfo()));
+      OverloadInfo &Record = I.first->second;
+      if (!I.second)
+        assert(Record.PtrArgNum == PtrArgNum &&
+               Record.HasConstPtr == HasConstPtr);
+      Record.Mask |= mask;
+      Record.PtrArgNum = PtrArgNum;
+      Record.HasConstPtr = HasConstPtr;
     }
     if (qmask) {
-      OS << "case NEON::BI__builtin_neon_";
-      OS << MangleName(name, TypeVec[qi], ClassB) << ": mask = "
-         << "0x" << utohexstr(qmask) << "ULL";
-      if (PtrArgNum >= 0)
-        OS << "; PtrArgNum = " << PtrArgNum;
-      if (HasConstPtr)
-        OS << "; HasConstPtr = true";
-      OS << "; break;\n";
+      std::pair<OverloadIterator, bool> I = OverloadMap.insert(std::make_pair(
+          MangleName(name, TypeVec[qi], ClassB), OverloadInfo()));
+      OverloadInfo &Record = I.first->second;
+      if (!I.second)
+        assert(Record.PtrArgNum == PtrArgNum &&
+               Record.HasConstPtr == HasConstPtr);
+      Record.Mask |= qmask;
+      Record.PtrArgNum = PtrArgNum;
+      Record.HasConstPtr = HasConstPtr;
     }
   }
+
+  for (OverloadIterator I = OverloadMap.begin(), E = OverloadMap.end(); I != E;
+       ++I) {
+    OverloadInfo &BuiltinOverloads = I->second;
+    OS << "case NEON::BI__builtin_neon_" << I->first << ": ";
+    OS << "mask = " << "0x" << utohexstr(BuiltinOverloads.Mask) << "ULL";
+    if (BuiltinOverloads.PtrArgNum >= 0)
+      OS << "; PtrArgNum = " << BuiltinOverloads.PtrArgNum;
+    if (BuiltinOverloads.HasConstPtr)
+      OS << "; HasConstPtr = true";
+    OS << "; break;\n";
+  }
+
   OS << "#endif\n\n";
 }
 
@@ -3248,41 +3232,14 @@
 void NeonEmitter::runHeader(raw_ostream &OS) {
   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
 
-  // build a map of AArch64 intriniscs to be used in uniqueness checks.
-  StringMap<ClassKind> A64IntrinsicMap;
-  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
-    Record *R = RV[i];
-
-    bool isA64 = R->getValueAsBit("isA64");
-    if (!isA64)
-      continue;
-
-    ClassKind CK = ClassNone;
-    if (R->getSuperClasses().size() >= 2)
-      CK = ClassMap[R->getSuperClasses()[1]];
-
-    std::string Name = R->getValueAsString("Name");
-    std::string Proto = R->getValueAsString("Prototype");
-    std::string Rename = Name + "@" + Proto;
-    if (A64IntrinsicMap.count(Rename))
-      continue;
-    A64IntrinsicMap[Rename] = CK;
-  }
-
   // Generate shared BuiltinsXXX.def
   genBuiltinsDef(OS);
 
   // Generate ARM overloaded type checking code for SemaChecking.cpp
-  genOverloadTypeCheckCode(OS, A64IntrinsicMap, false);
-
-  // Generate AArch64 overloaded type checking code for SemaChecking.cpp
-  genOverloadTypeCheckCode(OS, A64IntrinsicMap, true);
+  genOverloadTypeCheckCode(OS);
 
   // Generate ARM range checking code for shift/lane immediates.
-  genIntrinsicRangeCheckCode(OS, A64IntrinsicMap, false);
-
-  // Generate the AArch64 range checking code for shift/lane immediates.
-  genIntrinsicRangeCheckCode(OS, A64IntrinsicMap, true);
+  genIntrinsicRangeCheckCode(OS);
 }
 
 /// GenTest - Write out a test for the intrinsic specified by the name and
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to