summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/compilers.cc6
-rw-r--r--compiler/dex/quick/x86/codegen_x86.h2
-rwxr-xr-xcompiler/dex/quick/x86/target_x86.cc165
-rw-r--r--compiler/elf_writer_quick.cc12
-rw-r--r--compiler/oat_writer.cc10
5 files changed, 148 insertions, 47 deletions
diff --git a/compiler/compilers.cc b/compiler/compilers.cc
index bac1f12823..250924ad30 100644
--- a/compiler/compilers.cc
+++ b/compiler/compilers.cc
@@ -39,7 +39,7 @@ extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver* dr
const art::DexFile& dex_file);
// Hack for CFI CIE initialization
-extern std::vector<uint8_t>* X86CFIInitialization();
+extern std::vector<uint8_t>* X86CFIInitialization(bool is_x86_64);
void QuickCompiler::Init() const {
ArtInitQuickCompilerContext(GetCompilerDriver());
@@ -129,10 +129,10 @@ Backend* QuickCompiler::GetCodeGenerator(CompilationUnit* cu, void* compilation_
std::vector<uint8_t>* QuickCompiler::GetCallFrameInformationInitialization(
const CompilerDriver& driver) const {
if (driver.GetInstructionSet() == kX86) {
- return X86CFIInitialization();
+ return X86CFIInitialization(false);
}
if (driver.GetInstructionSet() == kX86_64) {
- return X86CFIInitialization();
+ return X86CFIInitialization(true);
}
return nullptr;
}
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 3bc79ad415..0a46f2e54a 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -394,7 +394,7 @@ class X86Mir2Lir : public Mir2Lir {
* @brief Generate the debug_frame CFI information.
* @returns pointer to vector containing CFE information
*/
- static std::vector<uint8_t>* ReturnCommonCallFrameInformation();
+ static std::vector<uint8_t>* ReturnCommonCallFrameInformation(bool is_x86_64);
/*
* @brief Generate the debug_frame FDE information.
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 31110251c9..3fa4b6ea42 100755
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -1443,56 +1443,123 @@ static void AdvanceLoc(std::vector<uint8_t>&buf, uint32_t increment) {
}
-std::vector<uint8_t>* X86CFIInitialization() {
- return X86Mir2Lir::ReturnCommonCallFrameInformation();
+std::vector<uint8_t>* X86CFIInitialization(bool is_x86_64) {
+ return X86Mir2Lir::ReturnCommonCallFrameInformation(is_x86_64);
}
-std::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation() {
+static void EncodeUnsignedLeb128(std::vector<uint8_t>& buf, uint32_t value) {
+ uint8_t buffer[12];
+ uint8_t *ptr = EncodeUnsignedLeb128(buffer, value);
+ for (uint8_t *p = buffer; p < ptr; p++) {
+ buf.push_back(*p);
+ }
+}
+
+static void EncodeSignedLeb128(std::vector<uint8_t>& buf, int32_t value) {
+ uint8_t buffer[12];
+ uint8_t *ptr = EncodeSignedLeb128(buffer, value);
+ for (uint8_t *p = buffer; p < ptr; p++) {
+ buf.push_back(*p);
+ }
+}
+
+std::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation(bool is_x86_64) {
std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
- // Length of the CIE (except for this field).
- PushWord(*cfi_info, 16);
+ // Length (will be filled in later in this routine).
+ PushWord(*cfi_info, 0);
- // CIE id.
- PushWord(*cfi_info, 0xFFFFFFFFU);
+ // CIE id: always 0.
+ PushWord(*cfi_info, 0);
- // Version: 3.
- cfi_info->push_back(0x03);
+ // Version: always 1.
+ cfi_info->push_back(0x01);
- // Augmentation: empty string.
+ // Augmentation: 'zR\0'
+ cfi_info->push_back(0x7a);
+ cfi_info->push_back(0x52);
cfi_info->push_back(0x0);
// Code alignment: 1.
- cfi_info->push_back(0x01);
+ EncodeUnsignedLeb128(*cfi_info, 1);
- // Data alignment: -4.
- cfi_info->push_back(0x7C);
+ // Data alignment.
+ if (is_x86_64) {
+ EncodeSignedLeb128(*cfi_info, -8);
+ } else {
+ EncodeSignedLeb128(*cfi_info, -4);
+ }
- // Return address register (R8).
- cfi_info->push_back(0x08);
+ // Return address register.
+ if (is_x86_64) {
+ // R16(RIP)
+ cfi_info->push_back(0x10);
+ } else {
+ // R8(EIP)
+ cfi_info->push_back(0x08);
+ }
- // Initial return PC is 4(ESP): DW_CFA_def_cfa R4 4.
- cfi_info->push_back(0x0C);
- cfi_info->push_back(0x04);
- cfi_info->push_back(0x04);
+ // Augmentation length: 1.
+ cfi_info->push_back(1);
- // Return address location: 0(SP): DW_CFA_offset R8 1 (* -4);.
- cfi_info->push_back(0x2 << 6 | 0x08);
- cfi_info->push_back(0x01);
+ // Augmentation data: 0x03 ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
+ cfi_info->push_back(0x03);
- // And 2 Noops to align to 4 byte boundary.
- cfi_info->push_back(0x0);
- cfi_info->push_back(0x0);
+ // Initial instructions.
+ if (is_x86_64) {
+ // DW_CFA_def_cfa R7(RSP) 8.
+ cfi_info->push_back(0x0c);
+ cfi_info->push_back(0x07);
+ cfi_info->push_back(0x08);
- DCHECK_EQ(cfi_info->size() & 3, 0U);
+ // DW_CFA_offset R16(RIP) 1 (* -8).
+ cfi_info->push_back(0x90);
+ cfi_info->push_back(0x01);
+ } else {
+ // DW_CFA_def_cfa R4(ESP) 4.
+ cfi_info->push_back(0x0c);
+ cfi_info->push_back(0x04);
+ cfi_info->push_back(0x04);
+
+ // DW_CFA_offset R8(EIP) 1 (* -4).
+ cfi_info->push_back(0x88);
+ cfi_info->push_back(0x01);
+ }
+
+ // Padding to a multiple of 4
+ while ((cfi_info->size() & 3) != 0) {
+ // DW_CFA_nop is encoded as 0.
+ cfi_info->push_back(0);
+ }
+
+ // Set the length of the CIE inside the generated bytes.
+ uint32_t length = cfi_info->size() - 4;
+ (*cfi_info)[0] = length;
+ (*cfi_info)[1] = length >> 8;
+ (*cfi_info)[2] = length >> 16;
+ (*cfi_info)[3] = length >> 24;
return cfi_info;
}
-static void EncodeUnsignedLeb128(std::vector<uint8_t>& buf, uint32_t value) {
- uint8_t buffer[12];
- uint8_t *ptr = EncodeUnsignedLeb128(buffer, value);
- for (uint8_t *p = buffer; p < ptr; p++) {
- buf.push_back(*p);
+static bool ARTRegIDToDWARFRegID(bool is_x86_64, int art_reg_id, int* dwarf_reg_id) {
+ if (is_x86_64) {
+ switch (art_reg_id) {
+ case 3 : *dwarf_reg_id = 3; return true; // %rbx
+ // This is the only discrepancy between ART & DWARF register numbering.
+ case 5 : *dwarf_reg_id = 6; return true; // %rbp
+ case 12: *dwarf_reg_id = 12; return true; // %r12
+ case 13: *dwarf_reg_id = 13; return true; // %r13
+ case 14: *dwarf_reg_id = 14; return true; // %r14
+ case 15: *dwarf_reg_id = 15; return true; // %r15
+ default: return false; // Should not get here
+ }
+ } else {
+ switch (art_reg_id) {
+ case 5: *dwarf_reg_id = 5; return true; // %ebp
+ case 6: *dwarf_reg_id = 6; return true; // %esi
+ case 7: *dwarf_reg_id = 7; return true; // %edi
+ default: return false; // Should not get here
+ }
}
}
@@ -1505,8 +1572,7 @@ std::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() {
// Length (will be filled in later in this routine).
PushWord(*cfi_info, 0);
- // CIE_pointer (can be filled in by linker); might be left at 0 if there is only
- // one CIE for the whole debug_frame section.
+ // 'CIE_pointer' (filled in by linker).
PushWord(*cfi_info, 0);
// 'initial_location' (filled in by linker).
@@ -1515,6 +1581,9 @@ std::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() {
// 'address_range' (number of bytes in the method).
PushWord(*cfi_info, data_offset_);
+ // Augmentation length: 0
+ cfi_info->push_back(0);
+
// The instructions in the FDE.
if (stack_decrement_ != nullptr) {
// Advance LOC to just past the stack decrement.
@@ -1525,6 +1594,30 @@ std::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() {
cfi_info->push_back(0x0e);
EncodeUnsignedLeb128(*cfi_info, frame_size_);
+ // Handle register spills
+ const uint32_t kSpillInstLen = (cu_->target64) ? 5 : 4;
+ const int kDataAlignmentFactor = (cu_->target64) ? -8 : -4;
+ uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum());
+ int offset = -(GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_);
+ for (int reg = 0; mask; mask >>= 1, reg++) {
+ if (mask & 0x1) {
+ pc += kSpillInstLen;
+
+ // Advance LOC to pass this instruction
+ AdvanceLoc(*cfi_info, kSpillInstLen);
+
+ int dwarf_reg_id;
+ if (ARTRegIDToDWARFRegID(cu_->target64, reg, &dwarf_reg_id)) {
+ // DW_CFA_offset_extended_sf reg_no offset
+ cfi_info->push_back(0x11);
+ EncodeUnsignedLeb128(*cfi_info, dwarf_reg_id);
+ EncodeSignedLeb128(*cfi_info, offset / kDataAlignmentFactor);
+ }
+
+ offset += GetInstructionSetPointerSize(cu_->instruction_set);
+ }
+ }
+
// We continue with that stack until the epilogue.
if (stack_increment_ != nullptr) {
uint32_t new_pc = NEXT_LIR(stack_increment_)->offset;
@@ -1534,10 +1627,10 @@ std::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() {
// current state: DW_CFA_remember_state.
cfi_info->push_back(0x0a);
- // We have now popped the stack: DW_CFA_def_cfa_offset 4. There is only the return
- // PC on the stack now.
+ // We have now popped the stack: DW_CFA_def_cfa_offset 4/8.
+ // There is only the return PC on the stack now.
cfi_info->push_back(0x0e);
- EncodeUnsignedLeb128(*cfi_info, 4);
+ EncodeUnsignedLeb128(*cfi_info, GetInstructionSetPointerSize(cu_->instruction_set));
// Everything after that is the same as before the epilogue.
// Stack bump was followed by RET instruction.
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 42743862fe..1fde12ecaf 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -106,14 +106,14 @@ bool ElfWriterQuick::ElfBuilder::Write() {
// | .strtab\0 | (Optional)
// | .debug_str\0 | (Optional)
// | .debug_info\0 | (Optional)
- // | .debug_frame\0 | (Optional)
+ // | .eh_frame\0 | (Optional)
// | .debug_abbrev\0 | (Optional)
// +-------------------------+ (Optional)
// | .debug_str | (Optional)
// +-------------------------+ (Optional)
// | .debug_info | (Optional)
// +-------------------------+ (Optional)
- // | .debug_frame | (Optional)
+ // | .eh_frame | (Optional)
// +-------------------------+ (Optional)
// | .debug_abbrev | (Optional)
// +-------------------------+
@@ -127,7 +127,7 @@ bool ElfWriterQuick::ElfBuilder::Write() {
// | Elf32_Shdr .shstrtab |
// | Elf32_Shdr .debug_str | (Optional)
// | Elf32_Shdr .debug_info | (Optional)
- // | Elf32_Shdr .debug_frame | (Optional)
+ // | Elf32_Shdr .eh_frame | (Optional)
// | Elf32_Shdr .debug_abbrev| (Optional)
// +-------------------------+
@@ -844,14 +844,14 @@ bool ElfWriterQuick::Write(OatWriter* oat_writer,
ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
- ElfRawSectionBuilder debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, 4, 0);
- debug_frame.SetBuffer(*compiler_driver_->GetCallFrameInformation());
+ ElfRawSectionBuilder eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
+ eh_frame.SetBuffer(*compiler_driver_->GetCallFrameInformation());
FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
debug_abbrev.GetBuffer(), debug_str.GetBuffer());
builder.RegisterRawSection(debug_info);
builder.RegisterRawSection(debug_abbrev);
- builder.RegisterRawSection(debug_frame);
+ builder.RegisterRawSection(eh_frame);
builder.RegisterRawSection(debug_str);
}
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 22f36f4f9b..9da59ab7ff 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -410,8 +410,16 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
int cur_offset = cfi_info->size();
cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
+ // Set the 'CIE_pointer' field to cur_offset+4.
+ uint32_t CIE_pointer = cur_offset + 4;
+ uint32_t offset_to_update = cur_offset + sizeof(uint32_t);
+ (*cfi_info)[offset_to_update+0] = CIE_pointer;
+ (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
+ (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
+ (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
+
// Set the 'initial_location' field to address the start of the method.
- uint32_t offset_to_update = cur_offset + 2*sizeof(uint32_t);
+ offset_to_update = cur_offset + 2*sizeof(uint32_t);
(*cfi_info)[offset_to_update+0] = quick_code_start;
(*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
(*cfi_info)[offset_to_update+2] = quick_code_start >> 16;