asm-types.cc 7.38 KB
Newer Older
jpp's avatar
jpp committed
1 2 3 4
// Copyright 2016 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.

5
#include "src/asmjs/asm-types.h"
jpp's avatar
jpp committed
6

7 8
#include <cinttypes>

9
#include "src/init/v8.h"
10
#include "src/utils/utils.h"
11

jpp's avatar
jpp committed
12 13 14 15 16
namespace v8 {
namespace internal {
namespace wasm {

AsmCallableType* AsmType::AsCallableType() {
17 18 19 20
  if (AsValueType() != nullptr) {
    return nullptr;
  }

jpp's avatar
jpp committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
  return reinterpret_cast<AsmCallableType*>(this);
}

std::string AsmType::Name() {
  AsmValueType* avt = this->AsValueType();
  if (avt != nullptr) {
    switch (avt->Bitset()) {
#define RETURN_TYPE_NAME(CamelName, string_name, number, parent_types) \
  case AsmValueType::kAsm##CamelName:                                  \
    return string_name;
      FOR_EACH_ASM_VALUE_TYPE_LIST(RETURN_TYPE_NAME)
#undef RETURN_TYPE_NAME
      default:
        UNREACHABLE();
    }
  }
37

jpp's avatar
jpp committed
38 39 40
  return this->AsCallableType()->Name();
}

41 42 43 44
bool AsmType::IsExactly(AsmType* x, AsmType* y) {
  // TODO(jpp): maybe this can become x == y.
  if (x == nullptr) return y == nullptr;
  AsmValueType* avt = x->AsValueType();
jpp's avatar
jpp committed
45
  if (avt != nullptr) {
46
    AsmValueType* tavt = y->AsValueType();
jpp's avatar
jpp committed
47 48 49 50 51
    if (tavt == nullptr) {
      return false;
    }
    return avt->Bitset() == tavt->Bitset();
  }
52

jpp's avatar
jpp committed
53 54
  // TODO(jpp): is it useful to allow non-value types to be tested with
  // IsExactly?
55
  return x == y;
jpp's avatar
jpp committed
56 57 58 59 60
}

bool AsmType::IsA(AsmType* that) {
  // IsA is used for querying inheritance relationships. Therefore it is only
  // meaningful for basic types.
61 62 63
  if (auto* avt = this->AsValueType()) {
    if (auto* tavt = that->AsValueType()) {
      return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
jpp's avatar
jpp committed
64
    }
65 66 67 68 69
    return false;
  }

  if (auto* as_callable = this->AsCallableType()) {
    return as_callable->IsA(that);
jpp's avatar
jpp committed
70
  }
71

72
  UNREACHABLE();
jpp's avatar
jpp committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 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
}

int32_t AsmType::ElementSizeInBytes() {
  auto* value = AsValueType();
  if (value == nullptr) {
    return AsmType::kNotHeapType;
  }
  switch (value->Bitset()) {
    case AsmValueType::kAsmInt8Array:
    case AsmValueType::kAsmUint8Array:
      return 1;
    case AsmValueType::kAsmInt16Array:
    case AsmValueType::kAsmUint16Array:
      return 2;
    case AsmValueType::kAsmInt32Array:
    case AsmValueType::kAsmUint32Array:
    case AsmValueType::kAsmFloat32Array:
      return 4;
    case AsmValueType::kAsmFloat64Array:
      return 8;
    default:
      return AsmType::kNotHeapType;
  }
}

AsmType* AsmType::LoadType() {
  auto* value = AsValueType();
  if (value == nullptr) {
    return AsmType::None();
  }
  switch (value->Bitset()) {
    case AsmValueType::kAsmInt8Array:
    case AsmValueType::kAsmUint8Array:
    case AsmValueType::kAsmInt16Array:
    case AsmValueType::kAsmUint16Array:
    case AsmValueType::kAsmInt32Array:
    case AsmValueType::kAsmUint32Array:
      return AsmType::Intish();
    case AsmValueType::kAsmFloat32Array:
      return AsmType::FloatQ();
    case AsmValueType::kAsmFloat64Array:
      return AsmType::DoubleQ();
    default:
      return AsmType::None();
  }
}

AsmType* AsmType::StoreType() {
  auto* value = AsValueType();
  if (value == nullptr) {
    return AsmType::None();
  }
  switch (value->Bitset()) {
    case AsmValueType::kAsmInt8Array:
    case AsmValueType::kAsmUint8Array:
    case AsmValueType::kAsmInt16Array:
    case AsmValueType::kAsmUint16Array:
    case AsmValueType::kAsmInt32Array:
    case AsmValueType::kAsmUint32Array:
      return AsmType::Intish();
    case AsmValueType::kAsmFloat32Array:
      return AsmType::FloatishDoubleQ();
    case AsmValueType::kAsmFloat64Array:
      return AsmType::FloatQDoubleQ();
    default:
      return AsmType::None();
  }
}

142 143 144
bool AsmCallableType::IsA(AsmType* other) {
  return other->AsCallableType() == this;
}
145

146
std::string AsmFunctionType::Name() {
jpp's avatar
jpp committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160
  std::string ret;
  ret += "(";
  for (size_t ii = 0; ii < args_.size(); ++ii) {
    ret += args_[ii]->Name();
    if (ii != args_.size() - 1) {
      ret += ", ";
    }
  }
  ret += ") -> ";
  ret += return_type_->Name();
  return ret;
}

namespace {
161
class AsmFroundType final : public AsmCallableType {
jpp's avatar
jpp committed
162 163 164
 public:
  friend AsmType;

165
  AsmFroundType() : AsmCallableType() {}
166

167 168
  bool CanBeInvokedWith(AsmType* return_type,
                        const ZoneVector<AsmType*>& args) override;
169 170

  std::string Name() override { return "fround"; }
jpp's avatar
jpp committed
171 172 173
};
}  // namespace

174
AsmType* AsmType::FroundType(Zone* zone) {
175
  auto* Fround = zone->New<AsmFroundType>();
jpp's avatar
jpp committed
176 177 178
  return reinterpret_cast<AsmType*>(Fround);
}

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
bool AsmFroundType::CanBeInvokedWith(AsmType* return_type,
                                     const ZoneVector<AsmType*>& args) {
  if (args.size() != 1) {
    return false;
  }

  auto* arg = args[0];
  if (!arg->IsA(AsmType::Floatish()) && !arg->IsA(AsmType::DoubleQ()) &&
      !arg->IsA(AsmType::Signed()) && !arg->IsA(AsmType::Unsigned())) {
    return false;
  }

  return true;
}

jpp's avatar
jpp committed
194
namespace {
195
class AsmMinMaxType final : public AsmCallableType {
jpp's avatar
jpp committed
196 197
 private:
  friend AsmType;
198
  friend Zone;
jpp's avatar
jpp committed
199

200 201
  AsmMinMaxType(AsmType* dest, AsmType* src)
      : AsmCallableType(), return_type_(dest), arg_(src) {}
202 203 204

  bool CanBeInvokedWith(AsmType* return_type,
                        const ZoneVector<AsmType*>& args) override {
205
    if (!AsmType::IsExactly(return_type_, return_type)) {
206 207 208 209 210 211 212
      return false;
    }

    if (args.size() < 2) {
      return false;
    }

213 214
    for (size_t ii = 0; ii < args.size(); ++ii) {
      if (!args[ii]->IsA(arg_)) {
215 216 217 218 219 220
        return false;
      }
    }

    return true;
  }
221 222 223 224 225 226 227 228

  std::string Name() override {
    return "(" + arg_->Name() + ", " + arg_->Name() + "...) -> " +
           return_type_->Name();
  }

  AsmType* return_type_;
  AsmType* arg_;
jpp's avatar
jpp committed
229 230 231
};
}  // namespace

232
AsmType* AsmType::MinMaxType(Zone* zone, AsmType* dest, AsmType* src) {
233 234
  DCHECK_NOT_NULL(dest->AsValueType());
  DCHECK_NOT_NULL(src->AsValueType());
235
  auto* MinMax = zone->New<AsmMinMaxType>(dest, src);
jpp's avatar
jpp committed
236 237 238
  return reinterpret_cast<AsmType*>(MinMax);
}

239 240 241 242 243
bool AsmFunctionType::IsA(AsmType* other) {
  auto* that = other->AsFunctionType();
  if (that == nullptr) {
    return false;
  }
244
  if (!AsmType::IsExactly(return_type_, that->return_type_)) {
245
    return false;
jpp's avatar
jpp committed
246 247
  }

248 249
  if (args_.size() != that->args_.size()) {
    return false;
jpp's avatar
jpp committed
250 251 252
  }

  for (size_t ii = 0; ii < args_.size(); ++ii) {
253
    if (!AsmType::IsExactly(args_[ii], that->args_[ii])) {
254
      return false;
jpp's avatar
jpp committed
255 256 257
    }
  }

258
  return true;
jpp's avatar
jpp committed
259 260
}

261 262
bool AsmFunctionType::CanBeInvokedWith(AsmType* return_type,
                                       const ZoneVector<AsmType*>& args) {
263
  if (!AsmType::IsExactly(return_type_, return_type)) {
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
    return false;
  }

  if (args_.size() != args.size()) {
    return false;
  }

  for (size_t ii = 0; ii < args_.size(); ++ii) {
    if (!args[ii]->IsA(args_[ii])) {
      return false;
    }
  }

  return true;
}

jpp's avatar
jpp committed
280 281 282 283 284 285 286 287 288 289 290 291 292
std::string AsmOverloadedFunctionType::Name() {
  std::string ret;

  for (size_t ii = 0; ii < overloads_.size(); ++ii) {
    if (ii != 0) {
      ret += " /\\ ";
    }
    ret += overloads_[ii]->Name();
  }

  return ret;
}

293 294 295 296 297 298 299 300 301 302 303
bool AsmOverloadedFunctionType::CanBeInvokedWith(
    AsmType* return_type, const ZoneVector<AsmType*>& args) {
  for (size_t ii = 0; ii < overloads_.size(); ++ii) {
    if (overloads_[ii]->AsCallableType()->CanBeInvokedWith(return_type, args)) {
      return true;
    }
  }

  return false;
}

jpp's avatar
jpp committed
304
void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
305
  DCHECK_NOT_NULL(overload->AsCallableType());
jpp's avatar
jpp committed
306 307 308 309 310 311
  overloads_.push_back(overload);
}

}  // namespace wasm
}  // namespace internal
}  // namespace v8