/*
 * 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"

namespace art {

/**
 * Create a simple control-flow graph composed of two blocks:
 *
 *   BasicBlock 0, succ: 1
 *     0: ReturnVoid 1
 *   BasicBlock 1, pred: 0
 *     1: Exit
 */
HGraph* CreateSimpleCFG(ArenaAllocator* allocator) {
  HGraph* graph = CreateGraph(allocator);
  HBasicBlock* entry_block = new (allocator) HBasicBlock(graph);
  entry_block->AddInstruction(new (allocator) HReturnVoid());
  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);
  graph->BuildDominatorTree();
  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(graph);
  graph_checker.Run();
  ASSERT_TRUE(graph_checker.IsValid());
}

class GraphCheckerTest : public CommonCompilerTest {};

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

  TestCode(data);
}

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

  TestCode(data);
}

TEST_F(GraphCheckerTest, 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_F(GraphCheckerTest, 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_F(GraphCheckerTest, InconsistentPredecessorsAndSuccessors) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = CreateSimpleCFG(&allocator);
  GraphChecker graph_checker(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_F(GraphCheckerTest, BlockEndingWithNonBranchInstruction) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = CreateSimpleCFG(&allocator);
  GraphChecker graph_checker(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_F(GraphCheckerTest, 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);

  TestCode(data);
}

}  // namespace art
