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
16 #include <unordered_map>
17
18 #include "assembly-type.h"
19
20 namespace ark::pandasm {
21
22 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
23 static std::unordered_map<std::string_view, std::string_view> g_primitiveTypes = {
24 {"u1", "Z"}, {"i8", "B"}, {"u8", "H"}, {"i16", "S"}, {"u16", "C"}, {"i32", "I"}, {"u32", "U"},
25 {"f32", "F"}, {"f64", "D"}, {"i64", "J"}, {"u64", "Q"}, {"void", "V"}, {"any", "A"}};
26
GetDescriptor(bool ignorePrimitive) const27 std::string Type::GetDescriptor(bool ignorePrimitive) const
28 {
29 if (!ignorePrimitive) {
30 auto it = g_primitiveTypes.find(componentName_);
31 if (it != g_primitiveTypes.cend()) {
32 return std::string(rank_, '[') + it->second.data();
33 }
34 }
35
36 std::string res = std::string(rank_, '[') + "L" + componentName_ + ";";
37 std::replace(res.begin(), res.end(), '.', '/');
38 return res;
39 }
40
41 /* static */
GetId(std::string_view name,bool ignorePrimitive)42 panda_file::Type::TypeId Type::GetId(std::string_view name, bool ignorePrimitive)
43 {
44 static std::unordered_map<std::string_view, panda_file::Type::TypeId> pandaTypes = {
45 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
46 #define PANDATYPE(name, inst_code) {std::string_view(name), panda_file::Type::TypeId::inst_code},
47 PANDA_ASSEMBLER_TYPES(PANDATYPE)
48 #undef PANDATYPE
49 };
50
51 if (!ignorePrimitive) {
52 auto iter = pandaTypes.find(name);
53 if (iter == pandaTypes.end()) {
54 return panda_file::Type::TypeId::REFERENCE;
55 }
56 return iter->second;
57 }
58
59 return panda_file::Type::TypeId::REFERENCE;
60 }
61
62 /* static */
FromPrimitiveId(panda_file::Type::TypeId id)63 pandasm::Type Type::FromPrimitiveId(panda_file::Type::TypeId id)
64 {
65 static std::unordered_map<panda_file::Type::TypeId, std::string_view> pandaTypes = {
66 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
67 #define PANDATYPE(name, inst_code) {panda_file::Type::TypeId::inst_code, std::string_view(name)},
68 PANDA_ASSEMBLER_TYPES(PANDATYPE)
69 #undef PANDATYPE
70 };
71 auto iter = pandaTypes.find(id);
72 ASSERT(iter != pandaTypes.end());
73 pandasm::Type ret {iter->second, 0};
74 ASSERT(ret.typeId_ == id);
75 return ret;
76 }
77
78 /* static */
GetName(std::string_view componentName,size_t rank)79 std::string Type::GetName(std::string_view componentName, size_t rank)
80 {
81 std::string name(componentName);
82 while (rank-- > 0) {
83 name += "[]";
84 }
85 return name;
86 }
87
88 /* static */
FromDescriptor(std::string_view descriptor)89 Type Type::FromDescriptor(std::string_view descriptor)
90 {
91 static std::unordered_map<std::string_view, std::string_view> reversePrimitiveTypes = {
92 {"Z", "u1"}, {"B", "i8"}, {"H", "u8"}, {"S", "i16"}, {"C", "u16"}, {"I", "i32"}, {"U", "u32"},
93 {"F", "f32"}, {"D", "f64"}, {"J", "i64"}, {"Q", "u64"}, {"V", "void"}, {"A", "any"}};
94
95 size_t i = 0;
96 while (descriptor[i] == '[') {
97 ++i;
98 }
99
100 size_t rank = i;
101 bool isRefType = descriptor[i] == 'L';
102 if (isRefType) {
103 descriptor.remove_suffix(1); /* Remove semicolon */
104 ++i;
105 }
106
107 descriptor.remove_prefix(i);
108
109 if (isRefType) {
110 return Type(descriptor, rank);
111 }
112
113 return Type(reversePrimitiveTypes[descriptor], rank);
114 }
115
116 /* static */
FromName(std::string_view name,bool ignorePrimitive)117 Type Type::FromName(std::string_view name, bool ignorePrimitive)
118 {
119 constexpr size_t STEP = 2;
120
121 size_t size = name.size();
122 size_t i = 0;
123
124 while (name[size - i - 1] == ']') {
125 i += STEP;
126 }
127
128 name.remove_suffix(i);
129
130 return Type(name, i / STEP, ignorePrimitive);
131 }
132
133 /* static */
IsStringType(const std::string & name,ark::panda_file::SourceLang lang)134 bool Type::IsStringType(const std::string &name, ark::panda_file::SourceLang lang)
135 {
136 auto stringType = Type::FromDescriptor(ark::panda_file::GetStringClassDescriptor(lang));
137 return name == stringType.GetName();
138 }
139
140 /* static */
IsPandaPrimitiveType(const std::string & name)141 bool Type::IsPandaPrimitiveType(const std::string &name)
142 {
143 auto it = g_primitiveTypes.find(name);
144 return it != g_primitiveTypes.cend();
145 }
146
147 } // namespace ark::pandasm
148