| Index: test/cctest/compiler/test-multiple-return.cc | 
| diff --git a/test/cctest/compiler/test-multiple-return.cc b/test/cctest/compiler/test-multiple-return.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..7b2cdc4df7dfb184b946a0d7cea63b8b405b5a99 | 
| --- /dev/null | 
| +++ b/test/cctest/compiler/test-multiple-return.cc | 
| @@ -0,0 +1,110 @@ | 
| +// 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" | 
| + | 
| + | 
| +using namespace v8::base; | 
| +using namespace v8::internal; | 
| +using namespace v8::internal::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); | 
| + | 
| +  // Add return location(s). | 
| +  for (int i = 0; i < return_count; i++) { | 
| +    msig.AddReturn(compiler::kMachInt32); | 
| +    locations.AddReturn(LinkageLocation::ForRegister(i)); | 
| +  } | 
| + | 
| +  // Add register and/or stack parameter(s). | 
| +  for (int i = 0; i < param_count; i++) { | 
| +    msig.AddParam(compiler::kMachInt32); | 
| +    locations.AddParam(LinkageLocation::ForRegister(i)); | 
| +  } | 
| + | 
| +  const RegList kCalleeSaveRegisters = 0; | 
| +  const RegList kCalleeSaveFPRegisters = 0; | 
| + | 
| +  // The target for WASM calls is always a code object. | 
| +  MachineType target_type = compiler::kMachAnyTagged; | 
| +  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) { | 
| +  Zone zone; | 
| +  CallDescriptor* desc = GetCallDescriptor(&zone, 3, 2); | 
| +  HandleAndZoneScope handles; | 
| +  RawMachineAssembler m(handles.main_isolate(), | 
| +                        new (handles.main_zone()) Graph(handles.main_zone()), | 
| +                        desc, kMachPtr, | 
| +                        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("testing", handles.main_isolate(), handles.main_zone()); | 
| +  Handle<Code> code = | 
| +      Pipeline::GenerateCodeForTesting(&info, desc, m.graph(), m.Export()); | 
| +#ifdef DEBUG | 
| +  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 DEBUG | 
| +  Handle<Code> code2 = mt.GetCode(); | 
| +  if (FLAG_print_code) { | 
| +    OFStream os(stdout); | 
| +    code2->Disassemble("three_value", os); | 
| +  } | 
| +#endif | 
| +  CHECK_EQ((123 + 456) + (123 - 456) + (123 * 456), mt.Call()); | 
| +} | 
|  |