• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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