types.cc 8.76 KB
Newer Older
1 2 3 4 5 6
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <iostream>

7
#include "src/torque/declarable.h"
8
#include "src/torque/type-oracle.h"
9 10 11 12 13 14
#include "src/torque/types.h"

namespace v8 {
namespace internal {
namespace torque {

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
std::string Type::ToString() const {
  if (aliases_.size() == 0) return ToExplicitString();
  if (aliases_.size() == 1) return *aliases_.begin();
  std::stringstream result;
  int i = 0;
  for (const std::string& alias : aliases_) {
    if (i == 0) {
      result << alias << " (aka. ";
    } else if (i == 1) {
      result << alias;
    } else {
      result << ", " << alias;
    }
    ++i;
  }
  result << ")";
  return result.str();
}

34
bool Type::IsSubtypeOf(const Type* supertype) const {
35
  if (IsNever()) return true;
36 37 38
  if (const UnionType* union_type = UnionType::DynamicCast(supertype)) {
    return union_type->IsSupertypeOf(this);
  }
39 40 41 42 43 44 45 46
  const Type* subtype = this;
  while (subtype != nullptr) {
    if (subtype == supertype) return true;
    subtype = subtype->parent();
  }
  return false;
}

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
// static
const Type* Type::CommonSupertype(const Type* a, const Type* b) {
  int diff = a->Depth() - b->Depth();
  const Type* a_supertype = a;
  const Type* b_supertype = b;
  for (; diff > 0; --diff) a_supertype = a_supertype->parent();
  for (; diff < 0; ++diff) b_supertype = b_supertype->parent();
  while (a_supertype && b_supertype) {
    if (a_supertype == b_supertype) return a_supertype;
    a_supertype = a_supertype->parent();
    b_supertype = b_supertype->parent();
  }
  ReportError("types " + a->ToString() + " and " + b->ToString() +
              " have no common supertype");
}

int Type::Depth() const {
  int result = 0;
  for (const Type* current = parent_; current; current = current->parent_) {
    ++result;
  }
  return result;
}

71 72 73 74 75 76 77 78 79 80 81 82
bool Type::IsAbstractName(const std::string& name) const {
  if (!IsAbstractType()) return false;
  return AbstractType::cast(this)->name() == name;
}

std::string AbstractType::GetGeneratedTNodeTypeName() const {
  std::string result = GetGeneratedTypeName();
  DCHECK_EQ(result.substr(0, 6), "TNode<");
  result = result.substr(6, result.length() - 7);
  return result;
}

83
std::string FunctionPointerType::ToExplicitString() const {
84 85
  std::stringstream result;
  result << "builtin (";
86 87
  PrintCommaSeparatedList(result, parameter_types_);
  result << ") => " << *return_type_;
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
  return result.str();
}

std::string FunctionPointerType::MangledName() const {
  std::stringstream result;
  result << "FT";
  for (const Type* t : parameter_types_) {
    std::string arg_type_string = t->MangledName();
    result << arg_type_string.size() << arg_type_string;
  }
  std::string return_type_string = return_type_->MangledName();
  result << return_type_string.size() << return_type_string;
  return result.str();
}

103 104 105 106 107 108 109 110 111
std::string UnionType::ToExplicitString() const {
  std::stringstream result;
  result << "(";
  bool first = true;
  for (const Type* t : types_) {
    if (!first) {
      result << " | ";
    }
    first = false;
112
    result << *t;
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
  }
  result << ")";
  return result.str();
}

std::string UnionType::MangledName() const {
  std::stringstream result;
  result << "UT";
  for (const Type* t : types_) {
    std::string arg_type_string = t->MangledName();
    result << arg_type_string.size() << arg_type_string;
  }
  return result.str();
}

std::string UnionType::GetGeneratedTNodeTypeName() const {
  if (types_.size() <= 3) {
    std::set<std::string> members;
    for (const Type* t : types_) {
      members.insert(t->GetGeneratedTNodeTypeName());
    }
    if (members == std::set<std::string>{"Smi", "HeapNumber"}) {
      return "Number";
    }
    if (members == std::set<std::string>{"Smi", "HeapNumber", "BigInt"}) {
      return "Numeric";
    }
  }
  return parent()->GetGeneratedTNodeTypeName();
}

144 145 146 147 148 149 150 151 152 153 154 155 156
const Type* UnionType::NonConstexprVersion() const {
  if (IsConstexpr()) {
    auto it = types_.begin();
    UnionType result((*it)->NonConstexprVersion());
    ++it;
    for (; it != types_.end(); ++it) {
      result.Extend((*it)->NonConstexprVersion());
    }
    return TypeOracle::GetUnionType(std::move(result));
  }
  return this;
}

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
void UnionType::RecomputeParent() {
  const Type* parent = nullptr;
  for (const Type* t : types_) {
    if (parent == nullptr) {
      parent = t;
    } else {
      parent = CommonSupertype(parent, t);
    }
  }
  set_parent(parent);
}

void UnionType::Subtract(const Type* t) {
  for (auto it = types_.begin(); it != types_.end();) {
    if ((*it)->IsSubtypeOf(t)) {
      it = types_.erase(it);
    } else {
      ++it;
    }
  }
  if (types_.size() == 0) types_.insert(TypeOracle::GetNeverType());
  RecomputeParent();
}

const Type* SubtractType(const Type* a, const Type* b) {
  UnionType result = UnionType::FromType(a);
  result.Subtract(b);
  return TypeOracle::GetUnionType(result);
}

187 188 189 190 191 192 193 194
std::string StructType::ToExplicitString() const {
  std::stringstream result;
  result << "{";
  PrintCommaSeparatedList(result, fields_);
  result << "}";
  return result.str();
}

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 200 201 202
    if (with_names && !sig.parameter_names.empty()) {
      os << sig.parameter_names[i] << ": ";
    }
    os << *sig.parameter_types.types[i];
203 204 205 206 207 208
  }
  if (sig.parameter_types.var_args) {
    if (sig.parameter_names.size()) os << ", ";
    os << "...";
  }
  os << ")";
209
  os << ": " << *sig.return_type;
210

211
  if (sig.labels.empty()) return;
212 213 214 215

  os << " labels ";
  for (size_t i = 0; i < sig.labels.size(); ++i) {
    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
}

222 223 224 225 226 227 228
std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type) {
  os << name_and_type.name;
  os << ": ";
  os << *name_and_type.type;
  return os;
}

229 230
std::ostream& operator<<(std::ostream& os, const Signature& sig) {
  PrintSignature(os, sig, true);
231 232 233 234
  return os;
}

std::ostream& operator<<(std::ostream& os, const TypeVector& types) {
235
  PrintCommaSeparatedList(os, types);
236 237 238 239
  return os;
}

std::ostream& operator<<(std::ostream& os, const ParameterTypes& p) {
240
  PrintCommaSeparatedList(os, p.types);
241 242 243 244 245 246 247
  if (p.var_args) {
    if (p.types.size() > 0) os << ", ";
    os << "...";
  }
  return os;
}

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
bool Signature::HasSameTypesAs(const Signature& other) const {
  if (!(parameter_types.types == other.parameter_types.types &&
        parameter_types.var_args == other.parameter_types.var_args &&
        return_type == other.return_type)) {
    return false;
  }
  if (labels.size() != other.labels.size()) {
    return false;
  }
  size_t i = 0;
  for (auto l : labels) {
    if (l.types != other.labels[i++].types) {
      return false;
    }
  }
  return true;
}

266 267
bool IsAssignableFrom(const Type* to, const Type* from) {
  if (to == from) return true;
268 269
  if (from->IsSubtypeOf(to)) return true;
  return TypeOracle::IsImplicitlyConvertableFrom(to, from);
270 271
}

272 273 274
bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
                           const std::vector<Label*>& labels) {
  auto i = sig.parameter_types.types.begin();
275
  if (sig.parameter_types.types.size() > types.size()) return false;
276 277 278 279 280 281 282 283
  // TODO(danno): The test below is actually insufficient. The labels'
  // parameters must be checked too. ideally, the named part of
  // LabelDeclarationVector would be factored out so that the label count and
  // parameter types could be passed separately.
  if (sig.labels.size() != labels.size()) return false;
  for (auto current : types) {
    if (i == sig.parameter_types.types.end()) {
      if (!sig.parameter_types.var_args) return false;
284 285 286 287 288 289 290 291
      if (!IsAssignableFrom(TypeOracle::GetObjectType(), current)) return false;
    } else {
      if (!IsAssignableFrom(*i++, current)) return false;
    }
  }
  return true;
}

292 293 294 295
bool operator<(const Type& a, const Type& b) {
  return a.MangledName() < b.MangledName();
}

296
VisitResult::VisitResult(const Type* type, const Value* declarable)
297
    : type_(type), value_(), declarable_(declarable) {}
298

299 300 301
std::string VisitResult::LValue() const {
  return std::string("*") + (declarable_ ? (*declarable_)->value() : value_);
}
302 303

std::string VisitResult::RValue() const {
304
  std::string result;
305 306 307 308 309 310 311
  if (declarable()) {
    auto value = *declarable();
    if (value->IsVariable() && !Variable::cast(value)->IsDefined()) {
      std::stringstream s;
      s << "\"" << value->name() << "\" is used before it is defined";
      ReportError(s.str());
    }
312
    result = value->RValue();
313
  } else {
314
    result = value_;
315
  }
316 317
  return "implicit_cast<" + type()->GetGeneratedTypeName() + ">(" + result +
         ")";
318 319
}

320 321 322
}  // namespace torque
}  // namespace internal
}  // namespace v8