summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator_arm64.cc
diff options
context:
space:
mode:
authorDavid Srbecky <dsrbecky@google.com>2015-04-07 20:32:43 +0100
committerDavid Srbecky <dsrbecky@google.com>2015-04-09 16:47:50 +0100
commitc6b4dd8980350aaf250f0185f73e9c42ec17cd57 (patch)
treeef8d73e37abc04aecb430072a8bc463c73398fee /compiler/optimizing/code_generator_arm64.cc
parentdd97393aca1a3ff2abec4dc4f78d7724300971bc (diff)
downloadart-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.cc61
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) {