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>.

llvm-svn: 149227
This commit is contained in:
Douglas Gregor 2012-01-30 06:38:25 +00:00
parent 978fe0c75a
commit 0070c0bfbe
5 changed files with 198 additions and 3 deletions

View File

@ -601,6 +601,11 @@ public:
virtual void HandleTargetFeatures(std::vector<std::string> &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");

View File

@ -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<bool>(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

View File

@ -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<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 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
}
}
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 @@ public:
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 @@ 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<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 @@ 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 {
}

View File

@ -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"
}
}

View File

@ -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