// 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::ArchDefault(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
