| Index: src/wasm/asm-types.cc
|
| diff --git a/src/wasm/asm-types.cc b/src/wasm/asm-types.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3d58aae1d456993055b878c8d878f6ce2ea3ff0c
|
| --- /dev/null
|
| +++ b/src/wasm/asm-types.cc
|
| @@ -0,0 +1,275 @@
|
| +// 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.
|
| +
|
| +#include "src/v8.h"
|
| +
|
| +#include "src/wasm/asm-types.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +namespace wasm {
|
| +
|
| +AsmCallableType* AsmType::AsCallableType() {
|
| + DCHECK(this->AsFunctionType() != nullptr ||
|
| + this->AsOverloadedFunctionType() != nullptr);
|
| + 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();
|
| + }
|
| + }
|
| + return this->AsCallableType()->Name();
|
| +}
|
| +
|
| +bool AsmType::IsExactly(AsmType* that) {
|
| + // TODO(jpp): maybe this can become this == that.
|
| + AsmValueType* avt = this->AsValueType();
|
| + if (avt != nullptr) {
|
| + AsmValueType* tavt = that->AsValueType();
|
| + if (tavt == nullptr) {
|
| + return false;
|
| + }
|
| + return avt->Bitset() == tavt->Bitset();
|
| + }
|
| + // TODO(jpp): is it useful to allow non-value types to be tested with
|
| + // IsExactly?
|
| + return that == this;
|
| +}
|
| +
|
| +bool AsmType::IsA(AsmType* that) {
|
| + // IsA is used for querying inheritance relationships. Therefore it is only
|
| + // meaningful for basic types.
|
| + AsmValueType* tavt = that->AsValueType();
|
| + if (tavt != nullptr) {
|
| + AsmValueType* avt = this->AsValueType();
|
| + if (avt == nullptr) {
|
| + return false;
|
| + }
|
| + return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
|
| + }
|
| + // TODO(jpp): is it useful to allow non-value types to be tested with IsA?
|
| + return that == this;
|
| +}
|
| +
|
| +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();
|
| + }
|
| +}
|
| +
|
| +std::string AsmFunctionType::Name() {
|
| + std::string ret;
|
| + ret += "(";
|
| + for (size_t ii = 0; ii < args_.size(); ++ii) {
|
| + ret += args_[ii]->Name();
|
| + if (ii != args_.size() - 1) {
|
| + ret += ", ";
|
| + }
|
| + }
|
| + if (IsMinMaxType()) {
|
| + DCHECK_EQ(args_.size(), 2);
|
| + ret += "...";
|
| + }
|
| + ret += ") -> ";
|
| + ret += return_type_->Name();
|
| + return ret;
|
| +}
|
| +
|
| +namespace {
|
| +class AsmFroundType final : public AsmFunctionType {
|
| + public:
|
| + bool IsFroundType() const override { return true; }
|
| +
|
| + private:
|
| + friend AsmType;
|
| +
|
| + AsmFroundType(Zone* zone, AsmType* src)
|
| + : AsmFunctionType(zone, AsmType::Float()) {
|
| + AddArgument(src);
|
| + }
|
| +};
|
| +} // namespace
|
| +
|
| +AsmType* AsmType::FroundType(Zone* zone, AsmType* src) {
|
| + DCHECK(src->AsValueType() != nullptr);
|
| + auto* Fround = new (zone) AsmFroundType(zone, src);
|
| + return reinterpret_cast<AsmType*>(Fround);
|
| +}
|
| +
|
| +namespace {
|
| +class AsmMinMaxType final : public AsmFunctionType {
|
| + public:
|
| + bool IsMinMaxType() const override { return true; }
|
| +
|
| + private:
|
| + friend AsmType;
|
| +
|
| + AsmMinMaxType(Zone* zone, AsmType* type) : AsmFunctionType(zone, type) {
|
| + AddArgument(type);
|
| + AddArgument(type);
|
| + }
|
| +
|
| + AsmType* ValidateCall(AsmType* function_type) override {
|
| + auto* callable = function_type->AsFunctionType();
|
| + if (callable == nullptr) {
|
| + return nullptr;
|
| + }
|
| +
|
| + if (!ReturnType()->IsExactly(callable->ReturnType())) {
|
| + return AsmType::None();
|
| + }
|
| +
|
| + if (callable->Arguments().size() < 2) {
|
| + return AsmType::None();
|
| + }
|
| +
|
| + for (size_t ii = 0; ii < Arguments().size(); ++ii) {
|
| + if (!Arguments()[0]->IsExactly(callable->Arguments()[ii])) {
|
| + return AsmType::None();
|
| + }
|
| + }
|
| +
|
| + return ReturnType();
|
| + }
|
| +};
|
| +} // namespace
|
| +
|
| +AsmType* AsmType::MinMaxType(Zone* zone, AsmType* type) {
|
| + DCHECK(type->AsValueType() != nullptr);
|
| + auto* MinMax = new (zone) AsmMinMaxType(zone, type);
|
| + return reinterpret_cast<AsmType*>(MinMax);
|
| +}
|
| +
|
| +AsmType* AsmFunctionType::ValidateCall(AsmType* function_type) {
|
| + auto* callable = function_type->AsFunctionType();
|
| + if (callable == nullptr) {
|
| + return nullptr;
|
| + }
|
| +
|
| + if (!return_type_->IsExactly(callable->return_type_)) {
|
| + return AsmType::None();
|
| + }
|
| +
|
| + if (args_.size() != callable->args_.size()) {
|
| + return AsmType::None();
|
| + }
|
| +
|
| + for (size_t ii = 0; ii < args_.size(); ++ii) {
|
| + if (!args_[ii]->IsExactly(callable->args_[ii])) {
|
| + return AsmType::None();
|
| + }
|
| + }
|
| +
|
| + return return_type_;
|
| +}
|
| +
|
| +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;
|
| +}
|
| +
|
| +AsmType* AsmOverloadedFunctionType::ValidateCall(AsmType* function_type) {
|
| + auto* callable = function_type->AsFunctionType();
|
| + if (callable == nullptr) {
|
| + return AsmType::None();
|
| + }
|
| +
|
| + for (size_t ii = 0; ii < overloads_.size(); ++ii) {
|
| + auto* validated_type =
|
| + overloads_[ii]->AsCallableType()->ValidateCall(function_type);
|
| + if (validated_type != AsmType::None()) {
|
| + return validated_type;
|
| + }
|
| + }
|
| +
|
| + return AsmType::None();
|
| +}
|
| +
|
| +void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
|
| + DCHECK(overload->AsFunctionType() != nullptr);
|
| + overloads_.push_back(overload);
|
| +}
|
| +
|
| +} // namespace wasm
|
| +} // namespace internal
|
| +} // namespace v8
|
|
|