diff options
author | David Srbecky <dsrbecky@google.com> | 2015-04-07 20:32:43 +0100 |
---|---|---|
committer | David Srbecky <dsrbecky@google.com> | 2015-04-09 16:47:50 +0100 |
commit | c6b4dd8980350aaf250f0185f73e9c42ec17cd57 (patch) | |
tree | ef8d73e37abc04aecb430072a8bc463c73398fee /compiler/optimizing/code_generator_arm64.cc | |
parent | dd97393aca1a3ff2abec4dc4f78d7724300971bc (diff) | |
download | art-c6b4dd8980350aaf250f0185f73e9c42ec17cd57.tar.gz art-c6b4dd8980350aaf250f0185f73e9c42ec17cd57.tar.bz2 art-c6b4dd8980350aaf250f0185f73e9c42ec17cd57.zip |
Implement CFI for Optimizing.
CFI is necessary for stack unwinding in gdb, lldb, and libunwind.
Change-Id: I1a3480e3a4a99f48bf7e6e63c4e83a80cfee40a2
Diffstat (limited to 'compiler/optimizing/code_generator_arm64.cc')
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 61 |
1 files changed, 57 insertions, 4 deletions
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 439e85ca6c..12eb0c78ea 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -465,20 +465,67 @@ void CodeGeneratorARM64::GenerateFrameEntry() { // ... : reserved frame space. // sp[0] : current method. __ Str(kArtMethodRegister, MemOperand(sp, -frame_size, PreIndex)); - __ PokeCPURegList(GetFramePreservedCoreRegisters(), frame_size - GetCoreSpillSize()); - __ PokeCPURegList(GetFramePreservedFPRegisters(), frame_size - FrameEntrySpillSize()); + GetAssembler()->cfi().AdjustCFAOffset(frame_size); + SpillRegisters(GetFramePreservedCoreRegisters(), frame_size - GetCoreSpillSize()); + SpillRegisters(GetFramePreservedFPRegisters(), frame_size - FrameEntrySpillSize()); } } void CodeGeneratorARM64::GenerateFrameExit() { if (!HasEmptyFrame()) { int frame_size = GetFrameSize(); - __ PeekCPURegList(GetFramePreservedFPRegisters(), frame_size - FrameEntrySpillSize()); - __ PeekCPURegList(GetFramePreservedCoreRegisters(), frame_size - GetCoreSpillSize()); + UnspillRegisters(GetFramePreservedFPRegisters(), frame_size - FrameEntrySpillSize()); + UnspillRegisters(GetFramePreservedCoreRegisters(), frame_size - GetCoreSpillSize()); __ Drop(frame_size); + GetAssembler()->cfi().AdjustCFAOffset(-frame_size); } } +static inline dwarf::Reg DWARFReg(CPURegister reg) { + if (reg.IsFPRegister()) { + return dwarf::Reg::Arm64Fp(reg.code()); + } else { + DCHECK_LT(reg.code(), 31u); // X0 - X30. + return dwarf::Reg::Arm64Core(reg.code()); + } +} + +void CodeGeneratorARM64::SpillRegisters(vixl::CPURegList registers, int offset) { + int size = registers.RegisterSizeInBytes(); + while (registers.Count() >= 2) { + const CPURegister& dst0 = registers.PopLowestIndex(); + const CPURegister& dst1 = registers.PopLowestIndex(); + __ Stp(dst0, dst1, MemOperand(__ StackPointer(), offset)); + GetAssembler()->cfi().RelOffset(DWARFReg(dst0), offset); + GetAssembler()->cfi().RelOffset(DWARFReg(dst1), offset + size); + offset += 2 * size; + } + if (!registers.IsEmpty()) { + const CPURegister& dst0 = registers.PopLowestIndex(); + __ Str(dst0, MemOperand(__ StackPointer(), offset)); + GetAssembler()->cfi().RelOffset(DWARFReg(dst0), offset); + } + DCHECK(registers.IsEmpty()); +} + +void CodeGeneratorARM64::UnspillRegisters(vixl::CPURegList registers, int offset) { + int size = registers.RegisterSizeInBytes(); + while (registers.Count() >= 2) { + const CPURegister& dst0 = registers.PopLowestIndex(); + const CPURegister& dst1 = registers.PopLowestIndex(); + __ Ldp(dst0, dst1, MemOperand(__ StackPointer(), offset)); + GetAssembler()->cfi().Restore(DWARFReg(dst0)); + GetAssembler()->cfi().Restore(DWARFReg(dst1)); + offset += 2 * size; + } + if (!registers.IsEmpty()) { + const CPURegister& dst0 = registers.PopLowestIndex(); + __ Ldr(dst0, MemOperand(__ StackPointer(), offset)); + GetAssembler()->cfi().Restore(DWARFReg(dst0)); + } + DCHECK(registers.IsEmpty()); +} + void CodeGeneratorARM64::Bind(HBasicBlock* block) { __ Bind(GetLabelOf(block)); } @@ -2403,8 +2450,11 @@ void LocationsBuilderARM64::VisitReturn(HReturn* instruction) { void InstructionCodeGeneratorARM64::VisitReturn(HReturn* instruction) { UNUSED(instruction); + GetAssembler()->cfi().RememberState(); codegen_->GenerateFrameExit(); __ Ret(); + GetAssembler()->cfi().RestoreState(); + GetAssembler()->cfi().DefCFAOffset(codegen_->GetFrameSize()); } void LocationsBuilderARM64::VisitReturnVoid(HReturnVoid* instruction) { @@ -2413,8 +2463,11 @@ void LocationsBuilderARM64::VisitReturnVoid(HReturnVoid* instruction) { void InstructionCodeGeneratorARM64::VisitReturnVoid(HReturnVoid* instruction) { UNUSED(instruction); + GetAssembler()->cfi().RememberState(); codegen_->GenerateFrameExit(); __ Ret(); + GetAssembler()->cfi().RestoreState(); + GetAssembler()->cfi().DefCFAOffset(codegen_->GetFrameSize()); } void LocationsBuilderARM64::VisitShl(HShl* shl) { |