royjacobson created this revision. royjacobson added reviewers: erichkeane, aaron.ballman. Herald added a project: All. royjacobson requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
While working on D140664 <https://reviews.llvm.org/D140664>, I thought it would be nice to be able to write tests for parameter passing ABI. Currently we test this by dumping the AST and matching the results which makes it hard to write new tests. Adding this builtin will allow writing better ABI tests which can help improve our coverage in this area. While less useful, maybe some users would also find it useful for asserting against pessimisations for their classes. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D141775 Files: clang/docs/LanguageExtensions.rst clang/include/clang/Basic/TokenKinds.def clang/lib/Sema/SemaExprCXX.cpp clang/test/SemaCXX/type-traits.cpp Index: clang/test/SemaCXX/type-traits.cpp =================================================================== --- clang/test/SemaCXX/type-traits.cpp +++ clang/test/SemaCXX/type-traits.cpp @@ -3055,6 +3055,23 @@ } // namespace is_trivially_relocatable +namespace can_pass_in_regs { + +struct A { }; + +struct B { + ~B(); +}; + +static_assert(__can_pass_in_regs(A), ""); +static_assert(__can_pass_in_regs(A&), ""); +static_assert(!__can_pass_in_regs(B), ""); +static_assert(__can_pass_in_regs(B&), ""); +static_assert(__can_pass_in_regs(int), ""); +static_assert(__can_pass_in_regs(int&), ""); + +} + struct S {}; template <class T> using remove_const_t = __remove_const(T); Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -4892,6 +4892,7 @@ case UTT_IsLiteral: // By analogy, is_trivially_relocatable imposes the same constraints. case UTT_IsTriviallyRelocatable: + case UTT_CanPassInRegs: // Per the GCC type traits documentation, T shall be a complete type, cv void, // or an array of unknown bound. But GCC actually imposes the same constraints // as above. @@ -5380,6 +5381,10 @@ return T.isTriviallyRelocatableType(C); case UTT_IsReferenceable: return T.isReferenceable(); + case UTT_CanPassInRegs: + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->canPassInRegisters(); + return true; } } Index: clang/include/clang/Basic/TokenKinds.def =================================================================== --- clang/include/clang/Basic/TokenKinds.def +++ clang/include/clang/Basic/TokenKinds.def @@ -523,6 +523,7 @@ TYPE_TRAIT_1(__is_nullptr, IsNullPointer, KEYCXX) TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX) TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX) +TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) // Embarcadero Expression Traits Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -1398,6 +1398,10 @@ * ``__array_extent(type, dim)`` (Embarcadero): The ``dim``'th array bound in the type ``type``, or ``0`` if ``dim >= __array_rank(type)``. +* ``__can_pass_in_regs`` (C++) + Returns whether a class can be passed in registers under the current + ABI. Returns ``true`` for non-class types like builtins or references. + This is not a portable type trait. * ``__has_nothrow_assign`` (GNU, Microsoft, Embarcadero): Deprecated, use ``__is_nothrow_assignable`` instead. * ``__has_nothrow_move_assign`` (GNU, Microsoft):
Index: clang/test/SemaCXX/type-traits.cpp =================================================================== --- clang/test/SemaCXX/type-traits.cpp +++ clang/test/SemaCXX/type-traits.cpp @@ -3055,6 +3055,23 @@ } // namespace is_trivially_relocatable +namespace can_pass_in_regs { + +struct A { }; + +struct B { + ~B(); +}; + +static_assert(__can_pass_in_regs(A), ""); +static_assert(__can_pass_in_regs(A&), ""); +static_assert(!__can_pass_in_regs(B), ""); +static_assert(__can_pass_in_regs(B&), ""); +static_assert(__can_pass_in_regs(int), ""); +static_assert(__can_pass_in_regs(int&), ""); + +} + struct S {}; template <class T> using remove_const_t = __remove_const(T); Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -4892,6 +4892,7 @@ case UTT_IsLiteral: // By analogy, is_trivially_relocatable imposes the same constraints. case UTT_IsTriviallyRelocatable: + case UTT_CanPassInRegs: // Per the GCC type traits documentation, T shall be a complete type, cv void, // or an array of unknown bound. But GCC actually imposes the same constraints // as above. @@ -5380,6 +5381,10 @@ return T.isTriviallyRelocatableType(C); case UTT_IsReferenceable: return T.isReferenceable(); + case UTT_CanPassInRegs: + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->canPassInRegisters(); + return true; } } Index: clang/include/clang/Basic/TokenKinds.def =================================================================== --- clang/include/clang/Basic/TokenKinds.def +++ clang/include/clang/Basic/TokenKinds.def @@ -523,6 +523,7 @@ TYPE_TRAIT_1(__is_nullptr, IsNullPointer, KEYCXX) TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX) TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX) +TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) // Embarcadero Expression Traits Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -1398,6 +1398,10 @@ * ``__array_extent(type, dim)`` (Embarcadero): The ``dim``'th array bound in the type ``type``, or ``0`` if ``dim >= __array_rank(type)``. +* ``__can_pass_in_regs`` (C++) + Returns whether a class can be passed in registers under the current + ABI. Returns ``true`` for non-class types like builtins or references. + This is not a portable type trait. * ``__has_nothrow_assign`` (GNU, Microsoft, Embarcadero): Deprecated, use ``__is_nothrow_assignable`` instead. * ``__has_nothrow_move_assign`` (GNU, Microsoft):
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits