// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <utility>

#include "vm/closure_functions_cache.h"
#include "vm/compiler/backend/il_test_helper.h"
#include "vm/compiler/compiler_pass.h"
#include "vm/object.h"
#include "vm/unit_test.h"

namespace dart {

using Pair = std::pair<intptr_t, TokenPosition>;
using YieldPoints = ZoneGrowableArray<Pair>;

int LowestFirst(const Pair* a, const Pair* b) {
  return a->first - b->first;
}

static YieldPoints* GetYieldPointsFromGraph(FlowGraph* flow_graph) {
  auto array = new (flow_graph->zone()) YieldPoints();
  const auto& blocks = flow_graph->reverse_postorder();
  for (auto block : blocks) {
    ForwardInstructionIterator it(block);
    while (!it.Done()) {
      if (auto return_instr = it.Current()->AsReturn()) {
        if (return_instr->yield_index() !=
            UntaggedPcDescriptors::kInvalidYieldIndex) {
          ASSERT(return_instr->yield_index() > 0);
          array->Add(
              Pair(return_instr->yield_index(), return_instr->token_pos()));
        }
      }
      it.Advance();
    }
  }
  array->Sort(LowestFirst);
  return array;
}

static YieldPoints* GetYieldPointsFromCode(const Code& code) {
  auto array = new YieldPoints();
  const auto& pc_descriptor = PcDescriptors::Handle(code.pc_descriptors());
  PcDescriptors::Iterator it(pc_descriptor, UntaggedPcDescriptors::kOther);
  while (it.MoveNext()) {
    if (it.YieldIndex() != UntaggedPcDescriptors::kInvalidYieldIndex) {
      array->Add(Pair(it.YieldIndex(), it.TokenPos()));
    }
  }
  array->Sort(LowestFirst);
  return array;
}

void RunTestInMode(CompilerPass::PipelineMode mode) {
  const char* kScript =
      R"(
      import 'dart:async';

      Future foo() async {
        print('pos-0');
        await 0;
        print('pos-1');
        await 1;
        print('pos-2');
        await 2;
      }
      )";

  SetupCoreLibrariesForUnitTest();

  const auto& root_library = Library::Handle(LoadTestScript(kScript));
  // Ensure the outer function was compiled once, ensuring we have a closure
  // function for the inner closure.
  Invoke(root_library, "foo");

  const auto& outer_function =
      Function::Handle(GetFunction(root_library, "foo"));

  // Grab the inner, lazily created, closure from the object store.
  const auto& function = Function::Handle(
      ClosureFunctionsCache::GetUniqueInnerClosure(outer_function));
  RELEASE_ASSERT(function.IsFunction());

  // Ensure we have 3 different return instructions with yield indices attached
  // to them.
  TestPipeline pipeline(function, mode);
  FlowGraph* flow_graph = pipeline.RunPasses({
      CompilerPass::kComputeSSA,
  });

  auto validate_indices = [](const YieldPoints& yield_points) {
    EXPECT_EQ(3, yield_points.length());

    EXPECT_EQ(1, yield_points[0].first);
    EXPECT_EQ(88, yield_points[0].second.Pos());
    EXPECT_EQ(2, yield_points[1].first);
    EXPECT_EQ(129, yield_points[1].second.Pos());
    EXPECT_EQ(3, yield_points[2].first);
    EXPECT_EQ(170, yield_points[2].second.Pos());
  };

  validate_indices(*GetYieldPointsFromGraph(flow_graph));

  // Ensure we have 3 different yield indices attached to the code via pc
  // descriptors.
  const auto& error = Error::Handle(
      Compiler::EnsureUnoptimizedCode(Thread::Current(), function));
  RELEASE_ASSERT(error.IsNull());
  const auto& code = Code::Handle(function.CurrentCode());
  validate_indices(*GetYieldPointsFromCode(code));
}

ISOLATE_UNIT_TEST_CASE(IRTest_YieldIndexAvailableJIT) {
  RunTestInMode(CompilerPass::kJIT);
}

ISOLATE_UNIT_TEST_CASE(IRTest_YieldIndexAvailableAOT) {
  RunTestInMode(CompilerPass::kAOT);
}

}  // namespace dart
