V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
types.h
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/utils.h"
16 
17 namespace v8 {
18 namespace internal {
19 namespace torque {
20 
21 static const char* const CONSTEXPR_TYPE_PREFIX = "constexpr ";
22 static const char* const NEVER_TYPE_STRING = "never";
23 static const char* const CONSTEXPR_BOOL_TYPE_STRING = "constexpr bool";
24 static const char* const BOOL_TYPE_STRING = "bool";
25 static const char* const VOID_TYPE_STRING = "void";
26 static const char* const ARGUMENTS_TYPE_STRING = "constexpr Arguments";
27 static const char* const CONTEXT_TYPE_STRING = "Context";
28 static const char* const OBJECT_TYPE_STRING = "Object";
29 static const char* const CONST_STRING_TYPE_STRING = "constexpr string";
30 static const char* const CODE_TYPE_STRING = "Code";
31 static const char* const INTPTR_TYPE_STRING = "intptr";
32 static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
33 static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
34 static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
35 
36 class Value;
37 class Namespace;
38 
39 class TypeBase {
40  public:
41  enum class Kind {
42  kTopType,
43  kAbstractType,
44  kFunctionPointerType,
45  kUnionType,
46  kStructType
47  };
48  virtual ~TypeBase() = default;
49  bool IsTopType() const { return kind() == Kind::kTopType; }
50  bool IsAbstractType() const { return kind() == Kind::kAbstractType; }
51  bool IsFunctionPointerType() const {
52  return kind() == Kind::kFunctionPointerType;
53  }
54  bool IsUnionType() const { return kind() == Kind::kUnionType; }
55  bool IsStructType() const { return kind() == Kind::kStructType; }
56 
57  protected:
58  explicit TypeBase(Kind kind) : kind_(kind) {}
59  Kind kind() const { return kind_; }
60 
61  private:
62  const Kind kind_;
63 };
64 
65 #define DECLARE_TYPE_BOILERPLATE(x) \
66  static x* cast(TypeBase* declarable) { \
67  DCHECK(declarable->Is##x()); \
68  return static_cast<x*>(declarable); \
69  } \
70  static const x* cast(const TypeBase* declarable) { \
71  DCHECK(declarable->Is##x()); \
72  return static_cast<const x*>(declarable); \
73  } \
74  static x* DynamicCast(TypeBase* declarable) { \
75  if (!declarable) return nullptr; \
76  if (!declarable->Is##x()) return nullptr; \
77  return static_cast<x*>(declarable); \
78  } \
79  static const x* DynamicCast(const TypeBase* declarable) { \
80  if (!declarable) return nullptr; \
81  if (!declarable->Is##x()) return nullptr; \
82  return static_cast<const x*>(declarable); \
83  }
84 
85 class Type : public TypeBase {
86  public:
87  virtual bool IsSubtypeOf(const Type* supertype) const;
88 
89  std::string ToString() const;
90  virtual std::string MangledName() const = 0;
91  bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); }
92  bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); }
93  bool IsBool() const { return IsAbstractName(BOOL_TYPE_STRING); }
94  bool IsConstexprBool() const {
95  return IsAbstractName(CONSTEXPR_BOOL_TYPE_STRING);
96  }
97  bool IsVoidOrNever() const { return IsVoid() || IsNever(); }
98  virtual std::string GetGeneratedTypeName() const = 0;
99  virtual std::string GetGeneratedTNodeTypeName() const = 0;
100  virtual bool IsConstexpr() const = 0;
101  virtual bool IsTransient() const { return false; }
102  virtual const Type* NonConstexprVersion() const = 0;
103  static const Type* CommonSupertype(const Type* a, const Type* b);
104  void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
105 
106  protected:
107  Type(TypeBase::Kind kind, const Type* parent)
108  : TypeBase(kind), parent_(parent) {}
109  const Type* parent() const { return parent_; }
110  void set_parent(const Type* t) { parent_ = t; }
111  int Depth() const;
112  virtual std::string ToExplicitString() const = 0;
113 
114  private:
115  bool IsAbstractName(const std::string& name) const;
116 
117  // If {parent_} is not nullptr, then this type is a subtype of {parent_}.
118  const Type* parent_;
119  mutable std::set<std::string> aliases_;
120 };
121 
122 using TypeVector = std::vector<const Type*>;
123 
124 inline size_t hash_value(const TypeVector& types) {
125  size_t hash = 0;
126  for (const Type* t : types) {
127  hash = base::hash_combine(hash, t);
128  }
129  return hash;
130 }
131 
132 struct NameAndType {
133  std::string name;
134  const Type* type;
135 };
136 
137 std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);
138 
139 class TopType final : public Type {
140  public:
141  DECLARE_TYPE_BOILERPLATE(TopType);
142  virtual std::string MangledName() const { return "top"; }
143  virtual std::string GetGeneratedTypeName() const { UNREACHABLE(); }
144  virtual std::string GetGeneratedTNodeTypeName() const {
145  return source_type_->GetGeneratedTNodeTypeName();
146  }
147  virtual bool IsConstexpr() const { return false; }
148  virtual const Type* NonConstexprVersion() const { return nullptr; }
149  virtual std::string ToExplicitString() const {
150  std::stringstream s;
151  s << "inaccessible " + source_type_->ToString();
152  return s.str();
153  }
154 
155  const Type* source_type() const { return source_type_; }
156  const std::string reason() const { return reason_; }
157 
158  private:
159  friend class TypeOracle;
160  explicit TopType(std::string reason, const Type* source_type)
161  : Type(Kind::kTopType, nullptr),
162  reason_(std::move(reason)),
163  source_type_(source_type) {}
164  std::string reason_;
165  const Type* source_type_;
166 };
167 
168 class AbstractType final : public Type {
169  public:
170  DECLARE_TYPE_BOILERPLATE(AbstractType);
171  const std::string& name() const { return name_; }
172  std::string ToExplicitString() const override { return name(); }
173  std::string MangledName() const override { return "AT" + name(); }
174  std::string GetGeneratedTypeName() const override {
175  return IsConstexpr() ? generated_type_
176  : "compiler::TNode<" + generated_type_ + ">";
177  }
178  std::string GetGeneratedTNodeTypeName() const override;
179  bool IsConstexpr() const override {
180  return name().substr(0, strlen(CONSTEXPR_TYPE_PREFIX)) ==
181  CONSTEXPR_TYPE_PREFIX;
182  }
183  const Type* NonConstexprVersion() const override {
184  if (IsConstexpr()) return *non_constexpr_version_;
185  return this;
186  }
187 
188  private:
189  friend class TypeOracle;
190  AbstractType(const Type* parent, bool transient, const std::string& name,
191  const std::string& generated_type,
192  base::Optional<const AbstractType*> non_constexpr_version)
193  : Type(Kind::kAbstractType, parent),
194  transient_(transient),
195  name_(name),
196  generated_type_(generated_type),
197  non_constexpr_version_(non_constexpr_version) {
198  DCHECK_EQ(non_constexpr_version_.has_value(), IsConstexpr());
199  if (parent) DCHECK(parent->IsConstexpr() == IsConstexpr());
200  }
201 
202  bool IsTransient() const override { return transient_; }
203 
204  bool transient_;
205  const std::string name_;
206  const std::string generated_type_;
207  base::Optional<const AbstractType*> non_constexpr_version_;
208 };
209 
210 // For now, function pointers are restricted to Code objects of Torque-defined
211 // builtins.
212 class FunctionPointerType final : public Type {
213  public:
214  DECLARE_TYPE_BOILERPLATE(FunctionPointerType);
215  std::string ToExplicitString() const override;
216  std::string MangledName() const override;
217  std::string GetGeneratedTypeName() const override {
218  return parent()->GetGeneratedTypeName();
219  }
220  std::string GetGeneratedTNodeTypeName() const override {
221  return parent()->GetGeneratedTNodeTypeName();
222  }
223  bool IsConstexpr() const override {
224  DCHECK(!parent()->IsConstexpr());
225  return false;
226  }
227  const Type* NonConstexprVersion() const override { return this; }
228 
229  const TypeVector& parameter_types() const { return parameter_types_; }
230  const Type* return_type() const { return return_type_; }
231 
232  friend size_t hash_value(const FunctionPointerType& p) {
233  size_t result = base::hash_value(p.return_type_);
234  for (const Type* parameter : p.parameter_types_) {
235  result = base::hash_combine(result, parameter);
236  }
237  return result;
238  }
239  bool operator==(const FunctionPointerType& other) const {
240  return parameter_types_ == other.parameter_types_ &&
241  return_type_ == other.return_type_;
242  }
243  size_t function_pointer_type_id() const { return function_pointer_type_id_; }
244 
245  private:
246  friend class TypeOracle;
247  FunctionPointerType(const Type* parent, TypeVector parameter_types,
248  const Type* return_type, size_t function_pointer_type_id)
249  : Type(Kind::kFunctionPointerType, parent),
250  parameter_types_(parameter_types),
251  return_type_(return_type),
252  function_pointer_type_id_(function_pointer_type_id) {}
253 
254  const TypeVector parameter_types_;
255  const Type* const return_type_;
256  const size_t function_pointer_type_id_;
257 };
258 
259 bool operator<(const Type& a, const Type& b);
260 struct TypeLess {
261  bool operator()(const Type* const a, const Type* const b) const {
262  return *a < *b;
263  }
264 };
265 
266 class UnionType final : public Type {
267  public:
268  DECLARE_TYPE_BOILERPLATE(UnionType);
269  std::string ToExplicitString() const override;
270  std::string MangledName() const override;
271  std::string GetGeneratedTypeName() const override {
272  return "compiler::TNode<" + GetGeneratedTNodeTypeName() + ">";
273  }
274  std::string GetGeneratedTNodeTypeName() const override;
275 
276  bool IsConstexpr() const override {
277  DCHECK_EQ(false, parent()->IsConstexpr());
278  return false;
279  }
280  const Type* NonConstexprVersion() const override;
281 
282  friend size_t hash_value(const UnionType& p) {
283  size_t result = 0;
284  for (const Type* t : p.types_) {
285  result = base::hash_combine(result, t);
286  }
287  return result;
288  }
289  bool operator==(const UnionType& other) const {
290  return types_ == other.types_;
291  }
292 
293  base::Optional<const Type*> GetSingleMember() const {
294  if (types_.size() == 1) {
295  DCHECK_EQ(*types_.begin(), parent());
296  return *types_.begin();
297  }
298  return base::nullopt;
299  }
300 
301  bool IsSubtypeOf(const Type* other) const override {
302  for (const Type* member : types_) {
303  if (!member->IsSubtypeOf(other)) return false;
304  }
305  return true;
306  }
307 
308  bool IsSupertypeOf(const Type* other) const {
309  for (const Type* member : types_) {
310  if (other->IsSubtypeOf(member)) {
311  return true;
312  }
313  }
314  return false;
315  }
316 
317  bool IsTransient() const override {
318  for (const Type* member : types_) {
319  if (member->IsTransient()) {
320  return true;
321  }
322  }
323  return false;
324  }
325 
326  void Extend(const Type* t) {
327  if (const UnionType* union_type = UnionType::DynamicCast(t)) {
328  for (const Type* member : union_type->types_) {
329  Extend(member);
330  }
331  } else {
332  if (t->IsSubtypeOf(this)) return;
333  set_parent(CommonSupertype(parent(), t));
334  for (const Type* member : types_) {
335  if (member->IsSubtypeOf(t)) {
336  types_.erase(member);
337  }
338  }
339  types_.insert(t);
340  }
341  }
342 
343  void Subtract(const Type* t);
344 
345  static UnionType FromType(const Type* t) {
346  const UnionType* union_type = UnionType::DynamicCast(t);
347  return union_type ? UnionType(*union_type) : UnionType(t);
348  }
349 
350  private:
351  explicit UnionType(const Type* t) : Type(Kind::kUnionType, t), types_({t}) {}
352  void RecomputeParent();
353 
354  std::set<const Type*, TypeLess> types_;
355 };
356 
357 const Type* SubtractType(const Type* a, const Type* b);
358 
359 class StructType final : public Type {
360  public:
361  DECLARE_TYPE_BOILERPLATE(StructType);
362  std::string ToExplicitString() const override;
363  std::string MangledName() const override { return name_; }
364  std::string GetGeneratedTypeName() const override;
365  std::string GetGeneratedTNodeTypeName() const override { UNREACHABLE(); }
366  const Type* NonConstexprVersion() const override { return this; }
367 
368  bool IsConstexpr() const override { return false; }
369 
370  const std::vector<NameAndType>& fields() const { return fields_; }
371  const Type* GetFieldType(const std::string& fieldname) const {
372  for (const NameAndType& field : fields()) {
373  if (field.name == fieldname) return field.type;
374  }
375  std::stringstream s;
376  s << "\"" << fieldname << "\" is not a field of struct type \"" << name()
377  << "\"";
378  ReportError(s.str());
379  }
380  const std::string& name() const { return name_; }
381  Namespace* nspace() const { return namespace_; }
382 
383  private:
384  friend class TypeOracle;
385  StructType(Namespace* nspace, const std::string& name,
386  const std::vector<NameAndType>& fields)
387  : Type(Kind::kStructType, nullptr),
388  namespace_(nspace),
389  name_(name),
390  fields_(fields) {}
391 
392  const std::string& GetStructName() const { return name_; }
393 
394  Namespace* namespace_;
395  std::string name_;
396  std::vector<NameAndType> fields_;
397 };
398 
399 inline std::ostream& operator<<(std::ostream& os, const Type& t) {
400  os << t.ToString();
401  return os;
402 }
403 
404 class VisitResult {
405  public:
406  VisitResult() = default;
407  VisitResult(const Type* type, const std::string& constexpr_value)
408  : type_(type), constexpr_value_(constexpr_value) {
409  DCHECK(type->IsConstexpr());
410  }
411  static VisitResult NeverResult();
412  VisitResult(const Type* type, StackRange stack_range)
413  : type_(type), stack_range_(stack_range) {
414  DCHECK(!type->IsConstexpr());
415  }
416  const Type* type() const { return type_; }
417  const std::string& constexpr_value() const { return *constexpr_value_; }
418  const StackRange& stack_range() const { return *stack_range_; }
419  void SetType(const Type* new_type) { type_ = new_type; }
420  bool IsOnStack() const { return stack_range_ != base::nullopt; }
421  bool operator==(const VisitResult& other) const {
422  return type_ == other.type_ && constexpr_value_ == other.constexpr_value_ &&
423  stack_range_ == other.stack_range_;
424  }
425 
426  private:
427  const Type* type_ = nullptr;
428  base::Optional<std::string> constexpr_value_;
429  base::Optional<StackRange> stack_range_;
430 };
431 
432 VisitResult ProjectStructField(VisitResult structure,
433  const std::string& fieldname);
434 
435 class VisitResultVector : public std::vector<VisitResult> {
436  public:
437  VisitResultVector() : std::vector<VisitResult>() {}
438  VisitResultVector(std::initializer_list<VisitResult> init)
439  : std::vector<VisitResult>(init) {}
440  TypeVector GetTypeVector() const {
441  TypeVector result;
442  for (auto& visit_result : *this) {
443  result.push_back(visit_result.type());
444  }
445  return result;
446  }
447 };
448 
449 std::ostream& operator<<(std::ostream& os, const TypeVector& types);
450 
451 typedef std::vector<NameAndType> NameAndTypeVector;
452 
454  std::string name;
455  NameAndTypeVector parameters;
456 };
457 
458 typedef std::vector<LabelDefinition> LabelDefinitionVector;
459 
461  std::string name;
462  TypeVector types;
463 };
464 
465 typedef std::vector<LabelDeclaration> LabelDeclarationVector;
466 
468  TypeVector types;
469  bool var_args;
470 };
471 
472 std::ostream& operator<<(std::ostream& os, const ParameterTypes& parameters);
473 
474 enum class ParameterMode { kProcessImplicit, kIgnoreImplicit };
475 
476 struct Signature {
477  Signature(NameVector n, base::Optional<std::string> arguments_variable,
478  ParameterTypes p, size_t i, const Type* r, LabelDeclarationVector l)
479  : parameter_names(std::move(n)),
480  arguments_variable(arguments_variable),
481  parameter_types(std::move(p)),
482  implicit_count(i),
483  return_type(r),
484  labels(std::move(l)) {}
485  Signature() : implicit_count(0), return_type(nullptr) {}
486  const TypeVector& types() const { return parameter_types.types; }
487  NameVector parameter_names;
488  base::Optional<std::string> arguments_variable;
489  ParameterTypes parameter_types;
490  size_t implicit_count;
491  const Type* return_type;
492  LabelDeclarationVector labels;
493  bool HasSameTypesAs(
494  const Signature& other,
495  ParameterMode mode = ParameterMode::kProcessImplicit) const;
496  const TypeVector& GetTypes() const { return parameter_types.types; }
497  TypeVector GetImplicitTypes() const {
498  return TypeVector(parameter_types.types.begin(),
499  parameter_types.types.begin() + implicit_count);
500  }
501  TypeVector GetExplicitTypes() const {
502  return TypeVector(parameter_types.types.begin() + implicit_count,
503  parameter_types.types.end());
504  }
505 };
506 
507 void PrintSignature(std::ostream& os, const Signature& sig, bool with_names);
508 std::ostream& operator<<(std::ostream& os, const Signature& sig);
509 
510 bool IsAssignableFrom(const Type* to, const Type* from);
511 
512 TypeVector LowerType(const Type* type);
513 size_t LoweredSlotCount(const Type* type);
514 TypeVector LowerParameterTypes(const TypeVector& parameters);
515 TypeVector LowerParameterTypes(const ParameterTypes& parameter_types,
516  size_t vararg_count = 0);
517 
518 } // namespace torque
519 } // namespace internal
520 } // namespace v8
521 
522 #endif // V8_TORQUE_TYPES_H_
Definition: libplatform.h:13