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 #ifndef PANDA_VERIFICATION_TYPE_TYPE_TYPE_H 17 #define PANDA_VERIFICATION_TYPE_TYPE_TYPE_H 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 ark::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 PandaString IntersectionToString(TypeSystem const *&tsys) const; 91 PandaString UnionToString(TypeSystem const *&tsys) const; 92 93 private: 94 static int constexpr INTERSECTION_TAG = 1; 95 static int constexpr UNION_TAG = 2; 96 97 static size_t constexpr BITS_FOR_SPAN_SIZE = 8; 98 // NOLINTNEXTLINE(hicpp-signed-bitwise) 99 static size_t constexpr SPAN_MASK = (1 << BITS_FOR_SPAN_SIZE) - 1; 100 // NOLINTNEXTLINE(hicpp-signed-bitwise) 101 static size_t constexpr MAX_SPAN_SIZE = (1 << BITS_FOR_SPAN_SIZE) - 1; 102 SpanSize(uintptr_t v)103 static size_t SpanSize(uintptr_t v) 104 { 105 return v & SPAN_MASK; 106 } 107 SpanIndex(uintptr_t v)108 static size_t SpanIndex(uintptr_t v) 109 { 110 return v >> BITS_FOR_SPAN_SIZE; 111 } 112 ConstructPayload(size_t spanSize,size_t spanIndex)113 static uintptr_t ConstructPayload(size_t spanSize, size_t spanIndex) 114 { 115 ASSERT(spanSize > 0); 116 ASSERT(spanSize <= MAX_SPAN_SIZE); 117 return (spanIndex << BITS_FOR_SPAN_SIZE) | spanSize; 118 } 119 120 public: 121 static Type FromTypeId(panda_file::Type::TypeId tid); 122 Bot()123 static Type Bot() 124 { 125 return Type {Builtin::BOT}; 126 } Top()127 static Type Top() 128 { 129 return Type {Builtin::TOP}; 130 } 131 IsNone()132 ALWAYS_INLINE bool IsNone() const 133 { 134 return content_ == 0; 135 } IsValid()136 ALWAYS_INLINE bool IsValid() const 137 { 138 return content_ != 0; 139 } IsBuiltin()140 ALWAYS_INLINE bool IsBuiltin() const 141 { 142 return IsValid() && content_ < Builtin::LAST; 143 } IsClass()144 ALWAYS_INLINE bool IsClass() const 145 { 146 return IsValid() && !IsBuiltin() && IsPointer(content_); 147 } IsIntersection()148 ALWAYS_INLINE bool IsIntersection() const 149 { 150 return IsNotPointer(content_) && GetTag(content_) == INTERSECTION_TAG; 151 } IsUnion()152 ALWAYS_INLINE bool IsUnion() const 153 { 154 return IsNotPointer(content_) && GetTag(content_) == UNION_TAG; 155 } 156 GetBuiltin()157 ALWAYS_INLINE Builtin GetBuiltin() const 158 { 159 ASSERT(IsBuiltin()); 160 return static_cast<Builtin>(content_); 161 } GetClass()162 ALWAYS_INLINE Class const *GetClass() const 163 { 164 ASSERT(IsClass()); 165 return reinterpret_cast<Class const *>(content_); 166 } 167 168 bool IsConsistent() const; 169 170 panda_file::Type::TypeId ToTypeId() const; 171 172 size_t GetTypeWidth() const; 173 174 Type GetArrayElementType(TypeSystem *tsys) const; 175 176 // Careful: span is invalidated whenever a new intersection or union is created. 177 Span<Type const> GetIntersectionMembers(TypeSystem const *tsys) const; 178 Span<Type const> GetUnionMembers(TypeSystem const *tsys) const; 179 180 private: 181 uintptr_t content_ {0}; 182 183 static Type IntersectSpans(Span<Type const> lhs, Span<Type const> rhs, TypeSystem *tsys); 184 185 friend bool IsSubtypeImpl(Type lhs, Type rhs, TypeSystem *tsys); 186 friend Type TpIntersection(Type lhs, Type rhs, TypeSystem *tsys); 187 friend Type TpUnion(Type lhs, Type rhs, TypeSystem *tsys); 188 friend struct std::hash<Type>; 189 friend bool operator==(Type lhs, Type rhs); 190 }; 191 192 ALWAYS_INLINE inline bool operator==(Type lhs, Type rhs) 193 { 194 return lhs.content_ == rhs.content_; 195 } 196 197 ALWAYS_INLINE inline bool operator!=(Type lhs, Type rhs) 198 { 199 return !(lhs == rhs); 200 } 201 202 ALWAYS_INLINE inline bool IsSubtype(Type lhs, Type rhs, TypeSystem *tsys) 203 { 204 return lhs == rhs || IsSubtypeImpl(lhs, rhs, tsys); 205 } 206 207 struct MethodSignature { 208 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 209 PandaVector<Type> args; 210 Type result; 211 // NOLINTEND(misc-non-private-member-variables-in-classes) 212 213 PandaString ToString(TypeSystem const *tsys) const 214 { 215 std::stringstream ss; 216 ss << "("; 217 bool first = true; 218 for (auto const &arg : args) { 219 if (first) { 220 first = false; 221 } else { 222 ss << ", "; 223 } 224 ss << arg.ToString(tsys); 225 } 226 ss << ") -> "; 227 ss << result.ToString(tsys); 228 return PandaString(ss.str()); 229 } 230 }; 231 232 } // namespace ark::verifier 233 234 namespace std { 235 template <> 236 struct hash<ark::verifier::Type> { 237 size_t operator()(ark::verifier::Type tp) const 238 { 239 return hash<uintptr_t>()(tp.content_); 240 } 241 }; 242 } // namespace std 243 244 #endif // PANDA_VERIFICATION_TYPE_TYPE_TYPE_H 245