// 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 "src/assembler.h"
#include "src/base/bits.h"
#include "src/base/utils/random-number-generator.h"
#include "src/codegen.h"
#include "src/compiler.h"
#include "src/compiler/linkage.h"
#include "src/macro-assembler.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* GetCallDescriptor(Zone* zone, int return_count,
                                  int param_count) {
  MachineSignature::Builder msig(zone, return_count, param_count);
  LocationSignature::Builder locations(zone, return_count, param_count);
  const RegisterConfiguration* config = RegisterConfiguration::Turbofan();

  // Add return location(s).
  CHECK(return_count <= config->num_allocatable_general_registers());
  for (int i = 0; i < return_count; i++) {
    msig.AddReturn(MachineType::Int32());
    locations.AddReturn(
        LinkageLocation::ForRegister(config->allocatable_general_codes()[i]));
  }

  // Add register and/or stack parameter(s).
  CHECK(param_count <= config->num_allocatable_general_registers());
  for (int i = 0; i < param_count; i++) {
    msig.AddParam(MachineType::Int32());
    locations.AddParam(
        LinkageLocation::ForRegister(config->allocatable_general_codes()[i]));
  }

  const RegList kCalleeSaveRegisters = 0;
  const RegList kCalleeSaveFPRegisters = 0;

  // The target for WASM calls is always a code object.
  MachineType target_type = MachineType::AnyTagged();
  LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
  return new (zone) CallDescriptor(       // --
      CallDescriptor::kCallCodeObject,    // kind
      target_type,                        // target MachineType
      target_loc,                         // target location
      msig.Build(),                       // machine_sig
      locations.Build(),                  // location_sig
      0,                                  // js_parameter_count
      compiler::Operator::kNoProperties,  // properties
      kCalleeSaveRegisters,               // callee-saved registers
      kCalleeSaveFPRegisters,             // callee-saved fp regs
      CallDescriptor::kNoFlags,           // flags
      "c-call");
}
}  // namespace


TEST(ReturnThreeValues) {
  base::AccountingAllocator allocator;
  Zone zone(&allocator);
  CallDescriptor* desc = GetCallDescriptor(&zone, 3, 2);
  HandleAndZoneScope handles;
  RawMachineAssembler m(handles.main_isolate(),
                        new (handles.main_zone()) Graph(handles.main_zone()),
                        desc, MachineType::PointerRepresentation(),
                        InstructionSelector::SupportedMachineOperatorFlags());

  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
  Node* sub = m.Int32Sub(p0, p1);
  Node* mul = m.Int32Mul(p0, p1);
  m.Return(add, sub, mul);

  CompilationInfo info(ArrayVector("testing"), handles.main_isolate(),
                       handles.main_zone());
  Handle<Code> code =
      Pipeline::GenerateCodeForTesting(&info, desc, m.graph(), m.Export());
#ifdef ENABLE_DISASSEMBLER
  if (FLAG_print_code) {
    OFStream os(stdout);
    code->Disassemble("three_value", os);
  }
#endif

  RawMachineAssemblerTester<int32_t> mt;
  Node* a = mt.Int32Constant(123);
  Node* b = mt.Int32Constant(456);
  Node* ret3 = mt.AddNode(mt.common()->Call(desc), mt.HeapConstant(code), a, b);
  Node* x = mt.AddNode(mt.common()->Projection(0), ret3);
  Node* y = mt.AddNode(mt.common()->Projection(1), ret3);
  Node* z = mt.AddNode(mt.common()->Projection(2), ret3);
  Node* ret = mt.Int32Add(mt.Int32Add(x, y), z);
  mt.Return(ret);
#ifdef ENABLE_DISASSEMBLER
  Handle<Code> code2 = mt.GetCode();
  if (FLAG_print_code) {
    OFStream os(stdout);
    code2->Disassemble("three_value_call", os);
  }
#endif
  CHECK_EQ((123 + 456) + (123 - 456) + (123 * 456), mt.Call());
}

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