diff options
author | 2015-10-22 15:25:54 +0100 | |
---|---|---|
committer | 2015-11-04 14:54:23 +0000 | |
commit | 10ef6941648aad04d54527d4a7a6070bf7065e88 (patch) | |
tree | 50fe6b50a3020ec7d25fbd5e4393db1c04452ce7 /compiler/utils/assembler.h | |
parent | c74e69f831608964f89ac7a641fbcc09156eefaa (diff) |
Delay emitting CFI PC adjustments until after Thumb2/Mips fixup.
On Mips also take into account out-of-order CFI data emitted
from EmitBranches().
Change-Id: I03b0b0b4c2b1ea31a02699ef5fa1c55aa42c23c3
Diffstat (limited to 'compiler/utils/assembler.h')
-rw-r--r-- | compiler/utils/assembler.h | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h index dfe6babb25..1dbc142391 100644 --- a/compiler/utils/assembler.h +++ b/compiler/utils/assembler.h @@ -271,16 +271,71 @@ class AssemblerBuffer { class DebugFrameOpCodeWriterForAssembler FINAL : public dwarf::DebugFrameOpCodeWriter<> { public: + struct DelayedAdvancePC { + uint32_t stream_pos; + uint32_t pc; + }; + // This method is called the by the opcode writers. virtual void ImplicitlyAdvancePC() FINAL; explicit DebugFrameOpCodeWriterForAssembler(Assembler* buffer) - : dwarf::DebugFrameOpCodeWriter<>(), - assembler_(buffer) { + : dwarf::DebugFrameOpCodeWriter<>(false /* enabled */), + assembler_(buffer), + delay_emitting_advance_pc_(false), + delayed_advance_pcs_() { + } + + ~DebugFrameOpCodeWriterForAssembler() { + DCHECK(delayed_advance_pcs_.empty()); + } + + // Tell the writer to delay emitting advance PC info. + // The assembler must explicitly process all the delayed advances. + void DelayEmittingAdvancePCs() { + delay_emitting_advance_pc_ = true; + } + + // Override the last delayed PC. The new PC can be out of order. + void OverrideDelayedPC(size_t pc) { + DCHECK(delay_emitting_advance_pc_); + DCHECK(!delayed_advance_pcs_.empty()); + delayed_advance_pcs_.back().pc = pc; + } + + // Return the number of delayed advance PC entries. + size_t NumberOfDelayedAdvancePCs() const { + return delayed_advance_pcs_.size(); + } + + // Release the CFI stream and advance PC infos so that the assembler can patch it. + std::pair<std::vector<uint8_t>, std::vector<DelayedAdvancePC>> + ReleaseStreamAndPrepareForDelayedAdvancePC() { + DCHECK(delay_emitting_advance_pc_); + delay_emitting_advance_pc_ = false; + std::pair<std::vector<uint8_t>, std::vector<DelayedAdvancePC>> result; + result.first.swap(opcodes_); + result.second.swap(delayed_advance_pcs_); + return result; + } + + // Reserve space for the CFI stream. + void ReserveCFIStream(size_t capacity) { + opcodes_.reserve(capacity); + } + + // Append raw data to the CFI stream. + void AppendRawData(const std::vector<uint8_t>& raw_data, size_t first, size_t last) { + DCHECK_LE(0u, first); + DCHECK_LE(first, last); + DCHECK_LE(last, raw_data.size()); + opcodes_.insert(opcodes_.end(), raw_data.begin() + first, raw_data.begin() + last); } private: Assembler* assembler_; + bool delay_emitting_advance_pc_; + std::vector<DelayedAdvancePC> delayed_advance_pcs_; }; class Assembler { |