Introduce TargetInfo::hasFeature() to query various feature names in
each of the targets. Use this for module requirements, so that we can
pin the availability of certain modules to certain target features,
e.g., provide a module for xmmintrin.h only when SSE support is
available.

Use these feature names to provide a nearly-complete module map for
Clang's built-in headers. Only mm_alloc.h and unwind.h are missing,
and those two are fairly specialized at the moment. Finishes
<rdar://problem/10710060>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149227 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 5dc63e7..39bb869 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -583,6 +583,8 @@
   virtual void getTargetDefines(const LangOptions &Opts,
                                 MacroBuilder &Builder) const;
 
+  virtual bool hasFeature(StringRef Feature) const;
+  
   virtual void getGCCRegNames(const char * const *&Names,
                               unsigned &NumNames) const;
   virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -735,7 +737,11 @@
   }
 }
 
+bool PPCTargetInfo::hasFeature(StringRef Feature) const {
+  return Feature == "powerpc";
+}
 
+  
 const char * const PPCTargetInfo::GCCRegNames[] = {
   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
@@ -964,7 +970,10 @@
       Records = BuiltinInfo;
       NumRecords = clang::PTX::LastTSBuiltin-Builtin::FirstTSBuiltin;
     }
-
+    virtual bool hasFeature(StringRef Feature) const {
+      return Feature == "ptx";
+    }
+    
     virtual void getGCCRegNames(const char * const *&Names,
                                 unsigned &NumNames) const;
     virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -1063,6 +1072,10 @@
   virtual void getTargetDefines(const LangOptions &Opts,
                                 MacroBuilder &Builder) const;
 
+  virtual bool hasFeature(StringRef Feature) const {
+    return Feature == "mblaze";
+  }
+  
   virtual const char *getVAListDeclaration() const {
     return "typedef char* __builtin_va_list;";
   }
@@ -1402,6 +1415,7 @@
                                  const std::string &Name,
                                  bool Enabled) const;
   virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const;
+  virtual bool hasFeature(StringRef Feature) const;
   virtual void HandleTargetFeatures(std::vector<std::string> &Features);
   virtual const char* getABI() const {
     if (PointerWidth == 64 && SSELevel >= AVX)
@@ -2072,6 +2086,30 @@
   }
 }
 
+bool X86TargetInfo::hasFeature(StringRef Feature) const {
+  return llvm::StringSwitch<bool>(Feature)
+      .Case("aes", HasAES)
+      .Case("avx", SSELevel >= AVX)
+      .Case("avx2", SSELevel >= AVX2)
+      .Case("bmi", HasBMI)
+      .Case("bmi2", HasBMI2)
+      .Case("fma4", HasFMA4)
+      .Case("lzcnt", HasLZCNT)
+      .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
+      .Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon)
+      .Case("mmx", MMX3DNowLevel >= MMX)
+      .Case("popcnt", HasPOPCNT)
+      .Case("sse", SSELevel >= SSE1)
+      .Case("sse2", SSELevel >= SSE2)
+      .Case("sse3", SSELevel >= SSE3)
+      .Case("ssse3", SSELevel >= SSSE3)
+      .Case("sse41", SSELevel >= SSE41)
+      .Case("sse42", SSELevel >= SSE42)
+      .Case("x86", true)
+      .Case("x86_32", PointerWidth == 32)
+      .Case("x86_64", PointerWidth == 64)
+      .Default(false);
+}
 
 bool
 X86TargetInfo::validateAsmConstraint(const char *&Name,
@@ -2702,6 +2740,15 @@
       Features.erase(it);
   }
 
+  virtual bool hasFeature(StringRef Feature) const {
+    return llvm::StringSwitch<bool>(Feature)
+        .Case("arm", true)
+        .Case("softfloat", SoftFloat)
+        .Case("thumb", IsThumb)
+        .Case("neon", FPU == NeonFPU && !SoftFloat && 
+              StringRef(getCPUDefineSuffix(CPU)).startswith("7"))    
+        .Default(false);
+  }
   static const char *getCPUDefineSuffix(StringRef Name) {
     return llvm::StringSwitch<const char*>(Name)
       .Cases("arm8", "arm810", "4")
@@ -2964,6 +3011,10 @@
   virtual void getTargetDefines(const LangOptions &Opts,
                                 MacroBuilder &Builder) const;
 
+  virtual bool hasFeature(StringRef Feature) const {
+    return Feature == "hexagon";
+  }
+  
   virtual const char *getVAListDeclaration() const {
     return "typedef char* __builtin_va_list;";
   }
@@ -3111,6 +3162,14 @@
     if (SoftFloat)
       Builder.defineMacro("SOFT_FLOAT", "1");
   }
+  
+  virtual bool hasFeature(StringRef Feature) const {
+    return llvm::StringSwitch<bool>(Feature)
+             .Case("softfloat", SoftFloat)
+             .Case("sparc", true)
+             .Default(false);
+  }
+  
   virtual void getTargetBuiltins(const Builtin::Info *&Records,
                                  unsigned &NumRecords) const {
     // FIXME: Implement!
@@ -3239,6 +3298,9 @@
       Records = 0;
       NumRecords = 0;
     }
+    virtual bool hasFeature(StringRef Feature) const {
+      return Feature == "msp430";
+    }
     virtual void getGCCRegNames(const char * const *&Names,
                                 unsigned &NumNames) const;
     virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -3328,6 +3390,10 @@
       Builder.defineMacro("__TCE__");
       Builder.defineMacro("__TCE_V1__");
     }
+    virtual bool hasFeature(StringRef Feature) const {
+      return Feature == "tce";
+    }
+    
     virtual void getTargetBuiltins(const Builtin::Info *&Records,
                                    unsigned &NumRecords) const {}
     virtual const char *getClobbers() const {
@@ -3373,6 +3439,9 @@
                                  unsigned &NumRecords) const {
     // FIXME: Implement!
   }
+  virtual bool hasFeature(StringRef Feature) const {
+    return Feature == "mips";
+  }
   virtual const char *getVAListDeclaration() const {
     return "typedef void* __builtin_va_list;";
   }
@@ -3699,6 +3768,9 @@
     Builder.defineMacro("__native_client__");
     getArchDefines(Opts, Builder);
   }
+  virtual bool hasFeature(StringRef Feature) const {
+    return Feature == "pnacl";
+  }
   virtual void getTargetBuiltins(const Builtin::Info *&Records,
                                  unsigned &NumRecords) const {
   }