// 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.

#if defined(DEBUG)

#include "vm/compiler/backend/flow_graph_checker.h"

#include "vm/compiler/backend/flow_graph.h"
#include "vm/compiler/backend/il.h"
#include "vm/compiler/backend/loops.h"

namespace dart {

DECLARE_FLAG(bool, trace_compiler);

DEFINE_FLAG(int,
            verify_definitions_threshold,
            250,
            "Definition count threshold for extensive instruction checks");

#define ASSERT1(cond, ctxt1)                                                   \
  do {                                                                         \
    if (!(cond))                                                               \
      dart::Assert(__FILE__, __LINE__)                                         \
          .Fail("expected: %s (%s=%s)", #cond, #ctxt1, (ctxt1)->ToCString());  \
  } while (false)

#define ASSERT2(cond, ctxt1, ctxt2)                                            \
  do {                                                                         \
    if (!(cond))                                                               \
      dart::Assert(__FILE__, __LINE__)                                         \
          .Fail("expected: %s (%s=%s, %s=%s)", #cond, #ctxt1,                  \
                (ctxt1)->ToCString(), #ctxt2, (ctxt2)->ToCString());           \
  } while (false)

// Returns true for the "optimized out" and "null" constant.
// Such constants reside outside the IR in the sense that
// succ/pred/block links are not maintained.
static bool IsSpecialConstant(Definition* def) {
  if (auto c = def->AsConstant()) {
    return c->value().ptr() == Symbols::OptimizedOut().ptr() ||
           c->value().ptr() == Object::ZoneHandle().ptr();
  }
  return false;
}

// Returns true if block is a predecessor of succ.
static bool IsPred(BlockEntryInstr* block, BlockEntryInstr* succ) {
  for (intptr_t i = 0, n = succ->PredecessorCount(); i < n; ++i) {
    if (succ->PredecessorAt(i) == block) {
      return true;
    }
  }
  return false;
}

// Returns true if block is a successor of pred.
static bool IsSucc(BlockEntryInstr* block, BlockEntryInstr* pred) {
  Instruction* last = pred->last_instruction();
  for (intptr_t i = 0, n = last->SuccessorCount(); i < n; ++i) {
    if (last->SuccessorAt(i) == block) {
      return true;
    }
  }
  return false;
}

// Returns true if dom directly dominates block.
static bool IsDirectlyDominated(BlockEntryInstr* block, BlockEntryInstr* dom) {
  for (intptr_t i = 0, n = dom->dominated_blocks().length(); i < n; ++i) {
    if (dom->dominated_blocks()[i] == block) {
      return true;
    }
  }
  return false;
}

// Returns true if instruction appears in use list.
static bool IsInUseList(Value* use, Instruction* instruction) {
  for (; use != nullptr; use = use->next_use()) {
    if (use->instruction() == instruction) {
      return true;
    }
  }
  return false;
}

// Returns true if definition dominates instruction. Note that this
// helper is required to account for some situations that are not
// accounted for in the IR methods that compute dominance.
static bool DefDominatesUse(Definition* def, Instruction* instruction) {
  if (instruction->IsPhi()) {
    // A phi use is not necessarily dominated by a definition.
    // Proper dominance relation on the input values of Phis is
    // checked by the Phi visitor below.
    return true;
  } else if (def->IsMaterializeObject() || instruction->IsMaterializeObject()) {
    // These instructions reside outside the IR.
    return true;
  } else if (auto entry =
                 instruction->GetBlock()->AsBlockEntryWithInitialDefs()) {
    // An initial definition in the same block.
    // TODO(ajcbik): use an initial def too?
    for (auto idef : *entry->initial_definitions()) {
      if (idef == def) {
        return true;
      }
    }
  }
  // Use the standard IR method for dominance.
  return instruction->IsDominatedBy(def);
}

// Returns true if instruction forces control flow.
static bool IsControlFlow(Instruction* instruction) {
  return instruction->IsBranch() || instruction->IsGoto() ||
         instruction->IsIndirectGoto() || instruction->IsReturn() ||
         instruction->IsThrow() || instruction->IsReThrow() ||
         instruction->IsTailCall();
}

// Asserts that arguments appear in environment at the right place.
static void AssertArgumentsInEnv(FlowGraph* flow_graph, Definition* call) {
  Environment* env = call->env();
  if (env == nullptr) {
    // Environments can be removed by EliminateEnvironments pass and
    // are not present before SSA.
  } else if (flow_graph->function().IsIrregexpFunction()) {
    // TODO(dartbug.com/38577): cleanup regexp pipeline too....
  } else {
    // Otherwise, the trailing environment entries must
    // correspond directly with the arguments.
    const intptr_t env_count = env->Length();
    const intptr_t arg_count = call->ArgumentCount();
    // Some calls (e.g. closure calls) have more inputs than actual arguments.
    // Those extra inputs will be consumed from the stack before the call.
    const intptr_t after_args_input_count = call->env()->LazyDeoptPruneCount();
    ASSERT1((arg_count + after_args_input_count) <= env_count, call);
    const intptr_t env_base = env_count - arg_count - after_args_input_count;
    for (intptr_t i = 0; i < arg_count; i++) {
      if (call->HasPushArguments()) {
        ASSERT1(call->ArgumentAt(i) == env->ValueAt(env_base + i)
                                           ->definition()
                                           ->AsPushArgument()
                                           ->value()
                                           ->definition(),
                call);
      } else {
        // Redefintion instructions and boxing/unboxing are inserted
        // without updating environment uses (FlowGraph::RenameDominatedUses,
        // FlowGraph::InsertConversionsFor).
        // Also, constants may belong to different blocks (e.g. function entry
        // and graph entry).
        Definition* arg_def =
            call->ArgumentAt(i)->OriginalDefinitionIgnoreBoxingAndConstraints();
        Definition* env_def =
            env->ValueAt(env_base + i)
                ->definition()
                ->OriginalDefinitionIgnoreBoxingAndConstraints();
        ASSERT2((arg_def == env_def) ||
                    (arg_def->IsConstant() && env_def->IsConstant() &&
                     arg_def->AsConstant()->value().ptr() ==
                         env_def->AsConstant()->value().ptr()),
                arg_def, env_def);
      }
    }
  }
}

void FlowGraphChecker::VisitBlocks() {
  const GrowableArray<BlockEntryInstr*>& preorder = flow_graph_->preorder();
  const GrowableArray<BlockEntryInstr*>& postorder = flow_graph_->postorder();
  const GrowableArray<BlockEntryInstr*>& rev_postorder =
      flow_graph_->reverse_postorder();

  // Make sure lengths match.
  const intptr_t block_count = preorder.length();
  ASSERT(block_count == postorder.length());
  ASSERT(block_count == rev_postorder.length());

  // Make sure postorder has true reverse.
  for (intptr_t i = 0; i < block_count; ++i) {
    ASSERT(postorder[i] == rev_postorder[block_count - i - 1]);
  }

  // Iterate over all basic blocks.
  const intptr_t max_block_id = flow_graph_->max_block_id();
  for (BlockIterator it = flow_graph_->reverse_postorder_iterator(); !it.Done();
       it.Advance()) {
    BlockEntryInstr* block = it.Current();
    ASSERT1(block->block_id() <= max_block_id, block);
    // Make sure ordering is consistent.
    ASSERT1(block->preorder_number() <= block_count, block);
    ASSERT1(block->postorder_number() <= block_count, block);
    ASSERT1(preorder[block->preorder_number()] == block, block);
    ASSERT1(postorder[block->postorder_number()] == block, block);
    // Make sure predecessors and successors agree.
    Instruction* last = block->last_instruction();
    for (intptr_t i = 0, n = last->SuccessorCount(); i < n; ++i) {
      ASSERT1(IsPred(block, last->SuccessorAt(i)), block);
    }
    for (intptr_t i = 0, n = block->PredecessorCount(); i < n; ++i) {
      ASSERT1(IsSucc(block, block->PredecessorAt(i)), block);
    }
    // Make sure dominance relations agree.
    for (intptr_t i = 0, n = block->dominated_blocks().length(); i < n; ++i) {
      ASSERT1(block->dominated_blocks()[i]->dominator() == block, block);
    }
    if (block->dominator() != nullptr) {
      ASSERT1(IsDirectlyDominated(block, block->dominator()), block);
    }
    // Visit all instructions in this block.
    VisitInstructions(block);
  }
}

void FlowGraphChecker::VisitInstructions(BlockEntryInstr* block) {
  // To avoid excessive runtimes, skip the instructions check if there
  // are many definitions (as happens in e.g. an initialization block).
  if (flow_graph_->current_ssa_temp_index() >
      FLAG_verify_definitions_threshold) {
    return;
  }
  // Give all visitors quick access.
  current_block_ = block;
  // Visit initial definitions.
  if (auto entry = block->AsBlockEntryWithInitialDefs()) {
    for (auto def : *entry->initial_definitions()) {
      ASSERT(def != nullptr);
      ASSERT1(
          def->IsConstant() || def->IsParameter() || def->IsSpecialParameter(),
          def);
      // Special constants reside outside the IR.
      if (IsSpecialConstant(def)) continue;
      // Make sure block lookup agrees.
      ASSERT1(def->GetBlock() == entry, def);
      // Initial definitions are partially linked into graph.
      ASSERT1(def->next() == nullptr, def);
      ASSERT1(def->previous() == entry, def);
      // Visit the initial definition as instruction.
      VisitInstruction(def);
    }
  }
  // Visit phis in join.
  if (auto entry = block->AsJoinEntry()) {
    for (PhiIterator it(entry); !it.Done(); it.Advance()) {
      PhiInstr* phi = it.Current();
      // Make sure block lookup agrees.
      ASSERT1(phi->GetBlock() == entry, phi);
      // Phis are never linked into graph.
      ASSERT1(phi->next() == nullptr, phi);
      ASSERT1(phi->previous() == nullptr, phi);
      // Visit the phi as instruction.
      VisitInstruction(phi);
    }
  }
  // Visit regular instructions.
  Instruction* last = block->last_instruction();
  ASSERT1((last == block) == block->IsGraphEntry(), block);
  Instruction* prev = block;
  ASSERT(prev->previous() == nullptr);
  for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
    Instruction* instruction = it.Current();
    // Make sure block lookup agrees (scan in scan).
    ASSERT1(instruction->GetBlock() == block, instruction);
    // Make sure linked list agrees.
    ASSERT1(prev->next() == instruction, instruction);
    ASSERT1(instruction->previous() == prev, instruction);
    prev = instruction;
    // Make sure control flow makes sense.
    ASSERT1(IsControlFlow(instruction) == (instruction == last), instruction);
    ASSERT1(!instruction->IsPhi(), instruction);
    // Visit the instruction.
    VisitInstruction(instruction);
  }
  ASSERT(prev->next() == nullptr);
  ASSERT(prev == last);
  // Make sure loop information, when up-to-date, agrees.
  if (flow_graph_->loop_hierarchy_ != nullptr) {
    for (LoopInfo* loop = block->loop_info(); loop != nullptr;
         loop = loop->outer()) {
      ASSERT1(loop->Contains(block), block);
    }
  }
}

void FlowGraphChecker::VisitInstruction(Instruction* instruction) {
  ASSERT1(!instruction->IsBlockEntry(), instruction);

#if !defined(DART_PRECOMPILER)
  // In JIT mode, any instruction which may throw must have a deopt-id, except
  // tail-call because it replaces the stack frame.
  ASSERT1(!instruction->MayThrow() || instruction->IsTailCall() ||
              instruction->deopt_id() != DeoptId::kNone,
          instruction);
#endif  // !defined(DART_PRECOMPILER)

  // If checking token positions and the flow graph has an inlining ID,
  // check the inlining ID and token position for instructions with real or
  // synthetic token positions.
  if (FLAG_check_token_positions && flow_graph_->inlining_id() >= 0) {
    const TokenPosition& pos = instruction->token_pos();
    if (pos.IsReal() || pos.IsSynthetic()) {
      ASSERT1(instruction->has_inlining_id(), instruction);
      const intptr_t inlining_id = instruction->inlining_id();
      const auto& function = *inline_id_to_function_[inlining_id];
      if (function.end_token_pos().IsReal() &&
          !pos.IsWithin(function.token_pos(), function.end_token_pos())) {
        TextBuffer buffer(256);
        buffer.Printf("Token position %s is invalid for function %s (%s, %s)",
                      pos.ToCString(), function.ToFullyQualifiedCString(),
                      function.token_pos().ToCString(),
                      function.end_token_pos().ToCString());
        if (inlining_id > 0) {
          buffer.Printf(" while compiling function %s",
                        inline_id_to_function_[0]->ToFullyQualifiedCString());
        }
        FATAL("%s", buffer.buffer());
      }
      script_ = function.script();
      if (!script_.IsNull() && !script_.IsValidTokenPosition(pos)) {
        TextBuffer buffer(256);
        buffer.Printf(
            "Token position %s is invalid for script %s of function %s",
            pos.ToCString(), script_.ToCString(),
            function.ToFullyQualifiedCString());
        if (inlining_id > 0) {
          buffer.Printf(" while compiling function %s",
                        inline_id_to_function_[0]->ToFullyQualifiedCString());
        }
        FATAL("%s", buffer.buffer());
      }
    }
  }
  ASSERT1(flow_graph_->unmatched_representations_allowed() ||
              !instruction->HasUnmatchedInputRepresentations(),
          instruction);

  // Check all regular inputs.
  for (intptr_t i = 0, n = instruction->InputCount(); i < n; ++i) {
    VisitUseDef(instruction, instruction->InputAt(i), i, /*is_env*/ false);
  }
  // Check all environment inputs (including outer ones).
  intptr_t i = 0;
  for (Environment::DeepIterator it(instruction->env()); !it.Done();
       it.Advance()) {
    VisitUseDef(instruction, it.CurrentValue(), i++, /*is_env*/ true);
  }
  // Visit specific instructions (definitions and anything with Visit()).
  if (auto def = instruction->AsDefinition()) {
    VisitDefinition(def);
  }
  instruction->Accept(this);
}

void FlowGraphChecker::VisitDefinition(Definition* def) {
  // Used definitions must have an SSA name, and the SSA name must
  // be less than the current_ssa_temp_index.
  if (def->HasSSATemp()) {
    ASSERT1(def->ssa_temp_index() < flow_graph_->current_ssa_temp_index(), def);
  } else {
    ASSERT1(def->input_use_list() == nullptr, def);
  }
  // Check all regular uses.
  Value* prev = nullptr;
  for (Value* use = def->input_use_list(); use != nullptr;
       use = use->next_use()) {
    VisitDefUse(def, use, prev, /*is_env*/ false);
    prev = use;
  }
  // Check all environment uses.
  prev = nullptr;
  for (Value* use = def->env_use_list(); use != nullptr;
       use = use->next_use()) {
    VisitDefUse(def, use, prev, /*is_env*/ true);
    prev = use;
  }
}

void FlowGraphChecker::VisitUseDef(Instruction* instruction,
                                   Value* use,
                                   intptr_t index,
                                   bool is_env) {
  ASSERT2(use->instruction() == instruction, use, instruction);
  ASSERT1(use->use_index() == index, use);
  // Get definition.
  Definition* def = use->definition();
  ASSERT(def != nullptr);
  ASSERT1(def != instruction || def->IsPhi() || def->IsMaterializeObject(),
          def);
  // Make sure each input is properly defined in the graph by something
  // that dominates the input (note that the proper dominance relation
  // on the input values of Phis is checked by the Phi visitor below).
  if (def->IsPhi()) {
    ASSERT1(def->GetBlock()->IsJoinEntry(), def);
    // Phis are never linked into graph.
    ASSERT1(def->next() == nullptr, def);
    ASSERT1(def->previous() == nullptr, def);
  } else if (def->IsConstant() || def->IsParameter() ||
             def->IsSpecialParameter()) {
    // Special constants reside outside the IR.
    if (IsSpecialConstant(def)) return;
    // Initial definitions are partially linked into graph, but some
    // constants are fully linked into graph (so no next() assert).
    ASSERT1(def->previous() != nullptr, def);
  } else {
    // Others are fully linked into graph.
    ASSERT1(def->next() != nullptr, def);
    ASSERT1(def->previous() != nullptr, def);
  }
  if (def->HasSSATemp()) {
    ASSERT2(DefDominatesUse(def, instruction), def, instruction);
    ASSERT2(IsInUseList(is_env ? def->env_use_list() : def->input_use_list(),
                        instruction),
            def, instruction);
  }
}

void FlowGraphChecker::VisitDefUse(Definition* def,
                                   Value* use,
                                   Value* prev,
                                   bool is_env) {
  ASSERT2(use->definition() == def, use, def);
  ASSERT1(use->previous_use() == prev, use);
  // Get using instruction.
  Instruction* instruction = use->instruction();
  ASSERT(instruction != nullptr);
  ASSERT1(def != instruction || def->IsPhi() || def->IsMaterializeObject(),
          def);
  if (is_env) {
    ASSERT2(instruction->env()->ValueAtUseIndex(use->use_index()) == use,
            instruction, use);
  } else {
    ASSERT2(instruction->InputAt(use->use_index()) == use, instruction, use);
  }
  // Make sure the reaching type, if any, has an owner consistent with this use.
  if (auto const type = use->reaching_type()) {
    ASSERT1(type->owner() == nullptr || type->owner() == def, use);
  }
  // Make sure each use appears in the graph and is properly dominated
  // by the definition (note that the proper dominance relation on the
  // input values of Phis is checked by the Phi visitor below).
  if (instruction->IsPhi()) {
    ASSERT1(instruction->AsPhi()->is_alive(), instruction);
    ASSERT1(instruction->GetBlock()->IsJoinEntry(), instruction);
    // Phis are never linked into graph.
    ASSERT1(instruction->next() == nullptr, instruction);
    ASSERT1(instruction->previous() == nullptr, instruction);
  } else if (instruction->IsBlockEntry()) {
    // BlockEntry instructions have environments attached to them but
    // have no reliable way to verify if they are still in the graph.
    ASSERT1(is_env, instruction);
    ASSERT1(instruction->next() != nullptr, instruction);
    ASSERT2(DefDominatesUse(def, instruction), def, instruction);
  } else {
    // Others are fully linked into graph.
    ASSERT1(IsControlFlow(instruction) || instruction->next() != nullptr,
            instruction);
    ASSERT1(instruction->previous() != nullptr, instruction);
    ASSERT2(!def->HasSSATemp() || DefDominatesUse(def, instruction), def,
            instruction);
  }
}

void FlowGraphChecker::VisitConstant(ConstantInstr* constant) {
  // Range check on smi.
  const Object& value = constant->value();
  if (value.IsSmi()) {
    const int64_t smi_value = Integer::Cast(value).AsInt64Value();
    ASSERT(compiler::target::kSmiMin <= smi_value);
    ASSERT(smi_value <= compiler::target::kSmiMax);
  }
  // Any constant involved in SSA should appear in the entry (making it more
  // likely it was inserted by the utility that avoids duplication).
  //
  // TODO(dartbug.com/36894)
  //
  // ASSERT(constant->GetBlock() == flow_graph_->graph_entry());
}

void FlowGraphChecker::VisitPhi(PhiInstr* phi) {
  // Make sure the definition of each input value of a Phi dominates
  // the corresponding incoming edge, as defined by order.
  ASSERT1(phi->InputCount() == current_block_->PredecessorCount(), phi);
  for (intptr_t i = 0, n = phi->InputCount(); i < n; ++i) {
    Definition* def = phi->InputAt(i)->definition();
    ASSERT1(def->HasSSATemp(), def);  // phis have SSA defs
    BlockEntryInstr* edge = current_block_->PredecessorAt(i);
    ASSERT1(DefDominatesUse(def, edge->last_instruction()), def);
  }
}

void FlowGraphChecker::VisitGoto(GotoInstr* jmp) {
  ASSERT1(jmp->SuccessorCount() == 1, jmp);
}

void FlowGraphChecker::VisitIndirectGoto(IndirectGotoInstr* jmp) {
  ASSERT1(jmp->SuccessorCount() >= 1, jmp);
}

void FlowGraphChecker::VisitBranch(BranchInstr* branch) {
  ASSERT1(branch->SuccessorCount() == 2, branch);
}

void FlowGraphChecker::VisitRedefinition(RedefinitionInstr* def) {
  ASSERT1(def->value()->definition() != def, def);
}

void FlowGraphChecker::VisitClosureCall(ClosureCallInstr* call) {
  AssertArgumentsInEnv(flow_graph_, call);
}

void FlowGraphChecker::VisitStaticCall(StaticCallInstr* call) {
  AssertArgumentsInEnv(flow_graph_, call);
}

void FlowGraphChecker::VisitInstanceCall(InstanceCallInstr* call) {
  AssertArgumentsInEnv(flow_graph_, call);
  // Force-optimized functions may not have instance calls inside them because
  // we do not reset ICData for these.
  ASSERT(!flow_graph_->function().ForceOptimize());
}

void FlowGraphChecker::VisitPolymorphicInstanceCall(
    PolymorphicInstanceCallInstr* call) {
  AssertArgumentsInEnv(flow_graph_, call);
  // Force-optimized functions may not have instance calls inside them because
  // we do not reset ICData for these.
  ASSERT(!flow_graph_->function().ForceOptimize());
}

// Main entry point of graph checker.
void FlowGraphChecker::Check(const char* pass_name) {
  if (FLAG_trace_compiler) {
    THR_Print("Running checker after %s\n", pass_name);
  }
  ASSERT(flow_graph_ != nullptr);
  VisitBlocks();
}

}  // namespace dart

#endif  // defined(DEBUG)
