// Copyright 2016 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/backend/x64/unwinding-info-writer-x64.h"
#include "src/compiler/backend/instruction.h"

namespace v8 {
namespace internal {
namespace compiler {

void UnwindingInfoWriter::BeginInstructionBlock(int pc_offset,
                                                const InstructionBlock* block) {
  if (!enabled()) return;

  block_will_exit_ = false;

  DCHECK_LT(block->rpo_number().ToInt(),
            static_cast<int>(block_initial_states_.size()));
  const BlockInitialState* initial_state =
      block_initial_states_[block->rpo_number().ToInt()];
  if (!initial_state) return;
  if (initial_state->register_ != eh_frame_writer_.base_register() &&
      initial_state->offset_ != eh_frame_writer_.base_offset()) {
    eh_frame_writer_.AdvanceLocation(pc_offset);
    eh_frame_writer_.SetBaseAddressRegisterAndOffset(initial_state->register_,
                                                     initial_state->offset_);
  } else if (initial_state->register_ != eh_frame_writer_.base_register()) {
    eh_frame_writer_.AdvanceLocation(pc_offset);
    eh_frame_writer_.SetBaseAddressRegister(initial_state->register_);
  } else if (initial_state->offset_ != eh_frame_writer_.base_offset()) {
    eh_frame_writer_.AdvanceLocation(pc_offset);
    eh_frame_writer_.SetBaseAddressOffset(initial_state->offset_);
  }

    tracking_fp_ = initial_state->tracking_fp_;
}

void UnwindingInfoWriter::EndInstructionBlock(const InstructionBlock* block) {
  if (!enabled() || block_will_exit_) return;

  for (const RpoNumber& successor : block->successors()) {
    int successor_index = successor.ToInt();
    DCHECK_LT(successor_index, static_cast<int>(block_initial_states_.size()));
    const BlockInitialState* existing_state =
        block_initial_states_[successor_index];
    // If we already had an entry for this BB, check that the values are the
    // same we are trying to insert.
    if (existing_state) {
      DCHECK(existing_state->register_ == eh_frame_writer_.base_register());
      DCHECK_EQ(existing_state->offset_, eh_frame_writer_.base_offset());
      DCHECK_EQ(existing_state->tracking_fp_, tracking_fp_);
    } else {
      block_initial_states_[successor_index] = zone_->New<BlockInitialState>(
          eh_frame_writer_.base_register(), eh_frame_writer_.base_offset(),
          tracking_fp_);
    }
  }
}

void UnwindingInfoWriter::MarkFrameConstructed(int pc_base) {
  if (!enabled()) return;

  // push rbp
  eh_frame_writer_.AdvanceLocation(pc_base + 1);
  eh_frame_writer_.IncreaseBaseAddressOffset(kInt64Size);
  // <base address> points at the bottom of the current frame on x64 and
  // <base register> is rsp, which points to the top of the frame by definition.
  // Thus, the distance between <base address> and the top is -<base offset>.
  int top_of_stack = -eh_frame_writer_.base_offset();
  eh_frame_writer_.RecordRegisterSavedToStack(rbp, top_of_stack);

  // mov rbp, rsp
  eh_frame_writer_.AdvanceLocation(pc_base + 4);
  eh_frame_writer_.SetBaseAddressRegister(rbp);

  tracking_fp_ = true;
}

void UnwindingInfoWriter::MarkFrameDeconstructed(int pc_base) {
  if (!enabled()) return;

  // mov rsp, rbp
  eh_frame_writer_.AdvanceLocation(pc_base + 3);
  eh_frame_writer_.SetBaseAddressRegister(rsp);

  // pop rbp
  eh_frame_writer_.AdvanceLocation(pc_base + 4);
  eh_frame_writer_.IncreaseBaseAddressOffset(-kInt64Size);

  tracking_fp_ = false;
}

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