// Copyright 2018 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/torque/cfg.h"

#include "src/torque/type-oracle.h"

namespace v8 {
namespace internal {
namespace torque {

void Block::SetInputTypes(const Stack<const Type*>& input_types) {
  if (!input_types_) {
    input_types_ = input_types;
    return;
  } else if (*input_types_ == input_types) {
    return;
  }

  DCHECK_EQ(input_types.Size(), input_types_->Size());
  Stack<const Type*> merged_types;
  bool widened = false;
  auto c2_iterator = input_types.begin();
  for (const Type* c1 : *input_types_) {
    const Type* merged_type = TypeOracle::GetUnionType(c1, *c2_iterator++);
    if (!merged_type->IsSubtypeOf(c1)) {
      widened = true;
    }
    merged_types.Push(merged_type);
  }
  if (merged_types.Size() == input_types_->Size()) {
    if (widened) {
      input_types_ = merged_types;
      Retype();
    }
    return;
  }

  std::stringstream error;
  error << "incompatible types at branch:\n";
  for (intptr_t i = std::max(input_types_->Size(), input_types.Size()) - 1;
       i >= 0; --i) {
    base::Optional<const Type*> left;
    base::Optional<const Type*> right;
    if (static_cast<size_t>(i) < input_types.Size()) {
      left = input_types.Peek(BottomOffset{static_cast<size_t>(i)});
    }
    if (static_cast<size_t>(i) < input_types_->Size()) {
      right = input_types_->Peek(BottomOffset{static_cast<size_t>(i)});
    }
    if (left && right && *left == *right) {
      error << **left << "\n";
    } else {
      if (left) {
        error << **left;
      } else {
        error << "/*missing*/";
      }
      error << "   =>   ";
      if (right) {
        error << **right;
      } else {
        error << "/*missing*/";
      }
      error << "\n";
    }
  }
  ReportError(error.str());
}

void CfgAssembler::Bind(Block* block) {
  DCHECK(current_block_->IsComplete());
  DCHECK(block->instructions().empty());
  DCHECK(block->HasInputTypes());
  current_block_ = block;
  current_stack_ = block->InputTypes();
  cfg_.PlaceBlock(block);
}

void CfgAssembler::Goto(Block* block) {
  if (block->HasInputTypes()) {
    DropTo(block->InputTypes().AboveTop());
  }
  Emit(GotoInstruction{block});
}

StackRange CfgAssembler::Goto(Block* block, size_t preserved_slots) {
  DCHECK(block->HasInputTypes());
  DCHECK_GE(CurrentStack().Size(), block->InputTypes().Size());
  Emit(DeleteRangeInstruction{
      StackRange{block->InputTypes().AboveTop() - preserved_slots,
                 CurrentStack().AboveTop() - preserved_slots}});
  StackRange preserved_slot_range = TopRange(preserved_slots);
  Emit(GotoInstruction{block});
  return preserved_slot_range;
}

void CfgAssembler::Branch(Block* if_true, Block* if_false) {
  Emit(BranchInstruction{if_true, if_false});
}

// Delete the specified range of slots, moving upper slots to fill the gap.
void CfgAssembler::DeleteRange(StackRange range) {
  DCHECK_LE(range.end(), current_stack_.AboveTop());
  if (range.Size() == 0) return;
  Emit(DeleteRangeInstruction{range});
}

void CfgAssembler::DropTo(BottomOffset new_level) {
  DeleteRange(StackRange{new_level, CurrentStack().AboveTop()});
}

StackRange CfgAssembler::Peek(StackRange range,
                              base::Optional<const Type*> type) {
  std::vector<const Type*> lowered_types;
  if (type) {
    lowered_types = LowerType(*type);
    DCHECK_EQ(lowered_types.size(), range.Size());
  }
  for (size_t i = 0; i < range.Size(); ++i) {
    Emit(PeekInstruction{
        range.begin() + i,
        type ? lowered_types[i] : base::Optional<const Type*>{}});
  }
  return TopRange(range.Size());
}

void CfgAssembler::Poke(StackRange destination, StackRange origin,
                        base::Optional<const Type*> type) {
  DCHECK_EQ(destination.Size(), origin.Size());
  DCHECK_LE(destination.end(), origin.begin());
  DCHECK_EQ(origin.end(), CurrentStack().AboveTop());
  std::vector<const Type*> lowered_types;
  if (type) {
    lowered_types = LowerType(*type);
    DCHECK_EQ(lowered_types.size(), origin.Size());
  }
  for (intptr_t i = origin.Size() - 1; i >= 0; --i) {
    Emit(PokeInstruction{
        destination.begin() + i,
        type ? lowered_types[i] : base::Optional<const Type*>{}});
  }
}

void CfgAssembler::Print(std::string s) {
  Emit(PrintConstantStringInstruction{std::move(s)});
}

void CfgAssembler::AssertionFailure(std::string message) {
  Emit(AbortInstruction{AbortInstruction::Kind::kAssertionFailure,
                        std::move(message)});
}

void CfgAssembler::Unreachable() {
  Emit(AbortInstruction{AbortInstruction::Kind::kUnreachable});
}

void CfgAssembler::DebugBreak() {
  Emit(AbortInstruction{AbortInstruction::Kind::kDebugBreak});
}

std::vector<std::size_t> CountBlockPredecessors(const ControlFlowGraph& cfg) {
  std::vector<std::size_t> count(cfg.NumberOfBlockIds(), 0);
  count[cfg.start()->id()] = 1;

  for (const Block* block : cfg.blocks()) {
    std::vector<Block*> successors;
    for (const auto& instruction : block->instructions()) {
      instruction->AppendSuccessorBlocks(&successors);
    }
    for (Block* successor : successors) {
      DCHECK_LT(successor->id(), count.size());
      ++count[successor->id()];
    }
  }

  return count;
}

void CfgAssembler::OptimizeCfg() {
  auto predecessor_count = CountBlockPredecessors(cfg_);

  for (Block* block : cfg_.blocks()) {
    if (cfg_.end() && *cfg_.end() == block) continue;
    if (predecessor_count[block->id()] == 0) continue;

    while (!block->instructions().empty()) {
      const auto& instruction = block->instructions().back();
      if (!instruction.Is<GotoInstruction>()) break;
      Block* destination = instruction.Cast<GotoInstruction>().destination;
      if (destination == block) break;
      if (cfg_.end() && *cfg_.end() == destination) break;
      DCHECK_GT(predecessor_count[destination->id()], 0);
      if (predecessor_count[destination->id()] != 1) break;

      DCHECK_GT(destination->instructions().size(), 0);
      block->instructions().pop_back();
      block->instructions().insert(block->instructions().end(),
                                   destination->instructions().begin(),
                                   destination->instructions().end());

      --predecessor_count[destination->id()];
      DCHECK_EQ(predecessor_count[destination->id()], 0);
    }
  }

  cfg_.UnplaceBlockIf(
      [&](Block* b) { return predecessor_count[b->id()] == 0; });
}

void CfgAssembler::ComputeInputDefinitions() {
  Worklist<Block*> worklist;

  // Setup start block.
  Stack<DefinitionLocation> parameter_defs;
  for (std::size_t i = 0; i < cfg_.ParameterCount(); ++i) {
    parameter_defs.Push(DefinitionLocation::Parameter(i));
  }
  cfg_.start()->MergeInputDefinitions(parameter_defs, &worklist);

  // Run fixpoint algorithm.
  while (!worklist.IsEmpty()) {
    Block* block = worklist.Dequeue();
    Stack<DefinitionLocation> definitions = block->InputDefinitions();

    // Propagate through block's instructions.
    for (const auto& instruction : block->instructions()) {
      instruction.RecomputeDefinitionLocations(&definitions, &worklist);
    }
  }

  for (Block* block : cfg_.blocks()) {
    DCHECK_IMPLIES(!block->IsDead(), block->InputDefinitions().Size() ==
                                         block->InputTypes().Size());
    USE(block);
  }
}

}  // namespace torque
}  // namespace internal
}  // namespace v8
