1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// found in the LICENSE file.
4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler/arm/unwinding-info-writer-arm.h"
6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler/instruction.h"
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace v8 {
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace internal {
10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace compiler {
11f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid UnwindingInfoWriter::BeginInstructionBlock(int pc_offset,
13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                                const InstructionBlock* block) {
14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!enabled()) return;
15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  block_will_exit_ = false;
17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
18c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK_LT(block->rpo_number().ToInt(),
19c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            static_cast<int>(block_initial_states_.size()));
20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const BlockInitialState* initial_state =
21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      block_initial_states_[block->rpo_number().ToInt()];
22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (initial_state) {
23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (initial_state->saved_lr_ != saved_lr_) {
24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      eh_frame_writer_.AdvanceLocation(pc_offset);
25f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (initial_state->saved_lr_) {
26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        eh_frame_writer_.RecordRegisterSavedToStack(lr, kPointerSize);
27f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      } else {
28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        eh_frame_writer_.RecordRegisterFollowsInitialRule(lr);
29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      saved_lr_ = initial_state->saved_lr_;
31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // The entry block always lacks an explicit initial state.
34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // The exit block may lack an explicit state, if it is only reached by
35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    //   the block ending in a bx lr.
36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // All the other blocks must have an explicit initial state.
37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(block->predecessors().empty() || block->successors().empty());
38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid UnwindingInfoWriter::EndInstructionBlock(const InstructionBlock* block) {
42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!enabled() || block_will_exit_) return;
43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (const RpoNumber& successor : block->successors()) {
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    int successor_index = successor.ToInt();
46c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_LT(successor_index, static_cast<int>(block_initial_states_.size()));
47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const BlockInitialState* existing_state =
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        block_initial_states_[successor_index];
49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // If we already had an entry for this BB, check that the values are the
51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // same we are trying to insert.
52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (existing_state) {
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_EQ(existing_state->saved_lr_, saved_lr_);
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      block_initial_states_[successor_index] =
56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          new (zone_) BlockInitialState(saved_lr_);
57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid UnwindingInfoWriter::MarkFrameConstructed(int at_pc) {
62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!enabled()) return;
63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Regardless of the type of frame constructed, the relevant part of the
65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // layout is always the one in the diagram:
66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |   ....   |         higher addresses
68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // +----------+               ^
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |    LR    |               |            |
70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // +----------+               |            |
71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // | saved FP |               |            |
72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // +----------+ <-- FP                     v
73f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |   ....   |                       stack growth
74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // The LR is pushed on the stack, and we can record this fact at the end of
76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // the construction, since the LR itself is not modified in the process.
77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.AdvanceLocation(at_pc);
78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.RecordRegisterSavedToStack(lr, kPointerSize);
79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  saved_lr_ = true;
80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid UnwindingInfoWriter::MarkFrameDeconstructed(int at_pc) {
83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!enabled()) return;
84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // The lr is restored by the last operation in LeaveFrame().
86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.AdvanceLocation(at_pc);
87f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.RecordRegisterFollowsInitialRule(lr);
88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  saved_lr_ = false;
89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid UnwindingInfoWriter::MarkLinkRegisterOnTopOfStack(int pc_offset) {
92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!enabled()) return;
93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.AdvanceLocation(pc_offset);
95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.SetBaseAddressRegisterAndOffset(sp, 0);
96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.RecordRegisterSavedToStack(lr, 0);
97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid UnwindingInfoWriter::MarkPopLinkRegisterFromTopOfStack(int pc_offset) {
100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!enabled()) return;
101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.AdvanceLocation(pc_offset);
103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.SetBaseAddressRegisterAndOffset(fp, 0);
104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  eh_frame_writer_.RecordRegisterFollowsInitialRule(lr);
105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace compiler
108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace internal
109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace v8
110