• 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 #include <iostream>
6 
7 #include "src/torque/declarable.h"
8 #include "src/torque/type-oracle.h"
9 #include "src/torque/types.h"
10 
11 namespace v8 {
12 namespace internal {
13 namespace torque {
14 
ToString() const15 std::string Type::ToString() const {
16   if (aliases_.size() == 0) return ToExplicitString();
17   if (aliases_.size() == 1) return *aliases_.begin();
18   std::stringstream result;
19   int i = 0;
20   for (const std::string& alias : aliases_) {
21     if (i == 0) {
22       result << alias << " (aka. ";
23     } else if (i == 1) {
24       result << alias;
25     } else {
26       result << ", " << alias;
27     }
28     ++i;
29   }
30   result << ")";
31   return result.str();
32 }
33 
IsSubtypeOf(const Type * supertype) const34 bool Type::IsSubtypeOf(const Type* supertype) const {
35   if (IsNever()) return true;
36   if (const UnionType* union_type = UnionType::DynamicCast(supertype)) {
37     return union_type->IsSupertypeOf(this);
38   }
39   const Type* subtype = this;
40   while (subtype != nullptr) {
41     if (subtype == supertype) return true;
42     subtype = subtype->parent();
43   }
44   return false;
45 }
46 
47 // static
CommonSupertype(const Type * a,const Type * b)48 const Type* Type::CommonSupertype(const Type* a, const Type* b) {
49   int diff = a->Depth() - b->Depth();
50   const Type* a_supertype = a;
51   const Type* b_supertype = b;
52   for (; diff > 0; --diff) a_supertype = a_supertype->parent();
53   for (; diff < 0; ++diff) b_supertype = b_supertype->parent();
54   while (a_supertype && b_supertype) {
55     if (a_supertype == b_supertype) return a_supertype;
56     a_supertype = a_supertype->parent();
57     b_supertype = b_supertype->parent();
58   }
59   ReportError("types " + a->ToString() + " and " + b->ToString() +
60               " have no common supertype");
61 }
62 
Depth() const63 int Type::Depth() const {
64   int result = 0;
65   for (const Type* current = parent_; current; current = current->parent_) {
66     ++result;
67   }
68   return result;
69 }
70 
IsAbstractName(const std::string & name) const71 bool Type::IsAbstractName(const std::string& name) const {
72   if (!IsAbstractType()) return false;
73   return AbstractType::cast(this)->name() == name;
74 }
75 
GetGeneratedTNodeTypeName() const76 std::string AbstractType::GetGeneratedTNodeTypeName() const {
77   std::string result = GetGeneratedTypeName();
78   DCHECK_EQ(result.substr(0, 6), "TNode<");
79   result = result.substr(6, result.length() - 7);
80   return result;
81 }
82 
ToExplicitString() const83 std::string FunctionPointerType::ToExplicitString() const {
84   std::stringstream result;
85   result << "builtin (";
86   PrintCommaSeparatedList(result, parameter_types_);
87   result << ") => " << *return_type_;
88   return result.str();
89 }
90 
MangledName() const91 std::string FunctionPointerType::MangledName() const {
92   std::stringstream result;
93   result << "FT";
94   for (const Type* t : parameter_types_) {
95     std::string arg_type_string = t->MangledName();
96     result << arg_type_string.size() << arg_type_string;
97   }
98   std::string return_type_string = return_type_->MangledName();
99   result << return_type_string.size() << return_type_string;
100   return result.str();
101 }
102 
ToExplicitString() const103 std::string UnionType::ToExplicitString() const {
104   std::stringstream result;
105   result << "(";
106   bool first = true;
107   for (const Type* t : types_) {
108     if (!first) {
109       result << " | ";
110     }
111     first = false;
112     result << *t;
113   }
114   result << ")";
115   return result.str();
116 }
117 
MangledName() const118 std::string UnionType::MangledName() const {
119   std::stringstream result;
120   result << "UT";
121   for (const Type* t : types_) {
122     std::string arg_type_string = t->MangledName();
123     result << arg_type_string.size() << arg_type_string;
124   }
125   return result.str();
126 }
127 
GetGeneratedTNodeTypeName() const128 std::string UnionType::GetGeneratedTNodeTypeName() const {
129   if (types_.size() <= 3) {
130     std::set<std::string> members;
131     for (const Type* t : types_) {
132       members.insert(t->GetGeneratedTNodeTypeName());
133     }
134     if (members == std::set<std::string>{"Smi", "HeapNumber"}) {
135       return "Number";
136     }
137     if (members == std::set<std::string>{"Smi", "HeapNumber", "BigInt"}) {
138       return "Numeric";
139     }
140   }
141   return parent()->GetGeneratedTNodeTypeName();
142 }
143 
NonConstexprVersion() const144 const Type* UnionType::NonConstexprVersion() const {
145   if (IsConstexpr()) {
146     auto it = types_.begin();
147     UnionType result((*it)->NonConstexprVersion());
148     ++it;
149     for (; it != types_.end(); ++it) {
150       result.Extend((*it)->NonConstexprVersion());
151     }
152     return TypeOracle::GetUnionType(std::move(result));
153   }
154   return this;
155 }
156 
RecomputeParent()157 void UnionType::RecomputeParent() {
158   const Type* parent = nullptr;
159   for (const Type* t : types_) {
160     if (parent == nullptr) {
161       parent = t;
162     } else {
163       parent = CommonSupertype(parent, t);
164     }
165   }
166   set_parent(parent);
167 }
168 
Subtract(const Type * t)169 void UnionType::Subtract(const Type* t) {
170   for (auto it = types_.begin(); it != types_.end();) {
171     if ((*it)->IsSubtypeOf(t)) {
172       it = types_.erase(it);
173     } else {
174       ++it;
175     }
176   }
177   if (types_.size() == 0) types_.insert(TypeOracle::GetNeverType());
178   RecomputeParent();
179 }
180 
SubtractType(const Type * a,const Type * b)181 const Type* SubtractType(const Type* a, const Type* b) {
182   UnionType result = UnionType::FromType(a);
183   result.Subtract(b);
184   return TypeOracle::GetUnionType(result);
185 }
186 
ToExplicitString() const187 std::string StructType::ToExplicitString() const {
188   std::stringstream result;
189   result << "{";
190   PrintCommaSeparatedList(result, fields_);
191   result << "}";
192   return result.str();
193 }
194 
PrintSignature(std::ostream & os,const Signature & sig,bool with_names)195 void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
196   os << "(";
197   for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) {
198     if (i > 0) os << ", ";
199     if (with_names && !sig.parameter_names.empty()) {
200       os << sig.parameter_names[i] << ": ";
201     }
202     os << *sig.parameter_types.types[i];
203   }
204   if (sig.parameter_types.var_args) {
205     if (sig.parameter_names.size()) os << ", ";
206     os << "...";
207   }
208   os << ")";
209   os << ": " << *sig.return_type;
210 
211   if (sig.labels.empty()) return;
212 
213   os << " labels ";
214   for (size_t i = 0; i < sig.labels.size(); ++i) {
215     if (i > 0) os << ", ";
216     if (with_names) os << sig.labels[i].name;
217 
218     if (sig.labels[i].types.size() > 0) os << "(" << sig.labels[i].types << ")";
219   }
220 }
221 
operator <<(std::ostream & os,const NameAndType & name_and_type)222 std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type) {
223   os << name_and_type.name;
224   os << ": ";
225   os << *name_and_type.type;
226   return os;
227 }
228 
operator <<(std::ostream & os,const Signature & sig)229 std::ostream& operator<<(std::ostream& os, const Signature& sig) {
230   PrintSignature(os, sig, true);
231   return os;
232 }
233 
operator <<(std::ostream & os,const TypeVector & types)234 std::ostream& operator<<(std::ostream& os, const TypeVector& types) {
235   PrintCommaSeparatedList(os, types);
236   return os;
237 }
238 
operator <<(std::ostream & os,const ParameterTypes & p)239 std::ostream& operator<<(std::ostream& os, const ParameterTypes& p) {
240   PrintCommaSeparatedList(os, p.types);
241   if (p.var_args) {
242     if (p.types.size() > 0) os << ", ";
243     os << "...";
244   }
245   return os;
246 }
247 
HasSameTypesAs(const Signature & other) const248 bool Signature::HasSameTypesAs(const Signature& other) const {
249   if (!(parameter_types.types == other.parameter_types.types &&
250         parameter_types.var_args == other.parameter_types.var_args &&
251         return_type == other.return_type)) {
252     return false;
253   }
254   if (labels.size() != other.labels.size()) {
255     return false;
256   }
257   size_t i = 0;
258   for (auto l : labels) {
259     if (l.types != other.labels[i++].types) {
260       return false;
261     }
262   }
263   return true;
264 }
265 
IsAssignableFrom(const Type * to,const Type * from)266 bool IsAssignableFrom(const Type* to, const Type* from) {
267   if (to == from) return true;
268   if (from->IsSubtypeOf(to)) return true;
269   return TypeOracle::IsImplicitlyConvertableFrom(to, from);
270 }
271 
IsCompatibleSignature(const Signature & sig,const TypeVector & types,const std::vector<Label * > & labels)272 bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
273                            const std::vector<Label*>& labels) {
274   auto i = sig.parameter_types.types.begin();
275   if (sig.parameter_types.types.size() > types.size()) return false;
276   // TODO(danno): The test below is actually insufficient. The labels'
277   // parameters must be checked too. ideally, the named part of
278   // LabelDeclarationVector would be factored out so that the label count and
279   // parameter types could be passed separately.
280   if (sig.labels.size() != labels.size()) return false;
281   for (auto current : types) {
282     if (i == sig.parameter_types.types.end()) {
283       if (!sig.parameter_types.var_args) return false;
284       if (!IsAssignableFrom(TypeOracle::GetObjectType(), current)) return false;
285     } else {
286       if (!IsAssignableFrom(*i++, current)) return false;
287     }
288   }
289   return true;
290 }
291 
operator <(const Type & a,const Type & b)292 bool operator<(const Type& a, const Type& b) {
293   return a.MangledName() < b.MangledName();
294 }
295 
VisitResult(const Type * type,const Value * declarable)296 VisitResult::VisitResult(const Type* type, const Value* declarable)
297     : type_(type), value_(), declarable_(declarable) {}
298 
LValue() const299 std::string VisitResult::LValue() const {
300   return std::string("*") + (declarable_ ? (*declarable_)->value() : value_);
301 }
302 
RValue() const303 std::string VisitResult::RValue() const {
304   std::string result;
305   if (declarable()) {
306     auto value = *declarable();
307     if (value->IsVariable() && !Variable::cast(value)->IsDefined()) {
308       std::stringstream s;
309       s << "\"" << value->name() << "\" is used before it is defined";
310       ReportError(s.str());
311     }
312     result = value->RValue();
313   } else {
314     result = value_;
315   }
316   return "implicit_cast<" + type()->GetGeneratedTypeName() + ">(" + result +
317          ")";
318 }
319 
320 }  // namespace torque
321 }  // namespace internal
322 }  // namespace v8
323