// Copyright 2020 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/wasm/wasm-subtyping.h"
#include "test/unittests/test-utils.h"

namespace v8 {
namespace internal {
namespace wasm {
namespace subtyping_unittest {

class WasmSubtypingTest : public ::testing::Test {};
using FieldInit = std::pair<ValueType, bool>;

ValueType ref(uint32_t index) { return ValueType::Ref(index, kNonNullable); }
ValueType optRef(uint32_t index) { return ValueType::Ref(index, kNullable); }

FieldInit mut(ValueType type) { return FieldInit(type, true); }
FieldInit immut(ValueType type) { return FieldInit(type, false); }

void DefineStruct(WasmModule* module, std::initializer_list<FieldInit> fields) {
  StructType::Builder builder(module->signature_zone.get(),
                              static_cast<uint32_t>(fields.size()));
  for (FieldInit field : fields) {
    builder.AddField(field.first, field.second);
  }
  return module->add_struct_type(builder.Build());
}

void DefineArray(WasmModule* module, FieldInit element_type) {
  module->add_array_type(module->signature_zone->New<ArrayType>(
      element_type.first, element_type.second));
}

TEST_F(WasmSubtypingTest, Subtyping) {
  v8::internal::AccountingAllocator allocator;
  WasmModule module1_(std::make_unique<Zone>(&allocator, ZONE_NAME));
  WasmModule module2_(std::make_unique<Zone>(&allocator, ZONE_NAME));

  WasmModule* module1 = &module1_;
  WasmModule* module2 = &module2_;

  // Set up two identical modules.
  for (WasmModule* module : {module1, module2}) {
    /* 0 */ DefineStruct(module, {mut(ref(2)), immut(optRef(2))});
    /* 1 */ DefineStruct(module, {mut(ref(2)), immut(ref(2))});
    /* 2 */ DefineArray(module, immut(ref(0)));
    /* 3 */ DefineArray(module, immut(ref(1)));
    /* 4 */ DefineStruct(module, {mut(ref(2)), immut(ref(3)), immut(kWasmF64)});
    /* 5 */ DefineStruct(module, {mut(optRef(2)), immut(ref(2))});
    /* 6 */ DefineArray(module, mut(kWasmI32));
    /* 7 */ DefineArray(module, immut(kWasmI32));
    /* 8 */ DefineStruct(module, {mut(kWasmI32), immut(optRef(8))});
    /* 9 */ DefineStruct(module, {mut(kWasmI32), immut(optRef(8))});
  }

  ValueType numeric_types[] = {kWasmI32, kWasmI64, kWasmF32, kWasmF64,
                               kWasmS128};
  ValueType ref_types[] = {kWasmExternRef, kWasmFuncRef, kWasmExnRef,
                           kWasmEqRef,     kWasmI31Ref,  optRef(0),
                           ref(0),         optRef(2),    ref(2)};

  // Type judgements across modules should work the same as within one module.
  for (WasmModule* module : {module1, module2}) {
    // Value types are unrelated, except if they are equal.
    for (ValueType subtype : numeric_types) {
      for (ValueType supertype : numeric_types) {
        CHECK_EQ(IsSubtypeOf(subtype, supertype, module1, module),
                 subtype == supertype);
      }
    }

    // Value types are unrelated with reference types.
    for (ValueType value_type : numeric_types) {
      for (ValueType ref_type : ref_types) {
        CHECK(!IsSubtypeOf(value_type, ref_type, module1, module));
        CHECK(!IsSubtypeOf(ref_type, value_type, module1, module));
      }
    }

    for (ValueType ref_type : ref_types) {
      // Concrete reference types and i31ref are subtypes of eqref,
      // exnref/externref/funcref are not.
      CHECK_EQ(IsSubtypeOf(ref_type, kWasmEqRef, module1, module),
               ref_type != kWasmFuncRef && ref_type != kWasmExternRef &&
                   ref_type != kWasmExnRef);
      // Each reference type is a subtype of itself.
      CHECK(IsSubtypeOf(ref_type, ref_type, module1, module));
    }

    // The rest of ref. types are unrelated.
    for (ValueType type_1 :
         {kWasmExternRef, kWasmFuncRef, kWasmExnRef, kWasmI31Ref}) {
      for (ValueType type_2 :
           {kWasmExternRef, kWasmFuncRef, kWasmExnRef, kWasmI31Ref}) {
        CHECK_EQ(IsSubtypeOf(type_1, type_2, module1, module),
                 type_1 == type_2);
      }
    }

    // Unrelated refs are unrelated.
    CHECK(!IsSubtypeOf(ref(0), ref(2), module1, module));
    CHECK(!IsSubtypeOf(optRef(3), optRef(1), module1, module));
    // ref is a subtype of optref for the same struct/array.
    CHECK(IsSubtypeOf(ref(0), optRef(0), module1, module));
    CHECK(IsSubtypeOf(ref(2), optRef(2), module1, module));
    // optref is not a subtype of ref for the same struct/array.
    CHECK(!IsSubtypeOf(optRef(0), ref(0), module1, module));
    CHECK(!IsSubtypeOf(optRef(2), ref(2), module1, module));
    // ref is a subtype of optref if the same is true for the underlying
    // structs/arrays.
    CHECK(IsSubtypeOf(ref(3), optRef(2), module1, module));
    // Prefix subtyping for structs.
    CHECK(IsSubtypeOf(optRef(4), optRef(0), module1, module));
    // Mutable fields are invariant.
    CHECK(!IsSubtypeOf(ref(0), ref(5), module1, module));
    // Immutable fields are covariant.
    CHECK(IsSubtypeOf(ref(1), ref(0), module1, module));
    // Prefix subtyping + immutable field covariance for structs.
    CHECK(IsSubtypeOf(optRef(4), optRef(1), module1, module));
    // No subtyping between mutable/immutable fields.
    CHECK(!IsSubtypeOf(ref(7), ref(6), module1, module));
    CHECK(!IsSubtypeOf(ref(6), ref(7), module1, module));
    // Recursive types.
    CHECK(IsSubtypeOf(ref(9), ref(8), module1, module));

    // Identical rtts are subtypes of each other.
    CHECK(IsSubtypeOf(ValueType::Rtt(5, 3), ValueType::Rtt(5, 3), module1,
                      module2));
    CHECK(IsSubtypeOf(ValueType::Rtt(HeapType::kExn, 3),
                      ValueType::Rtt(HeapType::kExn, 3), module1, module2));
    // Rtts of different depth are unrelated.
    CHECK(!IsSubtypeOf(ValueType::Rtt(5, 1), ValueType::Rtt(5, 3), module1,
                       module2));
    CHECK(!IsSubtypeOf(ValueType::Rtt(5, 8), ValueType::Rtt(5, 3), module1,
                       module2));
    // Rtts of identical types are subtype-related.
    CHECK(IsSubtypeOf(ValueType::Rtt(8, 1), ValueType::Rtt(9, 1), module1,
                      module));
    // Rtts of subtypes are not related.
    CHECK(!IsSubtypeOf(ValueType::Rtt(1, 1), ValueType::Rtt(0, 1), module1,
                       module));
  }
}

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