1 /*
2 * Copyright (c) 2021-2023 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 panda::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 if (!ignorePrimitive) {
51 auto iter = pandaTypes.find(name);
52 if (iter == pandaTypes.end()) {
53 return panda_file::Type::TypeId::REFERENCE;
54 }
55 return iter->second;
56 }
57
58 return panda_file::Type::TypeId::REFERENCE;
59 }
60
61 /* static */
FromPrimitiveId(panda_file::Type::TypeId id)62 pandasm::Type Type::FromPrimitiveId(panda_file::Type::TypeId id)
63 {
64 static std::unordered_map<panda_file::Type::TypeId, std::string_view> pandaTypes = {
65 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
66 #define PANDATYPE(name, inst_code) {panda_file::Type::TypeId::inst_code, std::string_view(name)},
67 PANDA_ASSEMBLER_TYPES(PANDATYPE)
68 #undef PANDATYPE
69 };
70 auto iter = pandaTypes.find(id);
71 ASSERT(iter != pandaTypes.end());
72 pandasm::Type ret {iter->second, 0};
73 ASSERT(ret.typeId_ == id);
74 return ret;
75 }
76
77 /* static */
GetName(std::string_view componentName,size_t rank)78 std::string Type::GetName(std::string_view componentName, size_t rank)
79 {
80 std::string name(componentName);
81 while (rank-- > 0) {
82 name += "[]";
83 }
84 return name;
85 }
86
87 /* static */
FromDescriptor(std::string_view descriptor)88 Type Type::FromDescriptor(std::string_view descriptor)
89 {
90 static std::unordered_map<std::string_view, std::string_view> reversePrimitiveTypes = {
91 {"Z", "u1"}, {"B", "i8"}, {"H", "u8"}, {"S", "i16"}, {"C", "u16"}, {"I", "i32"}, {"U", "u32"},
92 {"F", "f32"}, {"D", "f64"}, {"J", "i64"}, {"Q", "u64"}, {"V", "void"}, {"A", "any"}};
93
94 size_t i = 0;
95 while (descriptor[i] == '[') {
96 ++i;
97 }
98
99 size_t rank = i;
100 bool isRefType = descriptor[i] == 'L';
101 if (isRefType) {
102 descriptor.remove_suffix(1); /* Remove semicolon */
103 ++i;
104 }
105
106 descriptor.remove_prefix(i);
107
108 if (isRefType) {
109 return Type(descriptor, rank);
110 }
111
112 return Type(reversePrimitiveTypes[descriptor], rank);
113 }
114
115 /* static */
FromName(std::string_view name,bool ignorePrimitive)116 Type Type::FromName(std::string_view name, bool ignorePrimitive)
117 {
118 constexpr size_t STEP = 2;
119
120 size_t size = name.size();
121 size_t i = 0;
122
123 while (name[size - i - 1] == ']') {
124 i += STEP;
125 }
126
127 name.remove_suffix(i);
128
129 return Type(name, i / STEP, ignorePrimitive);
130 }
131
132 /* static */
IsStringType(const std::string & name,panda::panda_file::SourceLang lang)133 bool Type::IsStringType(const std::string &name, panda::panda_file::SourceLang lang)
134 {
135 auto stringType = Type::FromDescriptor(panda::panda_file::GetStringClassDescriptor(lang));
136 return name == stringType.GetName();
137 }
138
139 /* static */
IsPandaPrimitiveType(const std::string & name)140 bool Type::IsPandaPrimitiveType(const std::string &name)
141 {
142 auto it = g_primitiveTypes.find(name);
143 return it != g_primitiveTypes.cend();
144 }
145
146 } // namespace panda::pandasm
147