// Copyright 2014 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 <cmath>
#include <functional>
#include <limits>
#include <memory>

#include "src/base/bits.h"
#include "src/codegen/assembler.h"
#include "src/codegen/compiler.h"
#include "src/codegen/machine-type.h"
#include "src/codegen/macro-assembler.h"
#include "src/compiler/linkage.h"
#include "src/compiler/wasm-compiler.h"
#include "src/objects/objects-inl.h"
#include "src/wasm/function-compiler.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-opcodes.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/value-helper.h"

namespace v8 {
namespace internal {
namespace compiler {

namespace {

CallDescriptor* CreateCallDescriptor(Zone* zone, int return_count,
                                     int param_count, MachineType type) {
  wasm::FunctionSig::Builder builder(zone, return_count, param_count);

  for (int i = 0; i < param_count; i++) {
    builder.AddParam(wasm::ValueType::For(type));
  }

  for (int i = 0; i < return_count; i++) {
    builder.AddReturn(wasm::ValueType::For(type));
  }
  return compiler::GetWasmCallDescriptor(zone, builder.Build());
}

Node* MakeConstant(RawMachineAssembler* m, MachineType type, int value) {
  switch (type.representation()) {
    case MachineRepresentation::kWord32:
      return m->Int32Constant(static_cast<int32_t>(value));
    case MachineRepresentation::kWord64:
      return m->Int64Constant(static_cast<int64_t>(value));
    case MachineRepresentation::kFloat32:
      return m->Float32Constant(static_cast<float>(value));
    case MachineRepresentation::kFloat64:
      return m->Float64Constant(static_cast<double>(value));
    default:
      UNREACHABLE();
  }
}

Node* Add(RawMachineAssembler* m, MachineType type, Node* a, Node* b) {
  switch (type.representation()) {
    case MachineRepresentation::kWord32:
      return m->Int32Add(a, b);
    case MachineRepresentation::kWord64:
      return m->Int64Add(a, b);
    case MachineRepresentation::kFloat32:
      return m->Float32Add(a, b);
    case MachineRepresentation::kFloat64:
      return m->Float64Add(a, b);
    default:
      UNREACHABLE();
  }
}

Node* Sub(RawMachineAssembler* m, MachineType type, Node* a, Node* b) {
  switch (type.representation()) {
    case MachineRepresentation::kWord32:
      return m->Int32Sub(a, b);
    case MachineRepresentation::kWord64:
      return m->Int64Sub(a, b);
    case MachineRepresentation::kFloat32:
      return m->Float32Sub(a, b);
    case MachineRepresentation::kFloat64:
      return m->Float64Sub(a, b);
    default:
      UNREACHABLE();
  }
}

Node* Mul(RawMachineAssembler* m, MachineType type, Node* a, Node* b) {
  switch (type.representation()) {
    case MachineRepresentation::kWord32:
      return m->Int32Mul(a, b);
    case MachineRepresentation::kWord64:
      return m->Int64Mul(a, b);
    case MachineRepresentation::kFloat32:
      return m->Float32Mul(a, b);
    case MachineRepresentation::kFloat64:
      return m->Float64Mul(a, b);
    default:
      UNREACHABLE();
  }
}

Node* ToInt32(RawMachineAssembler* m, MachineType type, Node* a) {
  switch (type.representation()) {
    case MachineRepresentation::kWord32:
      return a;
    case MachineRepresentation::kWord64:
      return m->TruncateInt64ToInt32(a);
    case MachineRepresentation::kFloat32:
      return m->TruncateFloat32ToInt32(a, TruncateKind::kArchitectureDefault);
    case MachineRepresentation::kFloat64:
      return m->RoundFloat64ToInt32(a);
    default:
      UNREACHABLE();
  }
}

std::shared_ptr<wasm::NativeModule> AllocateNativeModule(Isolate* isolate,
                                                         size_t code_size) {
  std::shared_ptr<wasm::WasmModule> module(new wasm::WasmModule());
  module->num_declared_functions = 1;
  // We have to add the code object to a NativeModule, because the
  // WasmCallDescriptor assumes that code is on the native heap and not
  // within a code object.
  auto native_module = isolate->wasm_engine()->NewNativeModule(
      isolate, wasm::WasmFeatures::All(), std::move(module), code_size);
  native_module->SetWireBytes({});
  return native_module;
}

template <int kMinParamCount, int kMaxParamCount>
void TestReturnMultipleValues(MachineType type, int min_count, int max_count) {
  for (int param_count : {kMinParamCount, kMaxParamCount}) {
    for (int count = min_count; count < max_count; ++count) {
      printf("\n==== type = %s, parameter_count = %d, count = %d ====\n\n\n",
             MachineReprToString(type.representation()), param_count, count);
      v8::internal::AccountingAllocator allocator;
      Zone zone(&allocator, ZONE_NAME);
      CallDescriptor* desc =
          CreateCallDescriptor(&zone, count, param_count, type);
      HandleAndZoneScope handles(kCompressGraphZone);
      RawMachineAssembler m(
          handles.main_isolate(),
          handles.main_zone()->New<Graph>(handles.main_zone()), desc,
          MachineType::PointerRepresentation(),
          InstructionSelector::SupportedMachineOperatorFlags());

      // m.Parameter(0) is the WasmContext.
      Node* p0 = m.Parameter(1);
      Node* p1 = m.Parameter(2);
      using Node_ptr = Node*;
      std::unique_ptr<Node_ptr[]> returns(new Node_ptr[count]);
      for (int i = 0; i < count; ++i) {
        if (i % 3 == 0) returns[i] = Add(&m, type, p0, p1);
        if (i % 3 == 1) returns[i] = Sub(&m, type, p0, p1);
        if (i % 3 == 2) returns[i] = Mul(&m, type, p0, p1);
      }
      m.Return(count, returns.get());

      OptimizedCompilationInfo info(ArrayVector("testing"), handles.main_zone(),
                                    CodeKind::WASM_FUNCTION);
      Handle<Code> code = Pipeline::GenerateCodeForTesting(
                              &info, handles.main_isolate(), desc, m.graph(),
                              AssemblerOptions::Default(handles.main_isolate()),
                              m.ExportForTest())
                              .ToHandleChecked();
#ifdef ENABLE_DISASSEMBLER
      if (FLAG_print_code) {
        StdoutStream os;
        code->Disassemble("multi_value", os, handles.main_isolate());
      }
#endif

      const int a = 47, b = 12;
      int expect = 0;
      for (int i = 0, sign = +1; i < count; ++i) {
        if (i % 3 == 0) expect += sign * (a + b);
        if (i % 3 == 1) expect += sign * (a - b);
        if (i % 3 == 2) expect += sign * (a * b);
        if (i % 4 == 0) sign = -sign;
      }

      std::shared_ptr<wasm::NativeModule> module = AllocateNativeModule(
          handles.main_isolate(), code->raw_instruction_size());
      wasm::WasmCodeRefScope wasm_code_ref_scope;
      byte* code_start =
          module->AddCodeForTesting(code)->instructions().begin();

      RawMachineAssemblerTester<int32_t> mt(CodeKind::JS_TO_WASM_FUNCTION);
      const int input_count = 2 + param_count;
      Node* call_inputs[2 + kMaxParamCount];
      call_inputs[0] = mt.PointerConstant(code_start);
      // WasmContext dummy
      call_inputs[1] = mt.PointerConstant(nullptr);
      // Special inputs for the test.
      call_inputs[2] = MakeConstant(&mt, type, a);
      call_inputs[3] = MakeConstant(&mt, type, b);
      for (int i = 2; i < param_count; i++) {
        call_inputs[2 + i] = MakeConstant(&mt, type, i);
      }

      Node* ret_multi = mt.AddNode(mt.common()->Call(desc),
                                   input_count, call_inputs);
      Node* ret = MakeConstant(&mt, type, 0);
      bool sign = false;
      for (int i = 0; i < count; ++i) {
        Node* x = (count == 1)
                      ? ret_multi
                      : mt.AddNode(mt.common()->Projection(i), ret_multi);
        ret = sign ? Sub(&mt, type, ret, x) : Add(&mt, type, ret, x);
        if (i % 4 == 0) sign = !sign;
      }
      mt.Return(ToInt32(&mt, type, ret));
#ifdef ENABLE_DISASSEMBLER
      Handle<Code> code2 = mt.GetCode();
      if (FLAG_print_code) {
        StdoutStream os;
        code2->Disassemble("multi_value_call", os, handles.main_isolate());
      }
#endif
      CHECK_EQ(expect, mt.Call());
    }
  }
}

}  // namespace

// Use 9 parameters as a regression test or https://crbug.com/838098.
#define TEST_MULTI(Type, type) \
  TEST(ReturnMultiple##Type) { TestReturnMultipleValues<2, 9>(type, 0, 20); }

// Create a frame larger than UINT16_MAX to force TF to use an extra register
// when popping the frame.
TEST(TestReturnMultipleValuesLargeFrame) {
  TestReturnMultipleValues<20000, 20000>(MachineType::Int32(), 2, 3);
}

TEST_MULTI(Int32, MachineType::Int32())
#if (!V8_TARGET_ARCH_32_BIT)
TEST_MULTI(Int64, MachineType::Int64())
#endif
TEST_MULTI(Float32, MachineType::Float32())
TEST_MULTI(Float64, MachineType::Float64())

#undef TEST_MULTI

void ReturnLastValue(MachineType type) {
  int slot_counts[] = {1, 2, 3, 600};
  for (auto slot_count : slot_counts) {
    v8::internal::AccountingAllocator allocator;
    Zone zone(&allocator, ZONE_NAME);
    // The wasm-linkage provides 2 return registers at the moment, on all
    // platforms.
    const int return_count = 2 + slot_count;

    CallDescriptor* desc = CreateCallDescriptor(&zone, return_count, 0, type);

    HandleAndZoneScope handles(kCompressGraphZone);
    RawMachineAssembler m(handles.main_isolate(),
                          handles.main_zone()->New<Graph>(handles.main_zone()),
                          desc, MachineType::PointerRepresentation(),
                          InstructionSelector::SupportedMachineOperatorFlags());

    std::unique_ptr<Node* []> returns(new Node*[return_count]);

    for (int i = 0; i < return_count; ++i) {
      returns[i] = MakeConstant(&m, type, i);
    }

    m.Return(return_count, returns.get());

    OptimizedCompilationInfo info(ArrayVector("testing"), handles.main_zone(),
                                  CodeKind::WASM_FUNCTION);
    Handle<Code> code = Pipeline::GenerateCodeForTesting(
                            &info, handles.main_isolate(), desc, m.graph(),
                            AssemblerOptions::Default(handles.main_isolate()),
                            m.ExportForTest())
                            .ToHandleChecked();

    std::shared_ptr<wasm::NativeModule> module = AllocateNativeModule(
        handles.main_isolate(), code->raw_instruction_size());
    wasm::WasmCodeRefScope wasm_code_ref_scope;
    byte* code_start = module->AddCodeForTesting(code)->instructions().begin();

    // Generate caller.
    int expect = return_count - 1;
    RawMachineAssemblerTester<int32_t> mt;
    Node* inputs[] = {mt.PointerConstant(code_start),
                      // WasmContext dummy
                      mt.PointerConstant(nullptr)};

    Node* call = mt.AddNode(mt.common()->Call(desc), 2, inputs);

    mt.Return(
        ToInt32(&mt, type,
                mt.AddNode(mt.common()->Projection(return_count - 1), call)));

    CHECK_EQ(expect, mt.Call());
  }
}

TEST(ReturnLastValueInt32) { ReturnLastValue(MachineType::Int32()); }
#if (!V8_TARGET_ARCH_32_BIT)
TEST(ReturnLastValueInt64) { ReturnLastValue(MachineType::Int64()); }
#endif
TEST(ReturnLastValueFloat32) { ReturnLastValue(MachineType::Float32()); }
TEST(ReturnLastValueFloat64) { ReturnLastValue(MachineType::Float64()); }

void ReturnSumOfReturns(MachineType type) {
  for (int unused_stack_slots = 0; unused_stack_slots <= 2;
       ++unused_stack_slots) {
    v8::internal::AccountingAllocator allocator;
    Zone zone(&allocator, ZONE_NAME);
    // Let {unused_stack_slots + 1} returns be on the stack.
    // The wasm-linkage provides 2 return registers at the moment, on all
    // platforms.
    const int return_count = 2 + unused_stack_slots + 1;

    CallDescriptor* desc = CreateCallDescriptor(&zone, return_count, 0, type);

    HandleAndZoneScope handles(kCompressGraphZone);
    RawMachineAssembler m(handles.main_isolate(),
                          handles.main_zone()->New<Graph>(handles.main_zone()),
                          desc, MachineType::PointerRepresentation(),
                          InstructionSelector::SupportedMachineOperatorFlags());

    std::unique_ptr<Node* []> returns(new Node*[return_count]);

    for (int i = 0; i < return_count; ++i) {
      returns[i] = MakeConstant(&m, type, i);
    }

    m.Return(return_count, returns.get());

    OptimizedCompilationInfo info(ArrayVector("testing"), handles.main_zone(),
                                  CodeKind::WASM_FUNCTION);
    Handle<Code> code = Pipeline::GenerateCodeForTesting(
                            &info, handles.main_isolate(), desc, m.graph(),
                            AssemblerOptions::Default(handles.main_isolate()),
                            m.ExportForTest())
                            .ToHandleChecked();

    std::shared_ptr<wasm::NativeModule> module = AllocateNativeModule(
        handles.main_isolate(), code->raw_instruction_size());
    wasm::WasmCodeRefScope wasm_code_ref_scope;
    byte* code_start = module->AddCodeForTesting(code)->instructions().begin();

    // Generate caller.
    RawMachineAssemblerTester<int32_t> mt;
    Node* call_inputs[] = {mt.PointerConstant(code_start),
                           // WasmContext dummy
                           mt.PointerConstant(nullptr)};

    Node* call = mt.AddNode(mt.common()->Call(desc), 2, call_inputs);

    uint32_t expect = 0;
    Node* result = mt.Int32Constant(0);

    for (int i = 0; i < return_count; ++i) {
      expect += i;
      result = mt.Int32Add(
          result,
          ToInt32(&mt, type, mt.AddNode(mt.common()->Projection(i), call)));
    }

    mt.Return(result);

    CHECK_EQ(expect, mt.Call());
  }
}

TEST(ReturnSumOfReturnsInt32) { ReturnSumOfReturns(MachineType::Int32()); }
#if (!V8_TARGET_ARCH_32_BIT)
TEST(ReturnSumOfReturnsInt64) { ReturnSumOfReturns(MachineType::Int64()); }
#endif
TEST(ReturnSumOfReturnsFloat32) { ReturnSumOfReturns(MachineType::Float32()); }
TEST(ReturnSumOfReturnsFloat64) { ReturnSumOfReturns(MachineType::Float64()); }

}  // namespace compiler
}  // namespace internal
}  // namespace v8
