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