No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FieldLayout.cpp 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "il2cpp-config.h"
  2. #include "il2cpp-class-internals.h"
  3. #include "vm/Class.h"
  4. #include "vm/GenericClass.h"
  5. #include "vm/GlobalMetadata.h"
  6. #include "vm/Type.h"
  7. #include "vm/Field.h"
  8. #include "metadata/FieldLayout.h"
  9. #include <limits>
  10. #include <algorithm>
  11. using il2cpp::vm::Class;
  12. using il2cpp::vm::GenericClass;
  13. using il2cpp::vm::Type;
  14. namespace il2cpp
  15. {
  16. namespace metadata
  17. {
  18. typedef void* voidptr_t;
  19. #define IL2CPP_ALIGN_STRUCT(type) struct type ## AlignStruct {uint8_t pad; type t; };
  20. IL2CPP_ALIGN_STRUCT(voidptr_t)
  21. IL2CPP_ALIGN_STRUCT(int8_t)
  22. IL2CPP_ALIGN_STRUCT(int16_t)
  23. IL2CPP_ALIGN_STRUCT(int32_t)
  24. IL2CPP_ALIGN_STRUCT(int64_t)
  25. IL2CPP_ALIGN_STRUCT(intptr_t)
  26. IL2CPP_ALIGN_STRUCT(float)
  27. IL2CPP_ALIGN_STRUCT(double)
  28. #define IL2CPP_ALIGN_OF(type) ((size_t)offsetof(type ## AlignStruct, t))
  29. SizeAndAlignment FieldLayout::GetTypeSizeAndAlignment(const Il2CppType* type)
  30. {
  31. SizeAndAlignment sa = { 0 };
  32. if (type->byref)
  33. {
  34. sa.size = sizeof(voidptr_t);
  35. sa.alignment = IL2CPP_ALIGN_OF(voidptr_t);
  36. return sa;
  37. }
  38. switch (type->type)
  39. {
  40. case IL2CPP_TYPE_I1:
  41. case IL2CPP_TYPE_U1:
  42. case IL2CPP_TYPE_BOOLEAN:
  43. sa.size = sizeof(int8_t);
  44. sa.alignment = IL2CPP_ALIGN_OF(int8_t);
  45. return sa;
  46. case IL2CPP_TYPE_I2:
  47. case IL2CPP_TYPE_U2:
  48. case IL2CPP_TYPE_CHAR:
  49. sa.size = sizeof(int16_t);
  50. sa.alignment = IL2CPP_ALIGN_OF(int16_t);
  51. return sa;
  52. case IL2CPP_TYPE_I4:
  53. case IL2CPP_TYPE_U4:
  54. sa.size = sizeof(int32_t);
  55. sa.alignment = IL2CPP_ALIGN_OF(int32_t);
  56. return sa;
  57. case IL2CPP_TYPE_I8:
  58. case IL2CPP_TYPE_U8:
  59. sa.size = sizeof(int64_t);
  60. sa.alignment = IL2CPP_ALIGN_OF(int64_t);
  61. return sa;
  62. case IL2CPP_TYPE_I:
  63. case IL2CPP_TYPE_U:
  64. // TODO should we use pointer or size_t here?
  65. sa.size = sizeof(intptr_t);
  66. sa.alignment = IL2CPP_ALIGN_OF(intptr_t);
  67. return sa;
  68. case IL2CPP_TYPE_R4:
  69. sa.size = sizeof(float);
  70. sa.alignment = IL2CPP_ALIGN_OF(float);
  71. return sa;
  72. case IL2CPP_TYPE_R8:
  73. sa.size = sizeof(double);
  74. sa.alignment = IL2CPP_ALIGN_OF(double);
  75. return sa;
  76. case IL2CPP_TYPE_PTR:
  77. case IL2CPP_TYPE_FNPTR:
  78. case IL2CPP_TYPE_STRING:
  79. case IL2CPP_TYPE_SZARRAY:
  80. case IL2CPP_TYPE_ARRAY:
  81. case IL2CPP_TYPE_CLASS:
  82. case IL2CPP_TYPE_OBJECT:
  83. case IL2CPP_TYPE_VAR:
  84. case IL2CPP_TYPE_MVAR:
  85. sa.size = sizeof(voidptr_t);
  86. sa.alignment = IL2CPP_ALIGN_OF(voidptr_t);
  87. return sa;
  88. case IL2CPP_TYPE_VALUETYPE:
  89. if (Type::IsEnum(type))
  90. {
  91. return GetTypeSizeAndAlignment(Class::GetEnumBaseType(Type::GetClass(type)));
  92. }
  93. else
  94. {
  95. uint32_t alignment;
  96. Il2CppClass* klass = Type::GetClass(type);
  97. sa.size = Class::GetValueSize(klass, &alignment);
  98. sa.alignment = alignment;
  99. return sa;
  100. }
  101. case IL2CPP_TYPE_GENERICINST:
  102. {
  103. Il2CppGenericClass* gclass = type->data.generic_class;
  104. Il2CppClass* container_class = GenericClass::GetTypeDefinition(gclass);
  105. if (container_class != NULL && container_class->byval_arg.valuetype)
  106. {
  107. if (container_class->enumtype)
  108. {
  109. return GetTypeSizeAndAlignment(Class::GetEnumBaseType(container_class));
  110. }
  111. else
  112. {
  113. uint32_t alignment;
  114. sa.size = Class::GetValueSize(Class::FromIl2CppType(type), &alignment);
  115. sa.alignment = alignment;
  116. return sa;
  117. }
  118. }
  119. else
  120. {
  121. sa.size = sizeof(voidptr_t);
  122. sa.alignment = IL2CPP_ALIGN_OF(voidptr_t);
  123. return sa;
  124. }
  125. }
  126. default:
  127. IL2CPP_ASSERT(0);
  128. break;
  129. }
  130. return sa;
  131. }
  132. static size_t AlignTo(size_t size, size_t alignment)
  133. {
  134. if (size & (alignment - 1))
  135. {
  136. size += alignment - 1;
  137. size &= ~(alignment - 1);
  138. }
  139. return size;
  140. }
  141. void FieldLayout::LayoutInstanceFields(const Il2CppClass* klass, size_t parentSize, size_t actualParentSize, size_t parentAlignment, uint8_t packing, FieldLayoutData& data)
  142. {
  143. LayoutFields(klass, vm::Field::IsInstance, parentSize, actualParentSize, parentAlignment, packing, klass->flags & TYPE_ATTRIBUTE_EXPLICIT_LAYOUT && klass->generic_class == NULL, data);
  144. }
  145. void FieldLayout::LayoutStaticFields(const Il2CppClass* klass, FieldLayoutData& data)
  146. {
  147. LayoutFields(klass, vm::Field::IsNormalStatic, 0, 0, 1, 0, false, data);
  148. }
  149. void FieldLayout::LayoutThreadStaticFields(const Il2CppClass* klass, FieldLayoutData& data)
  150. {
  151. LayoutFields(klass, vm::Field::IsThreadStatic, 0, 0, 1, 0, false, data);
  152. }
  153. void FieldLayout::LayoutFields(const Il2CppClass* klass, FieldInfoFilter filter, size_t parentSize, size_t actualParentSize, size_t parentAlignment, uint8_t packing, bool isExplicitLayout, FieldLayoutData& data)
  154. {
  155. data.classSize = parentSize;
  156. data.actualClassSize = actualParentSize;
  157. IL2CPP_ASSERT(parentAlignment <= std::numeric_limits<uint8_t>::max());
  158. data.minimumAlignment = static_cast<uint8_t>(parentAlignment);
  159. for (uint16_t i = 0; i < klass->field_count; i++)
  160. {
  161. if (!filter(klass->fields + i))
  162. continue;
  163. SizeAndAlignment sa = GetTypeSizeAndAlignment(klass->fields[i].type);
  164. uint8_t alignment = sa.alignment;
  165. if (packing > 0)
  166. alignment = std::min(sa.alignment, packing);
  167. size_t offset = isExplicitLayout ? klass->fields[i].offset : data.actualClassSize;
  168. offset += alignment - 1;
  169. offset &= ~(alignment - 1);
  170. data.FieldOffsets.push_back(offset);
  171. data.actualClassSize = std::max(data.actualClassSize, offset + std::max(sa.size, (size_t)1));
  172. data.minimumAlignment = std::max(data.minimumAlignment, alignment);
  173. }
  174. data.classSize = AlignTo(data.actualClassSize, data.minimumAlignment);
  175. // C++ ABI difference between MS and Clang
  176. #if IL2CPP_CXX_ABI_MSVC
  177. data.actualClassSize = data.classSize;
  178. #endif
  179. }
  180. } /* namespace vm */
  181. } /* namespace il2cpp */