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