// 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 "src/compiler/common-operator.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-origin-table.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
#include "src/compiler/verifier.h"
#include "test/cctest/cctest.h"

namespace v8 {
namespace internal {
namespace compiler {

static Operator dummy_operator1(IrOpcode::kParameter, Operator::kNoWrite,
                                "dummy", 1, 0, 0, 1, 0, 0);
static Operator dummy_operator6(IrOpcode::kParameter, Operator::kNoWrite,
                                "dummy", 6, 0, 0, 1, 0, 0);


TEST(NodeWithNullInputReachableFromEnd) {
  HandleAndZoneScope scope;
  Graph graph(scope.main_zone());
  CommonOperatorBuilder common(scope.main_zone());

  Node* start = graph.NewNode(common.Start(0));
  graph.SetStart(start);
  Node* k = graph.NewNode(common.Int32Constant(0));
  Node* phi =
      graph.NewNode(common.Phi(MachineRepresentation::kTagged, 1), k, start);
  phi->ReplaceInput(0, nullptr);
  graph.SetEnd(phi);

  SourcePositionTable table(&graph);
  NodeOriginTable table2(&graph);
  StdoutStream{} << AsJSON(graph, &table, &table2);
}


TEST(NodeWithNullControlReachableFromEnd) {
  HandleAndZoneScope scope;
  Graph graph(scope.main_zone());
  CommonOperatorBuilder common(scope.main_zone());

  Node* start = graph.NewNode(common.Start(0));
  graph.SetStart(start);
  Node* k = graph.NewNode(common.Int32Constant(0));
  Node* phi =
      graph.NewNode(common.Phi(MachineRepresentation::kTagged, 1), k, start);
  phi->ReplaceInput(1, nullptr);
  graph.SetEnd(phi);

  SourcePositionTable table(&graph);
  NodeOriginTable table2(&graph);
  StdoutStream{} << AsJSON(graph, &table, &table2);
}


TEST(NodeWithNullInputReachableFromStart) {
  HandleAndZoneScope scope;
  Graph graph(scope.main_zone());
  CommonOperatorBuilder common(scope.main_zone());

  Node* start = graph.NewNode(common.Start(0));
  graph.SetStart(start);
  Node* k = graph.NewNode(common.Int32Constant(0));
  Node* phi =
      graph.NewNode(common.Phi(MachineRepresentation::kTagged, 1), k, start);
  phi->ReplaceInput(0, nullptr);
  graph.SetEnd(start);

  SourcePositionTable table(&graph);
  NodeOriginTable table2(&graph);
  StdoutStream{} << AsJSON(graph, &table, &table2);
}


TEST(NodeWithNullControlReachableFromStart) {
  HandleAndZoneScope scope;
  Graph graph(scope.main_zone());
  CommonOperatorBuilder common(scope.main_zone());

  Node* start = graph.NewNode(common.Start(0));
  graph.SetStart(start);
  Node* merge = graph.NewNode(common.Merge(2), start, start);
  merge->ReplaceInput(1, nullptr);
  graph.SetEnd(merge);

  SourcePositionTable table(&graph);
  NodeOriginTable table2(&graph);
  StdoutStream{} << AsJSON(graph, &table, &table2);
}


TEST(NodeNetworkOfDummiesReachableFromEnd) {
  HandleAndZoneScope scope;
  Graph graph(scope.main_zone());
  CommonOperatorBuilder common(scope.main_zone());

  Node* start = graph.NewNode(common.Start(0));
  graph.SetStart(start);
  Node* n2 = graph.NewNode(&dummy_operator1, graph.start());
  Node* n3 = graph.NewNode(&dummy_operator1, graph.start());
  Node* n4 = graph.NewNode(&dummy_operator1, n2);
  Node* n5 = graph.NewNode(&dummy_operator1, n2);
  Node* n6 = graph.NewNode(&dummy_operator1, n3);
  Node* n7 = graph.NewNode(&dummy_operator1, n3);
  Node* n8 = graph.NewNode(&dummy_operator1, n5);
  Node* n9 = graph.NewNode(&dummy_operator1, n5);
  Node* n10 = graph.NewNode(&dummy_operator1, n9);
  Node* n11 = graph.NewNode(&dummy_operator1, n9);
  Node* end_dependencies[6] = {n4, n8, n10, n11, n6, n7};
  Node* end = graph.NewNode(&dummy_operator6, 6, end_dependencies);
  graph.SetEnd(end);

  SourcePositionTable table(&graph);
  NodeOriginTable table2(&graph);
  StdoutStream{} << AsJSON(graph, &table, &table2);
}

TEST(TestSourceIdAssigner) {
  Handle<SharedFunctionInfo> shared1;
  Handle<SharedFunctionInfo> shared2;

  SourceIdAssigner assigner(2);
  const int source_id1 = assigner.GetIdFor(shared1);
  const int source_id2 = assigner.GetIdFor(shared2);

  CHECK_EQ(source_id1, source_id2);
  CHECK_EQ(source_id1, assigner.GetIdAt(0));
  CHECK_EQ(source_id2, assigner.GetIdAt(1));
}

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