1 // Copyright 2017 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_TORQUE_TYPES_H_ 6 #define V8_TORQUE_TYPES_H_ 7 8 #include <algorithm> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "src/base/optional.h" 14 #include "src/torque/utils.h" 15 16 namespace v8 { 17 namespace internal { 18 namespace torque { 19 20 static const char* const CONSTEXPR_TYPE_PREFIX = "constexpr "; 21 static const char* const NEVER_TYPE_STRING = "never"; 22 static const char* const CONSTEXPR_BOOL_TYPE_STRING = "constexpr bool"; 23 static const char* const BOOL_TYPE_STRING = "bool"; 24 static const char* const VOID_TYPE_STRING = "void"; 25 static const char* const ARGUMENTS_TYPE_STRING = "constexpr Arguments"; 26 static const char* const CONTEXT_TYPE_STRING = "Context"; 27 static const char* const OBJECT_TYPE_STRING = "Object"; 28 static const char* const CONST_STRING_TYPE_STRING = "constexpr string"; 29 static const char* const CODE_TYPE_STRING = "Code"; 30 static const char* const INTPTR_TYPE_STRING = "intptr"; 31 static const char* const CONST_INT31_TYPE_STRING = "constexpr int31"; 32 static const char* const CONST_INT32_TYPE_STRING = "constexpr int32"; 33 static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64"; 34 35 class Label; 36 class Value; 37 class Module; 38 39 class TypeBase { 40 public: 41 enum class Kind { 42 kAbstractType, 43 kFunctionPointerType, 44 kUnionType, 45 kStructType 46 }; ~TypeBase()47 virtual ~TypeBase() {} IsAbstractType()48 bool IsAbstractType() const { return kind() == Kind::kAbstractType; } IsFunctionPointerType()49 bool IsFunctionPointerType() const { 50 return kind() == Kind::kFunctionPointerType; 51 } IsUnionType()52 bool IsUnionType() const { return kind() == Kind::kUnionType; } IsStructType()53 bool IsStructType() const { return kind() == Kind::kStructType; } 54 55 protected: TypeBase(Kind kind)56 explicit TypeBase(Kind kind) : kind_(kind) {} kind()57 Kind kind() const { return kind_; } 58 59 private: 60 const Kind kind_; 61 }; 62 63 #define DECLARE_TYPE_BOILERPLATE(x) \ 64 static x* cast(TypeBase* declarable) { \ 65 DCHECK(declarable->Is##x()); \ 66 return static_cast<x*>(declarable); \ 67 } \ 68 static const x* cast(const TypeBase* declarable) { \ 69 DCHECK(declarable->Is##x()); \ 70 return static_cast<const x*>(declarable); \ 71 } \ 72 static x* DynamicCast(TypeBase* declarable) { \ 73 if (!declarable) return nullptr; \ 74 if (!declarable->Is##x()) return nullptr; \ 75 return static_cast<x*>(declarable); \ 76 } \ 77 static const x* DynamicCast(const TypeBase* declarable) { \ 78 if (!declarable) return nullptr; \ 79 if (!declarable->Is##x()) return nullptr; \ 80 return static_cast<const x*>(declarable); \ 81 } 82 83 class Type : public TypeBase { 84 public: 85 virtual bool IsSubtypeOf(const Type* supertype) const; 86 87 std::string ToString() const; 88 virtual std::string MangledName() const = 0; IsVoid()89 bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); } IsNever()90 bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); } IsBool()91 bool IsBool() const { return IsAbstractName(BOOL_TYPE_STRING); } IsConstexprBool()92 bool IsConstexprBool() const { 93 return IsAbstractName(CONSTEXPR_BOOL_TYPE_STRING); 94 } IsVoidOrNever()95 bool IsVoidOrNever() const { return IsVoid() || IsNever(); } 96 virtual std::string GetGeneratedTypeName() const = 0; 97 virtual std::string GetGeneratedTNodeTypeName() const = 0; 98 virtual bool IsConstexpr() const = 0; 99 virtual const Type* NonConstexprVersion() const = 0; 100 static const Type* CommonSupertype(const Type* a, const Type* b); AddAlias(std::string alias)101 void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); } 102 103 protected: Type(TypeBase::Kind kind,const Type * parent)104 Type(TypeBase::Kind kind, const Type* parent) 105 : TypeBase(kind), parent_(parent) {} parent()106 const Type* parent() const { return parent_; } set_parent(const Type * t)107 void set_parent(const Type* t) { parent_ = t; } 108 int Depth() const; 109 virtual std::string ToExplicitString() const = 0; 110 111 private: 112 bool IsAbstractName(const std::string& name) const; 113 114 // If {parent_} is not nullptr, then this type is a subtype of {parent_}. 115 const Type* parent_; 116 mutable std::set<std::string> aliases_; 117 }; 118 119 using TypeVector = std::vector<const Type*>; 120 121 struct NameAndType { 122 std::string name; 123 const Type* type; 124 }; 125 126 std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type); 127 128 class AbstractType final : public Type { 129 public: 130 DECLARE_TYPE_BOILERPLATE(AbstractType); name()131 const std::string& name() const { return name_; } ToExplicitString()132 std::string ToExplicitString() const override { return name(); } MangledName()133 std::string MangledName() const override { return "AT" + name(); } GetGeneratedTypeName()134 std::string GetGeneratedTypeName() const override { return generated_type_; } 135 std::string GetGeneratedTNodeTypeName() const override; IsConstexpr()136 bool IsConstexpr() const override { 137 return name().substr(0, strlen(CONSTEXPR_TYPE_PREFIX)) == 138 CONSTEXPR_TYPE_PREFIX; 139 } NonConstexprVersion()140 const Type* NonConstexprVersion() const override { 141 if (IsConstexpr()) return *non_constexpr_version_; 142 return this; 143 } 144 145 private: 146 friend class TypeOracle; AbstractType(const Type * parent,const std::string & name,const std::string & generated_type,base::Optional<const AbstractType * > non_constexpr_version)147 AbstractType(const Type* parent, const std::string& name, 148 const std::string& generated_type, 149 base::Optional<const AbstractType*> non_constexpr_version) 150 : Type(Kind::kAbstractType, parent), 151 name_(name), 152 generated_type_(generated_type), 153 non_constexpr_version_(non_constexpr_version) { 154 DCHECK_EQ(non_constexpr_version_.has_value(), IsConstexpr()); 155 if (parent) DCHECK(parent->IsConstexpr() == IsConstexpr()); 156 } 157 158 const std::string name_; 159 const std::string generated_type_; 160 base::Optional<const AbstractType*> non_constexpr_version_; 161 }; 162 163 // For now, function pointers are restricted to Code objects of Torque-defined 164 // builtins. 165 class FunctionPointerType final : public Type { 166 public: 167 DECLARE_TYPE_BOILERPLATE(FunctionPointerType); 168 std::string ToExplicitString() const override; 169 std::string MangledName() const override; GetGeneratedTypeName()170 std::string GetGeneratedTypeName() const override { 171 return parent()->GetGeneratedTypeName(); 172 } GetGeneratedTNodeTypeName()173 std::string GetGeneratedTNodeTypeName() const override { 174 return parent()->GetGeneratedTNodeTypeName(); 175 } IsConstexpr()176 bool IsConstexpr() const override { 177 DCHECK(!parent()->IsConstexpr()); 178 return false; 179 } NonConstexprVersion()180 const Type* NonConstexprVersion() const override { return this; } 181 parameter_types()182 const TypeVector& parameter_types() const { return parameter_types_; } return_type()183 const Type* return_type() const { return return_type_; } 184 hash_value(const FunctionPointerType & p)185 friend size_t hash_value(const FunctionPointerType& p) { 186 size_t result = base::hash_value(p.return_type_); 187 for (const Type* parameter : p.parameter_types_) { 188 result = base::hash_combine(result, parameter); 189 } 190 return result; 191 } 192 bool operator==(const FunctionPointerType& other) const { 193 return parameter_types_ == other.parameter_types_ && 194 return_type_ == other.return_type_; 195 } 196 197 private: 198 friend class TypeOracle; FunctionPointerType(const Type * parent,TypeVector parameter_types,const Type * return_type)199 FunctionPointerType(const Type* parent, TypeVector parameter_types, 200 const Type* return_type) 201 : Type(Kind::kFunctionPointerType, parent), 202 parameter_types_(parameter_types), 203 return_type_(return_type) {} 204 205 const TypeVector parameter_types_; 206 const Type* const return_type_; 207 }; 208 209 bool operator<(const Type& a, const Type& b); 210 struct TypeLess { operatorTypeLess211 bool operator()(const Type* const a, const Type* const b) const { 212 return *a < *b; 213 } 214 }; 215 216 class UnionType final : public Type { 217 public: 218 DECLARE_TYPE_BOILERPLATE(UnionType); 219 std::string ToExplicitString() const override; 220 std::string MangledName() const override; GetGeneratedTypeName()221 std::string GetGeneratedTypeName() const override { 222 return "TNode<" + GetGeneratedTNodeTypeName() + ">"; 223 } 224 std::string GetGeneratedTNodeTypeName() const override; 225 IsConstexpr()226 bool IsConstexpr() const override { 227 DCHECK_EQ(false, parent()->IsConstexpr()); 228 return false; 229 } 230 const Type* NonConstexprVersion() const override; 231 hash_value(const UnionType & p)232 friend size_t hash_value(const UnionType& p) { 233 size_t result = 0; 234 for (const Type* t : p.types_) { 235 result = base::hash_combine(result, t); 236 } 237 return result; 238 } 239 bool operator==(const UnionType& other) const { 240 return types_ == other.types_; 241 } 242 GetSingleMember()243 base::Optional<const Type*> GetSingleMember() const { 244 if (types_.size() == 1) { 245 DCHECK_EQ(*types_.begin(), parent()); 246 return *types_.begin(); 247 } 248 return base::nullopt; 249 } 250 IsSubtypeOf(const Type * other)251 bool IsSubtypeOf(const Type* other) const override { 252 for (const Type* member : types_) { 253 if (!member->IsSubtypeOf(other)) return false; 254 } 255 return true; 256 } 257 IsSupertypeOf(const Type * other)258 bool IsSupertypeOf(const Type* other) const { 259 for (const Type* member : types_) { 260 if (other->IsSubtypeOf(member)) { 261 return true; 262 } 263 } 264 return false; 265 } 266 Extend(const Type * t)267 void Extend(const Type* t) { 268 if (const UnionType* union_type = UnionType::DynamicCast(t)) { 269 for (const Type* member : union_type->types_) { 270 Extend(member); 271 } 272 } else { 273 if (t->IsSubtypeOf(this)) return; 274 set_parent(CommonSupertype(parent(), t)); 275 for (const Type* member : types_) { 276 if (member->IsSubtypeOf(t)) { 277 types_.erase(member); 278 } 279 } 280 types_.insert(t); 281 } 282 } 283 284 void Subtract(const Type* t); 285 FromType(const Type * t)286 static UnionType FromType(const Type* t) { 287 const UnionType* union_type = UnionType::DynamicCast(t); 288 return union_type ? UnionType(*union_type) : UnionType(t); 289 } 290 291 private: UnionType(const Type * t)292 explicit UnionType(const Type* t) : Type(Kind::kUnionType, t), types_({t}) {} 293 void RecomputeParent(); 294 295 std::set<const Type*, TypeLess> types_; 296 }; 297 298 const Type* SubtractType(const Type* a, const Type* b); 299 300 class StructType final : public Type { 301 public: 302 DECLARE_TYPE_BOILERPLATE(StructType); 303 std::string ToExplicitString() const override; MangledName()304 std::string MangledName() const override { return name_; } GetGeneratedTypeName()305 std::string GetGeneratedTypeName() const override { return GetStructName(); } GetGeneratedTNodeTypeName()306 std::string GetGeneratedTNodeTypeName() const override { UNREACHABLE(); } NonConstexprVersion()307 const Type* NonConstexprVersion() const override { return this; } 308 IsConstexpr()309 bool IsConstexpr() const override { return false; } 310 fields()311 const std::vector<NameAndType>& fields() const { return fields_; } GetFieldType(const std::string & fieldname)312 const Type* GetFieldType(const std::string& fieldname) const { 313 for (const NameAndType& field : fields()) { 314 if (field.name == fieldname) return field.type; 315 } 316 std::stringstream s; 317 s << "\"" << fieldname << "\" is not a field of struct type \"" << name() 318 << "\""; 319 ReportError(s.str()); 320 } name()321 const std::string& name() const { return name_; } module()322 Module* module() const { return module_; } 323 324 private: 325 friend class TypeOracle; StructType(Module * module,const std::string & name,const std::vector<NameAndType> & fields)326 StructType(Module* module, const std::string& name, 327 const std::vector<NameAndType>& fields) 328 : Type(Kind::kStructType, nullptr), 329 module_(module), 330 name_(name), 331 fields_(fields) {} 332 GetStructName()333 const std::string& GetStructName() const { return name_; } 334 335 Module* module_; 336 std::string name_; 337 std::vector<NameAndType> fields_; 338 }; 339 340 inline std::ostream& operator<<(std::ostream& os, const Type& t) { 341 os << t.ToString(); 342 return os; 343 } 344 345 class VisitResult { 346 public: VisitResult()347 VisitResult() {} VisitResult(const Type * type,const std::string & value)348 VisitResult(const Type* type, const std::string& value) 349 : type_(type), value_(value), declarable_{} {} 350 VisitResult(const Type* type, const Value* declarable); type()351 const Type* type() const { return type_; } declarable()352 base::Optional<const Value*> declarable() const { return declarable_; } 353 std::string LValue() const; 354 std::string RValue() const; SetType(const Type * new_type)355 void SetType(const Type* new_type) { type_ = new_type; } 356 357 private: 358 const Type* type_ = nullptr; 359 std::string value_; 360 base::Optional<const Value*> declarable_; 361 }; 362 363 class VisitResultVector : public std::vector<VisitResult> { 364 public: VisitResultVector()365 VisitResultVector() : std::vector<VisitResult>() {} VisitResultVector(std::initializer_list<VisitResult> init)366 VisitResultVector(std::initializer_list<VisitResult> init) 367 : std::vector<VisitResult>(init) {} GetTypeVector()368 TypeVector GetTypeVector() const { 369 TypeVector result; 370 for (auto& visit_result : *this) { 371 result.push_back(visit_result.type()); 372 } 373 return result; 374 } 375 }; 376 377 std::ostream& operator<<(std::ostream& os, const TypeVector& types); 378 379 typedef std::vector<NameAndType> NameAndTypeVector; 380 381 struct LabelDefinition { 382 std::string name; 383 NameAndTypeVector parameters; 384 }; 385 386 typedef std::vector<LabelDefinition> LabelDefinitionVector; 387 388 struct LabelDeclaration { 389 std::string name; 390 TypeVector types; 391 }; 392 393 typedef std::vector<LabelDeclaration> LabelDeclarationVector; 394 395 struct ParameterTypes { 396 TypeVector types; 397 bool var_args; 398 }; 399 400 std::ostream& operator<<(std::ostream& os, const ParameterTypes& parameters); 401 402 struct Signature { typesSignature403 const TypeVector& types() const { return parameter_types.types; } 404 NameVector parameter_names; 405 ParameterTypes parameter_types; 406 const Type* return_type; 407 LabelDeclarationVector labels; 408 bool HasSameTypesAs(const Signature& other) const; 409 }; 410 411 struct Arguments { 412 VisitResultVector parameters; 413 std::vector<Label*> labels; 414 }; 415 416 void PrintSignature(std::ostream& os, const Signature& sig, bool with_names); 417 std::ostream& operator<<(std::ostream& os, const Signature& sig); 418 419 bool IsAssignableFrom(const Type* to, const Type* from); 420 bool IsCompatibleSignature(const Signature& sig, const TypeVector& types, 421 const std::vector<Label*>& labels); 422 423 } // namespace torque 424 } // namespace internal 425 } // namespace v8 426 427 #endif // V8_TORQUE_TYPES_H_ 428