GenSpecialCase support for x86
Moved GenSpecialCase from being ARM specific to common code to allow
it to be used by x86 quick as well.
Change-Id: I728733e8f4c4da99af6091ef77e5c76ae0fee850
Signed-off-by: Razvan A Lupusoru <razvan.a.lupusoru@intel.com>
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index a30e80a..b36dde9 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -18,225 +18,11 @@
#include "arm_lir.h"
#include "codegen_arm.h"
-#include "dex/quick/dex_file_method_inliner.h"
#include "dex/quick/mir_to_lir-inl.h"
#include "entrypoints/quick/quick_entrypoints.h"
namespace art {
-// TODO: generalize & move to RegUtil.cc
-// The number of dalvik registers passed in core registers.
-constexpr int kInArgsInCoreRegs = 3;
-// The core register corresponding to the first (index 0) input argument.
-constexpr int kInArg0CoreReg = r1; // r0 is Method*.
-// Offset, in words, for getting args from stack (even core reg args have space on stack).
-constexpr int kInArgToStackOffset = 1;
-
-/* Lock argument if it's in register. */
-void ArmMir2Lir::LockArg(int in_position, bool wide) {
- if (in_position < kInArgsInCoreRegs) {
- LockTemp(kInArg0CoreReg + in_position);
- }
- if (wide && in_position + 1 < kInArgsInCoreRegs) {
- LockTemp(kInArg0CoreReg + in_position + 1);
- }
-}
-
-/* Load argument into register. LockArg(in_position, wide) must have been previously called. */
-int ArmMir2Lir::LoadArg(int in_position, bool wide) {
- if (in_position < kInArgsInCoreRegs) {
- int low_reg = kInArg0CoreReg + in_position;
- if (!wide) {
- return low_reg;
- }
- int high_reg = (in_position != kInArgsInCoreRegs - 1) ? low_reg + 1 : LoadArg(in_position + 1);
- return (low_reg & 0xff) | ((high_reg & 0xff) << 8);
- }
- int low_reg = AllocTemp();
- int offset = (in_position + kInArgToStackOffset) * sizeof(uint32_t);
- if (!wide) {
- LoadWordDisp(rARM_SP, offset, low_reg);
- return low_reg;
- }
- int high_reg = AllocTemp();
- LoadBaseDispWide(rARM_SP, offset, low_reg, high_reg, INVALID_SREG);
- return (low_reg & 0xff) | ((high_reg & 0xff) << 8);
-}
-
-void ArmMir2Lir::LoadArgDirect(int in_position, RegLocation rl_dest) {
- int reg = kInArg0CoreReg + in_position;
- int offset = (in_position + kInArgToStackOffset) * sizeof(uint32_t);
- if (!rl_dest.wide) {
- if (in_position < kInArgsInCoreRegs) {
- OpRegCopy(rl_dest.low_reg, reg);
- } else {
- LoadWordDisp(rARM_SP, offset, rl_dest.low_reg);
- }
- } else {
- if (in_position < kInArgsInCoreRegs - 1) {
- OpRegCopyWide(rl_dest.low_reg, rl_dest.high_reg, reg, reg + 1);
- } else if (in_position == kInArgsInCoreRegs - 1) {
- OpRegCopy(rl_dest.low_reg, reg);
- LoadWordDisp(rARM_SP, offset + sizeof(uint32_t), rl_dest.high_reg);
- } else {
- LoadBaseDispWide(rARM_SP, offset, rl_dest.low_reg, rl_dest.high_reg, INVALID_SREG);
- }
- }
-}
-
-/* Find the next MIR, which may be in a following basic block */
-// TODO: make this a utility in mir_graph.
-MIR* ArmMir2Lir::GetNextMir(BasicBlock** p_bb, MIR* mir) {
- BasicBlock* bb = *p_bb;
- MIR* orig_mir = mir;
- while (bb != NULL) {
- if (mir != NULL) {
- mir = mir->next;
- }
- if (mir != NULL) {
- return mir;
- } else {
- bb = mir_graph_->GetBasicBlock(bb->fall_through);
- *p_bb = bb;
- if (bb) {
- mir = bb->first_mir_insn;
- if (mir != NULL) {
- return mir;
- }
- }
- }
- }
- return orig_mir;
-}
-
-/* Used for the "verbose" listing */
-// TODO: move to common code
-void ArmMir2Lir::GenPrintLabel(MIR* mir) {
- /* Mark the beginning of a Dalvik instruction for line tracking */
- if (cu_->verbose) {
- char* inst_str = mir_graph_->GetDalvikDisassembly(mir);
- MarkBoundary(mir->offset, inst_str);
- }
-}
-
-MIR* ArmMir2Lir::SpecialIGet(BasicBlock** bb, MIR* mir, const InlineMethod& special) {
- // FastInstance() already checked by DexFileMethodInliner.
- const InlineIGetIPutData& data = special.d.ifield_data;
- if (data.method_is_static || data.object_arg != 0) {
- return NULL; // The object is not "this" and has to be null-checked.
- }
-
- DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
- bool wide = (data.op_size == kLong);
-
- // Point of no return - no aborts after this
- ArmMir2Lir::GenPrintLabel(mir);
- LockArg(data.object_arg);
- RegLocation rl_dest = wide ? GetReturnWide(false) : GetReturn(false);
- int reg_obj = LoadArg(data.object_arg);
- if (wide) {
- LoadBaseDispWide(reg_obj, data.field_offset, rl_dest.low_reg, rl_dest.high_reg, INVALID_SREG);
- } else {
- LoadBaseDisp(reg_obj, data.field_offset, rl_dest.low_reg, kWord, INVALID_SREG);
- }
- if (data.is_volatile) {
- GenMemBarrier(kLoadLoad);
- }
- return GetNextMir(bb, mir);
-}
-
-MIR* ArmMir2Lir::SpecialIPut(BasicBlock** bb, MIR* mir, const InlineMethod& special) {
- // FastInstance() already checked by DexFileMethodInliner.
- const InlineIGetIPutData& data = special.d.ifield_data;
- if (data.method_is_static || data.object_arg != 0) {
- return NULL; // The object is not "this" and has to be null-checked.
- }
-
- DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
- bool wide = (data.op_size == kLong);
-
- // Point of no return - no aborts after this
- ArmMir2Lir::GenPrintLabel(mir);
- LockArg(data.object_arg);
- LockArg(data.src_arg, wide);
- int reg_obj = LoadArg(data.object_arg);
- int reg_src = LoadArg(data.src_arg, wide);
- if (data.is_volatile) {
- GenMemBarrier(kStoreStore);
- }
- if (wide) {
- StoreBaseDispWide(reg_obj, data.field_offset, reg_src & 0xff, reg_src >> 8);
- } else {
- StoreBaseDisp(reg_obj, data.field_offset, reg_src, kWord);
- }
- if (data.is_volatile) {
- GenMemBarrier(kLoadLoad);
- }
- if (data.is_object) {
- MarkGCCard(reg_src, reg_obj);
- }
- return GetNextMir(bb, mir);
-}
-
-MIR* ArmMir2Lir::SpecialIdentity(MIR* mir, const InlineMethod& special) {
- const InlineReturnArgData& data = special.d.return_data;
- DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
- bool wide = (data.op_size == kLong);
-
- // Point of no return - no aborts after this
- ArmMir2Lir::GenPrintLabel(mir);
- LockArg(data.arg, wide);
- RegLocation rl_dest = wide ? GetReturnWide(false) : GetReturn(false);
- LoadArgDirect(data.arg, rl_dest);
- return mir;
-}
-
-/*
- * Special-case code genration for simple non-throwing leaf methods.
- */
-void ArmMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir,
- const InlineMethod& special) {
- DCHECK(special.flags & kInlineSpecial);
- current_dalvik_offset_ = mir->offset;
- MIR* next_mir = NULL;
- switch (special.opcode) {
- case kInlineOpNop:
- DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID);
- next_mir = mir;
- break;
- case kInlineOpConst:
- ArmMir2Lir::GenPrintLabel(mir);
- LoadConstant(rARM_RET0, static_cast<int>(special.d.data));
- next_mir = GetNextMir(&bb, mir);
- break;
- case kInlineOpIGet:
- next_mir = SpecialIGet(&bb, mir, special);
- break;
- case kInlineOpIPut:
- next_mir = SpecialIPut(&bb, mir, special);
- break;
- case kInlineOpReturnArg:
- next_mir = SpecialIdentity(mir, special);
- break;
- default:
- return;
- }
- if (next_mir != NULL) {
- current_dalvik_offset_ = next_mir->offset;
- if (special.opcode != kInlineOpReturnArg) {
- ArmMir2Lir::GenPrintLabel(next_mir);
- }
- NewLIR1(kThumbBx, rARM_LR);
- core_spill_mask_ = 0;
- num_core_spills_ = 0;
- fp_spill_mask_ = 0;
- num_fp_spills_ = 0;
- frame_size_ = 0;
- core_vmap_table_.clear();
- fp_vmap_table_.clear();
- }
-}
-
/*
* The sparse table in the literal pool is an array of <key,displacement>
* pairs. For each set, we'll load them as a pair using ldmia.
@@ -610,4 +396,8 @@
}
}
+void ArmMir2Lir::GenSpecialExitSequence() {
+ NewLIR1(kThumbBx, rARM_LR);
+}
+
} // namespace art