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 private:
90 template <typename Str = std::string>
91 static void AppendType(const uint8_t *descriptor, int rank, Str &result);
92
93 template <typename Str = std::string>
94 static void AppendNonPrimitiveType(const uint8_t *descriptor, int rank, Str &result);
95 };
96
97 // Str is std::string or PandaString
98 /* static */
99 template <typename Str>
GetName(const uint8_t * descriptor)100 Str ClassHelper::GetName(const uint8_t *descriptor)
101 {
102 switch (*descriptor) {
103 case 'V':
104 return "void";
105 case 'Z':
106 return "u1";
107 case 'B':
108 return "i8";
109 case 'H':
110 return "u8";
111 case 'S':
112 return "i16";
113 case 'C':
114 return "u16";
115 case 'I':
116 return "i32";
117 case 'U':
118 return "u32";
119 case 'J':
120 return "i64";
121 case 'Q':
122 return "u64";
123 case 'F':
124 return "f32";
125 case 'D':
126 return "f64";
127 case 'A':
128 return "any";
129 default: {
130 break;
131 }
132 }
133
134 Str name = utf::Mutf8AsCString(descriptor);
135 if (name[0] == '[') {
136 return name;
137 }
138
139 std::replace(name.begin(), name.end(), '/', '.');
140
141 ASSERT(name.size() > 2); // 2 - L and ;
142
143 name.erase(0, 1);
144 name.pop_back();
145
146 return name;
147 }
148
149 // Str is std::string or PandaString
150 /* static */
151 template <typename Str>
GetNameUndecorated(const uint8_t * descriptor)152 Str ClassHelper::GetNameUndecorated(const uint8_t *descriptor)
153 {
154 Str result;
155
156 auto rank = 0;
157 while (descriptor[rank] == '[') { // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
158 rank++;
159 }
160
161 AppendType(descriptor, rank, result);
162
163 while (rank > 0) {
164 result.append("[]");
165 rank--;
166 }
167
168 return result;
169 }
170
171 // Str is std::string or PandaString
172 /* static */
173 template <typename Str>
AppendType(const uint8_t * descriptor,int rank,Str & result)174 void ClassHelper::AppendType(const uint8_t *descriptor, int rank, Str &result)
175 {
176 switch (descriptor[rank]) { // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
177 case 'V':
178 result.append("void");
179 break;
180 case 'Z':
181 result.append("u1");
182 break;
183 case 'B':
184 result.append("i8");
185 break;
186 case 'H':
187 result.append("u8");
188 break;
189 case 'S':
190 result.append("i16");
191 break;
192 case 'C':
193 result.append("u16");
194 break;
195 case 'I':
196 result.append("i32");
197 break;
198 case 'U':
199 result.append("u32");
200 break;
201 case 'J':
202 result.append("i64");
203 break;
204 case 'Q':
205 result.append("u64");
206 break;
207 case 'F':
208 result.append("f32");
209 break;
210 case 'D':
211 result.append("f64");
212 break;
213 case 'A':
214 result.append("any");
215 break;
216 case 'L':
217 AppendNonPrimitiveType(descriptor, rank, result);
218 break;
219 default:
220 break;
221 }
222 }
223
224 // Str is std::string or PandaString
225 /* static */
226 template <typename Str>
AppendNonPrimitiveType(const uint8_t * descriptor,int rank,Str & result)227 void ClassHelper::AppendNonPrimitiveType(const uint8_t *descriptor, int rank, Str &result)
228 {
229 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
230 result.append(utf::Mutf8AsCString(descriptor + rank + 1)); // cut 'L' at the beginning
231 ASSERT(result.size() > 0);
232 result.pop_back(); // cut ';' at the end
233
234 std::replace(result.begin(), result.end(), '/', '.');
235 }
236
237 } // namespace ark
238
239 #endif // PANDA_RUNTIME_KLASS_HELPER_H_
240