1 /**
2 * Copyright (c) 2021-2024 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 #ifndef PANDA_RUNTIME_KLASS_HELPER_H_
16 #define PANDA_RUNTIME_KLASS_HELPER_H_
17
18 #include <cstdint>
19
20 #include "libpandabase/utils/span.h"
21 #include "libpandafile/file_items.h"
22 #include "runtime/include/coretypes/tagged_value.h"
23 #include "runtime/include/mem/panda_string.h"
24 #include "runtime/object_header_config.h"
25
26 namespace ark {
27
28 // Small helper
29 template <class Config>
30 class ClassConfig {
31 public:
32 using ClassWordSize = typename Config::Size;
33 };
34
35 class ClassHelper : private ClassConfig<MemoryModelConfig> {
36 public:
37 using ClassWordSize = typename ClassConfig::ClassWordSize; // To be visible outside
38
39 static constexpr size_t OBJECT_POINTER_SIZE = sizeof(ClassWordSize);
40 // In general for any T: sizeof(T*) != OBJECT_POINTER_SIZE
41 static constexpr size_t POINTER_SIZE = sizeof(uintptr_t);
42
43 PANDA_PUBLIC_API static const uint8_t *GetDescriptor(const uint8_t *name, PandaString *storage);
44
45 static const uint8_t *GetTypeDescriptor(const PandaString &name, PandaString *storage);
46
47 static const uint8_t *GetArrayDescriptor(const uint8_t *componentName, size_t rank, PandaString *storage);
48
49 static char GetPrimitiveTypeDescriptorChar(panda_file::Type::TypeId typeId);
50
51 static const uint8_t *GetPrimitiveTypeDescriptorStr(panda_file::Type::TypeId typeId);
52
53 static const char *GetPrimitiveTypeStr(panda_file::Type::TypeId typeId);
54
55 static const uint8_t *GetPrimitiveDescriptor(panda_file::Type type, PandaString *storage);
56
57 static const uint8_t *GetPrimitiveArrayDescriptor(panda_file::Type type, size_t rank, PandaString *storage);
58
59 template <typename Str = std::string>
60 static Str GetName(const uint8_t *descriptor);
61
62 template <typename Str = std::string>
63 static Str GetNameUndecorated(const uint8_t *descriptor);
64
IsArrayDescriptor(const uint8_t * descriptor)65 static bool IsArrayDescriptor(const uint8_t *descriptor)
66 {
67 Span<const uint8_t> sp(descriptor, 1);
68 return sp[0] == '[';
69 }
70
GetComponentDescriptor(const uint8_t * descriptor)71 static const uint8_t *GetComponentDescriptor(const uint8_t *descriptor)
72 {
73 ASSERT(IsArrayDescriptor(descriptor));
74 Span<const uint8_t> sp(descriptor, 1);
75 return sp.cend();
76 }
77
GetDimensionality(const uint8_t * descriptor)78 static size_t GetDimensionality(const uint8_t *descriptor)
79 {
80 ASSERT(IsArrayDescriptor(descriptor));
81 size_t dim = 0;
82 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
83 while (*descriptor++ == '[') {
84 ++dim;
85 }
86 return dim;
87 }
88 };
89
90 // Str is std::string or PandaString
91 /* static */
92 template <typename Str>
GetName(const uint8_t * descriptor)93 Str ClassHelper::GetName(const uint8_t *descriptor)
94 {
95 switch (*descriptor) {
96 case 'V':
97 return "void";
98 case 'Z':
99 return "u1";
100 case 'B':
101 return "i8";
102 case 'H':
103 return "u8";
104 case 'S':
105 return "i16";
106 case 'C':
107 return "u16";
108 case 'I':
109 return "i32";
110 case 'U':
111 return "u32";
112 case 'J':
113 return "i64";
114 case 'Q':
115 return "u64";
116 case 'F':
117 return "f32";
118 case 'D':
119 return "f64";
120 case 'A':
121 return "any";
122 default: {
123 break;
124 }
125 }
126
127 Str name = utf::Mutf8AsCString(descriptor);
128 if (name[0] == '[') {
129 return name;
130 }
131
132 std::replace(name.begin(), name.end(), '/', '.');
133
134 ASSERT(name.size() > 2); // 2 - L and ;
135
136 name.erase(0, 1);
137 name.pop_back();
138
139 return name;
140 }
141
142 // Str is std::string or PandaString
143 /* static */
144 template <typename Str>
GetNameUndecorated(const uint8_t * descriptor)145 Str ClassHelper::GetNameUndecorated(const uint8_t *descriptor)
146 {
147 Str result;
148
149 auto rank = 0;
150 while (descriptor[rank] == '[') { // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
151 rank++;
152 }
153
154 switch (descriptor[rank]) { // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
155 case 'V':
156 result.append("void");
157 break;
158 case 'Z':
159 result.append("u1");
160 break;
161 case 'B':
162 result.append("i8");
163 break;
164 case 'H':
165 result.append("u8");
166 break;
167 case 'S':
168 result.append("i16");
169 break;
170 case 'C':
171 result.append("u16");
172 break;
173 case 'I':
174 result.append("i32");
175 break;
176 case 'U':
177 result.append("u32");
178 break;
179 case 'J':
180 result.append("i64");
181 break;
182 case 'Q':
183 result.append("u64");
184 break;
185 case 'F':
186 result.append("f32");
187 break;
188 case 'D':
189 result.append("f64");
190 break;
191 case 'A':
192 result.append("any");
193 break;
194 case 'L':
195 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
196 result.append(utf::Mutf8AsCString(descriptor + rank + 1)); // cut 'L' at the beginning
197 ASSERT(result.size() > 0);
198 result.pop_back(); // cut ';' at the end
199
200 std::replace(result.begin(), result.end(), '/', '.');
201
202 break;
203 default:
204 break;
205 }
206
207 while (rank > 0) {
208 result.append("[]");
209 rank--;
210 }
211
212 return result;
213 }
214
215 } // namespace ark
216
217 #endif // PANDA_RUNTIME_KLASS_HELPER_H_
218