• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <map>
10 #include <set>
11 #include <string>
12 #include <vector>
13 
14 #include "src/base/optional.h"
15 #include "src/torque/ast.h"
16 #include "src/torque/constants.h"
17 #include "src/torque/source-positions.h"
18 #include "src/torque/utils.h"
19 
20 namespace v8 {
21 namespace internal {
22 namespace torque {
23 
24 class AggregateType;
25 struct Identifier;
26 class Macro;
27 class Method;
28 class GenericType;
29 class StructType;
30 class Type;
31 class ClassType;
32 class Value;
33 class Namespace;
34 
35 class TypeBase {
36  public:
37   enum class Kind {
38     kTopType,
39     kAbstractType,
40     kBuiltinPointerType,
41     kUnionType,
42     kBitFieldStructType,
43     kStructType,
44     kClassType
45   };
46   virtual ~TypeBase() = default;
IsTopType()47   bool IsTopType() const { return kind() == Kind::kTopType; }
IsAbstractType()48   bool IsAbstractType() const { return kind() == Kind::kAbstractType; }
IsBuiltinPointerType()49   bool IsBuiltinPointerType() const {
50     return kind() == Kind::kBuiltinPointerType;
51   }
IsUnionType()52   bool IsUnionType() const { return kind() == Kind::kUnionType; }
IsBitFieldStructType()53   bool IsBitFieldStructType() const {
54     return kind() == Kind::kBitFieldStructType;
55   }
IsStructType()56   bool IsStructType() const { return kind() == Kind::kStructType; }
IsClassType()57   bool IsClassType() const { return kind() == Kind::kClassType; }
IsAggregateType()58   bool IsAggregateType() const { return IsStructType() || IsClassType(); }
59 
60  protected:
TypeBase(Kind kind)61   explicit TypeBase(Kind kind) : kind_(kind) {}
kind()62   Kind kind() const { return kind_; }
63 
64  private:
65   const Kind kind_;
66 };
67 
68 #define DECLARE_TYPE_BOILERPLATE(x)                         \
69   static x* cast(TypeBase* declarable) {                    \
70     DCHECK(declarable->Is##x());                            \
71     return static_cast<x*>(declarable);                     \
72   }                                                         \
73   static const x* cast(const TypeBase* declarable) {        \
74     DCHECK(declarable->Is##x());                            \
75     return static_cast<const x*>(declarable);               \
76   }                                                         \
77   static x* DynamicCast(TypeBase* declarable) {             \
78     if (!declarable) return nullptr;                        \
79     if (!declarable->Is##x()) return nullptr;               \
80     return static_cast<x*>(declarable);                     \
81   }                                                         \
82   static const x* DynamicCast(const TypeBase* declarable) { \
83     if (!declarable) return nullptr;                        \
84     if (!declarable->Is##x()) return nullptr;               \
85     return static_cast<const x*>(declarable);               \
86   }
87 
88 using TypeVector = std::vector<const Type*>;
89 
90 template <typename T>
91 struct SpecializationKey {
92   T* generic;
93   TypeVector specialized_types;
94 };
95 
96 using MaybeSpecializationKey = base::Optional<SpecializationKey<GenericType>>;
97 
98 struct TypeChecker {
99   // The type of the object. This string is not guaranteed to correspond to a
100   // C++ class, but just to a type checker function: for any type "Foo" here,
101   // the function Object::IsFoo must exist.
102   std::string type;
103   // If {type} is "MaybeObject", then {weak_ref_to} indicates the corresponding
104   // strong object type. Otherwise, {weak_ref_to} is empty.
105   std::string weak_ref_to;
106 };
107 
108 class V8_EXPORT_PRIVATE Type : public TypeBase {
109  public:
110   Type& operator=(const Type& other) = delete;
111   virtual bool IsSubtypeOf(const Type* supertype) const;
112 
113   // Default rendering for error messages etc.
114   std::string ToString() const;
115 
116   // This name is not unique, but short and somewhat descriptive.
117   // Used for naming generated code.
118   virtual std::string SimpleName() const;
119 
120   std::string UnhandlifiedCppTypeName() const;
121   std::string HandlifiedCppTypeName() const;
122 
parent()123   const Type* parent() const { return parent_; }
IsVoid()124   bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); }
IsNever()125   bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); }
IsBool()126   bool IsBool() const { return IsAbstractName(BOOL_TYPE_STRING); }
IsConstexprBool()127   bool IsConstexprBool() const {
128     return IsAbstractName(CONSTEXPR_BOOL_TYPE_STRING);
129   }
IsVoidOrNever()130   bool IsVoidOrNever() const { return IsVoid() || IsNever(); }
131   std::string GetGeneratedTypeName() const;
132   std::string GetGeneratedTNodeTypeName() const;
IsConstexpr()133   virtual bool IsConstexpr() const {
134     if (parent()) DCHECK(!parent()->IsConstexpr());
135     return false;
136   }
IsTransient()137   virtual bool IsTransient() const { return false; }
NonConstexprVersion()138   virtual const Type* NonConstexprVersion() const { return this; }
139   std::string GetConstexprGeneratedTypeName() const;
140   base::Optional<const ClassType*> ClassSupertype() const;
141   base::Optional<const StructType*> StructSupertype() const;
GetTypeCheckers()142   virtual std::vector<TypeChecker> GetTypeCheckers() const { return {}; }
143   virtual std::string GetRuntimeType() const;
144   static const Type* CommonSupertype(const Type* a, const Type* b);
AddAlias(std::string alias)145   void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
id()146   size_t id() const { return id_; }
GetSpecializedFrom()147   const MaybeSpecializationKey& GetSpecializedFrom() const {
148     return specialized_from_;
149   }
150 
151   static base::Optional<const Type*> MatchUnaryGeneric(const Type* type,
152                                                        GenericType* generic);
153 
154   static std::string ComputeName(const std::string& basename,
155                                  MaybeSpecializationKey specialized_from);
SetConstexprVersion(const Type * type)156   virtual void SetConstexprVersion(const Type* type) const {
157     constexpr_version_ = type;
158   }
159 
ConstexprVersion()160   virtual const Type* ConstexprVersion() const {
161     if (constexpr_version_) return constexpr_version_;
162     if (IsConstexpr()) return this;
163     if (parent()) return parent()->ConstexprVersion();
164     return nullptr;
165   }
166 
167   virtual size_t AlignmentLog2() const;
168 
169  protected:
170   Type(TypeBase::Kind kind, const Type* parent,
171        MaybeSpecializationKey specialized_from = base::nullopt);
172   Type(const Type& other) V8_NOEXCEPT;
set_parent(const Type * t)173   void set_parent(const Type* t) { parent_ = t; }
174   int Depth() const;
175   virtual std::string ToExplicitString() const = 0;
176   virtual std::string GetGeneratedTypeNameImpl() const = 0;
177   virtual std::string GetGeneratedTNodeTypeNameImpl() const = 0;
178   virtual std::string SimpleNameImpl() const = 0;
179 
180  private:
181   bool IsAbstractName(const std::string& name) const;
182 
183   // If {parent_} is not nullptr, then this type is a subtype of {parent_}.
184   const Type* parent_;
185   mutable std::set<std::string> aliases_;
186   size_t id_;
187   MaybeSpecializationKey specialized_from_;
188   mutable const Type* constexpr_version_ = nullptr;
189 };
190 
hash_value(const TypeVector & types)191 inline size_t hash_value(const TypeVector& types) {
192   size_t hash = 0;
193   for (const Type* t : types) {
194     hash = base::hash_combine(hash, t);
195   }
196   return hash;
197 }
198 
199 struct NameAndType {
200   std::string name;
201   const Type* type;
202 };
203 
204 std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);
205 
206 struct Field {
207   // TODO(danno): This likely should be refactored, the handling of the types
208   // using the universal grab-bag utility with std::tie, as well as the
209   // reliance of string types is quite clunky.
210   std::tuple<size_t, std::string> GetFieldSizeInformation() const;
211 
212   void ValidateAlignment(ResidueClass at_offset) const;
213 
214   SourcePosition pos;
215   const AggregateType* aggregate;
216   base::Optional<Expression*> index;
217   NameAndType name_and_type;
218 
219   // The byte offset of this field from the beginning of the containing class or
220   // struct. Most structs are never packed together in memory, and are only used
221   // to hold a batch of related CSA TNode values, in which case |offset| is
222   // irrelevant.
223   // The offset may be unknown because the field is after an indexed field or
224   // because we don't support the struct field for on-heap layouts.
225   base::Optional<size_t> offset;
226 
227   bool is_weak;
228   bool const_qualified;
229   bool generate_verify;
230 };
231 
232 std::ostream& operator<<(std::ostream& os, const Field& name_and_type);
233 
234 class TopType final : public Type {
235  public:
DECLARE_TYPE_BOILERPLATE(TopType)236   DECLARE_TYPE_BOILERPLATE(TopType)
237   std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); }
GetGeneratedTNodeTypeNameImpl()238   std::string GetGeneratedTNodeTypeNameImpl() const override {
239     return source_type_->GetGeneratedTNodeTypeName();
240   }
ToExplicitString()241   std::string ToExplicitString() const override {
242     std::stringstream s;
243     s << "inaccessible " + source_type_->ToString();
244     return s.str();
245   }
246 
source_type()247   const Type* source_type() const { return source_type_; }
reason()248   const std::string reason() const { return reason_; }
249 
250  private:
251   friend class TypeOracle;
TopType(std::string reason,const Type * source_type)252   explicit TopType(std::string reason, const Type* source_type)
253       : Type(Kind::kTopType, nullptr),
254         reason_(std::move(reason)),
255         source_type_(source_type) {}
SimpleNameImpl()256   std::string SimpleNameImpl() const override { return "TopType"; }
257 
258   std::string reason_;
259   const Type* source_type_;
260 };
261 
262 class AbstractType final : public Type {
263  public:
DECLARE_TYPE_BOILERPLATE(AbstractType)264   DECLARE_TYPE_BOILERPLATE(AbstractType)
265   const std::string& name() const { return name_; }
ToExplicitString()266   std::string ToExplicitString() const override { return name(); }
GetGeneratedTypeNameImpl()267   std::string GetGeneratedTypeNameImpl() const override {
268     if (generated_type_.empty()) {
269       return parent()->GetGeneratedTypeName();
270     }
271     return IsConstexpr() ? generated_type_ : "TNode<" + generated_type_ + ">";
272   }
273   std::string GetGeneratedTNodeTypeNameImpl() const override;
IsConstexpr()274   bool IsConstexpr() const final {
275     const bool is_constexpr = flags_ & AbstractTypeFlag::kConstexpr;
276     DCHECK_IMPLIES(non_constexpr_version_ != nullptr, is_constexpr);
277     return is_constexpr;
278   }
279 
NonConstexprVersion()280   const Type* NonConstexprVersion() const override {
281     if (non_constexpr_version_) return non_constexpr_version_;
282     if (!IsConstexpr()) return this;
283     if (parent()) return parent()->NonConstexprVersion();
284     return nullptr;
285   }
286 
287   std::vector<TypeChecker> GetTypeCheckers() const override;
288 
289   size_t AlignmentLog2() const override;
290 
291  private:
292   friend class TypeOracle;
AbstractType(const Type * parent,AbstractTypeFlags flags,const std::string & name,const std::string & generated_type,const Type * non_constexpr_version,MaybeSpecializationKey specialized_from)293   AbstractType(const Type* parent, AbstractTypeFlags flags,
294                const std::string& name, const std::string& generated_type,
295                const Type* non_constexpr_version,
296                MaybeSpecializationKey specialized_from)
297       : Type(Kind::kAbstractType, parent, specialized_from),
298         flags_(flags),
299         name_(name),
300         generated_type_(generated_type),
301         non_constexpr_version_(non_constexpr_version) {
302     if (parent) DCHECK_EQ(parent->IsConstexpr(), IsConstexpr());
303     DCHECK_EQ(IsConstexprName(name), IsConstexpr());
304     DCHECK_IMPLIES(non_constexpr_version_ != nullptr, IsConstexpr());
305     DCHECK(!(IsConstexpr() && (flags_ & AbstractTypeFlag::kTransient)));
306   }
307 
SimpleNameImpl()308   std::string SimpleNameImpl() const override {
309     if (IsConstexpr()) {
310       const Type* non_constexpr_version = NonConstexprVersion();
311       if (non_constexpr_version == nullptr) {
312         ReportError("Cannot find non-constexpr type corresponding to ", *this);
313       }
314       return "constexpr_" + non_constexpr_version->SimpleName();
315     }
316     return name();
317   }
318 
IsTransient()319   bool IsTransient() const override {
320     return flags_ & AbstractTypeFlag::kTransient;
321   }
322 
UseParentTypeChecker()323   bool UseParentTypeChecker() const {
324     return flags_ & AbstractTypeFlag::kUseParentTypeChecker;
325   }
326 
327   AbstractTypeFlags flags_;
328   const std::string name_;
329   const std::string generated_type_;
330   const Type* non_constexpr_version_;
331 };
332 
333 // For now, builtin pointers are restricted to Torque-defined builtins.
334 class V8_EXPORT_PRIVATE BuiltinPointerType final : public Type {
335  public:
336   DECLARE_TYPE_BOILERPLATE(BuiltinPointerType)
337   std::string ToExplicitString() const override;
GetGeneratedTypeNameImpl()338   std::string GetGeneratedTypeNameImpl() const override {
339     return parent()->GetGeneratedTypeName();
340   }
GetGeneratedTNodeTypeNameImpl()341   std::string GetGeneratedTNodeTypeNameImpl() const override {
342     return parent()->GetGeneratedTNodeTypeName();
343   }
344 
parameter_types()345   const TypeVector& parameter_types() const { return parameter_types_; }
return_type()346   const Type* return_type() const { return return_type_; }
347 
hash_value(const BuiltinPointerType & p)348   friend size_t hash_value(const BuiltinPointerType& p) {
349     size_t result = base::hash_value(p.return_type_);
350     for (const Type* parameter : p.parameter_types_) {
351       result = base::hash_combine(result, parameter);
352     }
353     return result;
354   }
355   bool operator==(const BuiltinPointerType& other) const {
356     return parameter_types_ == other.parameter_types_ &&
357            return_type_ == other.return_type_;
358   }
function_pointer_type_id()359   size_t function_pointer_type_id() const { return function_pointer_type_id_; }
360 
GetTypeCheckers()361   std::vector<TypeChecker> GetTypeCheckers() const override {
362     return {{"Smi", ""}};
363   }
364 
365   bool HasContextParameter() const;
366 
367  private:
368   friend class TypeOracle;
BuiltinPointerType(const Type * parent,TypeVector parameter_types,const Type * return_type,size_t function_pointer_type_id)369   BuiltinPointerType(const Type* parent, TypeVector parameter_types,
370                      const Type* return_type, size_t function_pointer_type_id)
371       : Type(Kind::kBuiltinPointerType, parent),
372         parameter_types_(parameter_types),
373         return_type_(return_type),
374         function_pointer_type_id_(function_pointer_type_id) {}
375   std::string SimpleNameImpl() const override;
376 
377   const TypeVector parameter_types_;
378   const Type* const return_type_;
379   const size_t function_pointer_type_id_;
380 };
381 
382 bool operator<(const Type& a, const Type& b);
383 struct TypeLess {
operatorTypeLess384   bool operator()(const Type* const a, const Type* const b) const {
385     return *a < *b;
386   }
387 };
388 
389 class V8_EXPORT_PRIVATE UnionType final : public Type {
390  public:
DECLARE_TYPE_BOILERPLATE(UnionType)391   DECLARE_TYPE_BOILERPLATE(UnionType)
392   std::string GetGeneratedTypeNameImpl() const override {
393     return "TNode<" + GetGeneratedTNodeTypeName() + ">";
394   }
395   std::string GetGeneratedTNodeTypeNameImpl() const override;
GetRuntimeType()396   std::string GetRuntimeType() const override {
397     return parent()->GetRuntimeType();
398   }
399 
hash_value(const UnionType & p)400   friend size_t hash_value(const UnionType& p) {
401     size_t result = 0;
402     for (const Type* t : p.types_) {
403       result = base::hash_combine(result, t);
404     }
405     return result;
406   }
407   bool operator==(const UnionType& other) const {
408     return types_ == other.types_;
409   }
410 
GetSingleMember()411   base::Optional<const Type*> GetSingleMember() const {
412     if (types_.size() == 1) {
413       DCHECK_EQ(*types_.begin(), parent());
414       return *types_.begin();
415     }
416     return base::nullopt;
417   }
418 
IsSubtypeOf(const Type * other)419   bool IsSubtypeOf(const Type* other) const override {
420     for (const Type* member : types_) {
421       if (!member->IsSubtypeOf(other)) return false;
422     }
423     return true;
424   }
425 
IsSupertypeOf(const Type * other)426   bool IsSupertypeOf(const Type* other) const {
427     for (const Type* member : types_) {
428       if (other->IsSubtypeOf(member)) {
429         return true;
430       }
431     }
432     return false;
433   }
434 
IsTransient()435   bool IsTransient() const override {
436     for (const Type* member : types_) {
437       if (member->IsTransient()) {
438         return true;
439       }
440     }
441     return false;
442   }
443 
IsConstexpr()444   bool IsConstexpr() const override { return parent()->IsConstexpr(); }
445 
NonConstexprVersion()446   const Type* NonConstexprVersion() const override {
447     if (!IsConstexpr()) return this;
448     return parent()->NonConstexprVersion();
449   }
450 
Extend(const Type * t)451   void Extend(const Type* t) {
452     if (const UnionType* union_type = UnionType::DynamicCast(t)) {
453       for (const Type* member : union_type->types_) {
454         Extend(member);
455       }
456     } else {
457       if (t->IsSubtypeOf(this)) return;
458       set_parent(CommonSupertype(parent(), t));
459       EraseIf(&types_,
460               [&](const Type* member) { return member->IsSubtypeOf(t); });
461       types_.insert(t);
462     }
463   }
464   std::string ToExplicitString() const override;
465 
466   void Subtract(const Type* t);
467 
FromType(const Type * t)468   static UnionType FromType(const Type* t) {
469     const UnionType* union_type = UnionType::DynamicCast(t);
470     return union_type ? UnionType(*union_type) : UnionType(t);
471   }
472 
GetTypeCheckers()473   std::vector<TypeChecker> GetTypeCheckers() const override {
474     std::vector<TypeChecker> result;
475     for (const Type* member : types_) {
476       std::vector<TypeChecker> sub_result = member->GetTypeCheckers();
477       result.insert(result.end(), sub_result.begin(), sub_result.end());
478     }
479     return result;
480   }
481 
482  private:
UnionType(const Type * t)483   explicit UnionType(const Type* t) : Type(Kind::kUnionType, t), types_({t}) {}
484   void RecomputeParent();
485   std::string SimpleNameImpl() const override;
486 
487   std::set<const Type*, TypeLess> types_;
488 };
489 
490 const Type* SubtractType(const Type* a, const Type* b);
491 
492 struct BitField {
493   SourcePosition pos;
494   NameAndType name_and_type;
495   int offset;
496   int num_bits;
497 };
498 
499 class V8_EXPORT_PRIVATE BitFieldStructType final : public Type {
500  public:
501   DECLARE_TYPE_BOILERPLATE(BitFieldStructType)
502   std::string ToExplicitString() const override;
GetGeneratedTypeNameImpl()503   std::string GetGeneratedTypeNameImpl() const override {
504     return parent()->GetGeneratedTypeName();
505   }
GetGeneratedTNodeTypeNameImpl()506   std::string GetGeneratedTNodeTypeNameImpl() const override {
507     return parent()->GetGeneratedTNodeTypeName();
508   }
509 
GetTypeCheckers()510   std::vector<TypeChecker> GetTypeCheckers() const override {
511     return parent()->GetTypeCheckers();
512   }
513 
SetConstexprVersion(const Type *)514   void SetConstexprVersion(const Type*) const override { UNREACHABLE(); }
ConstexprVersion()515   const Type* ConstexprVersion() const override {
516     return parent()->ConstexprVersion();
517   }
518 
RegisterField(BitField field)519   void RegisterField(BitField field) { fields_.push_back(std::move(field)); }
520 
name()521   const std::string& name() const { return decl_->name->value; }
fields()522   const std::vector<BitField>& fields() const { return fields_; }
523 
524   const BitField& LookupField(const std::string& name) const;
525 
526  private:
527   friend class TypeOracle;
BitFieldStructType(Namespace * nspace,const Type * parent,const BitFieldStructDeclaration * decl)528   BitFieldStructType(Namespace* nspace, const Type* parent,
529                      const BitFieldStructDeclaration* decl)
530       : Type(Kind::kBitFieldStructType, parent),
531         namespace_(nspace),
532         decl_(decl) {}
SimpleNameImpl()533   std::string SimpleNameImpl() const override { return name(); }
534 
535   Namespace* namespace_;
536   const BitFieldStructDeclaration* decl_;
537   std::vector<BitField> fields_;
538 };
539 
540 class AggregateType : public Type {
541  public:
DECLARE_TYPE_BOILERPLATE(AggregateType)542   DECLARE_TYPE_BOILERPLATE(AggregateType)
543   std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); }
GetGeneratedTNodeTypeNameImpl()544   std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); }
545 
546   virtual void Finalize() const = 0;
547 
SetFields(std::vector<Field> fields)548   void SetFields(std::vector<Field> fields) { fields_ = std::move(fields); }
fields()549   const std::vector<Field>& fields() const {
550     if (!is_finalized_) Finalize();
551     return fields_;
552   }
553   bool HasField(const std::string& name) const;
554   const Field& LookupField(const std::string& name) const;
name()555   const std::string& name() const { return name_; }
nspace()556   Namespace* nspace() const { return namespace_; }
557 
RegisterField(Field field)558   virtual const Field& RegisterField(Field field) {
559     fields_.push_back(field);
560     return fields_.back();
561   }
562 
RegisterMethod(Method * method)563   void RegisterMethod(Method* method) { methods_.push_back(method); }
Methods()564   const std::vector<Method*>& Methods() const {
565     if (!is_finalized_) Finalize();
566     return methods_;
567   }
568   std::vector<Method*> Methods(const std::string& name) const;
569 
570   std::vector<const AggregateType*> GetHierarchy() const;
GetTypeCheckers()571   std::vector<TypeChecker> GetTypeCheckers() const override {
572     return {{name_, ""}};
573   }
574 
575  protected:
576   AggregateType(Kind kind, const Type* parent, Namespace* nspace,
577                 const std::string& name,
578                 MaybeSpecializationKey specialized_from = base::nullopt)
Type(kind,parent,specialized_from)579       : Type(kind, parent, specialized_from),
580         is_finalized_(false),
581         namespace_(nspace),
582         name_(name) {}
583 
584   void CheckForDuplicateFields() const;
585   // Use this lookup if you do not want to trigger finalization on this type.
586   const Field& LookupFieldInternal(const std::string& name) const;
SimpleNameImpl()587   std::string SimpleNameImpl() const override { return name_; }
588 
589  protected:
590   mutable bool is_finalized_;
591   std::vector<Field> fields_;
592 
593  private:
594   Namespace* namespace_;
595   std::string name_;
596   std::vector<Method*> methods_;
597 };
598 
599 class StructType final : public AggregateType {
600  public:
601   DECLARE_TYPE_BOILERPLATE(StructType)
602 
603   std::string GetGeneratedTypeNameImpl() const override;
604 
605   // Returns the sum of the size of all members.
606   size_t PackedSize() const;
607 
608   size_t AlignmentLog2() const override;
609 
610   enum class ClassificationFlag {
611     kEmpty = 0,
612     kTagged = 1 << 0,
613     kUntagged = 1 << 1,
614     kMixed = kTagged | kUntagged,
615   };
616   using Classification = base::Flags<ClassificationFlag>;
617 
618   // Classifies a struct as containing tagged data, untagged data, or both.
619   Classification ClassifyContents() const;
620 
GetPosition()621   SourcePosition GetPosition() const { return decl_->pos; }
622 
623  private:
624   friend class TypeOracle;
625   StructType(Namespace* nspace, const StructDeclaration* decl,
626              MaybeSpecializationKey specialized_from = base::nullopt);
627 
628   void Finalize() const override;
629   std::string ToExplicitString() const override;
630   std::string SimpleNameImpl() const override;
631 
632   const StructDeclaration* decl_;
633   std::string generated_type_name_;
634 };
635 
636 class TypeAlias;
637 
638 enum class ObjectSlotKind : uint8_t {
639   kNoPointer,
640   kStrongPointer,
641   kMaybeObjectPointer,
642   kCustomWeakPointer
643 };
644 
Combine(ObjectSlotKind a,ObjectSlotKind b)645 inline base::Optional<ObjectSlotKind> Combine(ObjectSlotKind a,
646                                               ObjectSlotKind b) {
647   if (a == b) return {a};
648   if (std::min(a, b) == ObjectSlotKind::kStrongPointer &&
649       std::max(a, b) == ObjectSlotKind::kMaybeObjectPointer) {
650     return {ObjectSlotKind::kMaybeObjectPointer};
651   }
652   return base::nullopt;
653 }
654 
655 class ClassType final : public AggregateType {
656  public:
657   DECLARE_TYPE_BOILERPLATE(ClassType)
658   std::string ToExplicitString() const override;
659   std::string GetGeneratedTypeNameImpl() const override;
660   std::string GetGeneratedTNodeTypeNameImpl() const override;
IsExtern()661   bool IsExtern() const { return flags_ & ClassFlag::kExtern; }
ShouldGeneratePrint()662   bool ShouldGeneratePrint() const {
663     return !IsExtern() ||
664            ((flags_ & ClassFlag::kGeneratePrint) && !HasUndefinedLayout());
665   }
ShouldGenerateVerify()666   bool ShouldGenerateVerify() const {
667     return !IsExtern() || ((flags_ & ClassFlag::kGenerateVerify) &&
668                            (!HasUndefinedLayout() && !IsShape()));
669   }
ShouldGenerateBodyDescriptor()670   bool ShouldGenerateBodyDescriptor() const {
671     if (IsAbstract()) return false;
672     return flags_ & ClassFlag::kGenerateBodyDescriptor || !IsExtern();
673   }
DoNotGenerateCast()674   bool DoNotGenerateCast() const {
675     return flags_ & ClassFlag::kDoNotGenerateCast;
676   }
IsTransient()677   bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
IsAbstract()678   bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; }
HasSameInstanceTypeAsParent()679   bool HasSameInstanceTypeAsParent() const {
680     return flags_ & ClassFlag::kHasSameInstanceTypeAsParent;
681   }
GenerateCppClassDefinitions()682   bool GenerateCppClassDefinitions() const {
683     return flags_ & ClassFlag::kGenerateCppClassDefinitions || !IsExtern() ||
684            ShouldGenerateBodyDescriptor();
685   }
ShouldGenerateFullClassDefinition()686   bool ShouldGenerateFullClassDefinition() const {
687     return !IsExtern() && !(flags_ & ClassFlag::kCustomCppClass);
688   }
689   // Class with multiple or non-standard maps, do not auto-generate map.
HasCustomMap()690   bool HasCustomMap() const { return flags_ & ClassFlag::kCustomMap; }
ShouldExport()691   bool ShouldExport() const { return flags_ & ClassFlag::kExport; }
IsShape()692   bool IsShape() const { return flags_ & ClassFlag::kIsShape; }
693   bool HasStaticSize() const;
header_size()694   size_t header_size() const {
695     if (!is_finalized_) Finalize();
696     return header_size_;
697   }
size()698   ResidueClass size() const {
699     if (!is_finalized_) Finalize();
700     return size_;
701   }
GetSuperClass()702   const ClassType* GetSuperClass() const {
703     if (parent() == nullptr) return nullptr;
704     return parent()->IsClassType() ? ClassType::DynamicCast(parent()) : nullptr;
705   }
706   void GenerateAccessors();
707   bool AllowInstantiation() const;
RegisterField(Field field)708   const Field& RegisterField(Field field) override {
709     return AggregateType::RegisterField(field);
710   }
711   void Finalize() const override;
712 
713   std::vector<Field> ComputeAllFields() const;
714   std::vector<Field> ComputeHeaderFields() const;
715   std::vector<Field> ComputeArrayFields() const;
716   // The slots of an object are the tagged pointer sized offsets in an object
717   // that may or may not require GC visiting. These helper functions determine
718   // what kind of GC visiting the individual slots require.
719   std::vector<ObjectSlotKind> ComputeHeaderSlotKinds() const;
720   base::Optional<ObjectSlotKind> ComputeArraySlotKind() const;
721   bool HasNoPointerSlots() const;
722   bool HasIndexedFieldsIncludingInParents() const;
723   const Field* GetFieldPreceding(size_t field_index) const;
724 
725   // Given that the field exists in this class or a superclass, returns the
726   // specific class that declared the field.
727   const ClassType* GetClassDeclaringField(const Field& f) const;
728 
729   std::string GetSliceMacroName(const Field& field) const;
730 
GetInstanceTypeConstraints()731   const InstanceTypeConstraints& GetInstanceTypeConstraints() const {
732     return decl_->instance_type_constraints;
733   }
IsHighestInstanceTypeWithinParent()734   bool IsHighestInstanceTypeWithinParent() const {
735     return flags_ & ClassFlag::kHighestInstanceTypeWithinParent;
736   }
IsLowestInstanceTypeWithinParent()737   bool IsLowestInstanceTypeWithinParent() const {
738     return flags_ & ClassFlag::kLowestInstanceTypeWithinParent;
739   }
HasUndefinedLayout()740   bool HasUndefinedLayout() const {
741     return flags_ & ClassFlag::kUndefinedLayout;
742   }
GetPosition()743   SourcePosition GetPosition() const { return decl_->pos; }
744   SourceId AttributedToFile() const;
745 
746   // TODO(tebbi): We should no longer pass around types as const pointers, so
747   // that we can avoid mutable fields and const initializers for
748   // late-initialized portions of types like this one.
749   void InitializeInstanceTypes(base::Optional<int> own,
750                                base::Optional<std::pair<int, int>> range) const;
751   base::Optional<int> OwnInstanceType() const;
752   base::Optional<std::pair<int, int>> InstanceTypeRange() const;
753 
754  private:
755   friend class TypeOracle;
756   friend class TypeVisitor;
757   ClassType(const Type* parent, Namespace* nspace, const std::string& name,
758             ClassFlags flags, const std::string& generates,
759             const ClassDeclaration* decl, const TypeAlias* alias);
760 
761   void GenerateSliceAccessor(size_t field_index);
762 
763   size_t header_size_;
764   ResidueClass size_;
765   mutable ClassFlags flags_;
766   const std::string generates_;
767   const ClassDeclaration* decl_;
768   const TypeAlias* alias_;
769   mutable base::Optional<int> own_instance_type_;
770   mutable base::Optional<std::pair<int, int>> instance_type_range_;
771 };
772 
773 inline std::ostream& operator<<(std::ostream& os, const Type& t) {
774   os << t.ToString();
775   return os;
776 }
777 
778 class VisitResult {
779  public:
780   VisitResult() = default;
VisitResult(const Type * type,const std::string & constexpr_value)781   VisitResult(const Type* type, const std::string& constexpr_value)
782       : type_(type), constexpr_value_(constexpr_value) {
783     DCHECK(type->IsConstexpr());
784   }
785   static VisitResult NeverResult();
786   static VisitResult TopTypeResult(std::string top_reason,
787                                    const Type* from_type);
VisitResult(const Type * type,StackRange stack_range)788   VisitResult(const Type* type, StackRange stack_range)
789       : type_(type), stack_range_(stack_range) {
790     DCHECK(!type->IsConstexpr());
791   }
type()792   const Type* type() const { return type_; }
constexpr_value()793   const std::string& constexpr_value() const { return *constexpr_value_; }
stack_range()794   const StackRange& stack_range() const { return *stack_range_; }
SetType(const Type * new_type)795   void SetType(const Type* new_type) { type_ = new_type; }
IsOnStack()796   bool IsOnStack() const { return stack_range_ != base::nullopt; }
797   bool operator==(const VisitResult& other) const {
798     return type_ == other.type_ && constexpr_value_ == other.constexpr_value_ &&
799            stack_range_ == other.stack_range_;
800   }
801 
802  private:
803   const Type* type_ = nullptr;
804   base::Optional<std::string> constexpr_value_;
805   base::Optional<StackRange> stack_range_;
806 };
807 
808 VisitResult ProjectStructField(VisitResult structure,
809                                const std::string& fieldname);
810 
811 class VisitResultVector : public std::vector<VisitResult> {
812  public:
VisitResultVector()813   VisitResultVector() : std::vector<VisitResult>() {}
VisitResultVector(std::initializer_list<VisitResult> init)814   VisitResultVector(std::initializer_list<VisitResult> init)
815       : std::vector<VisitResult>(init) {}
ComputeTypeVector()816   TypeVector ComputeTypeVector() const {
817     TypeVector result;
818     for (auto& visit_result : *this) {
819       result.push_back(visit_result.type());
820     }
821     return result;
822   }
823 };
824 
825 std::ostream& operator<<(std::ostream& os, const TypeVector& types);
826 
827 using NameAndTypeVector = std::vector<NameAndType>;
828 
829 struct LabelDefinition {
830   std::string name;
831   NameAndTypeVector parameters;
832 };
833 
834 using LabelDefinitionVector = std::vector<LabelDefinition>;
835 
836 struct LabelDeclaration {
837   Identifier* name;
838   TypeVector types;
839 };
840 
841 using LabelDeclarationVector = std::vector<LabelDeclaration>;
842 
843 struct ParameterTypes {
844   TypeVector types;
845   bool var_args;
846 };
847 
848 std::ostream& operator<<(std::ostream& os, const ParameterTypes& parameters);
849 
850 enum class ParameterMode { kProcessImplicit, kIgnoreImplicit };
851 
852 using NameVector = std::vector<Identifier*>;
853 
854 struct Signature {
SignatureSignature855   Signature(NameVector n, base::Optional<std::string> arguments_variable,
856             ParameterTypes p, size_t i, const Type* r, LabelDeclarationVector l,
857             bool transitioning)
858       : parameter_names(std::move(n)),
859         arguments_variable(arguments_variable),
860         parameter_types(std::move(p)),
861         implicit_count(i),
862         return_type(r),
863         labels(std::move(l)),
864         transitioning(transitioning) {}
865   Signature() = default;
typesSignature866   const TypeVector& types() const { return parameter_types.types; }
867   NameVector parameter_names;
868   base::Optional<std::string> arguments_variable;
869   ParameterTypes parameter_types;
870   size_t implicit_count = 0;
ExplicitCountSignature871   size_t ExplicitCount() const { return types().size() - implicit_count; }
872   const Type* return_type;
873   LabelDeclarationVector labels;
874   bool transitioning = false;
875   bool HasSameTypesAs(
876       const Signature& other,
877       ParameterMode mode = ParameterMode::kProcessImplicit) const;
GetImplicitTypesSignature878   TypeVector GetImplicitTypes() const {
879     return TypeVector(parameter_types.types.begin(),
880                       parameter_types.types.begin() + implicit_count);
881   }
GetExplicitTypesSignature882   TypeVector GetExplicitTypes() const {
883     return TypeVector(parameter_types.types.begin() + implicit_count,
884                       parameter_types.types.end());
885   }
886   bool HasContextParameter() const;
887 };
888 
889 void PrintSignature(std::ostream& os, const Signature& sig, bool with_names);
890 std::ostream& operator<<(std::ostream& os, const Signature& sig);
891 
892 bool IsAssignableFrom(const Type* to, const Type* from);
893 
894 TypeVector LowerType(const Type* type);
895 size_t LoweredSlotCount(const Type* type);
896 TypeVector LowerParameterTypes(const TypeVector& parameters);
897 TypeVector LowerParameterTypes(const ParameterTypes& parameter_types,
898                                size_t vararg_count = 0);
899 
900 base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type);
901 bool IsAnyUnsignedInteger(const Type* type);
902 bool IsAllowedAsBitField(const Type* type);
903 bool IsPointerSizeIntegralType(const Type* type);
904 bool Is32BitIntegralType(const Type* type);
905 
906 base::Optional<NameAndType> ExtractSimpleFieldArraySize(
907     const ClassType& class_type, Expression* array_size);
908 
909 }  // namespace torque
910 }  // namespace internal
911 }  // namespace v8
912 
913 #endif  // V8_TORQUE_TYPES_H_
914