diff options
author | Alex Lorenz <arphaman@gmail.com> | 2017-12-14 19:22:02 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2017-12-14 19:22:02 +0000 |
commit | d8ec43114389756f916ad12b73e49f39d3c29a49 (patch) | |
tree | bc5b99d1df33b059570482b27cf45367cb9cd0de /clang/lib/Lex/PPMacroExpansion.cpp | |
parent | 689c6960ef0a1f1448c699f64361c9be3dfa42b7 (diff) | |
download | bcm5719-llvm-d8ec43114389756f916ad12b73e49f39d3c29a49.tar.gz bcm5719-llvm-d8ec43114389756f916ad12b73e49f39d3c29a49.zip |
[Preprocessor] Implement __is_target_{arch|vendor|os|environment} function-like
builtin macros
This patch implements the __is_target_arch, __is_target_vendor, __is_target_os,
and __is_target_environment Clang preprocessor extensions that were proposed by
@compnerd in Bob's cfe-dev post:
http://lists.llvm.org/pipermail/cfe-dev/2017-November/056166.html.
These macros can be used to examine the components of the target triple at
compile time. A has_builtin(is_target_???) preprocessor check can be used to
check for their availability.
__is_target_arch allows you to check if an arch is specified without worring
about a specific subarch, e.g.
__is_target_arch(arm) returns 1 for the target arch "armv7"
__is_target_arch(armv7) returns 1 for the target arch "armv7"
__is_target_arch(armv6) returns 0 for the target arch "armv7"
__is_target_vendor and __is_target_environment match the specific vendor
or environment. __is_target_os matches the specific OS, but
__is_target_os(darwin) will match any Darwin-based OS. "Unknown" can be used
to test if the triple's component is specified.
rdar://35753116
Differential Revision: https://reviews.llvm.org/D41087
llvm-svn: 320734
Diffstat (limited to 'clang/lib/Lex/PPMacroExpansion.cpp')
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 2d83badfee9..3d72006bad4 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -375,6 +375,11 @@ void Preprocessor::RegisterBuiltinMacros() { Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next"); Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning"); Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier"); + Ident__is_target_arch = RegisterBuiltinMacro(*this, "__is_target_arch"); + Ident__is_target_vendor = RegisterBuiltinMacro(*this, "__is_target_vendor"); + Ident__is_target_os = RegisterBuiltinMacro(*this, "__is_target_os"); + Ident__is_target_environment = + RegisterBuiltinMacro(*this, "__is_target_environment"); // Modules. Ident__building_module = RegisterBuiltinMacro(*this, "__building_module"); @@ -1593,6 +1598,57 @@ static IdentifierInfo *ExpectFeatureIdentifierInfo(Token &Tok, return nullptr; } +/// Implements the __is_target_arch builtin macro. +static bool isTargetArch(const TargetInfo &TI, const IdentifierInfo *II) { + std::string ArchName = II->getName().lower() + "--"; + llvm::Triple Arch(ArchName); + const llvm::Triple &TT = TI.getTriple(); + if (TT.isThumb()) { + // arm matches thumb or thumbv7. armv7 matches thumbv7. + if ((Arch.getSubArch() == llvm::Triple::NoSubArch || + Arch.getSubArch() == TT.getSubArch()) && + ((TT.getArch() == llvm::Triple::thumb && + Arch.getArch() == llvm::Triple::arm) || + (TT.getArch() == llvm::Triple::thumbeb && + Arch.getArch() == llvm::Triple::armeb))) + return true; + } + // Check the parsed arch when it has no sub arch to allow Clang to + // match thumb to thumbv7 but to prohibit matching thumbv6 to thumbv7. + return (Arch.getSubArch() == llvm::Triple::NoSubArch && + Arch.getArch() == TT.getArch()) || + Arch.getArchName() == TT.getArchName(); +} + +/// Implements the __is_target_vendor builtin macro. +static bool isTargetVendor(const TargetInfo &TI, const IdentifierInfo *II) { + StringRef VendorName = TI.getTriple().getVendorName(); + if (VendorName.empty()) + VendorName = "unknown"; + return VendorName.equals_lower(II->getName()); +} + +/// Implements the __is_target_os builtin macro. +static bool isTargetOS(const TargetInfo &TI, const IdentifierInfo *II) { + std::string OSName = + (llvm::Twine("unknown-unknown-") + II->getName().lower()).str(); + llvm::Triple OS(OSName); + if (OS.getOS() == llvm::Triple::Darwin) { + // Darwin matches macos, ios, etc. + return TI.getTriple().isOSDarwin(); + } + return TI.getTriple().getOS() == OS.getOS(); +} + +/// Implements the __is_target_environment builtin macro. +static bool isTargetEnvironment(const TargetInfo &TI, + const IdentifierInfo *II) { + StringRef EnvName = TI.getTriple().getEnvironmentName(); + if (EnvName.empty()) + EnvName = "unknown"; + return EnvName.equals_lower(II->getName()); +} + /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. void Preprocessor::ExpandBuiltinMacro(Token &Tok) { @@ -1755,6 +1811,10 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { .Case("__make_integer_seq", LangOpts.CPlusPlus) .Case("__type_pack_element", LangOpts.CPlusPlus) .Case("__builtin_available", true) + .Case("__is_target_arch", true) + .Case("__is_target_vendor", true) + .Case("__is_target_os", true) + .Case("__is_target_environment", true) .Default(false); } }); @@ -1906,6 +1966,34 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Diag(LParenLoc, diag::note_matching) << tok::l_paren; } return; + } else if (II == Ident__is_target_arch) { + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo( + Tok, *this, diag::err_feature_check_malformed); + return II && isTargetArch(getTargetInfo(), II); + }); + } else if (II == Ident__is_target_vendor) { + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo( + Tok, *this, diag::err_feature_check_malformed); + return II && isTargetVendor(getTargetInfo(), II); + }); + } else if (II == Ident__is_target_os) { + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo( + Tok, *this, diag::err_feature_check_malformed); + return II && isTargetOS(getTargetInfo(), II); + }); + } else if (II == Ident__is_target_environment) { + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo( + Tok, *this, diag::err_feature_check_malformed); + return II && isTargetEnvironment(getTargetInfo(), II); + }); } else { llvm_unreachable("Unknown identifier!"); } |