From e727d21d3fd5f6f68d9e7a260bbf84dc2fc8ae3a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 30 Jan 2012 06:38:25 +0000 Subject: [PATCH] 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149227 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/TargetInfo.h | 5 ++ lib/Basic/Module.cpp | 6 +- lib/Basic/Targets.cpp | 74 ++++++++++++++++++++- lib/Headers/module.map | 108 ++++++++++++++++++++++++++++++- test/Modules/compiler_builtins.m | 8 +++ 5 files changed, 198 insertions(+), 3 deletions(-) diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 966797c4ff..0273f38372 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -601,6 +601,11 @@ public: virtual void HandleTargetFeatures(std::vector &Features) { } + /// \brief Determine whether the given target has the given feature. + virtual bool hasFeature(StringRef Feature) const { + return false; + } + // getRegParmMax - Returns maximal number of args passed in registers. unsigned getRegParmMax() const { assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle"); diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index 3052532650..c5838fb65f 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/Module.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallVector.h" @@ -50,12 +51,15 @@ Module::~Module() { static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, const TargetInfo &Target) { return llvm::StringSwitch(Feature) + .Case("altivec", LangOpts.AltiVec) .Case("blocks", LangOpts.Blocks) .Case("cplusplus", LangOpts.CPlusPlus) .Case("cplusplus11", LangOpts.CPlusPlus0x) .Case("objc", LangOpts.ObjC1) .Case("objc_arc", LangOpts.ObjCAutoRefCount) - .Default(false); + .Case("opencl", LangOpts.OpenCL) + .Case("tls", Target.isTLSSupported()) + .Default(Target.hasFeature(Feature)); } bool diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 5dc63e79cf..39bb8697dc 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -583,6 +583,8 @@ public: 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 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, } } +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 @@ namespace { 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 @@ public: 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 @@ public: const std::string &Name, bool Enabled) const; virtual void getDefaultFeatures(llvm::StringMap &Features) const; + virtual bool hasFeature(StringRef Feature) const; virtual void HandleTargetFeatures(std::vector &Features); virtual const char* getABI() const { if (PointerWidth == 64 && SSELevel >= AVX) @@ -2072,6 +2086,30 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, } } +bool X86TargetInfo::hasFeature(StringRef Feature) const { + return llvm::StringSwitch(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 @@ public: Features.erase(it); } + virtual bool hasFeature(StringRef Feature) const { + return llvm::StringSwitch(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(Name) .Cases("arm8", "arm810", "4") @@ -2964,6 +3011,10 @@ public: 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 @@ public: if (SoftFloat) Builder.defineMacro("SOFT_FLOAT", "1"); } + + virtual bool hasFeature(StringRef Feature) const { + return llvm::StringSwitch(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 @@ namespace { 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 @@ namespace { 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 @@ public: 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 @@ public: 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 { } diff --git a/lib/Headers/module.map b/lib/Headers/module.map index 5ff2139760..c8fe9d888e 100644 --- a/lib/Headers/module.map +++ b/lib/Headers/module.map @@ -1,4 +1,9 @@ module __compiler_builtins [system] { + explicit module altivec { + requires altivec + header "altivec.h" + } + explicit module float_constants { header "float.h" } @@ -35,5 +40,106 @@ module __compiler_builtins [system] { header "tgmath.h" } - // FIXME: add various altivec, *intrin headers. + explicit module intel { + requires x86 + + header "immintrin.h" + header "x86intrin.h" + + explicit module cpuid { + header "cpuid.h" + } + + explicit module mmx { + requires mmx + header "mmintrin.h" + } + + explicit module sse { + requires sse + export mmx + header "xmmintrin.h" + } + + explicit module sse2 { + requires sse2 + export sse + header "emmintrin.h" + } + + explicit module sse3 { + requires sse3 + export sse2 + header "pmmintrin.h" + } + + explicit module ssse3 { + requires ssse3 + export sse3 + header "tmmintrin.h" + } + + explicit module sse4_1 { + requires sse41 + export ssse3 + header "smmintrin.h" + } + + explicit module sse4_2 { + requires sse42 + export sse4_1 + header "nmmintrin.h" + } + + explicit module avx { + requires avx + export sse4_2 + header "avxintrin.h" + } + + explicit module avx2 { + requires avx2 + export acx + header "avx2intrin.h" + } + + explicit module bmi { + requires bmi + header "bmiintrin.h" + } + + explicit module bmi2 { + requires bmi2 + header "bmi2intrin.h" + } + + explicit module fma4 { + requires fma4 + export sse3 + header "fma4intrin.h" + } + + explicit module lzcnt { + requires lzcnt + header "lzcntintrin.h" + } + + explicit module popcnt { + requires popcnt + header "popcntintrin.h" + } + + explicit module mm3dnow { + requires mm3dnow + header "mm3dnow.h" + } + } + + // FIXME: mm_malloc.h + // FIXME: unwind.h + + explicit module varargs { + requires unavailable + header "varargs.h" + } } diff --git a/test/Modules/compiler_builtins.m b/test/Modules/compiler_builtins.m index 38ce2c9833..a451e8a7ad 100644 --- a/test/Modules/compiler_builtins.m +++ b/test/Modules/compiler_builtins.m @@ -13,3 +13,11 @@ float getFltMax() { return FLT_MAX; } char getCharMax() { return CHAR_MAX; } size_t size; // expected-error{{unknown type name 'size_t'}} + +#ifdef __SSE__ +@import __compiler_builtins.intel.sse; +#endif + +#ifdef __AVX2__ +@import __compiler_builtins.intel.avx2; +#endif -- 2.40.0