• 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 <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