1 /**
2 * Copyright (c) 2021-2022 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 static std::unordered_map<std::string_view, std::string_view> primitive_types = {
23 {"u1", "Z"}, {"i8", "B"}, {"u8", "H"}, {"i16", "S"}, {"u16", "C"}, {"i32", "I"}, {"u32", "U"},
24 {"f32", "F"}, {"f64", "D"}, {"i64", "J"}, {"u64", "Q"}, {"void", "V"}, {"any", "A"}};
25
GetDescriptor(bool ignore_primitive) const26 std::string Type::GetDescriptor(bool ignore_primitive) const
27 {
28 if (!ignore_primitive) {
29 auto it = primitive_types.find(component_name_);
30 if (it != primitive_types.cend()) {
31 return std::string(rank_, '[') + it->second.data();
32 }
33 }
34
35 std::string res = std::string(rank_, '[') + "L" + component_name_ + ";";
36 return res;
37 }
38
39 /* static */
GetId(std::string_view name,bool ignore_primitive)40 panda_file::Type::TypeId Type::GetId(std::string_view name, bool ignore_primitive)
41 {
42 static std::unordered_map<std::string_view, panda_file::Type::TypeId> panda_types = {
43 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
44 #define PANDATYPE(name, inst_code) {std::string_view(name), panda_file::Type::TypeId::inst_code},
45 PANDA_ASSEMBLER_TYPES(PANDATYPE)
46 #undef PANDATYPE
47 };
48
49 if (!ignore_primitive) {
50 auto iter = panda_types.find(name);
51
52 if (iter == panda_types.end()) {
53 return panda_file::Type::TypeId::REFERENCE;
54 }
55 return iter->second;
56 } else {
57 return panda_file::Type::TypeId::REFERENCE;
58 }
59 }
60
61 /* static */
GetName(std::string_view component_name,size_t rank)62 std::string Type::GetName(std::string_view component_name, size_t rank)
63 {
64 std::string name(component_name);
65 while (rank-- > 0) {
66 name += "[]";
67 }
68 return name;
69 }
70
71 /* static */
FromDescriptor(std::string_view descriptor)72 Type Type::FromDescriptor(std::string_view descriptor)
73 {
74 static std::unordered_map<std::string_view, std::string_view> reverse_primitive_types = {
75 {"Z", "u1"}, {"B", "i8"}, {"H", "u8"}, {"S", "i16"}, {"C", "u16"}, {"I", "i32"}, {"U", "u32"},
76 {"F", "f32"}, {"D", "f64"}, {"J", "i64"}, {"Q", "u64"}, {"V", "void"}, {"A", "any"}};
77
78 size_t i = 0;
79 while (descriptor[i] == '[') {
80 ++i;
81 }
82
83 size_t rank = i;
84 bool is_ref_type = descriptor[i] == 'L';
85 if (is_ref_type) {
86 descriptor.remove_suffix(1); /* Remove semicolon */
87 ++i;
88 }
89
90 descriptor.remove_prefix(i);
91
92 if (is_ref_type) {
93 return Type(descriptor, rank);
94 }
95
96 return Type(reverse_primitive_types[descriptor], rank);
97 }
98
99 /* static */
FromName(std::string_view name,bool ignore_primitive)100 Type Type::FromName(std::string_view name, bool ignore_primitive)
101 {
102 constexpr size_t STEP = 2;
103
104 size_t size = name.size();
105 size_t i = 0;
106
107 while (name[size - i - 1] == ']') {
108 i += STEP;
109 }
110
111 name.remove_suffix(i);
112
113 return Type(name, i / STEP, ignore_primitive);
114 }
115
116 /* static */
IsStringType(const std::string & name,panda::panda_file::SourceLang lang)117 bool Type::IsStringType(const std::string &name, panda::panda_file::SourceLang lang)
118 {
119 auto string_type = Type::FromDescriptor(panda::panda_file::GetStringClassDescriptor(lang));
120 if (name == string_type.GetName()) {
121 return true;
122 } else {
123 return false;
124 }
125 }
126
127 /* static */
IsPandaPrimitiveType(const std::string & name)128 bool Type::IsPandaPrimitiveType(const std::string &name)
129 {
130 auto it = primitive_types.find(name);
131 if (it != primitive_types.cend()) {
132 return true;
133 } else {
134 return false;
135 }
136 }
137
138 } // namespace panda::pandasm
139