1 /*
2 * Copyright (c) 2021 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 "panda_types.h"
17
18 #include "runtime/include/class_linker.h"
19 #include "runtime/include/method.h"
20 #include "runtime/include/method-inl.h"
21 #include "runtime/include/class.h"
22 #include "runtime/include/runtime.h"
23
24 #include "utils/span.h"
25 #include "verification/type/type_system.h"
26 #include "verification/type/type_sort.h"
27 #include "verification/type/type_image.h"
28 #include "verification/job_queue/cache.h"
29
30 #include "verification/type/type_params_inl.h"
31
32 #include "verifier_messages.h"
33
34 #include "utils/logger.h"
35
36 #include "runtime/include/mem/panda_containers.h"
37 #include "runtime/include/mem/panda_string.h"
38
39 #include "libpandabase/os/mutex.h"
40
41 namespace panda::verifier {
42
NormalizedTypeOf(Type type)43 Type PandaTypes::NormalizedTypeOf(Type type)
44 {
45 ASSERT(type.IsValid());
46 if (type.IsBot() || type.IsTop()) {
47 return type;
48 }
49 auto t = NormalizedTypeOf_.find(type);
50 if (t != NormalizedTypeOf_.cend()) {
51 return t->second;
52 }
53 Type result = type;
54 if (type <= Integral32Type()) {
55 result = Normalize()(~Integral32Type());
56 NormalizedTypeOf_[type] = result;
57 } else if (type <= Integral64Type()) {
58 result = Normalize()(~Integral64Type());
59 NormalizedTypeOf_[type] = result;
60 // NOLINTNEXTLINE(bugprone-branch-clone)
61 } else if (type <= F32()) {
62 result = Normalize()(~F64());
63 NormalizedTypeOf_[type] = result;
64 } else if (type <= F64()) {
65 result = Normalize()(~F64());
66 NormalizedTypeOf_[type] = result;
67 } else if (type <= MethodType()) {
68 result = NormalizedMethod()(NormalizeMethodSignature(type.Params()));
69 }
70 NormalizedTypeOf_[type] = result;
71 return result;
72 }
73
NormalizeMethodSignature(const TypeParams & sig)74 TypeParams PandaTypes::NormalizeMethodSignature(const TypeParams &sig)
75 {
76 TypeParams result {kind_};
77 sig.ForEach([&result, this](const auto ¶m) {
78 const Type &type = param;
79 result >> (NormalizedTypeOf(type) * param.Variance());
80 });
81 return result;
82 }
83
NormalizedMethodSignature(const PandaTypes::CachedMethod & method)84 const TypeParams &PandaTypes::NormalizedMethodSignature(const PandaTypes::CachedMethod &method)
85 {
86 auto &&method_id = method.id;
87 auto it = NormalizedSigOfMethod_.find(method_id);
88 if (it != NormalizedSigOfMethod_.end()) {
89 return it->second;
90 }
91 auto &&sig = MethodSignature(method);
92 auto &&normalized_sig = NormalizeMethodSignature(sig);
93 NormalizedSigOfMethod_[method_id] = normalized_sig;
94 return NormalizedSigOfMethod_[method_id];
95 }
96
MethodSignature(const PandaTypes::CachedMethod & method)97 const TypeParams &PandaTypes::MethodSignature(const PandaTypes::CachedMethod &method)
98 {
99 auto &&method_id = method.id;
100 auto it = SigOfMethod_.find(method_id);
101 if (it != SigOfMethod_.end()) {
102 return it->second;
103 }
104 TypeParams params {kind_};
105 Type return_type;
106 bool return_is_processed = false;
107 for (const auto &arg : method.signature) {
108 Type t;
109 if (CacheOfRuntimeThings::IsRef(arg)) {
110 const auto &cached_class = CacheOfRuntimeThings::GetRef(arg);
111 if (cached_class.type_id == TypeId::VOID) {
112 t = Top();
113 } else {
114 t = TypeOf(cached_class);
115 }
116 } else if (CacheOfRuntimeThings::IsDescriptor(arg)) {
117 LOG_VERIFIER_JAVA_TYPES_METHOD_ARG_WAS_NOT_RESOLVED(method.GetName());
118 t = Top();
119 } else {
120 LOG_VERIFIER_JAVA_TYPES_METHOD_ARG_CANNOT_BE_PROCESSED(method.GetName());
121 t = Top();
122 }
123 if (!t.IsValid()) {
124 LOG_VERIFIER_JAVA_TYPES_METHOD_ARG_CANNOT_BE_CONVERTED_TO_TYPE(method.GetName());
125 }
126 if (return_is_processed) {
127 params >> -t;
128 } else {
129 return_type = t;
130 return_is_processed = true;
131 }
132 }
133 params >> +return_type;
134 SigOfMethod_[method_id] = params;
135 return SigOfMethod_[method_id];
136 }
137
TypeIdOf(const Type & type) const138 PandaTypes::TypeId PandaTypes::TypeIdOf(const Type &type) const
139 {
140 std::vector<std::pair<Type, PandaTypes::TypeId>> types_table = {
141 {U1_, TypeId::U1}, {U8_, TypeId::U8}, {U16_, TypeId::U16}, {U32_, TypeId::U32},
142 {U64_, TypeId::U64}, {I8_, TypeId::I8}, {I16_, TypeId::I16}, {I32_, TypeId::I32},
143 {I64_, TypeId::I64}, {F32_, TypeId::F32}, {F64_, TypeId::F64}, {RefType_, TypeId::REFERENCE}};
144
145 for (const auto &val : types_table) {
146 if (val.first == type) {
147 return val.second;
148 }
149 }
150
151 if (type.IsTop()) {
152 return TypeId::VOID;
153 }
154
155 return TypeId::INVALID;
156 }
157
TypeOf(const PandaTypes::CachedMethod & method)158 Type PandaTypes::TypeOf(const PandaTypes::CachedMethod &method)
159 {
160 auto id = method.id;
161 auto k = TypeOfMethod_.find(id);
162 if (k != TypeOfMethod_.end()) {
163 return k->second;
164 }
165 ASSERT(!DoNotCalculateMethodType_);
166 auto &&sig = MethodSignature(method);
167 auto &&norm_sig = NormalizedMethodSignature(method);
168 Type type;
169 type = Method()(sig);
170 type << MethodType();
171 TypeOfMethod_[id] = type;
172 // Normalize(Method) <: NormalizedMethod(NormalizedMethodSig)
173 auto norm_type = Normalize()(~type);
174 auto norm_method = NormalizedMethod()(norm_sig);
175 norm_type << norm_method;
176 NormalizedTypeOf_[type] = norm_method;
177 MethodNameOfId_[id] = method.GetName();
178 return type;
179 }
180
SetArraySubtyping(const Type & t)181 void PandaTypes::SetArraySubtyping(const Type &t)
182 {
183 PandaVector<Type> to_process;
184 PandaVector<Type> just_subtype;
185 t.ForAllSupertypes([&]([[maybe_unused]] const Type &st) {
186 if (!Array()[+st]) {
187 to_process.emplace_back(st);
188 } else {
189 just_subtype.emplace_back(st);
190 }
191 return true;
192 });
193 auto array_type = Array()(+t);
194 for (const auto &st : just_subtype) {
195 array_type << Array()(+st);
196 }
197 for (const auto &st : to_process) {
198 array_type << Array()(+st);
199 SetArraySubtyping(st);
200 }
201 }
202
TypeOfArray(const PandaTypes::CachedClass & klass)203 Type PandaTypes::TypeOfArray(const PandaTypes::CachedClass &klass)
204 {
205 ASSERT(klass.flags[CachedClass::Flag::ARRAY_CLASS]);
206
207 Type type;
208 const auto &component = klass.GetArrayComponent();
209 if (!Valid(component)) {
210 type = Array()(+Top());
211 LOG_VERIFIER_JAVA_TYPES_ARRAY_COMPONENT_TYPE_IS_UNDEFINED();
212 } else {
213 auto component_type = TypeOf(component);
214 type = Array()(+component_type);
215 SetArraySubtyping(component_type);
216 }
217 type << ArrayType();
218 if (klass.flags[CachedClass::Flag::OBJECT_ARRAY_CLASS]) {
219 type << ObjectArrayType();
220 }
221
222 return type;
223 }
224
TypeOf(const PandaTypes::CachedClass & klass)225 Type PandaTypes::TypeOf(const PandaTypes::CachedClass &klass)
226 {
227 auto id = klass.id;
228 auto k = TypeOfClass_.find(id);
229 if (k != TypeOfClass_.end()) {
230 return k->second;
231 }
232
233 PandaVector<Type> supertypes;
234 for (const auto &ancestor : klass.ancestors) {
235 // ancestor here cannot be unresolved descriptor
236 ASSERT(CacheOfRuntimeThings::IsRef(ancestor));
237 supertypes.emplace_back(TypeOf(CacheOfRuntimeThings::GetRef(ancestor)));
238 }
239
240 Type type;
241 bool is_primitive = klass.flags[CachedClass::Flag::PRIMITIVE];
242 bool is_string = klass.flags[CachedClass::Flag::STRING_CLASS];
243
244 auto class_name = klass.GetName();
245
246 if (klass.flags[CachedClass::Flag::ARRAY_CLASS]) {
247 type = TypeOfArray(klass);
248 } else if (!is_primitive) {
249 type = TypeSystem_.Parametric(GetSort(class_name))();
250 } else {
251 type = TypeOf(klass.type_id);
252 }
253
254 if (!is_primitive) {
255 if (!is_string) {
256 type << ObjectType();
257 } else {
258 type << StringType();
259 }
260 NullRefType() << type << RefType();
261 TypeClass()(~type) << TypeClassType() << RefType();
262 }
263 if (klass.flags[CachedClass::Flag::ABSTRACT]) {
264 Abstract()(~type) << AbstractType();
265 }
266 for (auto &super : supertypes) {
267 type << super;
268 }
269 ClassNameOfId_[id] = class_name;
270 TypeOfClass_[id] = type;
271 NormalizedTypeOf(type);
272 return type;
273 }
274
TypeOf(PandaTypes::TypeId id) const275 Type PandaTypes::TypeOf(PandaTypes::TypeId id) const
276 {
277 if (id == TypeId::VOID) {
278 return Top();
279 }
280
281 std::vector<std::pair<Type, PandaTypes::TypeId>> types_table = {
282 {U1_, TypeId::U1}, {U8_, TypeId::U8}, {U16_, TypeId::U16}, {U32_, TypeId::U32},
283 {U64_, TypeId::U64}, {I8_, TypeId::I8}, {I16_, TypeId::I16}, {I32_, TypeId::I32},
284 {I64_, TypeId::I64}, {F32_, TypeId::F32}, {F64_, TypeId::F64}, {RefType_, TypeId::REFERENCE}};
285
286 for (const auto &val : types_table) {
287 if (val.second == id) {
288 return val.first;
289 }
290 }
291
292 LOG_VERIFIER_JAVA_TYPES_CANNOT_CONVERT_TYPE_ID_TO_TYPE(id);
293 return Top();
294 }
295
Init()296 void PandaTypes::Init()
297 {
298 TypeSystem_.SetIncrementalRelationClosureMode(false);
299
300 // base subtyping of primitive types
301 I8() << I16() << I32();
302 U1() << U8() << U16() << U32();
303 F32() << F64();
304 // integral
305 (U1() | I8() | U8()) << Integral8Type();
306 (Integral8Type() | I16() | U16()) << Integral16Type();
307 (Integral16Type() | I32() | U32()) << Integral32Type();
308 (I64() | U64()) << Integral64Type();
309 // sizes
310 F32() << (Float32Type() | F64()) << Float64Type();
311 (Integral32Type() | Float32Type()) << Bits32Type();
312 (Integral64Type() | Float64Type()) << Bits64Type();
313 (Bits32Type() | Bits64Type()) << PrimitiveType();
314
315 TypeClassType() << RefType();
316 NullRefType() << (PandaClass() | PandaObject() | JavaObject() | JavaClass() | JavaThrowable())
317 << (ObjectType() | RefType());
318 NullRefType() << (ArrayType() | ObjectArrayType()) << RefType();
319 TypeClass()(~PandaObject()) << TypeClassType();
320 TypeClass()(~JavaObject()) << TypeClassType();
321
322 TypeSystem_.CloseSubtypingRelation();
323
324 TypeSystem_.SetIncrementalRelationClosureMode(false);
325 TypeSystem_.SetDeferIncrementalRelationClosure(false);
326 }
327
328 } // namespace panda::verifier
329