summaryrefslogtreecommitdiffstats
path: root/compiler/dex
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-03-02 20:09:10 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-03-02 20:09:10 +0000
commit1179b7b770c096e93442b9c6afea4730283256f0 (patch)
treee5f70dc307945fd510660ebde1fd259aecdf66a1 /compiler/dex
parent9fab32265f35c808b216210a8d5bebd931279041 (diff)
parentae9fd93c39a341e2dffe15c61cc7d9e841fa92c4 (diff)
downloadandroid_art-1179b7b770c096e93442b9c6afea4730283256f0.tar.gz
android_art-1179b7b770c096e93442b9c6afea4730283256f0.tar.bz2
android_art-1179b7b770c096e93442b9c6afea4730283256f0.zip
Merge "Tell GDB about Quick ART generated code"
Diffstat (limited to 'compiler/dex')
-rw-r--r--compiler/dex/quick/codegen_util.cc9
-rw-r--r--compiler/dex/quick/mir_to_lir.h5
-rw-r--r--compiler/dex/quick/x86/call_x86.cc4
-rw-r--r--compiler/dex/quick/x86/codegen_x86.h18
-rw-r--r--compiler/dex/quick/x86/target_x86.cc165
5 files changed, 197 insertions, 4 deletions
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 31854496ab..b0b8d1ea15 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -1070,10 +1070,12 @@ CompiledMethod* Mir2Lir::GetCompiledMethod() {
DCHECK_EQ(fp_vmap_table_.size(), 0u);
vmap_encoder.PushBackUnsigned(0u); // Size is 0.
}
+
+ UniquePtr<std::vector<uint8_t> > cfi_info(ReturnCallFrameInformation());
CompiledMethod* result =
new CompiledMethod(*cu_->compiler_driver, cu_->instruction_set, code_buffer_, frame_size_,
core_spill_mask_, fp_spill_mask_, encoded_mapping_table_,
- vmap_encoder.GetData(), native_gc_map_);
+ vmap_encoder.GetData(), native_gc_map_, cfi_info.get());
return result;
}
@@ -1216,4 +1218,9 @@ void Mir2Lir::LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_re
AppendLIR(load_pc_rel);
}
+std::vector<uint8_t>* Mir2Lir::ReturnCallFrameInformation() {
+ // Default case is to do nothing.
+ return nullptr;
+}
+
} // namespace art
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index b74052c117..8f199f8c85 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -1089,6 +1089,11 @@ class Mir2Lir : public Backend {
bool can_assume_type_is_in_dex_cache,
uint32_t type_idx, RegLocation rl_dest,
RegLocation rl_src);
+ /*
+ * @brief Generate the debug_frame FDE information if possible.
+ * @returns pointer to vector containg CFE information, or NULL.
+ */
+ virtual std::vector<uint8_t>* ReturnCallFrameInformation();
/**
* @brief Used to insert marker that can be used to associate MIR with LIR.
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 0613cdff7a..399001c397 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -198,7 +198,7 @@ void X86Mir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) {
LockTemp(rX86_ARG2);
/* Build frame, return address already on stack */
- OpRegImm(kOpSub, rX86_SP, frame_size_ - 4);
+ stack_decrement_ = OpRegImm(kOpSub, rX86_SP, frame_size_ - 4);
/*
* We can safely skip the stack overflow check if we're
@@ -246,7 +246,7 @@ void X86Mir2Lir::GenExitSequence() {
NewLIR0(kPseudoMethodExit);
UnSpillCoreRegs();
/* Remove frame except for return address */
- OpRegImm(kOpAdd, rX86_SP, frame_size_ - 4);
+ stack_increment_ = OpRegImm(kOpAdd, rX86_SP, frame_size_ - 4);
NewLIR0(kX86Ret);
}
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 421d51e4fd..c97d0e6f4d 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -302,6 +302,18 @@ class X86Mir2Lir : public Mir2Lir {
*/
void InstallLiteralPools();
+ /*
+ * @brief Generate the debug_frame CFI information.
+ * @returns pointer to vector containing CFE information
+ */
+ static std::vector<uint8_t>* ReturnCommonCallFrameInformation();
+
+ /*
+ * @brief Generate the debug_frame FDE information.
+ * @returns pointer to vector containing CFE information
+ */
+ std::vector<uint8_t>* ReturnCallFrameInformation();
+
private:
void EmitPrefix(const X86EncodingMap* entry);
void EmitOpcode(const X86EncodingMap* entry);
@@ -549,6 +561,12 @@ class X86Mir2Lir : public Mir2Lir {
// Instructions needing patching with PC relative code addresses.
GrowableArray<LIR*> call_method_insns_;
+
+ // Prologue decrement of stack pointer.
+ LIR* stack_decrement_;
+
+ // Epilogue increment of stack pointer.
+ LIR* stack_increment_;
};
} // namespace art
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index eea7191c3b..7bb866d4aa 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -539,7 +539,8 @@ X86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator*
: Mir2Lir(cu, mir_graph, arena),
method_address_insns_(arena, 100, kGrowableArrayMisc),
class_type_address_insns_(arena, 100, kGrowableArrayMisc),
- call_method_insns_(arena, 100, kGrowableArrayMisc) {
+ call_method_insns_(arena, 100, kGrowableArrayMisc),
+ stack_decrement_(nullptr), stack_increment_(nullptr) {
store_method_addr_used_ = false;
for (int i = 0; i < kX86Last; i++) {
if (X86Mir2Lir::EncodingMap[i].opcode != i) {
@@ -1118,4 +1119,166 @@ bool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) {
return true;
}
+/*
+ * @brief Enter a 32 bit quantity into the FDE buffer
+ * @param buf FDE buffer.
+ * @param data Data value.
+ */
+static void PushWord(std::vector<uint8_t>&buf, int data) {
+ buf.push_back(data & 0xff);
+ buf.push_back((data >> 8) & 0xff);
+ buf.push_back((data >> 16) & 0xff);
+ buf.push_back((data >> 24) & 0xff);
+}
+
+/*
+ * @brief Enter an 'advance LOC' into the FDE buffer
+ * @param buf FDE buffer.
+ * @param increment Amount by which to increase the current location.
+ */
+static void AdvanceLoc(std::vector<uint8_t>&buf, uint32_t increment) {
+ if (increment < 64) {
+ // Encoding in opcode.
+ buf.push_back(0x1 << 6 | increment);
+ } else if (increment < 256) {
+ // Single byte delta.
+ buf.push_back(0x02);
+ buf.push_back(increment);
+ } else if (increment < 256 * 256) {
+ // Two byte delta.
+ buf.push_back(0x03);
+ buf.push_back(increment & 0xff);
+ buf.push_back((increment >> 8) & 0xff);
+ } else {
+ // Four byte delta.
+ buf.push_back(0x04);
+ PushWord(buf, increment);
+ }
+}
+
+
+std::vector<uint8_t>* X86CFIInitialization() {
+ return X86Mir2Lir::ReturnCommonCallFrameInformation();
+}
+
+std::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation() {
+ std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
+
+ // Length of the CIE (except for this field).
+ PushWord(*cfi_info, 16);
+
+ // CIE id.
+ PushWord(*cfi_info, 0xFFFFFFFFU);
+
+ // Version: 3.
+ cfi_info->push_back(0x03);
+
+ // Augmentation: empty string.
+ cfi_info->push_back(0x0);
+
+ // Code alignment: 1.
+ cfi_info->push_back(0x01);
+
+ // Data alignment: -4.
+ cfi_info->push_back(0x7C);
+
+ // Return address register (R8).
+ 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);
+
+ // Return address location: 0(SP): DW_CFA_offset R8 1 (* -4);.
+ cfi_info->push_back(0x2 << 6 | 0x08);
+ cfi_info->push_back(0x01);
+
+ // And 2 Noops to align to 4 byte boundary.
+ cfi_info->push_back(0x0);
+ cfi_info->push_back(0x0);
+
+ DCHECK_EQ(cfi_info->size() & 3, 0U);
+ 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);
+ }
+}
+
+std::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() {
+ std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
+
+ // Generate the FDE for the method.
+ DCHECK_NE(data_offset_, 0U);
+
+ // 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.
+ PushWord(*cfi_info, 0);
+
+ // 'initial_location' (filled in by linker).
+ PushWord(*cfi_info, 0);
+
+ // 'address_range' (number of bytes in the method).
+ PushWord(*cfi_info, data_offset_);
+
+ // The instructions in the FDE.
+ if (stack_decrement_ != nullptr) {
+ // Advance LOC to just past the stack decrement.
+ uint32_t pc = NEXT_LIR(stack_decrement_)->offset;
+ AdvanceLoc(*cfi_info, pc);
+
+ // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size.
+ cfi_info->push_back(0x0e);
+ EncodeUnsignedLeb128(*cfi_info, frame_size_);
+
+ // We continue with that stack until the epilogue.
+ if (stack_increment_ != nullptr) {
+ uint32_t new_pc = NEXT_LIR(stack_increment_)->offset;
+ AdvanceLoc(*cfi_info, new_pc - pc);
+
+ // We probably have code snippets after the epilogue, so save the
+ // 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.
+ cfi_info->push_back(0x0e);
+ EncodeUnsignedLeb128(*cfi_info, 4);
+
+ // Everything after that is the same as before the epilogue.
+ // Stack bump was followed by RET instruction.
+ LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_));
+ if (post_ret_insn != nullptr) {
+ pc = new_pc;
+ new_pc = post_ret_insn->offset;
+ AdvanceLoc(*cfi_info, new_pc - pc);
+ // Restore the state: DW_CFA_restore_state.
+ cfi_info->push_back(0x0b);
+ }
+ }
+ }
+
+ // 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 FDE 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;
+}
+
} // namespace art