115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky/* 215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * Copyright (C) 2015 The Android Open Source Project 315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * 415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * Licensed under the Apache License, Version 2.0 (the "License"); 515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * you may not use this file except in compliance with the License. 615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * You may obtain a copy of the License at 715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * 815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * http://www.apache.org/licenses/LICENSE-2.0 915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * 1015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * Unless required by applicable law or agreed to in writing, software 1115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * distributed under the License is distributed on an "AS IS" BASIS, 1215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * See the License for the specific language governing permissions and 1415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * limitations under the License. 1515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky */ 1615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 1715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#ifndef ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_ 1815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#define ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_ 1915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 2041b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "base/bit_utils.h" 217c869b352d122ab0bbf7cb529b45fc0365837c3aDavid Srbecky#include "dwarf/dwarf_constants.h" 227c869b352d122ab0bbf7cb529b45fc0365837c3aDavid Srbecky#include "dwarf/register.h" 237c869b352d122ab0bbf7cb529b45fc0365837c3aDavid Srbecky#include "dwarf/writer.h" 2415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 2515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbeckynamespace art { 2615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbeckynamespace dwarf { 2715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 2815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky// Writer for .debug_frame opcodes (DWARF-3). 2915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky// See the DWARF specification for the precise meaning of the opcodes. 3015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky// The writer is very light-weight, however it will do the following for you: 3115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky// * Choose the most compact encoding of a given opcode. 3215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky// * Keep track of current state and convert absolute values to deltas. 3315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky// * Divide by header-defined factors as appropriate. 3415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbeckytemplate<typename Allocator = std::allocator<uint8_t> > 3515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbeckyclass DebugFrameOpCodeWriter : private Writer<Allocator> { 3615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky public: 3715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // To save space, DWARF divides most offsets by header-defined factors. 3815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // They are used in integer divisions, so we make them constants. 3915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // We usually subtract from stack base pointer, so making the factor 4015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // negative makes the encoded values positive and thus easier to encode. 4115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky static constexpr int kDataAlignmentFactor = -4; 4215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky static constexpr int kCodeAlignmentFactor = 1; 4315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 4415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Explicitely advance the program counter to given location. 45c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE AdvancePC(int absolute_pc) { 4615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky DCHECK_GE(absolute_pc, current_pc_); 47c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 48c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky int delta = FactorCodeOffset(absolute_pc - current_pc_); 49c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (delta != 0) { 50c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (delta <= 0x3F) { 51c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_advance_loc | delta); 52c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } else if (delta <= UINT8_MAX) { 53c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_advance_loc1); 54c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(delta); 55c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } else if (delta <= UINT16_MAX) { 56c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_advance_loc2); 57c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint16(delta); 58c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } else { 59c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_advance_loc4); 60c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint32(delta); 61c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 6215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 63c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky current_pc_ = absolute_pc; 6415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 6515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 6615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 6715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Override this method to automatically advance the PC before each opcode. 6815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky virtual void ImplicitlyAdvancePC() { } 6915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 7015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Common alias in assemblers - spill relative to current stack pointer. 71c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE RelOffset(Reg reg, int offset) { 7215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky Offset(reg, offset - current_cfa_offset_); 7315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 7415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 7515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Common alias in assemblers - increase stack frame size. 76c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE AdjustCFAOffset(int delta) { 7715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky DefCFAOffset(current_cfa_offset_ + delta); 7815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 7915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 8015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Custom alias - spill many registers based on bitmask. 81c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE RelOffsetForMany(Reg reg_base, int offset, 82c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky uint32_t reg_mask, int reg_size) { 8315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky DCHECK(reg_size == 4 || reg_size == 8); 84c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 85c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) { 86c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky // Skip zero bits and go to the set bit. 87c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky int num_zeros = CTZ(reg_mask); 88c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky i += num_zeros; 89c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky reg_mask >>= num_zeros; 9015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky RelOffset(Reg(reg_base.num() + i), offset); 9115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky offset += reg_size; 9215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 9315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 9415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 9515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 9615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Custom alias - unspill many registers based on bitmask. 97c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE RestoreMany(Reg reg_base, uint32_t reg_mask) { 98c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 99c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) { 100c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky // Skip zero bits and go to the set bit. 101c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky int num_zeros = CTZ(reg_mask); 102c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky i += num_zeros; 103c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky reg_mask >>= num_zeros; 10415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky Restore(Reg(reg_base.num() + i)); 10515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 10615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 10715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 10815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 109c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE Nop() { 110c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 111c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_nop); 112c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 11315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 11415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 115c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE Offset(Reg reg, int offset) { 116c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 117c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 118c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky int factored_offset = FactorDataOffset(offset); // May change sign. 119c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (factored_offset >= 0) { 120c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (0 <= reg.num() && reg.num() <= 0x3F) { 121c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_offset | reg.num()); 122c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(factored_offset); 123c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } else { 124c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_offset_extended); 125c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 126c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(factored_offset); 127c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 12815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } else { 129c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky uses_dwarf3_features_ = true; 130c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_offset_extended_sf); 13115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky this->PushUleb128(reg.num()); 132c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushSleb128(factored_offset); 13315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 13415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 13515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 13615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 137c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE Restore(Reg reg) { 138c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 139c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 140c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (0 <= reg.num() && reg.num() <= 0x3F) { 141c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_restore | reg.num()); 142c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } else { 143c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_restore_extended); 144c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 145c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 14615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 14715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 14815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 149c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE Undefined(Reg reg) { 150c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 151c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 152c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_undefined); 153c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 154c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 15515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 15615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 157c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE SameValue(Reg reg) { 158c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 159c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 160c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_same_value); 161c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 162c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 16315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 16415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 16515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // The previous value of "reg" is stored in register "new_reg". 166c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE Register(Reg reg, Reg new_reg) { 167c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 168c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 169c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_register); 170c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 171c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(new_reg.num()); 172c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 17315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 17415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 175c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE RememberState() { 176c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 177c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 178c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_remember_state); 17915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 18015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 18115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 182c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE RestoreState() { 183c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 184c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 185c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_restore_state); 186c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 18715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 18815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 189c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE DefCFA(Reg reg, int offset) { 190c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 19115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky ImplicitlyAdvancePC(); 19215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (offset >= 0) { 193c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_def_cfa); 194c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 19515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky this->PushUleb128(offset); // Non-factored. 19615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } else { 19715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky uses_dwarf3_features_ = true; 198c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_def_cfa_sf); 199c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 20015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky this->PushSleb128(FactorDataOffset(offset)); 20115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 20215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 203c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky current_cfa_offset_ = offset; 20415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 20515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 206c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE DefCFARegister(Reg reg) { 207c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 208c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 209c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_def_cfa_register); 21015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky this->PushUleb128(reg.num()); 21115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 21215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 21315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 214c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE DefCFAOffset(int offset) { 215c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 216c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (current_cfa_offset_ != offset) { 217c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 218c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (offset >= 0) { 219c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_def_cfa_offset); 220c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(offset); // Non-factored. 221c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } else { 222c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky uses_dwarf3_features_ = true; 223c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_def_cfa_offset_sf); 224c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushSleb128(FactorDataOffset(offset)); 225c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 226c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 227c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 228c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky // Uncoditional so that the user can still get and check the value. 229c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky current_cfa_offset_ = offset; 23015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 23115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 232c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE ValOffset(Reg reg, int offset) { 233c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 234c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 235c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky uses_dwarf3_features_ = true; 236c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky int factored_offset = FactorDataOffset(offset); // May change sign. 237c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (factored_offset >= 0) { 238c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_val_offset); 239c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 240c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(factored_offset); 241c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } else { 242c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_val_offset_sf); 243c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 244c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushSleb128(factored_offset); 245c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 246c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 24715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 24815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 249c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE DefCFAExpression(void * expr, int expr_size) { 250c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 251c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 252c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky uses_dwarf3_features_ = true; 253c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_def_cfa_expression); 254c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(expr_size); 255c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushData(expr, expr_size); 256c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 25715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 25815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 259c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE Expression(Reg reg, void * expr, int expr_size) { 260c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 261c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 262c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky uses_dwarf3_features_ = true; 263c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_expression); 264c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 265c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(expr_size); 266c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushData(expr, expr_size); 267c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 2681109fb3cacc8bb667979780c2b4b12ce5bb64549David Srbecky } 2691109fb3cacc8bb667979780c2b4b12ce5bb64549David Srbecky 270c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void ALWAYS_INLINE ValExpression(Reg reg, void * expr, int expr_size) { 271c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (UNLIKELY(enabled_)) { 272c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ImplicitlyAdvancePC(); 273c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky uses_dwarf3_features_ = true; 274c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUint8(DW_CFA_val_expression); 275c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(reg.num()); 276c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushUleb128(expr_size); 277c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky this->PushData(expr, expr_size); 278c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 27915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 28015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 281c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky bool IsEnabled() const { return enabled_; } 282c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky 283c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void SetEnabled(bool value) { enabled_ = value; } 284c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky 285c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky int GetCurrentPC() const { return current_pc_; } 286c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky 287c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky int GetCurrentCFAOffset() const { return current_cfa_offset_; } 288c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky 289c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky void SetCurrentCFAOffset(int offset) { current_cfa_offset_ = offset; } 29015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 29115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky using Writer<Allocator>::data; 29215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 293c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky DebugFrameOpCodeWriter(bool enabled = true, 294c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky const Allocator& alloc = Allocator()) 29515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky : Writer<Allocator>(&opcodes_), 296c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky enabled_(enabled), 29715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky opcodes_(alloc), 29815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky current_cfa_offset_(0), 29915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky current_pc_(0), 30015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky uses_dwarf3_features_(false) { 301c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky if (enabled) { 302c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky // Best guess based on couple of observed outputs. 303c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky opcodes_.reserve(16); 304c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky } 30515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 30615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 30715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky virtual ~DebugFrameOpCodeWriter() { } 30815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 30915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky protected: 31015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky int FactorDataOffset(int offset) const { 31115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky DCHECK_EQ(offset % kDataAlignmentFactor, 0); 31215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky return offset / kDataAlignmentFactor; 31315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 31415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 31515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky int FactorCodeOffset(int offset) const { 31615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky DCHECK_EQ(offset % kCodeAlignmentFactor, 0); 31715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky return offset / kCodeAlignmentFactor; 31815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 31915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 320c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky bool enabled_; // If disabled all writes are no-ops. 32115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<uint8_t, Allocator> opcodes_; 32215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky int current_cfa_offset_; 32315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky int current_pc_; 32415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky bool uses_dwarf3_features_; 32515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 32615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky private: 32715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky DISALLOW_COPY_AND_ASSIGN(DebugFrameOpCodeWriter); 32815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky}; 32915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 33015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky} // namespace dwarf 33115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky} // namespace art 33215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 33315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#endif // ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_ 334