少年修仙传客户端基础资源
hch
2024-04-01 d01413b00ef631ac20347716b23818b0b811f65f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include "il2cpp-config.h"
#include "il2cpp-class-internals.h"
#include "vm/Class.h"
#include "vm/GenericClass.h"
#include "vm/Type.h"
#include "metadata/FieldLayout.h"
#include <limits>
#include <algorithm>
 
using il2cpp::vm::Class;
using il2cpp::vm::GenericClass;
using il2cpp::vm::Type;
 
namespace il2cpp
{
namespace metadata
{
    typedef void* voidptr_t;
#define IL2CPP_ALIGN_STRUCT(type) struct type ## AlignStruct {uint8_t pad; type t; };
 
    IL2CPP_ALIGN_STRUCT(voidptr_t)
    IL2CPP_ALIGN_STRUCT(int8_t)
    IL2CPP_ALIGN_STRUCT(int16_t)
    IL2CPP_ALIGN_STRUCT(int32_t)
    IL2CPP_ALIGN_STRUCT(int64_t)
    IL2CPP_ALIGN_STRUCT(intptr_t)
    IL2CPP_ALIGN_STRUCT(float)
    IL2CPP_ALIGN_STRUCT(double)
 
#define IL2CPP_ALIGN_OF(type) ((size_t)offsetof(type ## AlignStruct, t))
 
    SizeAndAlignment FieldLayout::GetTypeSizeAndAlignment(const Il2CppType* type)
    {
        SizeAndAlignment sa = { 0 };
        if (type->byref)
        {
            sa.size = sizeof(voidptr_t);
            sa.alignment = IL2CPP_ALIGN_OF(voidptr_t);
            return sa;
        }
 
        switch (type->type)
        {
            case IL2CPP_TYPE_I1:
            case IL2CPP_TYPE_U1:
            case IL2CPP_TYPE_BOOLEAN:
                sa.size = sizeof(int8_t);
                sa.alignment = IL2CPP_ALIGN_OF(int8_t);
                return sa;
            case IL2CPP_TYPE_I2:
            case IL2CPP_TYPE_U2:
            case IL2CPP_TYPE_CHAR:
                sa.size = sizeof(int16_t);
                sa.alignment = IL2CPP_ALIGN_OF(int16_t);
                return sa;
            case IL2CPP_TYPE_I4:
            case IL2CPP_TYPE_U4:
                sa.size = sizeof(int32_t);
                sa.alignment = IL2CPP_ALIGN_OF(int32_t);
                return sa;
            case IL2CPP_TYPE_I8:
            case IL2CPP_TYPE_U8:
                sa.size = sizeof(int64_t);
                sa.alignment = IL2CPP_ALIGN_OF(int64_t);
                return sa;
            case IL2CPP_TYPE_I:
            case IL2CPP_TYPE_U:
                // TODO should we use pointer or size_t here?
                sa.size = sizeof(intptr_t);
                sa.alignment = IL2CPP_ALIGN_OF(intptr_t);
                return sa;
            case IL2CPP_TYPE_R4:
                sa.size = sizeof(float);
                sa.alignment = IL2CPP_ALIGN_OF(float);
                return sa;
            case IL2CPP_TYPE_R8:
                sa.size = sizeof(double);
                sa.alignment = IL2CPP_ALIGN_OF(double);
                return sa;
            case IL2CPP_TYPE_PTR:
            case IL2CPP_TYPE_FNPTR:
            case IL2CPP_TYPE_STRING:
            case IL2CPP_TYPE_SZARRAY:
            case IL2CPP_TYPE_ARRAY:
            case IL2CPP_TYPE_CLASS:
            case IL2CPP_TYPE_OBJECT:
            case IL2CPP_TYPE_VAR:
            case IL2CPP_TYPE_MVAR:
                sa.size = sizeof(voidptr_t);
                sa.alignment = IL2CPP_ALIGN_OF(voidptr_t);
                return sa;
            case IL2CPP_TYPE_VALUETYPE:
                if (Type::IsEnum(type))
                {
                    return GetTypeSizeAndAlignment(Class::GetEnumBaseType(Type::GetClass(type)));
                }
                else
                {
                    uint32_t alignment;
                    Il2CppClass* klass = Type::GetClass(type);
                    sa.size = Class::GetValueSize(klass, &alignment);
                    sa.alignment = alignment;
                    sa.naturalAlignment = klass->naturalAligment;
                    return sa;
                }
            case IL2CPP_TYPE_GENERICINST:
            {
                Il2CppGenericClass* gclass = type->data.generic_class;
                Il2CppClass* container_class = GenericClass::GetTypeDefinition(gclass);
 
                if (container_class != NULL && container_class->valuetype)
                {
                    if (container_class->enumtype)
                    {
                        return GetTypeSizeAndAlignment(Class::GetEnumBaseType(container_class));
                    }
                    else
                    {
                        uint32_t alignment;
                        sa.size = Class::GetValueSize(Class::FromIl2CppType(type), &alignment);
                        sa.alignment = alignment;
                        return sa;
                    }
                }
                else
                {
                    sa.size = sizeof(voidptr_t);
                    sa.alignment = IL2CPP_ALIGN_OF(voidptr_t);
                    return sa;
                }
            }
            default:
                IL2CPP_ASSERT(0);
                break;
        }
        return sa;
    }
 
    static size_t AlignTo(size_t size, size_t alignment)
    {
        if (size & (alignment - 1))
        {
            size += alignment - 1;
            size &= ~(alignment - 1);
        }
 
        return size;
    }
 
    void FieldLayout::LayoutFields(size_t parentSize, size_t actualParentSize, size_t parentAlignment, uint8_t packing, const metadata::Il2CppTypeVector& fieldTypes, FieldLayoutData& data)
    {
        data.classSize = parentSize;
        data.actualClassSize = actualParentSize;
        IL2CPP_ASSERT(parentAlignment <= std::numeric_limits<uint8_t>::max());
        data.minimumAlignment = static_cast<uint8_t>(parentAlignment);
        data.naturalAlignment = 0;
        for (Il2CppTypeVector::const_iterator iter = fieldTypes.begin(); iter != fieldTypes.end(); ++iter)
        {
            SizeAndAlignment sa = GetTypeSizeAndAlignment(*iter);
 
            // For fields, we might not want to take the actual alignment of the type - that might account for
            // packing. When a type is used as a field, we should not care about its alignment with packing,
            // instead let's use its natural alignment, without regard for packing. So if it's alignment
            // is less than the compiler's minimum alignment (4 bytes), lets use the natural alignment if we have it.
            uint8_t alignment = sa.alignment;
            if (alignment < 4 && sa.naturalAlignment != 0)
                alignment = sa.naturalAlignment;
            if (packing != 0)
                alignment = std::min(sa.alignment, packing);
            size_t offset = data.actualClassSize;
 
            offset += alignment - 1;
            offset &= ~(alignment - 1);
 
            data.FieldOffsets.push_back(offset);
            data.actualClassSize = offset + std::max(sa.size, (size_t)1);
            data.minimumAlignment = std::max(data.minimumAlignment, alignment);
            data.naturalAlignment = std::max({data.naturalAlignment, sa.alignment, sa.naturalAlignment});
        }
 
        data.classSize = AlignTo(data.actualClassSize, data.minimumAlignment);
 
        // C++ ABI difference between MS and Clang
#if IL2CPP_CXX_ABI_MSVC
        data.actualClassSize = data.classSize;
#endif
    }
} /* namespace vm */
} /* namespace il2cpp */