LCOV - code coverage report
Current view: top level - asmjit - type.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 11 16 68.8 %
Date: 2026-11-05 10:19:06 Functions: 7 11 63.6 %

          Line data    Source code
       1             : #ifdef __PLUMED_HAS_ASMJIT
       2             : // This file is part of AsmJit project <https://asmjit.com>
       3             : //
       4             : // See asmjit.h or LICENSE.md for license and copyright information
       5             : // SPDX-License-Identifier: Zlib
       6             : 
       7             : #ifndef ASMJIT_CORE_TYPE_H_INCLUDED
       8             : #define ASMJIT_CORE_TYPE_H_INCLUDED
       9             : 
      10             : #include "globals.h"
      11             : #include "support.h"
      12             : 
      13             : ASMJIT_BEGIN_NAMESPACE
      14             : 
      15             : //! \addtogroup asmjit_core
      16             : //! \{
      17             : 
      18             : //! Type identifier provides a minimalist type system used across AsmJit library.
      19             : //!
      20             : //! This is an additional information that can be used to describe a value-type of physical or virtual register. It's
      21             : //! used mostly by BaseCompiler to describe register representation (the group of data stored in the register and the
      22             : //! width used) and it's also used by APIs that allow to describe and work with function signatures.
      23             : enum class TypeId : uint8_t {
      24             :   //! Void type.
      25             :   kVoid = 0,
      26             : 
      27             :   _kBaseStart = 32,
      28             :   _kBaseEnd = 44,
      29             : 
      30             :   _kIntStart = 32,
      31             :   _kIntEnd = 41,
      32             : 
      33             :   //! Abstract signed integer type that has a native size.
      34             :   kIntPtr = 32,
      35             :   //! Abstract unsigned integer type that has a native size.
      36             :   kUIntPtr = 33,
      37             : 
      38             :   //! 8-bit signed integer type.
      39             :   kInt8 = 34,
      40             :   //! 8-bit unsigned integer type.
      41             :   kUInt8 = 35,
      42             :   //! 16-bit signed integer type.
      43             :   kInt16 = 36,
      44             :   //! 16-bit unsigned integer type.
      45             :   kUInt16 = 37,
      46             :   //! 32-bit signed integer type.
      47             :   kInt32 = 38,
      48             :   //! 32-bit unsigned integer type.
      49             :   kUInt32 = 39,
      50             :   //! 64-bit signed integer type.
      51             :   kInt64 = 40,
      52             :   //! 64-bit unsigned integer type.
      53             :   kUInt64 = 41,
      54             : 
      55             :   _kFloatStart  = 42,
      56             :   _kFloatEnd = 44,
      57             : 
      58             :   //! 32-bit floating point type.
      59             :   kFloat32 = 42,
      60             :   //! 64-bit floating point type.
      61             :   kFloat64 = 43,
      62             :   //! 80-bit floating point type.
      63             :   kFloat80 = 44,
      64             : 
      65             :   _kMaskStart = 45,
      66             :   _kMaskEnd = 48,
      67             : 
      68             :   //! 8-bit opmask register (K).
      69             :   kMask8 = 45,
      70             :   //! 16-bit opmask register (K).
      71             :   kMask16 = 46,
      72             :   //! 32-bit opmask register (K).
      73             :   kMask32 = 47,
      74             :   //! 64-bit opmask register (K).
      75             :   kMask64 = 48,
      76             : 
      77             :   _kMmxStart = 49,
      78             :   _kMmxEnd = 50,
      79             : 
      80             :   //! 64-bit MMX register only used for 32 bits.
      81             :   kMmx32 = 49,
      82             :   //! 64-bit MMX register.
      83             :   kMmx64 = 50,
      84             : 
      85             :   _kVec32Start  = 51,
      86             :   _kVec32End = 60,
      87             : 
      88             :   kInt8x4 = 51,
      89             :   kUInt8x4 = 52,
      90             :   kInt16x2 = 53,
      91             :   kUInt16x2 = 54,
      92             :   kInt32x1 = 55,
      93             :   kUInt32x1 = 56,
      94             :   kFloat32x1 = 59,
      95             : 
      96             :   _kVec64Start  = 61,
      97             :   _kVec64End = 70,
      98             : 
      99             :   kInt8x8 = 61,
     100             :   kUInt8x8 = 62,
     101             :   kInt16x4 = 63,
     102             :   kUInt16x4 = 64,
     103             :   kInt32x2 = 65,
     104             :   kUInt32x2 = 66,
     105             :   kInt64x1 = 67,
     106             :   kUInt64x1 = 68,
     107             :   kFloat32x2 = 69,
     108             :   kFloat64x1 = 70,
     109             : 
     110             :   _kVec128Start = 71,
     111             :   _kVec128End = 80,
     112             : 
     113             :   kInt8x16 = 71,
     114             :   kUInt8x16 = 72,
     115             :   kInt16x8 = 73,
     116             :   kUInt16x8 = 74,
     117             :   kInt32x4 = 75,
     118             :   kUInt32x4 = 76,
     119             :   kInt64x2 = 77,
     120             :   kUInt64x2 = 78,
     121             :   kFloat32x4 = 79,
     122             :   kFloat64x2 = 80,
     123             : 
     124             :   _kVec256Start = 81,
     125             :   _kVec256End = 90,
     126             : 
     127             :   kInt8x32 = 81,
     128             :   kUInt8x32 = 82,
     129             :   kInt16x16 = 83,
     130             :   kUInt16x16 = 84,
     131             :   kInt32x8 = 85,
     132             :   kUInt32x8 = 86,
     133             :   kInt64x4 = 87,
     134             :   kUInt64x4 = 88,
     135             :   kFloat32x8 = 89,
     136             :   kFloat64x4 = 90,
     137             : 
     138             :   _kVec512Start = 91,
     139             :   _kVec512End = 100,
     140             : 
     141             :   kInt8x64 = 91,
     142             :   kUInt8x64 = 92,
     143             :   kInt16x32 = 93,
     144             :   kUInt16x32 = 94,
     145             :   kInt32x16 = 95,
     146             :   kUInt32x16 = 96,
     147             :   kInt64x8 = 97,
     148             :   kUInt64x8 = 98,
     149             :   kFloat32x16 = 99,
     150             :   kFloat64x8 = 100,
     151             : 
     152             :   kLastAssigned = kFloat64x8,
     153             : 
     154             :   kMaxValue = 255
     155             : };
     156             : ASMJIT_DEFINE_ENUM_COMPARE(TypeId)
     157             : 
     158             : //! Type identifier utilities.
     159             : namespace TypeUtils {
     160             : 
     161             : struct TypeData {
     162             :   TypeId scalarOf[uint32_t(TypeId::kMaxValue) + 1];
     163             :   uint8_t sizeOf[uint32_t(TypeId::kMaxValue) + 1];
     164             : };
     165             : ASMJIT_VARAPI const TypeData _typeData;
     166             : 
     167             : //! Returns the scalar type of `typeId`.
     168       50201 : static inline TypeId scalarOf(TypeId typeId) noexcept { return _typeData.scalarOf[uint32_t(typeId)]; }
     169             : 
     170             : //! Returns the size [in bytes] of `typeId`.
     171      547554 : static inline uint32_t sizeOf(TypeId typeId) noexcept { return _typeData.sizeOf[uint32_t(typeId)]; }
     172             : 
     173             : //! Tests whether a given type `typeId` is between `a` and `b`.
     174             : static inline constexpr bool isBetween(TypeId typeId, TypeId a, TypeId b) noexcept {
     175      714518 :   return Support::isBetween(uint32_t(typeId), uint32_t(a), uint32_t(b));
     176             : }
     177             : 
     178             : //! Tests whether a given type `typeId` is \ref TypeId::kVoid.
     179             : static inline constexpr bool isVoid(TypeId typeId) noexcept { return typeId == TypeId::kVoid; }
     180             : //! Tests whether a given type `typeId` is a valid non-void type.
     181      273777 : static inline constexpr bool isValid(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kVec512End); }
     182             : //! Tests whether a given type `typeId` is scalar (has no vector part).
     183             : static inline constexpr bool isScalar(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kBaseStart, TypeId::_kBaseEnd); }
     184             : //! Tests whether a given type `typeId` is abstract, which means that its size depends on register size.
     185      273777 : static inline constexpr bool isAbstract(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kIntPtr, TypeId::kUIntPtr); }
     186             : 
     187             : //! Tests whether a given type is a scalar integer (signed or unsigned) of any size.
     188        9873 : static inline constexpr bool isInt(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kIntEnd); }
     189             : //! Tests whether a given type is a scalar 8-bit integer (signed).
     190             : static inline constexpr bool isInt8(TypeId typeId) noexcept { return typeId == TypeId::kInt8; }
     191             : //! Tests whether a given type is a scalar 8-bit integer (unsigned).
     192             : static inline constexpr bool isUInt8(TypeId typeId) noexcept { return typeId == TypeId::kUInt8; }
     193             : //! Tests whether a given type is a scalar 16-bit integer (signed).
     194             : static inline constexpr bool isInt16(TypeId typeId) noexcept { return typeId == TypeId::kInt16; }
     195             : //! Tests whether a given type is a scalar 16-bit integer (unsigned).
     196             : static inline constexpr bool isUInt16(TypeId typeId) noexcept { return typeId == TypeId::kUInt16; }
     197             : //! Tests whether a given type is a scalar 32-bit integer (signed).
     198             : static inline constexpr bool isInt32(TypeId typeId) noexcept { return typeId == TypeId::kInt32; }
     199             : //! Tests whether a given type is a scalar 32-bit integer (unsigned).
     200             : static inline constexpr bool isUInt32(TypeId typeId) noexcept { return typeId == TypeId::kUInt32; }
     201             : //! Tests whether a given type is a scalar 64-bit integer (signed).
     202             : static inline constexpr bool isInt64(TypeId typeId) noexcept { return typeId == TypeId::kInt64; }
     203             : //! Tests whether a given type is a scalar 64-bit integer (unsigned).
     204             : static inline constexpr bool isUInt64(TypeId typeId) noexcept { return typeId == TypeId::kUInt64; }
     205             : 
     206             : static inline constexpr bool isGp8(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt8, TypeId::kUInt8); }
     207             : static inline constexpr bool isGp16(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt16, TypeId::kUInt16); }
     208             : static inline constexpr bool isGp32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt32, TypeId::kUInt32); }
     209             : static inline constexpr bool isGp64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt64, TypeId::kUInt64); }
     210             : 
     211             : //! Tests whether a given type is a scalar floating point of any size.
     212        9685 : static inline constexpr bool isFloat(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kFloatStart, TypeId::_kFloatEnd); }
     213             : //! Tests whether a given type is a scalar 32-bit float.
     214             : static inline constexpr bool isFloat32(TypeId typeId) noexcept { return typeId == TypeId::kFloat32; }
     215             : //! Tests whether a given type is a scalar 64-bit float.
     216             : static inline constexpr bool isFloat64(TypeId typeId) noexcept { return typeId == TypeId::kFloat64; }
     217             : //! Tests whether a given type is a scalar 80-bit float.
     218             : static inline constexpr bool isFloat80(TypeId typeId) noexcept { return typeId == TypeId::kFloat80; }
     219             : 
     220           0 : static inline constexpr bool isMask(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMaskStart, TypeId::_kMaskEnd); }
     221             : static inline constexpr bool isMask8(TypeId typeId) noexcept { return typeId == TypeId::kMask8; }
     222             : static inline constexpr bool isMask16(TypeId typeId) noexcept { return typeId == TypeId::kMask16; }
     223             : static inline constexpr bool isMask32(TypeId typeId) noexcept { return typeId == TypeId::kMask32; }
     224             : static inline constexpr bool isMask64(TypeId typeId) noexcept { return typeId == TypeId::kMask64; }
     225             : 
     226           0 : static inline constexpr bool isMmx(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMmxStart, TypeId::_kMmxEnd); }
     227             : static inline constexpr bool isMmx32(TypeId typeId) noexcept { return typeId == TypeId::kMmx32; }
     228             : static inline constexpr bool isMmx64(TypeId typeId) noexcept { return typeId == TypeId::kMmx64; }
     229             : 
     230           0 : static inline constexpr bool isVec(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec512End); }
     231       50201 : static inline constexpr bool isVec32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec32End); }
     232       50201 : static inline constexpr bool isVec64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec64Start, TypeId::_kVec64End); }
     233           0 : static inline constexpr bool isVec128(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec128Start, TypeId::_kVec128End); }
     234             : static inline constexpr bool isVec256(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec256Start, TypeId::_kVec256End); }
     235             : static inline constexpr bool isVec512(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec512Start, TypeId::_kVec512End); }
     236             : 
     237             : //! \cond
     238             : enum TypeCategory : uint32_t {
     239             :   kTypeCategoryUnknown = 0,
     240             :   kTypeCategoryEnum = 1,
     241             :   kTypeCategoryIntegral = 2,
     242             :   kTypeCategoryFloatingPoint = 3,
     243             :   kTypeCategoryFunction = 4
     244             : };
     245             : 
     246             : template<typename T, TypeCategory kCategory>
     247             : struct TypeIdOfT_ByCategory {}; // Fails if not specialized.
     248             : 
     249             : template<typename T>
     250             : struct TypeIdOfT_ByCategory<T, kTypeCategoryIntegral> {
     251             :   enum : uint32_t {
     252             :     kTypeId = uint32_t(
     253             :       (sizeof(T) == 1 &&  std::is_signed<T>::value) ? TypeId::kInt8 :
     254             :       (sizeof(T) == 1 && !std::is_signed<T>::value) ? TypeId::kUInt8 :
     255             :       (sizeof(T) == 2 &&  std::is_signed<T>::value) ? TypeId::kInt16 :
     256             :       (sizeof(T) == 2 && !std::is_signed<T>::value) ? TypeId::kUInt16 :
     257             :       (sizeof(T) == 4 &&  std::is_signed<T>::value) ? TypeId::kInt32 :
     258             :       (sizeof(T) == 4 && !std::is_signed<T>::value) ? TypeId::kUInt32 :
     259             :       (sizeof(T) == 8 &&  std::is_signed<T>::value) ? TypeId::kInt64 :
     260             :       (sizeof(T) == 8 && !std::is_signed<T>::value) ? TypeId::kUInt64 : TypeId::kVoid)
     261             :   };
     262             : };
     263             : 
     264             : template<typename T>
     265             : struct TypeIdOfT_ByCategory<T, kTypeCategoryFloatingPoint> {
     266             :   enum : uint32_t {
     267             :     kTypeId = uint32_t(
     268             :       (sizeof(T) == 4 ) ? TypeId::kFloat32 :
     269             :       (sizeof(T) == 8 ) ? TypeId::kFloat64 :
     270             :       (sizeof(T) >= 10) ? TypeId::kFloat80 : TypeId::kVoid)
     271             :   };
     272             : };
     273             : 
     274             : template<typename T>
     275             : struct TypeIdOfT_ByCategory<T, kTypeCategoryEnum>
     276             :   : public TypeIdOfT_ByCategory<typename std::underlying_type<T>::type, kTypeCategoryIntegral> {};
     277             : 
     278             : template<typename T>
     279             : struct TypeIdOfT_ByCategory<T, kTypeCategoryFunction> {
     280             :   enum : uint32_t {
     281             :     kTypeId = uint32_t(TypeId::kUIntPtr)
     282             :   };
     283             : };
     284             : //! \endcond
     285             : 
     286             : //! TypeIdOfT<> template allows to get a TypeId from a C++ type `T`.
     287             : #ifdef _DOXYGEN
     288             : template<typename T>
     289             : struct TypeIdOfT {
     290             :   //! TypeId of C++ type `T`.
     291             :   static constexpr TypeId kTypeId = _TypeIdDeducedAtCompileTime_;
     292             : };
     293             : #else
     294             : template<typename T>
     295             : struct TypeIdOfT
     296             :   : public TypeIdOfT_ByCategory<T,
     297             :     std::is_enum<T>::value           ? kTypeCategoryEnum          :
     298             :     std::is_integral<T>::value       ? kTypeCategoryIntegral      :
     299             :     std::is_floating_point<T>::value ? kTypeCategoryFloatingPoint :
     300             :     std::is_function<T>::value       ? kTypeCategoryFunction      : kTypeCategoryUnknown> {};
     301             : #endif
     302             : 
     303             : //! \cond
     304             : template<typename T>
     305             : struct TypeIdOfT<T*> {
     306             :   enum : uint32_t {
     307             :     kTypeId = uint32_t(TypeId::kUIntPtr)
     308             :   };
     309             : };
     310             : 
     311             : template<typename T>
     312             : struct TypeIdOfT<T&> {
     313             :   enum : uint32_t {
     314             :     kTypeId = uint32_t(TypeId::kUIntPtr)
     315             :   };
     316             : };
     317             : //! \endcond
     318             : 
     319             : //! Returns a corresponding \ref TypeId of `T` type.
     320             : template<typename T>
     321             : static inline constexpr TypeId typeIdOfT() noexcept { return TypeId(TypeIdOfT<T>::kTypeId); }
     322             : 
     323             : //! Returns offset needed to convert a `kIntPtr` and `kUIntPtr` TypeId into a type that matches `registerSize`
     324             : //! (general-purpose register size). If you find such TypeId it's then only about adding the offset to it.
     325             : //!
     326             : //! For example:
     327             : //!
     328             : //! ```
     329             : //! uint32_t registerSize = /* 4 or 8 */;
     330             : //! uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize);
     331             : //!
     332             : //! TypeId typeId = 'some type-id';
     333             : //!
     334             : //! // Normalize some typeId into a non-abstract typeId.
     335             : //! if (TypeUtils::isAbstract(typeId)) typeId += deabstractDelta;
     336             : //!
     337             : //! // The same, but by using TypeUtils::deabstract() function.
     338             : //! typeId = TypeUtils::deabstract(typeId, deabstractDelta);
     339             : //! ```
     340             : static inline constexpr uint32_t deabstractDeltaOfSize(uint32_t registerSize) noexcept {
     341             :   return registerSize >= 8 ? uint32_t(TypeId::kInt64) - uint32_t(TypeId::kIntPtr)
     342             :                            : uint32_t(TypeId::kInt32) - uint32_t(TypeId::kIntPtr);
     343             : }
     344             : 
     345             : //! Deabstracts a given `typeId` into a native type by using `deabstractDelta`, which was previously
     346             : //! calculated by calling \ref deabstractDeltaOfSize() with a target native register size.
     347       47004 : static inline constexpr TypeId deabstract(TypeId typeId, uint32_t deabstractDelta) noexcept {
     348         188 :   return isAbstract(typeId) ? TypeId(uint32_t(typeId) + deabstractDelta) : typeId;
     349             : }
     350             : 
     351             : static inline constexpr TypeId scalarToVector(TypeId scalarTypeId, TypeId vecStartId) noexcept {
     352           0 :   return TypeId(uint32_t(vecStartId) + uint32_t(scalarTypeId) - uint32_t(TypeId::kInt8));
     353             : }
     354             : 
     355             : } // {TypeUtils}
     356             : 
     357             : //! Provides type identifiers that can be used in templates instead of native types.
     358             : namespace Type {
     359             : 
     360             : //! bool as C++ type-name.
     361             : struct Bool {};
     362             : //! int8_t as C++ type-name.
     363             : struct Int8 {};
     364             : //! uint8_t as C++ type-name.
     365             : struct UInt8 {};
     366             : //! int16_t as C++ type-name.
     367             : struct Int16 {};
     368             : //! uint16_t as C++ type-name.
     369             : struct UInt16 {};
     370             : //! int32_t as C++ type-name.
     371             : struct Int32 {};
     372             : //! uint32_t as C++ type-name.
     373             : struct UInt32 {};
     374             : //! int64_t as C++ type-name.
     375             : struct Int64 {};
     376             : //! uint64_t as C++ type-name.
     377             : struct UInt64 {};
     378             : //! intptr_t as C++ type-name.
     379             : struct IntPtr {};
     380             : //! uintptr_t as C++ type-name.
     381             : struct UIntPtr {};
     382             : //! float as C++ type-name.
     383             : struct Float32 {};
     384             : //! double as C++ type-name.
     385             : struct Float64 {};
     386             : 
     387             : } // {Type}
     388             : 
     389             : //! \cond
     390             : #define ASMJIT_DEFINE_TYPE_ID(T, TYPE_ID) \
     391             : namespace TypeUtils {                     \
     392             :   template<>                              \
     393             :   struct TypeIdOfT<T> {                   \
     394             :     enum : uint32_t {                     \
     395             :       kTypeId = uint32_t(TYPE_ID)         \
     396             :     };                                    \
     397             :   };                                      \
     398             : }
     399             : 
     400             : ASMJIT_DEFINE_TYPE_ID(void         , TypeId::kVoid);
     401             : ASMJIT_DEFINE_TYPE_ID(Type::Bool   , TypeId::kUInt8);
     402             : ASMJIT_DEFINE_TYPE_ID(Type::Int8   , TypeId::kInt8);
     403             : ASMJIT_DEFINE_TYPE_ID(Type::UInt8  , TypeId::kUInt8);
     404             : ASMJIT_DEFINE_TYPE_ID(Type::Int16  , TypeId::kInt16);
     405             : ASMJIT_DEFINE_TYPE_ID(Type::UInt16 , TypeId::kUInt16);
     406             : ASMJIT_DEFINE_TYPE_ID(Type::Int32  , TypeId::kInt32);
     407             : ASMJIT_DEFINE_TYPE_ID(Type::UInt32 , TypeId::kUInt32);
     408             : ASMJIT_DEFINE_TYPE_ID(Type::Int64  , TypeId::kInt64);
     409             : ASMJIT_DEFINE_TYPE_ID(Type::UInt64 , TypeId::kUInt64);
     410             : ASMJIT_DEFINE_TYPE_ID(Type::IntPtr , TypeId::kIntPtr);
     411             : ASMJIT_DEFINE_TYPE_ID(Type::UIntPtr, TypeId::kUIntPtr);
     412             : ASMJIT_DEFINE_TYPE_ID(Type::Float32, TypeId::kFloat32);
     413             : ASMJIT_DEFINE_TYPE_ID(Type::Float64, TypeId::kFloat64);
     414             : //! \endcond
     415             : 
     416             : //! \}
     417             : 
     418             : ASMJIT_END_NAMESPACE
     419             : 
     420             : #endif // ASMJIT_CORE_TYPE_H_INCLUDED
     421             : 
     422             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16