k_class_token.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include "common/bit_util.h"
  5. #include "common/common_types.h"
  6. namespace Kernel {
  7. class KAutoObject;
  8. class KClassTokenGenerator {
  9. public:
  10. using TokenBaseType = u16;
  11. public:
  12. static constexpr size_t BaseClassBits = 8;
  13. static constexpr size_t FinalClassBits = (sizeof(TokenBaseType) * CHAR_BIT) - BaseClassBits;
  14. // One bit per base class.
  15. static constexpr size_t NumBaseClasses = BaseClassBits;
  16. // Final classes are permutations of three bits.
  17. static constexpr size_t NumFinalClasses = [] {
  18. TokenBaseType index = 0;
  19. for (size_t i = 0; i < FinalClassBits; i++) {
  20. for (size_t j = i + 1; j < FinalClassBits; j++) {
  21. for (size_t k = j + 1; k < FinalClassBits; k++) {
  22. index++;
  23. }
  24. }
  25. }
  26. return index;
  27. }();
  28. private:
  29. template <TokenBaseType Index>
  30. static constexpr inline TokenBaseType BaseClassToken = 1U << Index;
  31. template <TokenBaseType Index>
  32. static constexpr inline TokenBaseType FinalClassToken = [] {
  33. TokenBaseType index = 0;
  34. for (size_t i = 0; i < FinalClassBits; i++) {
  35. for (size_t j = i + 1; j < FinalClassBits; j++) {
  36. for (size_t k = j + 1; k < FinalClassBits; k++) {
  37. if ((index++) == Index) {
  38. return static_cast<TokenBaseType>(((1ULL << i) | (1ULL << j) | (1ULL << k))
  39. << BaseClassBits);
  40. }
  41. }
  42. }
  43. }
  44. UNREACHABLE();
  45. }();
  46. template <typename T>
  47. static constexpr inline TokenBaseType GetClassToken() {
  48. static_assert(std::is_base_of<KAutoObject, T>::value);
  49. if constexpr (std::is_same<T, KAutoObject>::value) {
  50. static_assert(T::ObjectType == ObjectType::KAutoObject);
  51. return 0;
  52. } else if constexpr (!std::is_final<T>::value) {
  53. static_assert(ObjectType::BaseClassesStart <= T::ObjectType &&
  54. T::ObjectType < ObjectType::BaseClassesEnd);
  55. constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) -
  56. static_cast<TokenBaseType>(ObjectType::BaseClassesStart);
  57. return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
  58. } else if constexpr (ObjectType::FinalClassesStart <= T::ObjectType &&
  59. T::ObjectType < ObjectType::FinalClassesEnd) {
  60. constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) -
  61. static_cast<TokenBaseType>(ObjectType::FinalClassesStart);
  62. return FinalClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
  63. } else {
  64. static_assert(!std::is_same<T, T>::value, "GetClassToken: Invalid Type");
  65. }
  66. };
  67. public:
  68. enum class ObjectType {
  69. KAutoObject,
  70. BaseClassesStart,
  71. KSynchronizationObject = BaseClassesStart,
  72. KReadableEvent,
  73. BaseClassesEnd,
  74. FinalClassesStart = BaseClassesEnd,
  75. KInterruptEvent = FinalClassesStart,
  76. KDebug,
  77. KThread,
  78. KServerPort,
  79. KServerSession,
  80. KClientPort,
  81. KClientSession,
  82. KProcess,
  83. KResourceLimit,
  84. KLightSession,
  85. KPort,
  86. KSession,
  87. KSharedMemory,
  88. KEvent,
  89. KLightClientSession,
  90. KLightServerSession,
  91. KTransferMemory,
  92. KDeviceAddressSpace,
  93. KSessionRequest,
  94. KCodeMemory,
  95. // NOTE: True order for these has not been determined yet.
  96. KAlpha,
  97. KBeta,
  98. FinalClassesEnd = FinalClassesStart + NumFinalClasses,
  99. };
  100. template <typename T>
  101. static constexpr inline TokenBaseType ClassToken = GetClassToken<T>();
  102. };
  103. using ClassTokenType = KClassTokenGenerator::TokenBaseType;
  104. template <typename T>
  105. static constexpr inline ClassTokenType ClassToken = KClassTokenGenerator::ClassToken<T>;
  106. } // namespace Kernel