1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ECMASCRIPT_BASE_ALIGNED_STRUCT_H
17#define ECMASCRIPT_BASE_ALIGNED_STRUCT_H
18
19#include "ecmascript/base/bit_helper.h"
20
21namespace panda::ecmascript::base {
22template<typename...>
23struct TypeList {};
24
25template<typename T>
26struct TypeList<T> {
27    using Head = T;
28    using Next = TypeList<>;
29    static constexpr size_t Size = 1;
30};
31
32template<typename T, typename... Res>
33struct TypeList<T, Res...> {
34    using Head = T;
35    using Next = TypeList<Res...>;
36    static constexpr size_t Size = 1 + sizeof...(Res);
37};
38
39template<size_t ElementAlign, typename... Ts>
40struct AlignedStruct {
41    static constexpr size_t EAS = ElementAlign;
42
43    using ElemTypeList = TypeList<Ts...>;
44    static constexpr size_t NumOfTypes = ElemTypeList::Size;
45
46    template<size_t, typename>
47    struct OffsetAt;
48
49    template<>
50    struct OffsetAt<0, TypeList<>> {
51        static constexpr size_t OFFSET64 = 0;
52        static constexpr size_t OFFSET32 = 0;
53    };
54
55    template<typename Head, typename... Res>
56    struct OffsetAt<0, TypeList<Head, Res...>> {
57        static constexpr size_t OFFSET64 = 0;
58        static constexpr size_t OFFSET32 = 0;
59    };
60
61    template<size_t index, typename Head, typename... Res>
62    struct OffsetAt<index, TypeList<Head, Res...>> {
63        static_assert(std::is_class<Head>::value);
64        static constexpr size_t OFFSET64 =
65            RoundUp(Head::SizeArch64, EAS) + OffsetAt<index - 1, TypeList<Res...>>::OFFSET64;
66
67        static constexpr size_t OFFSET32 =
68            RoundUp(Head::SizeArch32, EAS) + OffsetAt<index - 1, TypeList<Res...>>::OFFSET32;
69    };
70
71    template<size_t index>
72    static size_t GetOffset(bool isArch32)
73    {
74        return isArch32 ? OffsetAt<index, ElemTypeList>::OFFSET32
75                        : OffsetAt<index, ElemTypeList>::OFFSET64;
76    };
77
78    static constexpr size_t SizeArch32 = OffsetAt<NumOfTypes, ElemTypeList>::OFFSET32;
79    static constexpr size_t SizeArch64 = OffsetAt<NumOfTypes, ElemTypeList>::OFFSET64;
80};
81
82struct AlignedPointer {
83    static constexpr size_t SizeArch32 = sizeof(uint32_t);
84    static constexpr size_t SizeArch64 = sizeof(uint64_t);
85    static constexpr size_t Size()
86    {
87        return sizeof(uintptr_t);
88    }
89};
90
91struct AlignedSize {
92    static constexpr size_t SizeArch32 = sizeof(uint32_t);
93    static constexpr size_t SizeArch64 = sizeof(uint64_t);
94    static constexpr size_t Size()
95    {
96        return sizeof(uintptr_t);
97    }
98};
99
100struct AlignedUint64 {
101    static constexpr size_t SizeArch32 = sizeof(uint64_t);
102    static constexpr size_t SizeArch64 = sizeof(uint64_t);
103    static constexpr size_t Size()
104    {
105        return sizeof(uint64_t);
106    }
107};
108
109struct AlignedUint32 {
110    static constexpr size_t SizeArch32 = sizeof(uint32_t);
111    static constexpr size_t SizeArch64 = sizeof(uint32_t);
112    static constexpr size_t Size()
113    {
114        return sizeof(uint32_t);
115    }
116};
117
118struct AlignedUint8 {
119    static constexpr size_t SizeArch32 = sizeof(uint8_t);
120    static constexpr size_t SizeArch64 = sizeof(uint8_t);
121    static constexpr size_t Size()
122    {
123        return sizeof(uint8_t);
124    }
125};
126
127struct AlignedBool {
128    static constexpr size_t SizeArch32 = sizeof(bool);
129    static constexpr size_t SizeArch64 = sizeof(bool);
130    static constexpr size_t Size()
131    {
132        return sizeof(bool);
133    }
134};
135}
136#endif // ECMASCRIPT_BASE_ALIGNED_STRUCT_H
137