https://github.com/sarnex updated https://github.com/llvm/llvm-project/pull/126324
>From fe555ce59762edf71f43d0cd61978d60f5f949ef Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Fri, 7 Feb 2025 14:57:12 -0800 Subject: [PATCH 1/3] [Clang] Add __has_target_builtin macro Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/docs/LanguageExtensions.rst | 33 +++++++++++++++++++ clang/include/clang/Lex/Preprocessor.h | 1 + clang/lib/Lex/PPMacroExpansion.cpp | 17 +++++++--- .../test/Preprocessor/has_target_builtin.cpp | 18 ++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 clang/test/Preprocessor/has_target_builtin.cpp diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 973cf8f9d091c30..87f7df50471e790 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -67,6 +67,10 @@ It can be used like this: ``__has_builtin`` should not be used to detect support for a builtin macro; use ``#ifdef`` instead. + When using device offloading, a builtin is considered available if it is + available on either the host or the device targets. + Use ``__has_target_builtin`` to consider only the current target. + ``__has_constexpr_builtin`` --------------------------- @@ -96,6 +100,35 @@ the ``<cmath>`` header file to conditionally make a function constexpr whenever the constant evaluation of the corresponding builtin (for example, ``std::fmax`` calls ``__builtin_fmax``) is supported in Clang. +``__has_target_builtin`` +----------------- + +This function-like macro takes a single identifier argument that is the name of +a builtin function, a builtin pseudo-function (taking one or more type +arguments), or a builtin template. +It evaluates to 1 if the builtin is supported on the current target or 0 if not. +The behavior is different than ``__has_builtin`` when there is an auxiliary target, +such when offloading to a target device. +It can be used like this: + +.. code-block:: c++ + + #ifndef __has_target_builtin // Optional of course. + #define __has_target_builtin(x) 0 // Compatibility with non-clang compilers. + #endif + + ... + #if __has_target_builtin(__builtin_trap) + __builtin_trap(); + #else + abort(); + #endif + ... + +.. note:: + ``__has_target_builtin`` should not be used to detect support for a builtin macro; + use ``#ifdef`` instead. + .. _langext-__has_feature-__has_extension: ``__has_feature`` and ``__has_extension`` diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 2bf4d1a16699430..240fe28aba93e33 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -174,6 +174,7 @@ class Preprocessor { IdentifierInfo *Ident__has_extension; // __has_extension IdentifierInfo *Ident__has_builtin; // __has_builtin IdentifierInfo *Ident__has_constexpr_builtin; // __has_constexpr_builtin + IdentifierInfo *Ident__has_target_builtin; // __has_target_builtin IdentifierInfo *Ident__has_attribute; // __has_attribute IdentifierInfo *Ident__has_embed; // __has_embed IdentifierInfo *Ident__has_include; // __has_include diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 347c13da0ad215a..b7b870e1a7fca82 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -357,6 +357,7 @@ void Preprocessor::RegisterBuiltinMacros() { Ident__has_builtin = RegisterBuiltinMacro("__has_builtin"); Ident__has_constexpr_builtin = RegisterBuiltinMacro("__has_constexpr_builtin"); + Ident__has_target_builtin = RegisterBuiltinMacro("__has_target_builtin"); Ident__has_attribute = RegisterBuiltinMacro("__has_attribute"); if (!getLangOpts().CPlusPlus) Ident__has_c_attribute = RegisterBuiltinMacro("__has_c_attribute"); @@ -1797,15 +1798,17 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { diag::err_feature_check_malformed); return II && HasExtension(*this, II->getName()); }); - } else if (II == Ident__has_builtin) { + } else if (II == Ident__has_builtin || II == Ident__has_target_builtin) { + bool IsHasTargetBuiltin = II == Ident__has_target_builtin; EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false, - [this](Token &Tok, bool &HasLexedNextToken) -> int { + [this, IsHasTargetBuiltin](Token &Tok, bool &HasLexedNextToken) -> int { IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, diag::err_feature_check_malformed); if (!II) return false; - else if (II->getBuiltinID() != 0) { - switch (II->getBuiltinID()) { + auto BuiltinID = II->getBuiltinID(); + if (BuiltinID != 0) { + switch (BuiltinID) { case Builtin::BI__builtin_cpu_is: return getTargetInfo().supportsCpuIs(); case Builtin::BI__builtin_cpu_init: @@ -1818,8 +1821,12 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // usual allocation and deallocation functions. Required by libc++ return 201802; default: + // __has_target_builtin should return false for aux builtins. + if(IsHasTargetBuiltin && + getBuiltinInfo().isAuxBuiltinID(BuiltinID)) + return false; return Builtin::evaluateRequiredTargetFeatures( - getBuiltinInfo().getRequiredFeatures(II->getBuiltinID()), + getBuiltinInfo().getRequiredFeatures(BuiltinID), getTargetInfo().getTargetOpts().FeatureMap); } return true; diff --git a/clang/test/Preprocessor/has_target_builtin.cpp b/clang/test/Preprocessor/has_target_builtin.cpp new file mode 100644 index 000000000000000..64b2d7e1b35d9ef --- /dev/null +++ b/clang/test/Preprocessor/has_target_builtin.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fopenmp -triple=spirv64 -fopenmp-is-target-device \ +// RUN: -aux-triple x86_64-linux-unknown -E %s | FileCheck -implicit-check-not=BAD %s + +// RUN: %clang_cc1 -fopenmp -triple=nvptx64 -fopenmp-is-target-device \ +// RUN: -aux-triple x86_64-linux-unknown -E %s | FileCheck -implicit-check-not=BAD %s + +// RUN: %clang_cc1 -fopenmp -triple=amdgcn-amd-amdhsa -fopenmp-is-target-device \ +// RUN: -aux-triple x86_64-linux-unknown -E %s | FileCheck -implicit-check-not=BAD %s + +// RUN: %clang_cc1 -fopenmp -triple=aarch64 -fopenmp-is-target-device \ +// RUN: -aux-triple x86_64-linux-unknown -E %s | FileCheck -implicit-check-not=BAD %s + +// CHECK: GOOD +#if __has_target_builtin(__builtin_ia32_pause) + BAD +#else + GOOD +#endif >From 0ca0587da63979205db6f0957811d3c17dba647d Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Fri, 7 Feb 2025 15:20:14 -0800 Subject: [PATCH 2/3] clang-format Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/lib/Lex/PPMacroExpansion.cpp | 109 ++++++++++++++--------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index b7b870e1a7fca82..23a693b105fca3a 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1800,59 +1800,60 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { }); } else if (II == Ident__has_builtin || II == Ident__has_target_builtin) { bool IsHasTargetBuiltin = II == Ident__has_target_builtin; - EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false, - [this, IsHasTargetBuiltin](Token &Tok, bool &HasLexedNextToken) -> int { - IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, - diag::err_feature_check_malformed); - if (!II) - return false; - auto BuiltinID = II->getBuiltinID(); - if (BuiltinID != 0) { - switch (BuiltinID) { - case Builtin::BI__builtin_cpu_is: - return getTargetInfo().supportsCpuIs(); - case Builtin::BI__builtin_cpu_init: - return getTargetInfo().supportsCpuInit(); - case Builtin::BI__builtin_cpu_supports: - return getTargetInfo().supportsCpuSupports(); - case Builtin::BI__builtin_operator_new: - case Builtin::BI__builtin_operator_delete: - // denotes date of behavior change to support calling arbitrary - // usual allocation and deallocation functions. Required by libc++ - return 201802; - default: - // __has_target_builtin should return false for aux builtins. - if(IsHasTargetBuiltin && - getBuiltinInfo().isAuxBuiltinID(BuiltinID)) + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, false, + [this, IsHasTargetBuiltin](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo( + Tok, *this, diag::err_feature_check_malformed); + if (!II) + return false; + auto BuiltinID = II->getBuiltinID(); + if (BuiltinID != 0) { + switch (BuiltinID) { + case Builtin::BI__builtin_cpu_is: + return getTargetInfo().supportsCpuIs(); + case Builtin::BI__builtin_cpu_init: + return getTargetInfo().supportsCpuInit(); + case Builtin::BI__builtin_cpu_supports: + return getTargetInfo().supportsCpuSupports(); + case Builtin::BI__builtin_operator_new: + case Builtin::BI__builtin_operator_delete: + // denotes date of behavior change to support calling arbitrary + // usual allocation and deallocation functions. Required by libc++ + return 201802; + default: + // __has_target_builtin should return false for aux builtins. + if (IsHasTargetBuiltin && + getBuiltinInfo().isAuxBuiltinID(BuiltinID)) return false; - return Builtin::evaluateRequiredTargetFeatures( - getBuiltinInfo().getRequiredFeatures(BuiltinID), - getTargetInfo().getTargetOpts().FeatureMap); + return Builtin::evaluateRequiredTargetFeatures( + getBuiltinInfo().getRequiredFeatures(BuiltinID), + getTargetInfo().getTargetOpts().FeatureMap); + } + return true; + } else if (IsBuiltinTrait(Tok)) { + return true; + } else if (II->getTokenID() != tok::identifier && + II->getName().starts_with("__builtin_")) { + return true; + } else { + return llvm::StringSwitch<bool>(II->getName()) + // Report builtin templates as being builtins. + .Case("__make_integer_seq", getLangOpts().CPlusPlus) + .Case("__type_pack_element", getLangOpts().CPlusPlus) + .Case("__builtin_common_type", getLangOpts().CPlusPlus) + // Likewise for some builtin preprocessor macros. + // FIXME: This is inconsistent; we usually suggest detecting + // builtin macros via #ifdef. Don't add more cases here. + .Case("__is_target_arch", true) + .Case("__is_target_vendor", true) + .Case("__is_target_os", true) + .Case("__is_target_environment", true) + .Case("__is_target_variant_os", true) + .Case("__is_target_variant_environment", true) + .Default(false); } - return true; - } else if (IsBuiltinTrait(Tok)) { - return true; - } else if (II->getTokenID() != tok::identifier && - II->getName().starts_with("__builtin_")) { - return true; - } else { - return llvm::StringSwitch<bool>(II->getName()) - // Report builtin templates as being builtins. - .Case("__make_integer_seq", getLangOpts().CPlusPlus) - .Case("__type_pack_element", getLangOpts().CPlusPlus) - .Case("__builtin_common_type", getLangOpts().CPlusPlus) - // Likewise for some builtin preprocessor macros. - // FIXME: This is inconsistent; we usually suggest detecting - // builtin macros via #ifdef. Don't add more cases here. - .Case("__is_target_arch", true) - .Case("__is_target_vendor", true) - .Case("__is_target_os", true) - .Case("__is_target_environment", true) - .Case("__is_target_variant_os", true) - .Case("__is_target_variant_environment", true) - .Default(false); - } - }); + }); } else if (II == Ident__has_constexpr_builtin) { EvaluateFeatureLikeBuiltinMacro( OS, Tok, II, *this, false, @@ -1893,8 +1894,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { return false; }); - } else if (II == Ident__has_cpp_attribute || - II == Ident__has_c_attribute) { + } else if (II == Ident__has_cpp_attribute || II == Ident__has_c_attribute) { bool IsCXX = II == Ident__has_cpp_attribute; EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, true, [&](Token &Tok, bool &HasLexedNextToken) -> int { @@ -1924,8 +1924,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { getLangOpts()) : 0; }); - } else if (II == Ident__has_include || - II == Ident__has_include_next) { + } else if (II == Ident__has_include || II == Ident__has_include_next) { // The argument to these two builtins should be a parenthesized // file name string literal using angle brackets (<>) or // double-quotes (""). >From e44e8064d7213e253026fe0bee0cd549d620efb8 Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Fri, 7 Feb 2025 15:31:22 -0800 Subject: [PATCH 3/3] doc warning Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/docs/LanguageExtensions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 87f7df50471e790..057ad564f970bb4 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -101,7 +101,7 @@ the constant evaluation of the corresponding builtin (for example, ``std::fmax`` calls ``__builtin_fmax``) is supported in Clang. ``__has_target_builtin`` ------------------ +------------------------ This function-like macro takes a single identifier argument that is the name of a builtin function, a builtin pseudo-function (taking one or more type _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits