/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "graph_checker.h"
#include "optimizing_unit_test.h"

#include "gtest/gtest.h"

namespace art {

/**
 * Create a simple control-flow graph composed of two blocks:
 *
 *   BasicBlock 0, succ: 1
 *     0: Goto 1
 *   BasicBlock 1, pred: 0
 *     1: Exit
 */
HGraph* CreateSimpleCFG(ArenaAllocator* allocator) {
  HGraph* graph = new (allocator) HGraph(allocator);
  HBasicBlock* entry_block = new (allocator) HBasicBlock(graph);
  entry_block->AddInstruction(new (allocator) HGoto());
  graph->AddBlock(entry_block);
  graph->SetEntryBlock(entry_block);
  HBasicBlock* exit_block = new (allocator) HBasicBlock(graph);
  exit_block->AddInstruction(new (allocator) HExit());
  graph->AddBlock(exit_block);
  graph->SetExitBlock(exit_block);
  entry_block->AddSuccessor(exit_block);
  return graph;
}


static void TestCode(const uint16_t* data) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);
  HGraph* graph = CreateCFG(&allocator, data);
  ASSERT_NE(graph, nullptr);

  GraphChecker graph_checker(&allocator, graph);
  graph_checker.Run();
  ASSERT_TRUE(graph_checker.IsValid());
}

static void TestCodeSSA(const uint16_t* data) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);
  HGraph* graph = CreateCFG(&allocator, data);
  ASSERT_NE(graph, nullptr);

  graph->BuildDominatorTree();
  graph->TransformToSsa();

  SSAChecker ssa_checker(&allocator, graph);
  ssa_checker.Run();
  ASSERT_TRUE(ssa_checker.IsValid());
}


TEST(GraphChecker, ReturnVoid) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
      Instruction::RETURN_VOID);

  TestCode(data);
}

TEST(GraphChecker, CFG1) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
      Instruction::GOTO | 0x100,
      Instruction::RETURN_VOID);

  TestCode(data);
}

TEST(GraphChecker, CFG2) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,
    Instruction::GOTO | 0x100,
    Instruction::RETURN_VOID);

  TestCode(data);
}

TEST(GraphChecker, CFG3) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,
    Instruction::GOTO | 0x100,
    Instruction::GOTO | 0xFF00);

  TestCode(data);
}

// Test case with an invalid graph containing inconsistent
// predecessor/successor arcs in CFG.
TEST(GraphChecker, InconsistentPredecessorsAndSuccessors) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = CreateSimpleCFG(&allocator);
  GraphChecker graph_checker(&allocator, graph);
  graph_checker.Run();
  ASSERT_TRUE(graph_checker.IsValid());

  // Remove the entry block from the exit block's predecessors, to create an
  // inconsistent successor/predecessor relation.
  graph->GetExitBlock()->RemovePredecessor(graph->GetEntryBlock());
  graph_checker.Run();
  ASSERT_FALSE(graph_checker.IsValid());
}

// Test case with an invalid graph containing a non-branch last
// instruction in a block.
TEST(GraphChecker, BlockEndingWithNonBranchInstruction) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = CreateSimpleCFG(&allocator);
  GraphChecker graph_checker(&allocator, graph);
  graph_checker.Run();
  ASSERT_TRUE(graph_checker.IsValid());

  // Remove the sole instruction of the exit block (composed of a
  // single Exit instruction) to make it invalid (i.e. not ending by a
  // branch instruction).
  HBasicBlock* exit_block = graph->GetExitBlock();
  HInstruction* last_inst = exit_block->GetLastInstruction();
  exit_block->RemoveInstruction(last_inst);

  graph_checker.Run();
  ASSERT_FALSE(graph_checker.IsValid());
}

TEST(SSAChecker, SSAPhi) {
  // This code creates one Phi function during the conversion to SSA form.
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,
    Instruction::CONST_4 | 4 << 12 | 0,
    Instruction::RETURN | 0 << 8);

  TestCodeSSA(data);
}

}  // namespace art
