• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef PANDA_VERIFIER_TYPE_TYPE_HPP
17 #define PANDA_VERIFIER_TYPE_TYPE_HPP
18 
19 #include "verification/util/mem.h"
20 
21 #include "macros.h"
22 #include "runtime/include/class.h"
23 #include "runtime/include/method.h"
24 
25 #include <variant>
26 
27 namespace panda::verifier {
28 class TypeSystem;
29 
30 class Type {
31     /* Invariant:
32        Intersections can only contain (builtins or classes).
33        Unions can only contain intersections or elementary types.
34        Top and Bot cannot be parts of intersections or unions.
35     */
36 public:
37     enum Builtin : size_t {
38         TOP = 1,
39         U1,
40         I8,
41         U8,
42         I16,
43         U16,
44         I32,
45         U32,
46         F32,
47         F64,
48         I64,
49         U64,
50         INTEGRAL8,
51         INTEGRAL16,
52         INTEGRAL32,
53         INTEGRAL64,
54         FLOAT32,
55         FLOAT64,
56         BITS32,
57         BITS64,
58         PRIMITIVE,
59         REFERENCE,
60         NULL_REFERENCE,
61         OBJECT,
62         TYPE_CLASS,
63         ARRAY,
64         BOT,
65 
66         LAST
67     };
68 
69 public:
70     Type() = default;
71     ~Type() = default;
72     DEFAULT_COPY_SEMANTIC(Type);
73     DEFAULT_MOVE_SEMANTIC(Type);
74 
Type(Builtin builtin)75     explicit Type(Builtin builtin) : content_ {builtin} {}
Type(Class const * klass)76     explicit Type(Class const *klass) : content_ {reinterpret_cast<uintptr_t>(klass)}
77     {
78         if (klass->IsPrimitive()) {
79             *this = FromTypeId(klass->GetType().GetId());
80         }
81     }
82 
83     PandaString ToString(TypeSystem const *tsys) const;
84 
85 private:
Type(uintptr_t content)86     explicit Type(uintptr_t content) : content_ {content} {}
87 
88     static Type Intersection(Span<Type> span, TypeSystem *tsys);
89     static Type Union(Span<Type> span, TypeSystem *tsys);
90 
91 private:
92     static int constexpr INTERSECTION_TAG = 1;
93     static int constexpr UNION_TAG = 2;
94 
95     static size_t constexpr BITS_FOR_SPAN_SIZE = 8;
96     // NOLINTNEXTLINE(hicpp-signed-bitwise)
97     static size_t constexpr SPAN_MASK = (1 << BITS_FOR_SPAN_SIZE) - 1;
98     // NOLINTNEXTLINE(hicpp-signed-bitwise)
99     static size_t constexpr MAX_SPAN_SIZE = (1 << BITS_FOR_SPAN_SIZE) - 1;
100 
SpanSize(uintptr_t v)101     static size_t SpanSize(uintptr_t v)
102     {
103         return v & SPAN_MASK;
104     }
105 
SpanIndex(uintptr_t v)106     static size_t SpanIndex(uintptr_t v)
107     {
108         return v >> BITS_FOR_SPAN_SIZE;
109     }
110 
ConstructPayload(size_t spanSize,size_t spanIndex)111     static uintptr_t ConstructPayload(size_t spanSize, size_t spanIndex)
112     {
113         ASSERT(spanSize > 0 && spanSize <= MAX_SPAN_SIZE);
114         return (spanIndex << BITS_FOR_SPAN_SIZE) | spanSize;
115     }
116 
117 public:
118     static Type FromTypeId(panda_file::Type::TypeId tid);
119 
Bot()120     static Type Bot()
121     {
122         return Type {Builtin::BOT};
123     }
Top()124     static Type Top()
125     {
126         return Type {Builtin::TOP};
127     }
128 
IsNone()129     ALWAYS_INLINE bool IsNone() const
130     {
131         return content_ == 0;
132     }
IsValid()133     ALWAYS_INLINE bool IsValid() const
134     {
135         return content_ != 0;
136     }
IsBuiltin()137     ALWAYS_INLINE bool IsBuiltin() const
138     {
139         return IsValid() && content_ < Builtin::LAST;
140     }
IsClass()141     ALWAYS_INLINE bool IsClass() const
142     {
143         return IsValid() && !IsBuiltin() && IsPointer(content_);
144     }
IsIntersection()145     ALWAYS_INLINE bool IsIntersection() const
146     {
147         return IsNotPointer(content_) && GetTag(content_) == INTERSECTION_TAG;
148     }
IsUnion()149     ALWAYS_INLINE bool IsUnion() const
150     {
151         return IsNotPointer(content_) && GetTag(content_) == UNION_TAG;
152     }
153 
GetBuiltin()154     ALWAYS_INLINE Builtin GetBuiltin() const
155     {
156         ASSERT(IsBuiltin());
157         return static_cast<Builtin>(content_);
158     }
GetClass()159     ALWAYS_INLINE Class const *GetClass() const
160     {
161         ASSERT(IsClass());
162         return reinterpret_cast<Class const *>(content_);
163     }
164 
165     bool IsConsistent() const;
166 
167     panda_file::Type::TypeId ToTypeId() const;
168 
169     size_t GetTypeWidth() const;
170 
171     Type GetArrayElementType(TypeSystem *tsys) const;
172 
173     // Careful: span is invalidated whenever a new intersection or union is created.
174     Span<Type const> GetIntersectionMembers(TypeSystem const *tsys) const;
175     Span<Type const> GetUnionMembers(TypeSystem const *tsys) const;
176 
177 private:
178     uintptr_t content_ {0};
179 
180     static Type IntersectSpans(Span<Type const> lhs, Span<Type const> rhs, TypeSystem *tsys);
181 
182     friend bool IsSubtypeImpl(Type lhs, Type rhs, TypeSystem *tsys);
183     friend Type TpIntersection(Type lhs, Type rhs, TypeSystem *tsys);
184     friend Type TpUnion(Type lhs, Type rhs, TypeSystem *tsys);
185     friend struct std::hash<Type>;
186     friend bool operator==(Type lhs, Type rhs);
187 };
188 
189 ALWAYS_INLINE inline bool operator==(Type lhs, Type rhs)
190 {
191     return lhs.content_ == rhs.content_;
192 }
193 
194 ALWAYS_INLINE inline bool operator!=(Type lhs, Type rhs)
195 {
196     return !(lhs == rhs);
197 }
198 
199 ALWAYS_INLINE inline bool IsSubtype(Type lhs, Type rhs, TypeSystem *tsys)
200 {
201     return lhs == rhs || IsSubtypeImpl(lhs, rhs, tsys);
202 }
203 
204 struct MethodSignature {
205     // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
206     PandaVector<Type> args;
207     Type result;
208     // NOLINTEND(misc-non-private-member-variables-in-classes)
209 
210     PandaString ToString(TypeSystem const *tsys) const
211     {
212         std::stringstream ss;
213         ss << "(";
214         bool first = true;
215         for (auto const &arg : args) {
216             if (first) {
217                 first = false;
218             } else {
219                 ss << ", ";
220             }
221             ss << arg.ToString(tsys);
222         }
223         ss << ") -> ";
224         ss << result.ToString(tsys);
225         return PandaString(ss.str());
226     }
227 };
228 
229 }  // namespace panda::verifier
230 
231 namespace std {
232 template <>
233 struct hash<panda::verifier::Type> {
234     size_t operator()(panda::verifier::Type tp) const
235     {
236         return hash<uintptr_t>()(tp.content_);
237     }
238 };
239 }  // namespace std
240 
241 #endif  // !PANDA_VERIFIER_TYPE_TYPE_HPP
242