diff options
| author | 2015-11-04 16:27:44 +0000 | |
|---|---|---|
| committer | 2015-11-04 16:27:44 +0000 | |
| commit | c8894ab5021aecd0fa5eba94af47f732914af33b (patch) | |
| tree | ee1ea3271d41b9a647a7ce7e4d1a0ed94eff9fcf /compiler/utils/mips/assembler_mips.cc | |
| parent | b178e11d9eb44fc0ac666049f3aa14f7f14ffd64 (diff) | |
| parent | 10ef6941648aad04d54527d4a7a6070bf7065e88 (diff) | |
Merge "Delay emitting CFI PC adjustments until after Thumb2/Mips fixup."
Diffstat (limited to 'compiler/utils/mips/assembler_mips.cc')
| -rw-r--r-- | compiler/utils/mips/assembler_mips.cc | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc index 6f35e9ef59..aee64120a8 100644 --- a/compiler/utils/mips/assembler_mips.cc +++ b/compiler/utils/mips/assembler_mips.cc @@ -43,8 +43,60 @@ void MipsAssembler::FinalizeCode() { } void MipsAssembler::FinalizeInstructions(const MemoryRegion& region) { + size_t number_of_delayed_adjust_pcs = cfi().NumberOfDelayedAdvancePCs(); EmitBranches(); Assembler::FinalizeInstructions(region); + PatchCFI(number_of_delayed_adjust_pcs); +} + +void MipsAssembler::PatchCFI(size_t number_of_delayed_adjust_pcs) { + if (cfi().NumberOfDelayedAdvancePCs() == 0u) { + DCHECK_EQ(number_of_delayed_adjust_pcs, 0u); + return; + } + + typedef DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC DelayedAdvancePC; + const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC(); + const std::vector<uint8_t>& old_stream = data.first; + const std::vector<DelayedAdvancePC>& advances = data.second; + + // PCs recorded before EmitBranches() need to be adjusted. + // PCs recorded during EmitBranches() are already adjusted. + // Both ranges are separately sorted but they may overlap. + if (kIsDebugBuild) { + auto cmp = [](const DelayedAdvancePC& lhs, const DelayedAdvancePC& rhs) { + return lhs.pc < rhs.pc; + }; + CHECK(std::is_sorted(advances.begin(), advances.begin() + number_of_delayed_adjust_pcs, cmp)); + CHECK(std::is_sorted(advances.begin() + number_of_delayed_adjust_pcs, advances.end(), cmp)); + } + + // Append initial CFI data if any. + size_t size = advances.size(); + DCHECK_NE(size, 0u); + cfi().AppendRawData(old_stream, 0u, advances[0].stream_pos); + // Emit PC adjustments interleaved with the old CFI stream. + size_t adjust_pos = 0u; + size_t late_emit_pos = number_of_delayed_adjust_pcs; + while (adjust_pos != number_of_delayed_adjust_pcs || late_emit_pos != size) { + size_t adjusted_pc = (adjust_pos != number_of_delayed_adjust_pcs) + ? GetAdjustedPosition(advances[adjust_pos].pc) + : static_cast<size_t>(-1); + size_t late_emit_pc = (late_emit_pos != size) + ? advances[late_emit_pos].pc + : static_cast<size_t>(-1); + size_t advance_pc = std::min(adjusted_pc, late_emit_pc); + DCHECK_NE(advance_pc, static_cast<size_t>(-1)); + size_t entry = (adjusted_pc <= late_emit_pc) ? adjust_pos : late_emit_pos; + if (adjusted_pc <= late_emit_pc) { + ++adjust_pos; + } else { + ++late_emit_pos; + } + cfi().AdvancePC(advance_pc); + size_t end_pos = (entry + 1u == size) ? old_stream.size() : advances[entry + 1u].stream_pos; + cfi().AppendRawData(old_stream, advances[entry].stream_pos, end_pos); + } } void MipsAssembler::EmitBranches() { @@ -1770,6 +1822,7 @@ void MipsAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg, const std::vector<ManagedRegister>& callee_save_regs, const ManagedRegisterEntrySpills& entry_spills) { CHECK_ALIGNED(frame_size, kStackAlignment); + DCHECK(!overwriting_); // Increase frame to required size. IncreaseFrameSize(frame_size); @@ -1811,6 +1864,7 @@ void MipsAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg, void MipsAssembler::RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs) { CHECK_ALIGNED(frame_size, kStackAlignment); + DCHECK(!overwriting_); cfi_.RememberState(); // Pop callee saves and return address. @@ -1840,12 +1894,18 @@ void MipsAssembler::IncreaseFrameSize(size_t adjust) { CHECK_ALIGNED(adjust, kFramePointerSize); Addiu32(SP, SP, -adjust); cfi_.AdjustCFAOffset(adjust); + if (overwriting_) { + cfi_.OverrideDelayedPC(overwrite_location_); + } } void MipsAssembler::DecreaseFrameSize(size_t adjust) { CHECK_ALIGNED(adjust, kFramePointerSize); Addiu32(SP, SP, adjust); cfi_.AdjustCFAOffset(-adjust); + if (overwriting_) { + cfi_.OverrideDelayedPC(overwrite_location_); + } } void MipsAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) { |