diff options
49 files changed, 7485 insertions, 7638 deletions
diff --git a/src/compiler/dex/quick/local_optimizations.h b/src/compiler/dex/backend.h index 3a376fe3cf..804bc3662d 100644 --- a/src/compiler/dex/quick/local_optimizations.h +++ b/src/compiler/dex/backend.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,25 @@ * limitations under the License. */ -#ifndef ART_SRC_COMPILER_DEX_QUICK_LOCALOPTIMIZATIONS_H_ -#define ART_SRC_COMPILER_DEX_QUICK_LOCALOPTIMIZATIONS_H_ +#ifndef ART_SRC_COMPILER_DEX_BACKEND_H_ +#define ART_SRC_COMPILER_DEX_BACKEND_H_ + +#include "compiled_method.h" namespace art { -void ApplyLocalOptimizations(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir); -void RemoveRedundantBranches(CompilationUnit* cu); +class Backend { + + public: + virtual ~Backend() {}; + virtual void Materialize() = 0; + virtual CompiledMethod* GetCompiledMethod() = 0; + + protected: + Backend() {}; + +}; // Class Backend } // namespace art -#endif // ART_SRC_COMPILER_DEX_QUICK_LOCALOPTIMIZATIONS_H_ +#endif // ART_SRC_COMPILER_DEX_BACKEND_H_ diff --git a/src/compiler/dex/compiler_internals.h b/src/compiler/dex/compiler_internals.h index 71792e0db6..8ef8a71bb4 100644 --- a/src/compiler/dex/compiler_internals.h +++ b/src/compiler/dex/compiler_internals.h @@ -24,7 +24,7 @@ #include "base/logging.h" #include "class_linker.h" -#include "quick/codegen.h" +#include "quick/mir_to_lir.h" #include "compiler/driver/compiler_driver.h" #include "mir_graph.h" #include "compiler_ir.h" diff --git a/src/compiler/dex/compiler_ir.h b/src/compiler/dex/compiler_ir.h index efae1f568a..d4bf3da182 100644 --- a/src/compiler/dex/compiler_ir.h +++ b/src/compiler/dex/compiler_ir.h @@ -18,10 +18,9 @@ #define ART_SRC_COMPILER_DEX_COMPILER_IR_H_ #include <vector> - #include <llvm/IR/Module.h> - -#include "compiler/dex/quick/codegen.h" +#include "compiler/dex/quick/mir_to_lir.h" +#include "backend.h" #include "compiler/driver/compiler_driver.h" #include "compiler/driver/dex_compilation_unit.h" #include "compiler/llvm/intrinsic_helper.h" @@ -33,268 +32,16 @@ namespace art { -//TODO: replace these macros -#define SLOW_FIELD_PATH (cu->enable_debug & (1 << kDebugSlowFieldPath)) -#define SLOW_INVOKE_PATH (cu->enable_debug & (1 << kDebugSlowInvokePath)) -#define SLOW_STRING_PATH (cu->enable_debug & (1 << kDebugSlowStringPath)) -#define SLOW_TYPE_PATH (cu->enable_debug & (1 << kDebugSlowTypePath)) -#define EXERCISE_SLOWEST_STRING_PATH (cu->enable_debug & \ - (1 << kDebugSlowestStringPath)) - -// Minimum field size to contain Dalvik v_reg number. -#define VREG_NUM_WIDTH 16 - struct ArenaBitVector; -struct LIR; class LLVMInfo; namespace llvm { class LlvmCompilationUnit; } // namespace llvm -struct PromotionMap { - RegLocationType core_location:3; - uint8_t core_reg; - RegLocationType fp_location:3; - uint8_t FpReg; - bool first_in_pair; -}; - -struct RegLocation { - RegLocationType location:3; - unsigned wide:1; - unsigned defined:1; // Do we know the type? - unsigned is_const:1; // Constant, value in mir_graph->constant_values[]. - unsigned fp:1; // Floating point? - unsigned core:1; // Non-floating point? - unsigned ref:1; // Something GC cares about. - unsigned high_word:1; // High word of pair? - unsigned home:1; // Does this represent the home location? - uint8_t low_reg; // First physical register. - uint8_t high_reg; // 2nd physical register (if wide). - int32_t s_reg_low; // SSA name for low Dalvik word. - int32_t orig_sreg; // TODO: remove after Bitcode gen complete - // and consolodate usage w/ s_reg_low. -}; - -struct CompilerTemp { - int s_reg; - ArenaBitVector* bv; -}; - -struct CallInfo { - int num_arg_words; // Note: word count, not arg count. - RegLocation* args; // One for each word of arguments. - RegLocation result; // Eventual target of MOVE_RESULT. - int opt_flags; - InvokeType type; - uint32_t dex_idx; - uint32_t index; // Method idx for invokes, type idx for FilledNewArray. - uintptr_t direct_code; - uintptr_t direct_method; - RegLocation target; // Target of following move_result. - bool skip_this; - bool is_range; - int offset; // Dalvik offset. -}; - - /* - * Data structure tracking the mapping between a Dalvik register (pair) and a - * native register (pair). The idea is to reuse the previously loaded value - * if possible, otherwise to keep the value in a native register as long as - * possible. - */ -struct RegisterInfo { - int reg; // Reg number - bool in_use; // Has it been allocated? - bool is_temp; // Can allocate as temp? - bool pair; // Part of a register pair? - int partner; // If pair, other reg of pair. - bool live; // Is there an associated SSA name? - bool dirty; // If live, is it dirty? - int s_reg; // Name of live value. - LIR *def_start; // Starting inst in last def sequence. - LIR *def_end; // Ending inst in last def sequence. -}; - -struct RegisterPool { - int num_core_regs; - RegisterInfo *core_regs; - int next_core_reg; - int num_fp_regs; - RegisterInfo *FPRegs; - int next_fp_reg; -}; - -#define INVALID_SREG (-1) -#define INVALID_VREG (0xFFFFU) -#define INVALID_REG (0xFF) -#define INVALID_OFFSET (0xDEADF00FU) - -/* SSA encodings for special registers */ -#define SSA_METHOD_BASEREG (-2) -/* First compiler temp basereg, grows smaller */ -#define SSA_CTEMP_BASEREG (SSA_METHOD_BASEREG - 1) - -/* - * Some code patterns cause the generation of excessively large - * methods - in particular initialization sequences. There isn't much - * benefit in optimizing these methods, and the cost can be very high. - * We attempt to identify these cases, and avoid performing most dataflow - * analysis. Two thresholds are used - one for known initializers and one - * for everything else. - */ -#define MANY_BLOCKS_INITIALIZER 1000 /* Threshold for switching dataflow off */ -#define MANY_BLOCKS 4000 /* Non-initializer threshold */ - -// Utility macros to traverse the LIR list. -#define NEXT_LIR(lir) (lir->next) -#define PREV_LIR(lir) (lir->prev) - -// Defines for alias_info (tracks Dalvik register references). -#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff) -#define DECODE_ALIAS_INFO_WIDE_FLAG (0x80000000) -#define DECODE_ALIAS_INFO_WIDE(X) ((X & DECODE_ALIAS_INFO_WIDE_FLAG) ? 1 : 0) -#define ENCODE_ALIAS_INFO(REG, ISWIDE) (REG | (ISWIDE ? DECODE_ALIAS_INFO_WIDE_FLAG : 0)) - -// Common resource macros. -#define ENCODE_CCODE (1ULL << kCCode) -#define ENCODE_FP_STATUS (1ULL << kFPStatus) - -// Abstract memory locations. -#define ENCODE_DALVIK_REG (1ULL << kDalvikReg) -#define ENCODE_LITERAL (1ULL << kLiteral) -#define ENCODE_HEAP_REF (1ULL << kHeapRef) -#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias) - -#define ENCODE_ALL (~0ULL) -#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \ - ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS) - -#define is_pseudo_opcode(opcode) (static_cast<int>(opcode) < 0) - -struct LIR { - int offset; // Offset of this instruction. - int dalvik_offset; // Offset of Dalvik opcode. - LIR* next; - LIR* prev; - LIR* target; - int opcode; - int operands[5]; // [0..4] = [dest, src1, src2, extra, extra2]. - struct { - bool is_nop:1; // LIR is optimized away. - bool pcRelFixup:1; // May need pc-relative fixup. - unsigned int size:5; // Note: size is in bytes. - unsigned int unused:25; - } flags; - int alias_info; // For Dalvik register & litpool disambiguation. - uint64_t use_mask; // Resource mask for use. - uint64_t def_mask; // Resource mask for def. -}; - -extern const char* extended_mir_op_names[kMirOpLast - kMirOpFirst]; - -struct SSARepresentation; - -#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck) -#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly) -#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck) -#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly) -#define MIR_INLINED (1 << kMIRInlined) -#define MIR_INLINED_PRED (1 << kMIRInlinedPred) -#define MIR_CALLEE (1 << kMIRCallee) -#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck) -#define MIR_DUP (1 << kMIRDup) - -struct Checkstats { - int null_checks; - int null_checks_eliminated; - int range_checks; - int range_checks_eliminated; -}; - -struct MIR { - DecodedInstruction dalvikInsn; - unsigned int width; - unsigned int offset; - int m_unit_index; // From which method was this MIR included - MIR* prev; - MIR* next; - SSARepresentation* ssa_rep; - int optimization_flags; - union { - // Establish link between two halves of throwing instructions. - MIR* throw_insn; - // Saved opcode for NOP'd MIRs - Instruction::Code original_opcode; - } meta; -}; - -struct BasicBlockDataFlow { - ArenaBitVector* use_v; - ArenaBitVector* def_v; - ArenaBitVector* live_in_v; - ArenaBitVector* phi_v; - int* vreg_to_ssa_map; - ArenaBitVector* ending_null_check_v; -}; - -struct SSARepresentation { - int num_uses; - int* uses; - bool* fp_use; - int num_defs; - int* defs; - bool* fp_def; -}; - -struct BasicBlock { - int id; - int dfs_id; - bool visited; - bool hidden; - bool catch_entry; - bool explicit_throw; - bool conditional_branch; - bool terminated_by_return; // Block ends with a Dalvik return opcode. - bool dominates_return; // Is a member of return extended basic block. - uint16_t start_offset; - uint16_t nesting_depth; - BBType block_type; - MIR* first_mir_insn; - MIR* last_mir_insn; - BasicBlock* fall_through; - BasicBlock* taken; - BasicBlock* i_dom; // Immediate dominator. - BasicBlockDataFlow* data_flow_info; - GrowableList* predecessors; - ArenaBitVector* dominators; - ArenaBitVector* i_dominated; // Set nodes being immediately dominated. - ArenaBitVector* dom_frontier; // Dominance frontier. - struct { // For one-to-many successors like. - BlockListType block_list_type; // switch and exception handling. - GrowableList blocks; - } successor_block_list; -}; - -/* - * The "blocks" field in "successor_block_list" points to an array of - * elements with the type "SuccessorBlockInfo". - * For catch blocks, key is type index for the exception. - * For swtich blocks, key is the case value. - */ -struct SuccessorBlockInfo { - BasicBlock* block; - int key; -}; - -struct LoopAnalysis; -struct RegisterPool; struct ArenaMemBlock; struct Memstats; class MIRGraph; -class Codegen; - -#define NOTVISITED (-1) +class Mir2Lir; struct CompilationUnit { CompilationUnit() @@ -311,54 +58,21 @@ struct CompilationUnit { disable_opt(0), enable_debug(0), verbose(false), - gen_bitcode(false), - disable_dataflow(false), + compiler_backend(kNoBackend), instruction_set(kNone), num_dalvik_registers(0), insns(NULL), num_ins(0), num_outs(0), num_regs(0), - num_core_spills(0), - num_fp_spills(0), num_compiler_temps(0), - frame_size(0), - core_spill_mask(0), - fp_spill_mask(0), - attributes(0), compiler_flip_match(false), arena_head(NULL), current_arena(NULL), num_arena_blocks(0), mstats(NULL), - checkstats(NULL), mir_graph(NULL), - cg(NULL), - live_sreg(0), - llvm_info(NULL), - context(NULL), - module(NULL), - func(NULL), - intrinsic_helper(NULL), - irb(NULL), - placeholder_bb(NULL), - entry_bb(NULL), - entryTarget_bb(NULL), - temp_name(0), - first_lir_insn(NULL), - last_lir_insn(NULL), - literal_list(NULL), - method_literal_list(NULL), - code_literal_list(NULL), - data_offset(0), - total_size(0), - reg_pool(NULL), - reg_location(NULL), - promotion_map(NULL), - method_sreg(0), - block_label_list(NULL), - current_dalvik_offset(0) - {} + cg(NULL) {} /* * Fields needed/generated by common frontend and generally used throughout * the compiler. @@ -375,130 +89,35 @@ struct CompilationUnit { const char* shorty; // compiling method's shorty. uint32_t disable_opt; // opt_control_vector flags. uint32_t enable_debug; // debugControlVector flags. - std::vector<uint8_t> code_buffer; bool verbose; - std::vector<uint32_t> combined_mapping_table; - std::vector<uint32_t> core_vmap_table; - std::vector<uint32_t> fp_vmap_table; - std::vector<uint8_t> native_gc_map; - bool gen_bitcode; - bool disable_dataflow; // Skip dataflow analysis if possible + CompilerBackend compiler_backend; InstructionSet instruction_set; - // CLEANUP: much of this info available elsewhere. Go to the original source? + // TODO: much of this info available elsewhere. Go to the original source? int num_dalvik_registers; // method->registers_size. const uint16_t* insns; - /* - * Frame layout details. - * NOTE: for debug support it will be necessary to add a structure - * to map the Dalvik virtual registers to the promoted registers. - * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes. - */ int num_ins; int num_outs; int num_regs; // Unlike num_dalvik_registers, does not include ins. - int num_core_spills; - int num_fp_spills; + + // TODO: may want to move this to MIRGraph. int num_compiler_temps; - int frame_size; - unsigned int core_spill_mask; - unsigned int fp_spill_mask; - unsigned int attributes; + // If non-empty, apply optimizer/debug flags only to matching methods. std::string compiler_method_match; // Flips sense of compiler_method_match - apply flags if doesn't match. bool compiler_flip_match; + + // TODO: move memory management to mir_graph, or just switch to using standard containers. ArenaMemBlock* arena_head; ArenaMemBlock* current_arena; int num_arena_blocks; Memstats* mstats; - Checkstats* checkstats; - UniquePtr<MIRGraph> mir_graph; // MIR container. - UniquePtr<Codegen> cg; // Target-specific codegen. - /* - * Sanity checking for the register temp tracking. The same ssa - * name should never be associated with one temp register per - * instruction compilation. - */ - int live_sreg; - - // Fields for Portable - llvm::LlvmCompilationUnit* llvm_compilation_unit; - /* - * Fields needed by GBC creation. Candidates for moving to a new MIR to - * llvm bitcode class. - */ - LLVMInfo* llvm_info; - std::string symbol; - ::llvm::LLVMContext* context; - ::llvm::Module* module; - ::llvm::Function* func; - art::llvm::IntrinsicHelper* intrinsic_helper; - art::llvm::IRBuilder* irb; - ::llvm::BasicBlock* placeholder_bb; - ::llvm::BasicBlock* entry_bb; - ::llvm::BasicBlock* entryTarget_bb; - std::string bitcode_filename; - GrowableList llvm_values; - int32_t temp_name; - SafeMap<int32_t, ::llvm::BasicBlock*> id_to_block_map; // block id -> llvm bb. - - /* - * Fields needed by the Quick backend. Candidates for moving to a new - * QuickBackend class. - */ - LIR* first_lir_insn; - LIR* last_lir_insn; - LIR* literal_list; // Constants. - LIR* method_literal_list; // Method literals requiring patching. - LIR* code_literal_list; // Code literals requiring patching. - int data_offset; // starting offset of literal pool. - int total_size; // header + code size. - RegisterPool* reg_pool; - // Map SSA names to location. - RegLocation* reg_location; - // Keep track of Dalvik v_reg to physical register mappings. - PromotionMap* promotion_map; - // SSA name for Method*. - int method_sreg; - RegLocation method_loc; // Describes location of method*. - GrowableList throw_launchpads; - GrowableList suspend_launchpads; - GrowableList intrinsic_launchpads; - GrowableList compiler_temps; - LIR* block_label_list; - /* - * TODO: The code generation utilities don't have a built-in - * mechanism to propagate the original Dalvik opcode address to the - * associated generated instructions. For the trace compiler, this wasn't - * necessary because the interpreter handled all throws and debugging - * requests. For now we'll handle this by placing the Dalvik offset - * in the CompilationUnit struct before codegen for each instruction. - * The low-level LIR creation utilites will pull it from here. Rework this. - */ - int current_dalvik_offset; - GrowableList switch_tables; - GrowableList fill_array_data; - SafeMap<unsigned int, unsigned int> block_id_map; // Block collapse lookup cache. - SafeMap<unsigned int, LIR*> boundary_map; // boundary lookup cache. - /* - * Holds mapping from native PC to dex PC for safepoints where we may deoptimize. - * Native PC is on the return address of the safepointed operation. Dex PC is for - * the instruction being executed at the safepoint. - */ - std::vector<uint32_t> pc2dexMappingTable; - /* - * Holds mapping from Dex PC to native PC for catch entry points. Native PC and Dex PC - * immediately preceed the instruction. - */ - std::vector<uint32_t> dex2pcMappingTable; + UniquePtr<MIRGraph> mir_graph; // MIR container. + UniquePtr<Backend> cg; // Target-specific codegen. }; -// TODO: move this -int SRegToVReg(const CompilationUnit* cu, int ssa_reg); - - } // namespace art #endif // ART_SRC_COMPILER_DEX_COMPILER_IR_H_ diff --git a/src/compiler/dex/compiler_utility.cc b/src/compiler/dex/compiler_utility.cc index 82a156d1c2..71c97139e5 100644 --- a/src/compiler/dex/compiler_utility.cc +++ b/src/compiler/dex/compiler_utility.cc @@ -19,23 +19,6 @@ namespace art { -const char* extended_mir_op_names[kMirOpLast - kMirOpFirst] = { - "Phi", - "Copy", - "FusedCmplFloat", - "FusedCmpgFloat", - "FusedCmplDouble", - "FusedCmpgDouble", - "FusedCmpLong", - "Nop", - "OpNullCheck", - "OpRangeCheck", - "OpDivZeroCheck", - "Check1", - "Check2", - "Select", -}; - #ifdef WITH_MEMSTATS struct Memstats { uint32_t alloc_stats[kNumAllocKinds]; @@ -301,9 +284,6 @@ void DumpMemStats(CompilationUnit* cu) LOG(INFO) << "MEMUSAGE: " << total << " : " << PrettyMethod(cu->method_idx, *cu->dex_file); LOG(INFO) << "insns_size: " << cu->code_item->insns_size_in_code_units_; - if (cu->disable_dataflow) { - LOG(INFO) << " ** Dataflow disabled ** "; - } LOG(INFO) << "===== Overall allocations"; for (int i = 0; i < kNumAllocKinds; i++) { LOG(INFO) << alloc_names[i] << std::setw(10) << @@ -328,43 +308,6 @@ void DumpMemStats(CompilationUnit* cu) } #endif -/* Debug Utility - dump a compilation unit */ -void DumpCompilationUnit(CompilationUnit* cu) -{ - BasicBlock* bb; - const char* block_type_names[] = { - "Entry Block", - "Code Block", - "Exit Block", - "Exception Handling", - "Catch Block" - }; - - LOG(INFO) << "Compiling " << PrettyMethod(cu->method_idx, *cu->dex_file); - LOG(INFO) << cu->insns << " insns"; - LOG(INFO) << cu->mir_graph->GetNumBlocks() << " blocks in total"; - GrowableListIterator iterator = cu->mir_graph->GetBasicBlockIterator(); - - while (true) { - bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iterator)); - if (bb == NULL) break; - LOG(INFO) << StringPrintf("Block %d (%s) (insn %04x - %04x%s)", - bb->id, - block_type_names[bb->block_type], - bb->start_offset, - bb->last_mir_insn ? bb->last_mir_insn->offset : bb->start_offset, - bb->last_mir_insn ? "" : " empty"); - if (bb->taken) { - LOG(INFO) << " Taken branch: block " << bb->taken->id - << "(0x" << std::hex << bb->taken->start_offset << ")"; - } - if (bb->fall_through) { - LOG(INFO) << " Fallthrough : block " << bb->fall_through->id - << " (0x" << std::hex << bb->fall_through->start_offset << ")"; - } - } -} - static uint32_t check_masks[32] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, @@ -669,34 +612,6 @@ void SetInitialBits(ArenaBitVector* p_bits, unsigned int num_bits) } } -void GetBlockName(BasicBlock* bb, char* name) -{ - switch (bb->block_type) { - case kEntryBlock: - snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id); - break; - case kExitBlock: - snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id); - break; - case kDalvikByteCode: - snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->start_offset, bb->id); - break; - case kExceptionHandling: - snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->start_offset, - bb->id); - break; - default: - snprintf(name, BLOCK_NAME_LEN, "_%d", bb->id); - break; - } -} - -const char* GetShortyFromTargetIdx(CompilationUnit *cu, int target_idx) -{ - const DexFile::MethodId& method_id = cu->dex_file->GetMethodId(target_idx); - return cu->dex_file->GetShorty(method_id.proto_idx_); -} - /* Allocate a new basic block */ BasicBlock* NewMemBB(CompilationUnit* cu, BBType block_type, int block_id) { @@ -708,270 +623,8 @@ BasicBlock* NewMemBB(CompilationUnit* cu, BBType block_type, int block_id) CompilerInitGrowableList(cu, bb->predecessors, (block_type == kExitBlock) ? 2048 : 2, kListPredecessors); - cu->block_id_map.Put(block_id, block_id); + cu->mir_graph->block_id_map_.Put(block_id, block_id); return bb; } -/* Insert an MIR instruction to the end of a basic block */ -void AppendMIR(BasicBlock* bb, MIR* mir) -{ - if (bb->first_mir_insn == NULL) { - DCHECK(bb->last_mir_insn == NULL); - bb->last_mir_insn = bb->first_mir_insn = mir; - mir->prev = mir->next = NULL; - } else { - bb->last_mir_insn->next = mir; - mir->prev = bb->last_mir_insn; - mir->next = NULL; - bb->last_mir_insn = mir; - } -} - -/* Insert an MIR instruction to the head of a basic block */ -void PrependMIR(BasicBlock* bb, MIR* mir) -{ - if (bb->first_mir_insn == NULL) { - DCHECK(bb->last_mir_insn == NULL); - bb->last_mir_insn = bb->first_mir_insn = mir; - mir->prev = mir->next = NULL; - } else { - bb->first_mir_insn->prev = mir; - mir->next = bb->first_mir_insn; - mir->prev = NULL; - bb->first_mir_insn = mir; - } -} - -/* Insert a MIR instruction after the specified MIR */ -void InsertMIRAfter(BasicBlock* bb, MIR* current_mir, MIR* new_mir) -{ - new_mir->prev = current_mir; - new_mir->next = current_mir->next; - current_mir->next = new_mir; - - if (new_mir->next) { - /* Is not the last MIR in the block */ - new_mir->next->prev = new_mir; - } else { - /* Is the last MIR in the block */ - bb->last_mir_insn = new_mir; - } -} - -/* - * Append an LIR instruction to the LIR list maintained by a compilation - * unit - */ -void AppendLIR(CompilationUnit *cu, LIR* lir) -{ - if (cu->first_lir_insn == NULL) { - DCHECK(cu->last_lir_insn == NULL); - cu->last_lir_insn = cu->first_lir_insn = lir; - lir->prev = lir->next = NULL; - } else { - cu->last_lir_insn->next = lir; - lir->prev = cu->last_lir_insn; - lir->next = NULL; - cu->last_lir_insn = lir; - } -} - -/* - * Insert an LIR instruction before the current instruction, which cannot be the - * first instruction. - * - * prev_lir <-> new_lir <-> current_lir - */ -void InsertLIRBefore(LIR* current_lir, LIR* new_lir) -{ - DCHECK(current_lir->prev != NULL); - LIR *prev_lir = current_lir->prev; - - prev_lir->next = new_lir; - new_lir->prev = prev_lir; - new_lir->next = current_lir; - current_lir->prev = new_lir; -} - -/* - * Insert an LIR instruction after the current instruction, which cannot be the - * first instruction. - * - * current_lir -> new_lir -> old_next - */ -void InsertLIRAfter(LIR* current_lir, LIR* new_lir) -{ - new_lir->prev = current_lir; - new_lir->next = current_lir->next; - current_lir->next = new_lir; - new_lir->next->prev = new_lir; -} - -/* Turn method name into a legal Linux file name */ -void ReplaceSpecialChars(std::string& str) -{ - static const struct { const char before; const char after; } match[] = - {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'}, - {'(','@'}, {')','@'}, {'<','='}, {'>','='}}; - for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) { - std::replace(str.begin(), str.end(), match[i].before, match[i].after); - } -} - -std::string GetSSAName(const CompilationUnit* cu, int ssa_reg) -{ - return StringPrintf("v%d_%d", cu->mir_graph->SRegToVReg(ssa_reg), cu->mir_graph->GetSSASubscript(ssa_reg)); -} - -// Similar to GetSSAName, but if ssa name represents an immediate show that as well. -std::string GetSSANameWithConst(const CompilationUnit* cu, int ssa_reg, bool singles_only) -{ - if (cu->reg_location == NULL) { - // Pre-SSA - just use the standard name - return GetSSAName(cu, ssa_reg); - } - if (cu->mir_graph->IsConst(cu->reg_location[ssa_reg])) { - if (!singles_only && cu->reg_location[ssa_reg].wide) { - return StringPrintf("v%d_%d#0x%llx", cu->mir_graph->SRegToVReg(ssa_reg), - cu->mir_graph->GetSSASubscript(ssa_reg), - cu->mir_graph->ConstantValueWide(cu->reg_location[ssa_reg])); - } else { - return StringPrintf("v%d_%d#0x%x", cu->mir_graph->SRegToVReg(ssa_reg), - cu->mir_graph->GetSSASubscript(ssa_reg), - cu->mir_graph->ConstantValue(cu->reg_location[ssa_reg])); - } - } else { - return StringPrintf("v%d_%d", cu->mir_graph->SRegToVReg(ssa_reg), - cu->mir_graph->GetSSASubscript(ssa_reg)); - } -} - -char* GetDalvikDisassembly(CompilationUnit* cu, const MIR* mir) -{ - DecodedInstruction insn = mir->dalvikInsn; - std::string str; - int flags = 0; - int opcode = insn.opcode; - char* ret; - bool nop = false; - SSARepresentation* ssa_rep = mir->ssa_rep; - Instruction::Format dalvik_format = Instruction::k10x; // Default to no-operand format - int defs = (ssa_rep != NULL) ? ssa_rep->num_defs : 0; - int uses = (ssa_rep != NULL) ? ssa_rep->num_uses : 0; - - // Handle special cases. - if ((opcode == kMirOpCheck) || (opcode == kMirOpCheckPart2)) { - str.append(extended_mir_op_names[opcode - kMirOpFirst]); - str.append(": "); - // Recover the original Dex instruction - insn = mir->meta.throw_insn->dalvikInsn; - ssa_rep = mir->meta.throw_insn->ssa_rep; - defs = ssa_rep->num_defs; - uses = ssa_rep->num_uses; - opcode = insn.opcode; - } else if (opcode == kMirOpNop) { - str.append("["); - insn.opcode = mir->meta.original_opcode; - opcode = mir->meta.original_opcode; - nop = true; - } - - if (opcode >= kMirOpFirst) { - str.append(extended_mir_op_names[opcode - kMirOpFirst]); - } else { - dalvik_format = Instruction::FormatOf(insn.opcode); - flags = Instruction::FlagsOf(insn.opcode); - str.append(Instruction::Name(insn.opcode)); - } - - if (opcode == kMirOpPhi) { - int* incoming = reinterpret_cast<int*>(insn.vB); - str.append(StringPrintf(" %s = (%s", - GetSSANameWithConst(cu, ssa_rep->defs[0], true).c_str(), - GetSSANameWithConst(cu, ssa_rep->uses[0], true).c_str())); - str.append(StringPrintf(":%d",incoming[0])); - int i; - for (i = 1; i < uses; i++) { - str.append(StringPrintf(", %s:%d", - GetSSANameWithConst(cu, ssa_rep->uses[i], true).c_str(), - incoming[i])); - } - str.append(")"); - } else if ((flags & Instruction::kBranch) != 0) { - // For branches, decode the instructions to print out the branch targets. - int offset = 0; - switch (dalvik_format) { - case Instruction::k21t: - str.append(StringPrintf(" %s,", GetSSANameWithConst(cu, ssa_rep->uses[0], false).c_str())); - offset = insn.vB; - break; - case Instruction::k22t: - str.append(StringPrintf(" %s, %s,", GetSSANameWithConst(cu, ssa_rep->uses[0], false).c_str(), - GetSSANameWithConst(cu, ssa_rep->uses[1], false).c_str())); - offset = insn.vC; - break; - case Instruction::k10t: - case Instruction::k20t: - case Instruction::k30t: - offset = insn.vA; - break; - default: - LOG(FATAL) << "Unexpected branch format " << dalvik_format << " from " << insn.opcode; - } - str.append(StringPrintf(" 0x%x (%c%x)", mir->offset + offset, - offset > 0 ? '+' : '-', offset > 0 ? offset : -offset)); - } else { - // For invokes-style formats, treat wide regs as a pair of singles - bool show_singles = ((dalvik_format == Instruction::k35c) || - (dalvik_format == Instruction::k3rc)); - if (defs != 0) { - str.append(StringPrintf(" %s", GetSSANameWithConst(cu, ssa_rep->defs[0], false).c_str())); - if (uses != 0) { - str.append(", "); - } - } - for (int i = 0; i < uses; i++) { - str.append( - StringPrintf(" %s", GetSSANameWithConst(cu, ssa_rep->uses[i], show_singles).c_str())); - if (!show_singles && (cu->reg_location != NULL) && cu->reg_location[i].wide) { - // For the listing, skip the high sreg. - i++; - } - if (i != (uses -1)) { - str.append(","); - } - } - switch (dalvik_format) { - case Instruction::k11n: // Add one immediate from vB - case Instruction::k21s: - case Instruction::k31i: - case Instruction::k21h: - str.append(StringPrintf(", #%d", insn.vB)); - break; - case Instruction::k51l: // Add one wide immediate - str.append(StringPrintf(", #%lld", insn.vB_wide)); - break; - case Instruction::k21c: // One register, one string/type/method index - case Instruction::k31c: - str.append(StringPrintf(", index #%d", insn.vB)); - break; - case Instruction::k22c: // Two registers, one string/type/method index - str.append(StringPrintf(", index #%d", insn.vC)); - break; - case Instruction::k22s: // Add one immediate from vC - case Instruction::k22b: - str.append(StringPrintf(", #%d", insn.vC)); - break; - default: - ; // Nothing left to print - } - } - if (nop) { - str.append("]--optimized away"); - } - int length = str.length() + 1; - ret = static_cast<char*>(NewMem(cu, length, false, kAllocDFInfo)); - strncpy(ret, str.c_str(), length); - return ret; -} } // namespace art diff --git a/src/compiler/dex/compiler_utility.h b/src/compiler/dex/compiler_utility.h index 4201f5d54a..b2dcd44ede 100644 --- a/src/compiler/dex/compiler_utility.h +++ b/src/compiler/dex/compiler_utility.h @@ -84,8 +84,6 @@ enum oat_bit_map_kind { kNumBitMapKinds }; -// Allocate the initial memory block for arena-based allocation. -bool HeapInit(CompilationUnit* cu); // Uncomment to collect memory usage statistics. //#define WITH_MEMSTATS @@ -97,10 +95,6 @@ struct ArenaMemBlock { char ptr[0]; }; -void* NewMem(CompilationUnit* cu, size_t size, bool zero, oat_alloc_kind kind); - -void ArenaReset(CompilationUnit *cu); - struct GrowableList { GrowableList() : num_allocated(0), num_used(0), elem_list(NULL) { } @@ -146,11 +140,13 @@ struct ArenaBitVectorIterator { // Forward declarations struct BasicBlock; struct CompilationUnit; -struct LIR; -struct RegLocation; -struct MIR; enum BBType; +// Allocate the initial memory block for arena-based allocation. +bool HeapInit(CompilationUnit* cu); +void* NewMem(CompilationUnit* cu, size_t size, bool zero, oat_alloc_kind kind); +BasicBlock* NewMemBB(CompilationUnit* cu, BBType block_type, int block_id); +void ArenaReset(CompilationUnit *cu); void CompilerInitGrowableList(CompilationUnit* cu, GrowableList* g_list, size_t init_length, oat_list_kind kind = kListMisc); void ReallocGrowableList(CompilationUnit* cu, GrowableList* g_list, size_t new_length); @@ -177,25 +173,15 @@ bool UnifyBitVetors(ArenaBitVector* dest, const ArenaBitVector* src1, const Aren bool CompareBitVectors(const ArenaBitVector* src1, const ArenaBitVector* src2); bool TestBitVectors(const ArenaBitVector* src1, const ArenaBitVector* src2); int CountSetBits(const ArenaBitVector* p_bits); -void DumpLIRInsn(CompilationUnit* cu, LIR* lir, unsigned char* base_addr); -void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix); void DumpBlockBitVector(const GrowableList* blocks, char* msg, const ArenaBitVector* bv, int length); -void GetBlockName(BasicBlock* bb, char* name); -const char* GetShortyFromTargetIdx(CompilationUnit*, int); void DumpMemStats(CompilationUnit* cu); -void DumpCompilationUnit(CompilationUnit* cu); -BasicBlock* NewMemBB(CompilationUnit* cu, BBType block_type, int block_id); -void AppendMIR(BasicBlock* bb, MIR* mir); -void PrependMIR(BasicBlock* bb, MIR* mir); -void InsertMIRAfter(BasicBlock* bb, MIR* current_mir, MIR* new_mir); -void AppendLIR(CompilationUnit *cu, LIR* lir); -void InsertLIRBefore(LIR* current_lir, LIR* new_lir); -void InsertLIRAfter(LIR* current_lir, LIR* new_lir); + void ReplaceSpecialChars(std::string& str); -char* GetDalvikDisassembly(CompilationUnit* cu, const MIR* mir); std::string GetSSAName(const CompilationUnit* cu, int ssa_reg); std::string GetSSANameWithConst(const CompilationUnit* cu, int ssa_reg, bool singles_only); +void GetBlockName(BasicBlock* bb, char* name); +const char* GetShortyFromTargetIdx(CompilationUnit*, int); } // namespace art diff --git a/src/compiler/dex/frontend.cc b/src/compiler/dex/frontend.cc index 049d662541..e99c1968c8 100644 --- a/src/compiler/dex/frontend.cc +++ b/src/compiler/dex/frontend.cc @@ -21,13 +21,12 @@ #include "dataflow_iterator.h" #if defined(ART_USE_PORTABLE_COMPILER) #include "compiler/llvm/llvm_compilation_unit.h" +#include "compiler/dex/portable/mir_to_gbc.h" #endif #include "leb128.h" #include "mirror/object.h" #include "runtime.h" -#include "quick/codegen_util.h" -#include "portable/mir_to_gbc.h" -#include "quick/mir_to_lir.h" +#include "backend.h" namespace { #if !defined(ART_USE_PORTABLE_COMPILER) @@ -116,9 +115,6 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler, { VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "..."; - // FIXME: now we detect this in MIRGraph. - SpecialCaseHandler special_case = kNoHandler; - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); UniquePtr<CompilationUnit> cu(new CompilationUnit); @@ -129,17 +125,12 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler, cu->compiler_driver = &compiler; cu->class_linker = class_linker; cu->instruction_set = compiler.GetInstructionSet(); + cu->compiler_backend = compiler_backend; DCHECK((cu->instruction_set == kThumb2) || (cu->instruction_set == kX86) || (cu->instruction_set == kMips)); - cu->gen_bitcode = (compiler_backend == kPortable); -#if defined(ART_USE_PORTABLE_COMPILER) - cu->llvm_compilation_unit = llvm_compilation_unit; - cu->llvm_info = llvm_compilation_unit->GetQuickContext(); - cu->symbol = llvm_compilation_unit->GetDexCompilationUnit()->GetSymbol(); -#endif /* Adjust this value accordingly once inlining is performed */ cu->num_dalvik_registers = code_item->registers_size_; // TODO: set this from command line @@ -155,9 +146,14 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler, (cu->enable_debug & (1 << kDebugVerbose)); } - // If debug build, always verify bitcode. - if (kIsDebugBuild && cu->gen_bitcode) { - cu->enable_debug |= (1 << kDebugVerifyBitcode); + /* + * TODO: rework handling of optimization and debug flags. Should we split out + * MIR and backend flags? Need command-line setting as well. + */ + + if (compiler_backend == kPortable) { + // Fused long branches not currently usseful in bitcode. + cu->disable_opt |= (1 << kBranchFusing); } if (cu->instruction_set == kMips) { @@ -175,9 +171,6 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler, (1 << kPromoteCompilerTemps)); } - /* Assume leaf */ - cu->attributes = METHOD_IS_LEAF; - cu->mir_graph.reset(new MIRGraph(cu.get())); /* Gathering opcode stats? */ @@ -192,10 +185,6 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler, /* Do a code layout pass */ cu->mir_graph->CodeLayout(); - if (cu->enable_debug & (1 << kDebugVerifyDataflow)) { - cu->mir_graph->VerifyDataflow(); - } - /* Perform SSA transformation for the whole method */ cu->mir_graph->SSATransformation(); @@ -218,123 +207,42 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler, cu->mir_graph->DumpCheckStats(); } + if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { + cu->mir_graph->ShowOpcodeStats(); + } + /* Set up regLocation[] array to describe values - one for each ssa_name. */ cu->mir_graph->BuildRegLocations(); + CompiledMethod* result = NULL; + #if defined(ART_USE_PORTABLE_COMPILER) - /* Go the LLVM path? */ - if (cu->gen_bitcode) { - // MIR->Bitcode - MethodMIR2Bitcode(cu.get()); - if (compiler_backend == kPortable) { - // all done - ArenaReset(cu.get()); - return NULL; - } + if (compiler_backend == kPortable) { + cu->cg.reset(PortableCodeGenerator(cu.get(), cu->mir_graph.get(), llvm_compilation_unit)); } else #endif { switch (compiler.GetInstructionSet()) { case kThumb2: - InitArmCodegen(cu.get()); break; + cu->cg.reset(ArmCodeGenerator(cu.get(), cu->mir_graph.get())); break; case kMips: - InitMipsCodegen(cu.get()); break; + cu->cg.reset(MipsCodeGenerator(cu.get(), cu->mir_graph.get())); break; case kX86: - InitX86Codegen(cu.get()); break; + cu->cg.reset(X86CodeGenerator(cu.get(), cu->mir_graph.get())); break; default: LOG(FATAL) << "Unexpected instruction set: " << compiler.GetInstructionSet(); } - -// ** MOVE ALL OF THIS TO Codegen.materialize() - - /* Initialize the switch_tables list */ // TO CODEGEN - CompilerInitGrowableList(cu.get(), &cu->switch_tables, 4, - kListSwitchTables); - - /* Intialize the fill_array_data list */ // TO CODEGEN - CompilerInitGrowableList(cu.get(), &cu->fill_array_data, 4, - kListFillArrayData); - - /* Intialize the throw_launchpads list, estimate size based on insns_size */ // TO CODEGEN - CompilerInitGrowableList(cu.get(), &cu->throw_launchpads, code_item->insns_size_in_code_units_, - kListThrowLaunchPads); - - /* Intialize the instrinsic_launchpads list */ // TO_CODEGEN - CompilerInitGrowableList(cu.get(), &cu->intrinsic_launchpads, 4, - kListMisc); - - - /* Intialize the suspend_launchpads list */ // TO_CODEGEN - CompilerInitGrowableList(cu.get(), &cu->suspend_launchpads, 2048, - kListSuspendLaunchPads); - - // TODO: Push these to codegen - cu.get()->cg->CompilerInitializeRegAlloc(cu.get()); // Needs to happen after SSA naming - - /* Allocate Registers using simple local allocation scheme */ - cu.get()->cg->SimpleRegAlloc(cu.get()); - - if (special_case != kNoHandler) { - /* - * Custom codegen for special cases. If for any reason the - * special codegen doesn't succeed, cu->first_lir_insn will - * set to NULL; - */ - SpecialMIR2LIR(cu.get(), special_case); - } - - /* Convert MIR to LIR, etc. */ - if (cu->first_lir_insn == NULL) { - MethodMIR2LIR(cu.get()); - } } - /* Method is not empty */ - if (cu->first_lir_insn) { - - // mark the targets of switch statement case labels - ProcessSwitchTables(cu.get()); - - /* Convert LIR into machine code. */ - AssembleLIR(cu.get()); + cu->cg->Materialize(); - if (cu->verbose) { - CodegenDump(cu.get()); - } - - } + result = cu->cg->GetCompiledMethod(); - if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { - cu->mir_graph->ShowOpcodeStats(); - } - - // Combine vmap tables - core regs, then fp regs - into vmap_table - std::vector<uint16_t> vmap_table; - // Core regs may have been inserted out of order - sort first - std::sort(cu->core_vmap_table.begin(), cu->core_vmap_table.end()); - for (size_t i = 0 ; i < cu->core_vmap_table.size(); i++) { - // Copy, stripping out the phys register sort key - vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & cu->core_vmap_table[i]); - } - // If we have a frame, push a marker to take place of lr - if (cu->frame_size > 0) { - vmap_table.push_back(INVALID_VREG); + if (result) { + VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file); } else { - DCHECK_EQ(__builtin_popcount(cu->core_spill_mask), 0); - DCHECK_EQ(__builtin_popcount(cu->fp_spill_mask), 0); - } - // Combine vmap tables - core regs, then fp regs. fp regs already sorted - for (uint32_t i = 0; i < cu->fp_vmap_table.size(); i++) { - vmap_table.push_back(cu->fp_vmap_table[i]); + VLOG(compiler) << "Deferred " << PrettyMethod(method_idx, dex_file); } - CompiledMethod* result = - new CompiledMethod(cu->instruction_set, cu->code_buffer, - cu->frame_size, cu->core_spill_mask, cu->fp_spill_mask, - cu->combined_mapping_table, vmap_table, cu->native_gc_map); - - VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file) - << " (" << (cu->code_buffer.size() * sizeof(cu->code_buffer[0])) - << " bytes)"; #ifdef WITH_MEMSTATS if (cu->enable_debug & (1 << kDebugShowMemoryUsage)) { diff --git a/src/compiler/dex/frontend.h b/src/compiler/dex/frontend.h index 874ee0b45a..2e62dc8c7b 100644 --- a/src/compiler/dex/frontend.h +++ b/src/compiler/dex/frontend.h @@ -50,6 +50,7 @@ enum opt_control_vector { kBBOpt, kMatch, kPromoteCompilerTemps, + kBranchFusing, }; // Force code generation paths for testing. @@ -73,14 +74,6 @@ enum debugControlVector { kDebugVerifyBitcode, }; -enum OatMethodAttributes { - kIsLeaf, // Method is leaf. - kHasLoop, // Method contains simple loop. -}; - -#define METHOD_IS_LEAF (1 << kIsLeaf) -#define METHOD_HAS_LOOP (1 << kHasLoop) - class LLVMInfo { public: LLVMInfo(); diff --git a/src/compiler/dex/mir_dataflow.cc b/src/compiler/dex/mir_dataflow.cc index 0c767aacd9..5e6eb8285e 100644 --- a/src/compiler/dex/mir_dataflow.cc +++ b/src/compiler/dex/mir_dataflow.cc @@ -29,7 +29,7 @@ namespace art { * TODO - many optimization flags are incomplete - they will only limit the * scope of optimizations but will not cause mis-optimizations. */ -const int oat_data_flow_attributes[kMirOpLast] = { +const int MIRGraph::oat_data_flow_attributes_[kMirOpLast] = { // 00 NOP DF_NOP, @@ -883,7 +883,7 @@ bool MIRGraph::FindLocalLiveIn(BasicBlock* bb) AllocBitVector(cu_, cu_->num_dalvik_registers, false, kBitMapLiveIn); for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { - int df_attributes = oat_data_flow_attributes[mir->dalvikInsn.opcode]; + int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; DecodedInstruction *d_insn = &mir->dalvikInsn; if (df_attributes & DF_HAS_USES) { @@ -934,7 +934,7 @@ int MIRGraph::AddNewSReg(int v_reg) SetNumSSARegs(ssa_reg + 1); InsertGrowableList(cu_, ssa_base_vregs_, v_reg); InsertGrowableList(cu_, ssa_subscripts_, subscript); - std::string ssa_name = GetSSAName(cu_, ssa_reg); + std::string ssa_name = GetSSAName(ssa_reg); char* name = static_cast<char*>(NewMem(cu_, ssa_name.length() + 1, false, kAllocDFInfo)); strncpy(name, ssa_name.c_str(), ssa_name.length() + 1); InsertGrowableList(cu_, ssa_strings_, reinterpret_cast<uintptr_t>(name)); @@ -1005,7 +1005,7 @@ bool MIRGraph::DoSSAConversion(BasicBlock* bb) mir->ssa_rep = static_cast<struct SSARepresentation *>(NewMem(cu_, sizeof(SSARepresentation), true, kAllocDFInfo)); - int df_attributes = oat_data_flow_attributes[mir->dalvikInsn.opcode]; + int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; // If not a pseudo-op, note non-leaf or can throw if (static_cast<int>(mir->dalvikInsn.opcode) < @@ -1013,7 +1013,7 @@ bool MIRGraph::DoSSAConversion(BasicBlock* bb) int flags = Instruction::FlagsOf(mir->dalvikInsn.opcode); if (flags & Instruction::kInvoke) { - cu_->attributes &= ~METHOD_IS_LEAF; + attributes_ &= ~METHOD_IS_LEAF; } } @@ -1114,19 +1114,17 @@ bool MIRGraph::DoSSAConversion(BasicBlock* bb) } } - if (!cu_->disable_dataflow) { - /* - * Take a snapshot of Dalvik->SSA mapping at the end of each block. The - * input to PHI nodes can be derived from the snapshot of all - * predecessor blocks. - */ - bb->data_flow_info->vreg_to_ssa_map = - static_cast<int*>(NewMem(cu_, sizeof(int) * cu_->num_dalvik_registers, false, - kAllocDFInfo)); - - memcpy(bb->data_flow_info->vreg_to_ssa_map, vreg_to_ssa_map_, - sizeof(int) * cu_->num_dalvik_registers); - } + /* + * Take a snapshot of Dalvik->SSA mapping at the end of each block. The + * input to PHI nodes can be derived from the snapshot of all + * predecessor blocks. + */ + bb->data_flow_info->vreg_to_ssa_map = + static_cast<int*>(NewMem(cu_, sizeof(int) * cu_->num_dalvik_registers, false, + kAllocDFInfo)); + + memcpy(bb->data_flow_info->vreg_to_ssa_map, vreg_to_ssa_map_, + sizeof(int) * cu_->num_dalvik_registers); return true; } @@ -1163,7 +1161,7 @@ void MIRGraph::CompilerInitializeSSAConversion() for (i = 0; i < num_dalvik_reg; i++) { InsertGrowableList(cu_, ssa_base_vregs_, i); InsertGrowableList(cu_, ssa_subscripts_, 0); - std::string ssa_name = GetSSAName(cu_, i); + std::string ssa_name = GetSSAName(i); char* name = static_cast<char*>(NewMem(cu_, ssa_name.length() + 1, true, kAllocDFInfo)); strncpy(name, ssa_name.c_str(), ssa_name.length() + 1); InsertGrowableList(cu_, ssa_strings_, reinterpret_cast<uintptr_t>(name)); @@ -1185,7 +1183,7 @@ void MIRGraph::CompilerInitializeSSAConversion() } /* Add ssa reg for Method* */ - cu_->method_sreg = AddNewSReg(SSA_METHOD_BASEREG); + method_sreg_ = AddNewSReg(SSA_METHOD_BASEREG); /* * Allocate the BasicBlockDataFlow structure for the entry and code blocks @@ -1283,7 +1281,7 @@ bool MIRGraph::CountUses(struct BasicBlock* bb) use_counts_.elem_list[s_reg] += (1 << weight); } if (!(cu_->disable_opt & (1 << kPromoteCompilerTemps))) { - int df_attributes = oat_data_flow_attributes[mir->dalvikInsn.opcode]; + int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; // Implicit use of Method* ? */ if (df_attributes & DF_UMS) { /* @@ -1298,8 +1296,8 @@ bool MIRGraph::CountUses(struct BasicBlock* bb) uses_method_star &= InvokeUsesMethodStar(mir); } if (uses_method_star) { - raw_use_counts_.elem_list[cu_->method_sreg]++; - use_counts_.elem_list[cu_->method_sreg] += (1 << weight); + raw_use_counts_.elem_list[method_sreg_]++; + use_counts_.elem_list[method_sreg_] += (1 << weight); } } } diff --git a/src/compiler/dex/mir_graph.cc b/src/compiler/dex/mir_graph.cc index 71aaa384e4..a6e9556c4c 100644 --- a/src/compiler/dex/mir_graph.cc +++ b/src/compiler/dex/mir_graph.cc @@ -53,8 +53,26 @@ static const CodePattern special_patterns[] = { {{Instruction::RETURN_WIDE}, kIdentity}, }; +const char* MIRGraph::extended_mir_op_names_[kMirOpLast - kMirOpFirst] = { + "Phi", + "Copy", + "FusedCmplFloat", + "FusedCmpgFloat", + "FusedCmplDouble", + "FusedCmpgDouble", + "FusedCmpLong", + "Nop", + "OpNullCheck", + "OpRangeCheck", + "OpDivZeroCheck", + "Check1", + "Check2", + "Select", +}; + MIRGraph::MIRGraph(CompilationUnit* cu) - : cu_(cu), + : reg_location_(NULL), + cu_(cu), ssa_base_vregs_(NULL), ssa_subscripts_(NULL), ssa_strings_(NULL), @@ -78,7 +96,10 @@ MIRGraph::MIRGraph(CompilationUnit* cu) current_offset_(kInvalidEntry), def_count_(0), opcode_count_(NULL), - num_ssa_regs_(0) { + num_ssa_regs_(0), + method_sreg_(0), + attributes_(METHOD_IS_LEAF) // Start with leaf assumption, change on encountering invoke. + { CompilerInitGrowableList(cu, &block_list_, 0, kListBlockList); try_block_addr_ = AllocBitVector(cu, 0, true /* expandable */); } @@ -623,7 +644,7 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ code_ptr += width; int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode); - int df_flags = oat_data_flow_attributes[insn->dalvikInsn.opcode]; + int df_flags = oat_data_flow_attributes_[insn->dalvikInsn.opcode]; if (df_flags & DF_HAS_DEFS) { def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1; @@ -684,7 +705,7 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ } if (cu_->verbose) { - DumpCompilationUnit(cu_); + DumpMIRGraph(); } } @@ -738,9 +759,9 @@ void MIRGraph::DumpCFG(const char* dir_prefix, bool all_blocks) for (mir = bb->first_mir_insn; mir; mir = mir->next) { int opcode = mir->dalvikInsn.opcode; fprintf(file, " {%04x %s %s %s\\l}%s\\\n", mir->offset, - mir->ssa_rep ? GetDalvikDisassembly(cu_, mir) : + mir->ssa_rep ? GetDalvikDisassembly(mir) : (opcode < kMirOpFirst) ? Instruction::Name(mir->dalvikInsn.opcode) : - extended_mir_op_names[opcode - kMirOpFirst], + extended_mir_op_names_[opcode - kMirOpFirst], (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ", (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ", mir->next ? " | " : " "); @@ -837,4 +858,315 @@ void MIRGraph::DumpCFG(const char* dir_prefix, bool all_blocks) fclose(file); } +/* Insert an MIR instruction to the end of a basic block */ +void MIRGraph::AppendMIR(BasicBlock* bb, MIR* mir) +{ + if (bb->first_mir_insn == NULL) { + DCHECK(bb->last_mir_insn == NULL); + bb->last_mir_insn = bb->first_mir_insn = mir; + mir->prev = mir->next = NULL; + } else { + bb->last_mir_insn->next = mir; + mir->prev = bb->last_mir_insn; + mir->next = NULL; + bb->last_mir_insn = mir; + } +} + +/* Insert an MIR instruction to the head of a basic block */ +void MIRGraph::PrependMIR(BasicBlock* bb, MIR* mir) +{ + if (bb->first_mir_insn == NULL) { + DCHECK(bb->last_mir_insn == NULL); + bb->last_mir_insn = bb->first_mir_insn = mir; + mir->prev = mir->next = NULL; + } else { + bb->first_mir_insn->prev = mir; + mir->next = bb->first_mir_insn; + mir->prev = NULL; + bb->first_mir_insn = mir; + } +} + +/* Insert a MIR instruction after the specified MIR */ +void MIRGraph::InsertMIRAfter(BasicBlock* bb, MIR* current_mir, MIR* new_mir) +{ + new_mir->prev = current_mir; + new_mir->next = current_mir->next; + current_mir->next = new_mir; + + if (new_mir->next) { + /* Is not the last MIR in the block */ + new_mir->next->prev = new_mir; + } else { + /* Is the last MIR in the block */ + bb->last_mir_insn = new_mir; + } +} + +char* MIRGraph::GetDalvikDisassembly(const MIR* mir) +{ + DecodedInstruction insn = mir->dalvikInsn; + std::string str; + int flags = 0; + int opcode = insn.opcode; + char* ret; + bool nop = false; + SSARepresentation* ssa_rep = mir->ssa_rep; + Instruction::Format dalvik_format = Instruction::k10x; // Default to no-operand format + int defs = (ssa_rep != NULL) ? ssa_rep->num_defs : 0; + int uses = (ssa_rep != NULL) ? ssa_rep->num_uses : 0; + + // Handle special cases. + if ((opcode == kMirOpCheck) || (opcode == kMirOpCheckPart2)) { + str.append(extended_mir_op_names_[opcode - kMirOpFirst]); + str.append(": "); + // Recover the original Dex instruction + insn = mir->meta.throw_insn->dalvikInsn; + ssa_rep = mir->meta.throw_insn->ssa_rep; + defs = ssa_rep->num_defs; + uses = ssa_rep->num_uses; + opcode = insn.opcode; + } else if (opcode == kMirOpNop) { + str.append("["); + insn.opcode = mir->meta.original_opcode; + opcode = mir->meta.original_opcode; + nop = true; + } + + if (opcode >= kMirOpFirst) { + str.append(extended_mir_op_names_[opcode - kMirOpFirst]); + } else { + dalvik_format = Instruction::FormatOf(insn.opcode); + flags = Instruction::FlagsOf(insn.opcode); + str.append(Instruction::Name(insn.opcode)); + } + + if (opcode == kMirOpPhi) { + int* incoming = reinterpret_cast<int*>(insn.vB); + str.append(StringPrintf(" %s = (%s", + GetSSANameWithConst(ssa_rep->defs[0], true).c_str(), + GetSSANameWithConst(ssa_rep->uses[0], true).c_str())); + str.append(StringPrintf(":%d",incoming[0])); + int i; + for (i = 1; i < uses; i++) { + str.append(StringPrintf(", %s:%d", + GetSSANameWithConst(ssa_rep->uses[i], true).c_str(), + incoming[i])); + } + str.append(")"); + } else if ((flags & Instruction::kBranch) != 0) { + // For branches, decode the instructions to print out the branch targets. + int offset = 0; + switch (dalvik_format) { + case Instruction::k21t: + str.append(StringPrintf(" %s,", GetSSANameWithConst(ssa_rep->uses[0], false).c_str())); + offset = insn.vB; + break; + case Instruction::k22t: + str.append(StringPrintf(" %s, %s,", GetSSANameWithConst(ssa_rep->uses[0], false).c_str(), + GetSSANameWithConst(ssa_rep->uses[1], false).c_str())); + offset = insn.vC; + break; + case Instruction::k10t: + case Instruction::k20t: + case Instruction::k30t: + offset = insn.vA; + break; + default: + LOG(FATAL) << "Unexpected branch format " << dalvik_format << " from " << insn.opcode; + } + str.append(StringPrintf(" 0x%x (%c%x)", mir->offset + offset, + offset > 0 ? '+' : '-', offset > 0 ? offset : -offset)); + } else { + // For invokes-style formats, treat wide regs as a pair of singles + bool show_singles = ((dalvik_format == Instruction::k35c) || + (dalvik_format == Instruction::k3rc)); + if (defs != 0) { + str.append(StringPrintf(" %s", GetSSANameWithConst(ssa_rep->defs[0], false).c_str())); + if (uses != 0) { + str.append(", "); + } + } + for (int i = 0; i < uses; i++) { + str.append( + StringPrintf(" %s", GetSSANameWithConst(ssa_rep->uses[i], show_singles).c_str())); + if (!show_singles && (reg_location_ != NULL) && reg_location_[i].wide) { + // For the listing, skip the high sreg. + i++; + } + if (i != (uses -1)) { + str.append(","); + } + } + switch (dalvik_format) { + case Instruction::k11n: // Add one immediate from vB + case Instruction::k21s: + case Instruction::k31i: + case Instruction::k21h: + str.append(StringPrintf(", #%d", insn.vB)); + break; + case Instruction::k51l: // Add one wide immediate + str.append(StringPrintf(", #%lld", insn.vB_wide)); + break; + case Instruction::k21c: // One register, one string/type/method index + case Instruction::k31c: + str.append(StringPrintf(", index #%d", insn.vB)); + break; + case Instruction::k22c: // Two registers, one string/type/method index + str.append(StringPrintf(", index #%d", insn.vC)); + break; + case Instruction::k22s: // Add one immediate from vC + case Instruction::k22b: + str.append(StringPrintf(", #%d", insn.vC)); + break; + default: + ; // Nothing left to print + } + } + if (nop) { + str.append("]--optimized away"); + } + int length = str.length() + 1; + ret = static_cast<char*>(NewMem(cu_, length, false, kAllocDFInfo)); + strncpy(ret, str.c_str(), length); + return ret; +} + +/* Turn method name into a legal Linux file name */ +void MIRGraph::ReplaceSpecialChars(std::string& str) +{ + static const struct { const char before; const char after; } match[] = + {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'}, + {'(','@'}, {')','@'}, {'<','='}, {'>','='}}; + for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) { + std::replace(str.begin(), str.end(), match[i].before, match[i].after); + } +} + +std::string MIRGraph::GetSSAName(int ssa_reg) +{ + return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg)); +} + +// Similar to GetSSAName, but if ssa name represents an immediate show that as well. +std::string MIRGraph::GetSSANameWithConst(int ssa_reg, bool singles_only) +{ + if (reg_location_ == NULL) { + // Pre-SSA - just use the standard name + return GetSSAName(ssa_reg); + } + if (IsConst(reg_location_[ssa_reg])) { + if (!singles_only && reg_location_[ssa_reg].wide) { + return StringPrintf("v%d_%d#0x%llx", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg), + ConstantValueWide(reg_location_[ssa_reg])); + } else { + return StringPrintf("v%d_%d#0x%x", SRegToVReg(ssa_reg),GetSSASubscript(ssa_reg), + ConstantValue(reg_location_[ssa_reg])); + } + } else { + return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg)); + } +} + +void MIRGraph::GetBlockName(BasicBlock* bb, char* name) +{ + switch (bb->block_type) { + case kEntryBlock: + snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id); + break; + case kExitBlock: + snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id); + break; + case kDalvikByteCode: + snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->start_offset, bb->id); + break; + case kExceptionHandling: + snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->start_offset, + bb->id); + break; + default: + snprintf(name, BLOCK_NAME_LEN, "_%d", bb->id); + break; + } +} + +const char* MIRGraph::GetShortyFromTargetIdx(int target_idx) +{ + // FIXME: use current code unit for inline support. + const DexFile::MethodId& method_id = cu_->dex_file->GetMethodId(target_idx); + return cu_->dex_file->GetShorty(method_id.proto_idx_); +} + +/* Debug Utility - dump a compilation unit */ +void MIRGraph::DumpMIRGraph() +{ + BasicBlock* bb; + const char* block_type_names[] = { + "Entry Block", + "Code Block", + "Exit Block", + "Exception Handling", + "Catch Block" + }; + + LOG(INFO) << "Compiling " << PrettyMethod(cu_->method_idx, *cu_->dex_file); + LOG(INFO) << cu_->insns << " insns"; + LOG(INFO) << GetNumBlocks() << " blocks in total"; + GrowableListIterator iterator = GetBasicBlockIterator(); + + while (true) { + bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iterator)); + if (bb == NULL) break; + LOG(INFO) << StringPrintf("Block %d (%s) (insn %04x - %04x%s)", + bb->id, + block_type_names[bb->block_type], + bb->start_offset, + bb->last_mir_insn ? bb->last_mir_insn->offset : bb->start_offset, + bb->last_mir_insn ? "" : " empty"); + if (bb->taken) { + LOG(INFO) << " Taken branch: block " << bb->taken->id + << "(0x" << std::hex << bb->taken->start_offset << ")"; + } + if (bb->fall_through) { + LOG(INFO) << " Fallthrough : block " << bb->fall_through->id + << " (0x" << std::hex << bb->fall_through->start_offset << ")"; + } + } +} + +/* + * Build an array of location records for the incoming arguments. + * Note: one location record per word of arguments, with dummy + * high-word loc for wide arguments. Also pull up any following + * MOVE_RESULT and incorporate it into the invoke. + */ +CallInfo* MIRGraph::NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, + bool is_range) +{ + CallInfo* info = static_cast<CallInfo*>(NewMem(cu_, sizeof(CallInfo), true, kAllocMisc)); + MIR* move_result_mir = FindMoveResult(bb, mir); + if (move_result_mir == NULL) { + info->result.location = kLocInvalid; + } else { + info->result = GetRawDest(move_result_mir); + move_result_mir->meta.original_opcode = move_result_mir->dalvikInsn.opcode; + move_result_mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); + } + info->num_arg_words = mir->ssa_rep->num_uses; + info->args = (info->num_arg_words == 0) ? NULL : static_cast<RegLocation*> + (NewMem(cu_, sizeof(RegLocation) * info->num_arg_words, false, kAllocMisc)); + for (int i = 0; i < info->num_arg_words; i++) { + info->args[i] = GetRawSrc(mir, i); + } + info->opt_flags = mir->optimization_flags; + info->type = type; + info->is_range = is_range; + info->index = mir->dalvikInsn.vB; + info->offset = mir->offset; + return info; +} + + + } // namespace art diff --git a/src/compiler/dex/mir_graph.h b/src/compiler/dex/mir_graph.h index 832901084a..514205d07c 100644 --- a/src/compiler/dex/mir_graph.h +++ b/src/compiler/dex/mir_graph.h @@ -114,7 +114,191 @@ enum DataFlowAttributePos { #define DF_IS_GETTER_OR_SETTER (DF_IS_GETTER | DF_IS_SETTER) #define DF_USES_FP (DF_FP_A | DF_FP_B | DF_FP_C) -extern const int oat_data_flow_attributes[kMirOpLast]; +enum OatMethodAttributes { + kIsLeaf, // Method is leaf. + kHasLoop, // Method contains simple loop. +}; + +#define METHOD_IS_LEAF (1 << kIsLeaf) +#define METHOD_HAS_LOOP (1 << kHasLoop) + +// Minimum field size to contain Dalvik v_reg number. +#define VREG_NUM_WIDTH 16 + +#define INVALID_SREG (-1) +#define INVALID_VREG (0xFFFFU) +#define INVALID_REG (0xFF) +#define INVALID_OFFSET (0xDEADF00FU) + +/* SSA encodings for special registers */ +#define SSA_METHOD_BASEREG (-2) +/* First compiler temp basereg, grows smaller */ +#define SSA_CTEMP_BASEREG (SSA_METHOD_BASEREG - 1) + +#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck) +#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly) +#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck) +#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly) +#define MIR_INLINED (1 << kMIRInlined) +#define MIR_INLINED_PRED (1 << kMIRInlinedPred) +#define MIR_CALLEE (1 << kMIRCallee) +#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck) +#define MIR_DUP (1 << kMIRDup) + +/* + * In general, vreg/sreg describe Dalvik registers that originated with dx. However, + * it is useful to have compiler-generated temporary registers and have them treated + * in the same manner as dx-generated virtual registers. This struct records the SSA + * name of compiler-introduced temporaries. + */ +struct CompilerTemp { + int s_reg; +}; + +// When debug option enabled, records effectiveness of null and range check elimination. +struct Checkstats { + int null_checks; + int null_checks_eliminated; + int range_checks; + int range_checks_eliminated; +}; + +// Dataflow attributes of a basic block. +struct BasicBlockDataFlow { + ArenaBitVector* use_v; + ArenaBitVector* def_v; + ArenaBitVector* live_in_v; + ArenaBitVector* phi_v; + int* vreg_to_ssa_map; + ArenaBitVector* ending_null_check_v; +}; + +/* + * Normalized use/def for a MIR operation using SSA names rather than vregs. Note that + * uses/defs retain the Dalvik convention that long operations operate on a pair of 32-bit + * vregs. For example, "ADD_LONG v0, v2, v3" would have 2 defs (v0/v1) and 4 uses (v2/v3, v4/v5). + * Following SSA renaming, this is the primary struct used by code generators to locate + * operand and result registers. This is a somewhat confusing and unhelpful convention that + * we may want to revisit in the future. + */ +struct SSARepresentation { + int num_uses; + int* uses; + bool* fp_use; + int num_defs; + int* defs; + bool* fp_def; +}; + +/* + * The Midlevel Intermediate Representation node, which may be largely considered a + * wrapper around a Dalvik byte code. + */ +struct MIR { + DecodedInstruction dalvikInsn; + unsigned int width; + unsigned int offset; + int m_unit_index; // From which method was this MIR included + MIR* prev; + MIR* next; + SSARepresentation* ssa_rep; + int optimization_flags; + union { + // Establish link between two halves of throwing instructions. + MIR* throw_insn; + // Saved opcode for NOP'd MIRs + Instruction::Code original_opcode; + } meta; +}; + +struct BasicBlock { + int id; + int dfs_id; + bool visited; + bool hidden; + bool catch_entry; + bool explicit_throw; + bool conditional_branch; + bool terminated_by_return; // Block ends with a Dalvik return opcode. + bool dominates_return; // Is a member of return extended basic block. + uint16_t start_offset; + uint16_t nesting_depth; + BBType block_type; + MIR* first_mir_insn; + MIR* last_mir_insn; + BasicBlock* fall_through; + BasicBlock* taken; + BasicBlock* i_dom; // Immediate dominator. + BasicBlockDataFlow* data_flow_info; + GrowableList* predecessors; + ArenaBitVector* dominators; + ArenaBitVector* i_dominated; // Set nodes being immediately dominated. + ArenaBitVector* dom_frontier; // Dominance frontier. + struct { // For one-to-many successors like. + BlockListType block_list_type; // switch and exception handling. + GrowableList blocks; + } successor_block_list; +}; + +/* + * The "blocks" field in "successor_block_list" points to an array of elements with the type + * "SuccessorBlockInfo". For catch blocks, key is type index for the exception. For swtich + * blocks, key is the case value. + */ +struct SuccessorBlockInfo { + BasicBlock* block; + int key; +}; + +/* + * Whereas a SSA name describes a definition of a Dalvik vreg, the RegLocation describes + * the type of an SSA name (and, can also be used by code generators to record where the + * value is located (i.e. - physical register, frame, spill, etc.). For each SSA name (SReg) + * there is a RegLocation. + * FIXME: The orig_sreg field was added as a workaround for llvm bitcode generation. With + * the latest restructuring, we should be able to remove it and rely on s_reg_low throughout. + */ +struct RegLocation { + RegLocationType location:3; + unsigned wide:1; + unsigned defined:1; // Do we know the type? + unsigned is_const:1; // Constant, value in mir_graph->constant_values[]. + unsigned fp:1; // Floating point? + unsigned core:1; // Non-floating point? + unsigned ref:1; // Something GC cares about. + unsigned high_word:1; // High word of pair? + unsigned home:1; // Does this represent the home location? + uint8_t low_reg; // First physical register. + uint8_t high_reg; // 2nd physical register (if wide). + int32_t s_reg_low; // SSA name for low Dalvik word. + int32_t orig_sreg; // TODO: remove after Bitcode gen complete + // and consolodate usage w/ s_reg_low. +}; + +/* + * Collection of information describing an invoke, and the destination of + * the subsequent MOVE_RESULT (if applicable). Collected as a unit to enable + * more efficient invoke code generation. + */ +struct CallInfo { + int num_arg_words; // Note: word count, not arg count. + RegLocation* args; // One for each word of arguments. + RegLocation result; // Eventual target of MOVE_RESULT. + int opt_flags; + InvokeType type; + uint32_t dex_idx; + uint32_t index; // Method idx for invokes, type idx for FilledNewArray. + uintptr_t direct_code; + uintptr_t direct_method; + RegLocation target; // Target of following move_result. + bool skip_this; + bool is_range; + int offset; // Dalvik offset. +}; + + +const RegLocation bad_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0, + INVALID_REG, INVALID_REG, INVALID_SREG, INVALID_SREG}; class MIRGraph { public: @@ -213,8 +397,6 @@ class MIRGraph { void DumpRegLocTable(RegLocation* table, int count); - int ComputeFrameSize(); - void BasicBlockOptimization(); bool IsConst(int32_t s_reg) const { @@ -273,6 +455,69 @@ class MIRGraph { return GET_ELEM_N(ssa_strings_, char*, ssa_reg); } + RegLocation GetRawSrc(MIR* mir, int num) + { + DCHECK(num < mir->ssa_rep->num_uses); + RegLocation res = reg_location_[mir->ssa_rep->uses[num]]; + return res; + } + + RegLocation GetRawDest(MIR* mir) + { + DCHECK_GT(mir->ssa_rep->num_defs, 0); + RegLocation res = reg_location_[mir->ssa_rep->defs[0]]; + return res; + } + + RegLocation GetDest(MIR* mir) + { + RegLocation res = GetRawDest(mir); + DCHECK(!res.wide); + return res; + } + + RegLocation GetSrc(MIR* mir, int num) + { + RegLocation res = GetRawSrc(mir, num); + DCHECK(!res.wide); + return res; + } + + RegLocation GetDestWide(MIR* mir) + { + RegLocation res = GetRawDest(mir); + DCHECK(res.wide); + return res; + } + + RegLocation GetSrcWide(MIR* mir, int low) + { + RegLocation res = GetRawSrc(mir, low); + DCHECK(res.wide); + return res; + } + + RegLocation GetBadLoc() { + return bad_loc; + } + + int GetMethodSReg() { + return method_sreg_; + } + + bool MethodIsLeaf() { + return attributes_ & METHOD_IS_LEAF; + } + + RegLocation GetRegLocation(int index) { + DCHECK((index >= 0) && (index > num_ssa_regs_)); + return reg_location_[index]; + } + + RegLocation GetMethodLoc() { + return reg_location_[method_sreg_]; + } + void BasicBlockCombine(); void CodeLayout(); void DumpCheckStats(); @@ -284,6 +529,23 @@ class MIRGraph { void SSATransformation(); void CheckForDominanceFrontier(BasicBlock* dom_bb, const BasicBlock* succ_bb); void NullCheckElimination(); + bool SetFp(int index, bool is_fp); + bool SetCore(int index, bool is_core); + bool SetRef(int index, bool is_ref); + bool SetWide(int index, bool is_wide); + bool SetHigh(int index, bool is_high); + void AppendMIR(BasicBlock* bb, MIR* mir); + void PrependMIR(BasicBlock* bb, MIR* mir); + void InsertMIRAfter(BasicBlock* bb, MIR* current_mir, MIR* new_mir); + char* GetDalvikDisassembly(const MIR* mir); + + void ReplaceSpecialChars(std::string& str); + std::string GetSSAName(int ssa_reg); + std::string GetSSANameWithConst(int ssa_reg, bool singles_only); + void GetBlockName(BasicBlock* bb, char* name); + const char* GetShortyFromTargetIdx(int); + void DumpMIRGraph(); + CallInfo* NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, bool is_range); /* * IsDebugBuild sanity check: keep track of the Dex PCs for catch entries so that later on @@ -291,6 +553,14 @@ class MIRGraph { */ std::set<uint32_t> catches_; + // TODO: make these private. + RegLocation* reg_location_; // Map SSA names to location. + GrowableList compiler_temps_; + SafeMap<unsigned int, unsigned int> block_id_map_; // Block collapse lookup cache. + + static const int oat_data_flow_attributes_[kMirOpLast]; + static const char* extended_mir_op_names_[kMirOpLast - kMirOpFirst]; + private: int FindCommonParent(int block1, int block2); @@ -393,6 +663,9 @@ class MIRGraph { int* opcode_count_; // Dex opcode coverage stats. int num_ssa_regs_; // Number of names following SSA transformation. std::vector<BasicBlock*> extended_basic_blocks_; // Heads of block "traces". + int method_sreg_; + unsigned int attributes_; + Checkstats* checkstats_; }; } // namespace art diff --git a/src/compiler/dex/mir_optimization.cc b/src/compiler/dex/mir_optimization.cc index 759dc328ef..51b9d9d292 100644 --- a/src/compiler/dex/mir_optimization.cc +++ b/src/compiler/dex/mir_optimization.cc @@ -45,7 +45,7 @@ bool MIRGraph::DoConstantPropogation(BasicBlock* bb) ArenaBitVector *is_constant_v = is_constant_v_; for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { - int df_attributes = oat_data_flow_attributes[mir->dalvikInsn.opcode]; + int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; DecodedInstruction *d_insn = &mir->dalvikInsn; @@ -107,7 +107,6 @@ void MIRGraph::PropagateConstants() for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { DoConstantPropogation(bb); } - } /* Advance to next strictly dominated MIR node in an extended basic block */ @@ -236,7 +235,7 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) case Instruction::CMPG_FLOAT: case Instruction::CMPG_DOUBLE: case Instruction::CMP_LONG: - if (cu_->gen_bitcode) { + if ((cu_->disable_opt & (1 << kBranchFusing)) != 0) { // Bitcode doesn't allow this optimization. break; } @@ -332,7 +331,7 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) // Is this the select pattern? // TODO: flesh out support for Mips and X86. NOTE: llvm's select op doesn't quite work here. // TUNING: expand to support IF_xx compare & branches - if (!cu_->gen_bitcode && (cu_->instruction_set == kThumb2) && + if (!(cu_->compiler_backend == kPortable) && (cu_->instruction_set == kThumb2) && ((mir->dalvikInsn.opcode == Instruction::IF_EQZ) || (mir->dalvikInsn.opcode == Instruction::IF_NEZ))) { BasicBlock* ft = bb->fall_through; @@ -485,18 +484,17 @@ bool MIRGraph::CountChecks(struct BasicBlock* bb) if (mir->ssa_rep == NULL) { continue; } - int df_attributes = oat_data_flow_attributes[mir->dalvikInsn.opcode]; + int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; if (df_attributes & DF_HAS_NULL_CHKS) { - //TODO: move checkstats to mir_graph - cu_->checkstats->null_checks++; + checkstats_->null_checks++; if (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) { - cu_->checkstats->null_checks_eliminated++; + checkstats_->null_checks_eliminated++; } } if (df_attributes & DF_HAS_RANGE_CHKS) { - cu_->checkstats->range_checks++; + checkstats_->range_checks++; if (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) { - cu_->checkstats->range_checks_eliminated++; + checkstats_->range_checks_eliminated++; } } } @@ -572,7 +570,7 @@ bool MIRGraph::CombineBlocks(struct BasicBlock* bb) MIR* mir = bb->last_mir_insn; // Grab the attributes from the paired opcode MIR* throw_insn = mir->meta.throw_insn; - int df_attributes = oat_data_flow_attributes[throw_insn->dalvikInsn.opcode]; + int df_attributes = oat_data_flow_attributes_[throw_insn->dalvikInsn.opcode]; bool can_combine = true; if (df_attributes & DF_HAS_NULL_CHKS) { can_combine &= ((throw_insn->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0); @@ -613,7 +611,7 @@ bool MIRGraph::CombineBlocks(struct BasicBlock* bb) // Kill bb_next and remap now-dead id to parent bb_next->block_type = kDead; - cu_->block_id_map.Overwrite(bb_next->id, bb->id); + block_id_map_.Overwrite(bb_next->id, bb->id); // Now, loop back and see if we can keep going } @@ -661,7 +659,7 @@ bool MIRGraph::EliminateNullChecks(struct BasicBlock* bb) if (mir->ssa_rep == NULL) { continue; } - int df_attributes = oat_data_flow_attributes[mir->dalvikInsn.opcode]; + int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; // Mark target of NEW* as non-null if (df_attributes & DF_NON_NULL_DST) { @@ -782,6 +780,9 @@ void MIRGraph::BasicBlockCombine() void MIRGraph::CodeLayout() { + if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) { + VerifyDataflow(); + } AllNodesIterator iter(this, false /* not iterative */); for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { LayoutBlocks(bb); @@ -795,7 +796,7 @@ void MIRGraph::DumpCheckStats() { Checkstats* stats = static_cast<Checkstats*>(NewMem(cu_, sizeof(Checkstats), true, kAllocDFInfo)); - cu_->checkstats = stats; + checkstats_ = stats; AllNodesIterator iter(this, false /* not iterative */); for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { CountChecks(bb); @@ -850,7 +851,7 @@ bool MIRGraph::BuildExtendedBBList(struct BasicBlock* bb) void MIRGraph::BasicBlockOptimization() { if (!(cu_->disable_opt & (1 << kBBOpt))) { - CompilerInitGrowableList(cu_, &cu_->compiler_temps, 6, kListMisc); + CompilerInitGrowableList(cu_, &compiler_temps_, 6, kListMisc); DCHECK_EQ(cu_->num_compiler_temps, 0); // Mark all blocks as not visited AllNodesIterator iter(this, false /* not iterative */); diff --git a/src/compiler/dex/portable/mir_to_gbc.cc b/src/compiler/dex/portable/mir_to_gbc.cc index af8e45942f..6dcdfcfc91 100644 --- a/src/compiler/dex/portable/mir_to_gbc.cc +++ b/src/compiler/dex/portable/mir_to_gbc.cc @@ -29,46 +29,44 @@ #include "compiler/dex/compiler_internals.h" #include "compiler/dex/dataflow_iterator.h" +#include "compiler/dex/frontend.h" +#include "mir_to_gbc.h" -//TODO: move gbc_to_lir code into quick directory (if necessary). -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/local_optimizations.h" -#include "compiler/dex/quick/ralloc_util.h" #include "compiler/llvm/llvm_compilation_unit.h" #include "compiler/llvm/utils_llvm.h" -static const char* kLabelFormat = "%c0x%x_%d"; -static const char kInvalidBlock = 0xff; -static const char kNormalBlock = 'L'; -static const char kCatchBlock = 'C'; +const char* kLabelFormat = "%c0x%x_%d"; +const char kInvalidBlock = 0xff; +const char kNormalBlock = 'L'; +const char kCatchBlock = 'C'; namespace art { -static ::llvm::BasicBlock* GetLLVMBlock(CompilationUnit* cu, int id) +::llvm::BasicBlock* MirConverter::GetLLVMBlock(int id) { - return cu->id_to_block_map.Get(id); + return id_to_block_map_.Get(id); } -static ::llvm::Value* GetLLVMValue(CompilationUnit* cu, int s_reg) +::llvm::Value* MirConverter::GetLLVMValue(int s_reg) { - return reinterpret_cast< ::llvm::Value*>(GrowableListGetElement(&cu->llvm_values, s_reg)); + return reinterpret_cast< ::llvm::Value*>(GrowableListGetElement(&llvm_values_, s_reg)); } -static void SetVregOnValue(CompilationUnit* cu, ::llvm::Value* val, int s_reg) +void MirConverter::SetVregOnValue(::llvm::Value* val, int s_reg) { // Set vreg for debugging art::llvm::IntrinsicHelper::IntrinsicId id = art::llvm::IntrinsicHelper::SetVReg; - ::llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id); - int v_reg = cu->mir_graph->SRegToVReg(s_reg); - ::llvm::Value* table_slot = cu->irb->getInt32(v_reg); + ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id); + int v_reg = mir_graph_->SRegToVReg(s_reg); + ::llvm::Value* table_slot = irb_->getInt32(v_reg); ::llvm::Value* args[] = { table_slot, val }; - cu->irb->CreateCall(func, args); + irb_->CreateCall(func, args); } // Replace the placeholder value with the real definition -static void DefineValueOnly(CompilationUnit* cu, ::llvm::Value* val, int s_reg) +void MirConverter::DefineValueOnly(::llvm::Value* val, int s_reg) { - ::llvm::Value* placeholder = GetLLVMValue(cu, s_reg); + ::llvm::Value* placeholder = GetLLVMValue(s_reg); if (placeholder == NULL) { // This can happen on instruction rewrite on verification failure LOG(WARNING) << "Null placeholder"; @@ -76,149 +74,148 @@ static void DefineValueOnly(CompilationUnit* cu, ::llvm::Value* val, int s_reg) } placeholder->replaceAllUsesWith(val); val->takeName(placeholder); - cu->llvm_values.elem_list[s_reg] = reinterpret_cast<uintptr_t>(val); + llvm_values_.elem_list[s_reg] = reinterpret_cast<uintptr_t>(val); ::llvm::Instruction* inst = ::llvm::dyn_cast< ::llvm::Instruction>(placeholder); DCHECK(inst != NULL); inst->eraseFromParent(); } -static void DefineValue(CompilationUnit* cu, ::llvm::Value* val, int s_reg) +void MirConverter::DefineValue(::llvm::Value* val, int s_reg) { - DefineValueOnly(cu, val, s_reg); - SetVregOnValue(cu, val, s_reg); + DefineValueOnly(val, s_reg); + SetVregOnValue(val, s_reg); } -static ::llvm::Type* LlvmTypeFromLocRec(CompilationUnit* cu, RegLocation loc) +::llvm::Type* MirConverter::LlvmTypeFromLocRec(RegLocation loc) { ::llvm::Type* res = NULL; if (loc.wide) { if (loc.fp) - res = cu->irb->getDoubleTy(); + res = irb_->getDoubleTy(); else - res = cu->irb->getInt64Ty(); + res = irb_->getInt64Ty(); } else { if (loc.fp) { - res = cu->irb->getFloatTy(); + res = irb_->getFloatTy(); } else { if (loc.ref) - res = cu->irb->getJObjectTy(); + res = irb_->getJObjectTy(); else - res = cu->irb->getInt32Ty(); + res = irb_->getInt32Ty(); } } return res; } -static void InitIR(CompilationUnit* cu) +void MirConverter::InitIR() { - LLVMInfo* llvm_info = cu->llvm_info; - if (llvm_info == NULL) { - CompilerTls* tls = cu->compiler_driver->GetTls(); + if (llvm_info_ == NULL) { + CompilerTls* tls = cu_->compiler_driver->GetTls(); CHECK(tls != NULL); - llvm_info = static_cast<LLVMInfo*>(tls->GetLLVMInfo()); - if (llvm_info == NULL) { - llvm_info = new LLVMInfo(); - tls->SetLLVMInfo(llvm_info); + llvm_info_ = static_cast<LLVMInfo*>(tls->GetLLVMInfo()); + if (llvm_info_ == NULL) { + llvm_info_ = new LLVMInfo(); + tls->SetLLVMInfo(llvm_info_); } } - cu->context = llvm_info->GetLLVMContext(); - cu->module = llvm_info->GetLLVMModule(); - cu->intrinsic_helper = llvm_info->GetIntrinsicHelper(); - cu->irb = llvm_info->GetIRBuilder(); + context_ = llvm_info_->GetLLVMContext(); + module_ = llvm_info_->GetLLVMModule(); + intrinsic_helper_ = llvm_info_->GetIntrinsicHelper(); + irb_ = llvm_info_->GetIRBuilder(); } -::llvm::BasicBlock* FindCaseTarget(CompilationUnit* cu, uint32_t vaddr) +::llvm::BasicBlock* MirConverter::FindCaseTarget(uint32_t vaddr) { - BasicBlock* bb = cu->mir_graph.get()->FindBlock(vaddr); + BasicBlock* bb = mir_graph_->FindBlock(vaddr); DCHECK(bb != NULL); - return GetLLVMBlock(cu, bb->id); + return GetLLVMBlock(bb->id); } -static void ConvertPackedSwitch(CompilationUnit* cu, BasicBlock* bb, +void MirConverter::ConvertPackedSwitch(BasicBlock* bb, int32_t table_offset, RegLocation rl_src) { const Instruction::PackedSwitchPayload* payload = reinterpret_cast<const Instruction::PackedSwitchPayload*>( - cu->insns + cu->current_dalvik_offset + table_offset); + cu_->insns + current_dalvik_offset_ + table_offset); - ::llvm::Value* value = GetLLVMValue(cu, rl_src.orig_sreg); + ::llvm::Value* value = GetLLVMValue(rl_src.orig_sreg); ::llvm::SwitchInst* sw = - cu->irb->CreateSwitch(value, GetLLVMBlock(cu, bb->fall_through->id), + irb_->CreateSwitch(value, GetLLVMBlock(bb->fall_through->id), payload->case_count); for (uint16_t i = 0; i < payload->case_count; ++i) { ::llvm::BasicBlock* llvm_bb = - FindCaseTarget(cu, cu->current_dalvik_offset + payload->targets[i]); - sw->addCase(cu->irb->getInt32(payload->first_key + i), llvm_bb); + FindCaseTarget(current_dalvik_offset_ + payload->targets[i]); + sw->addCase(irb_->getInt32(payload->first_key + i), llvm_bb); } ::llvm::MDNode* switch_node = - ::llvm::MDNode::get(*cu->context, cu->irb->getInt32(table_offset)); + ::llvm::MDNode::get(*context_, irb_->getInt32(table_offset)); sw->setMetadata("SwitchTable", switch_node); bb->taken = NULL; bb->fall_through = NULL; } -static void ConvertSparseSwitch(CompilationUnit* cu, BasicBlock* bb, +void MirConverter::ConvertSparseSwitch(BasicBlock* bb, int32_t table_offset, RegLocation rl_src) { const Instruction::SparseSwitchPayload* payload = reinterpret_cast<const Instruction::SparseSwitchPayload*>( - cu->insns + cu->current_dalvik_offset + table_offset); + cu_->insns + current_dalvik_offset_ + table_offset); const int32_t* keys = payload->GetKeys(); const int32_t* targets = payload->GetTargets(); - ::llvm::Value* value = GetLLVMValue(cu, rl_src.orig_sreg); + ::llvm::Value* value = GetLLVMValue(rl_src.orig_sreg); ::llvm::SwitchInst* sw = - cu->irb->CreateSwitch(value, GetLLVMBlock(cu, bb->fall_through->id), + irb_->CreateSwitch(value, GetLLVMBlock(bb->fall_through->id), payload->case_count); for (size_t i = 0; i < payload->case_count; ++i) { ::llvm::BasicBlock* llvm_bb = - FindCaseTarget(cu, cu->current_dalvik_offset + targets[i]); - sw->addCase(cu->irb->getInt32(keys[i]), llvm_bb); + FindCaseTarget(current_dalvik_offset_ + targets[i]); + sw->addCase(irb_->getInt32(keys[i]), llvm_bb); } ::llvm::MDNode* switch_node = - ::llvm::MDNode::get(*cu->context, cu->irb->getInt32(table_offset)); + ::llvm::MDNode::get(*context_, irb_->getInt32(table_offset)); sw->setMetadata("SwitchTable", switch_node); bb->taken = NULL; bb->fall_through = NULL; } -static void ConvertSget(CompilationUnit* cu, int32_t field_index, +void MirConverter::ConvertSget(int32_t field_index, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest) { - ::llvm::Constant* field_idx = cu->irb->getInt32(field_index); - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Value* res = cu->irb->CreateCall(intr, field_idx); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Constant* field_idx = irb_->getInt32(field_index); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Value* res = irb_->CreateCall(intr, field_idx); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertSput(CompilationUnit* cu, int32_t field_index, +void MirConverter::ConvertSput(int32_t field_index, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src) { ::llvm::SmallVector< ::llvm::Value*, 2> args; - args.push_back(cu->irb->getInt32(field_index)); - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - cu->irb->CreateCall(intr, args); + args.push_back(irb_->getInt32(field_index)); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + irb_->CreateCall(intr, args); } -static void ConvertFillArrayData(CompilationUnit* cu, int32_t offset, RegLocation rl_array) +void MirConverter::ConvertFillArrayData(int32_t offset, RegLocation rl_array) { art::llvm::IntrinsicHelper::IntrinsicId id; id = art::llvm::IntrinsicHelper::HLFillArrayData; ::llvm::SmallVector< ::llvm::Value*, 2> args; - args.push_back(cu->irb->getInt32(offset)); - args.push_back(GetLLVMValue(cu, rl_array.orig_sreg)); - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - cu->irb->CreateCall(intr, args); + args.push_back(irb_->getInt32(offset)); + args.push_back(GetLLVMValue(rl_array.orig_sreg)); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + irb_->CreateCall(intr, args); } -static ::llvm::Value* EmitConst(CompilationUnit* cu, ::llvm::ArrayRef< ::llvm::Value*> src, +::llvm::Value* MirConverter::EmitConst(::llvm::ArrayRef< ::llvm::Value*> src, RegLocation loc) { art::llvm::IntrinsicHelper::IntrinsicId id; @@ -237,18 +234,18 @@ static ::llvm::Value* EmitConst(CompilationUnit* cu, ::llvm::ArrayRef< ::llvm::V id = art::llvm::IntrinsicHelper::ConstInt; } } - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - return cu->irb->CreateCall(intr, src); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + return irb_->CreateCall(intr, src); } -static void EmitPopShadowFrame(CompilationUnit* cu) +void MirConverter::EmitPopShadowFrame() { - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction( + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction( art::llvm::IntrinsicHelper::PopShadowFrame); - cu->irb->CreateCall(intr); + irb_->CreateCall(intr); } -static ::llvm::Value* EmitCopy(CompilationUnit* cu, ::llvm::ArrayRef< ::llvm::Value*> src, +::llvm::Value* MirConverter::EmitCopy(::llvm::ArrayRef< ::llvm::Value*> src, RegLocation loc) { art::llvm::IntrinsicHelper::IntrinsicId id; @@ -267,111 +264,111 @@ static ::llvm::Value* EmitCopy(CompilationUnit* cu, ::llvm::ArrayRef< ::llvm::Va id = art::llvm::IntrinsicHelper::CopyInt; } } - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - return cu->irb->CreateCall(intr, src); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + return irb_->CreateCall(intr, src); } -static void ConvertMoveException(CompilationUnit* cu, RegLocation rl_dest) +void MirConverter::ConvertMoveException(RegLocation rl_dest) { - ::llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction( + ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction( art::llvm::IntrinsicHelper::GetException); - ::llvm::Value* res = cu->irb->CreateCall(func); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* res = irb_->CreateCall(func); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertThrow(CompilationUnit* cu, RegLocation rl_src) +void MirConverter::ConvertThrow(RegLocation rl_src) { - ::llvm::Value* src = GetLLVMValue(cu, rl_src.orig_sreg); - ::llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction( + ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg); + ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction( art::llvm::IntrinsicHelper::HLThrowException); - cu->irb->CreateCall(func, src); + irb_->CreateCall(func, src); } -static void ConvertMonitorEnterExit(CompilationUnit* cu, int opt_flags, +void MirConverter::ConvertMonitorEnterExit(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src) { ::llvm::SmallVector< ::llvm::Value*, 2> args; - args.push_back(cu->irb->getInt32(opt_flags)); - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - ::llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id); - cu->irb->CreateCall(func, args); + args.push_back(irb_->getInt32(opt_flags)); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id); + irb_->CreateCall(func, args); } -static void ConvertArrayLength(CompilationUnit* cu, int opt_flags, +void MirConverter::ConvertArrayLength(int opt_flags, RegLocation rl_dest, RegLocation rl_src) { ::llvm::SmallVector< ::llvm::Value*, 2> args; - args.push_back(cu->irb->getInt32(opt_flags)); - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - ::llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction( + args.push_back(irb_->getInt32(opt_flags)); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction( art::llvm::IntrinsicHelper::OptArrayLength); - ::llvm::Value* res = cu->irb->CreateCall(func, args); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* res = irb_->CreateCall(func, args); + DefineValue(res, rl_dest.orig_sreg); } -static void EmitSuspendCheck(CompilationUnit* cu) +void MirConverter::EmitSuspendCheck() { art::llvm::IntrinsicHelper::IntrinsicId id = art::llvm::IntrinsicHelper::CheckSuspend; - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - cu->irb->CreateCall(intr); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + irb_->CreateCall(intr); } -static ::llvm::Value* ConvertCompare(CompilationUnit* cu, ConditionCode cc, +::llvm::Value* MirConverter::ConvertCompare(ConditionCode cc, ::llvm::Value* src1, ::llvm::Value* src2) { ::llvm::Value* res = NULL; DCHECK_EQ(src1->getType(), src2->getType()); switch(cc) { - case kCondEq: res = cu->irb->CreateICmpEQ(src1, src2); break; - case kCondNe: res = cu->irb->CreateICmpNE(src1, src2); break; - case kCondLt: res = cu->irb->CreateICmpSLT(src1, src2); break; - case kCondGe: res = cu->irb->CreateICmpSGE(src1, src2); break; - case kCondGt: res = cu->irb->CreateICmpSGT(src1, src2); break; - case kCondLe: res = cu->irb->CreateICmpSLE(src1, src2); break; + case kCondEq: res = irb_->CreateICmpEQ(src1, src2); break; + case kCondNe: res = irb_->CreateICmpNE(src1, src2); break; + case kCondLt: res = irb_->CreateICmpSLT(src1, src2); break; + case kCondGe: res = irb_->CreateICmpSGE(src1, src2); break; + case kCondGt: res = irb_->CreateICmpSGT(src1, src2); break; + case kCondLe: res = irb_->CreateICmpSLE(src1, src2); break; default: LOG(FATAL) << "Unexpected cc value " << cc; } return res; } -static void ConvertCompareAndBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, +void MirConverter::ConvertCompareAndBranch(BasicBlock* bb, MIR* mir, ConditionCode cc, RegLocation rl_src1, RegLocation rl_src2) { if (bb->taken->start_offset <= mir->offset) { - EmitSuspendCheck(cu); + EmitSuspendCheck(); } - ::llvm::Value* src1 = GetLLVMValue(cu, rl_src1.orig_sreg); - ::llvm::Value* src2 = GetLLVMValue(cu, rl_src2.orig_sreg); - ::llvm::Value* cond_value = ConvertCompare(cu, cc, src1, src2); - cond_value->setName(StringPrintf("t%d", cu->temp_name++)); - cu->irb->CreateCondBr(cond_value, GetLLVMBlock(cu, bb->taken->id), - GetLLVMBlock(cu, bb->fall_through->id)); + ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg); + ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg); + ::llvm::Value* cond_value = ConvertCompare(cc, src1, src2); + cond_value->setName(StringPrintf("t%d", temp_name_++)); + irb_->CreateCondBr(cond_value, GetLLVMBlock(bb->taken->id), + GetLLVMBlock(bb->fall_through->id)); // Don't redo the fallthrough branch in the BB driver bb->fall_through = NULL; } -static void ConvertCompareZeroAndBranch(CompilationUnit* cu, BasicBlock* bb, +void MirConverter::ConvertCompareZeroAndBranch(BasicBlock* bb, MIR* mir, ConditionCode cc, RegLocation rl_src1) { if (bb->taken->start_offset <= mir->offset) { - EmitSuspendCheck(cu); + EmitSuspendCheck(); } - ::llvm::Value* src1 = GetLLVMValue(cu, rl_src1.orig_sreg); + ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg); ::llvm::Value* src2; if (rl_src1.ref) { - src2 = cu->irb->getJNull(); + src2 = irb_->getJNull(); } else { - src2 = cu->irb->getInt32(0); + src2 = irb_->getInt32(0); } - ::llvm::Value* cond_value = ConvertCompare(cu, cc, src1, src2); - cu->irb->CreateCondBr(cond_value, GetLLVMBlock(cu, bb->taken->id), - GetLLVMBlock(cu, bb->fall_through->id)); + ::llvm::Value* cond_value = ConvertCompare(cc, src1, src2); + irb_->CreateCondBr(cond_value, GetLLVMBlock(bb->taken->id), + GetLLVMBlock(bb->fall_through->id)); // Don't redo the fallthrough branch in the BB driver bb->fall_through = NULL; } -static ::llvm::Value* GenDivModOp(CompilationUnit* cu, bool is_div, bool is_long, +::llvm::Value* MirConverter::GenDivModOp(bool is_div, bool is_long, ::llvm::Value* src1, ::llvm::Value* src2) { art::llvm::IntrinsicHelper::IntrinsicId id; @@ -388,93 +385,93 @@ static ::llvm::Value* GenDivModOp(CompilationUnit* cu, bool is_div, bool is_long id = art::llvm::IntrinsicHelper::RemInt; } } - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::SmallVector< ::llvm::Value*, 2>args; args.push_back(src1); args.push_back(src2); - return cu->irb->CreateCall(intr, args); + return irb_->CreateCall(intr, args); } -static ::llvm::Value* GenArithOp(CompilationUnit* cu, OpKind op, bool is_long, +::llvm::Value* MirConverter::GenArithOp(OpKind op, bool is_long, ::llvm::Value* src1, ::llvm::Value* src2) { ::llvm::Value* res = NULL; switch(op) { - case kOpAdd: res = cu->irb->CreateAdd(src1, src2); break; - case kOpSub: res = cu->irb->CreateSub(src1, src2); break; - case kOpRsub: res = cu->irb->CreateSub(src2, src1); break; - case kOpMul: res = cu->irb->CreateMul(src1, src2); break; - case kOpOr: res = cu->irb->CreateOr(src1, src2); break; - case kOpAnd: res = cu->irb->CreateAnd(src1, src2); break; - case kOpXor: res = cu->irb->CreateXor(src1, src2); break; - case kOpDiv: res = GenDivModOp(cu, true, is_long, src1, src2); break; - case kOpRem: res = GenDivModOp(cu, false, is_long, src1, src2); break; - case kOpLsl: res = cu->irb->CreateShl(src1, src2); break; - case kOpLsr: res = cu->irb->CreateLShr(src1, src2); break; - case kOpAsr: res = cu->irb->CreateAShr(src1, src2); break; + case kOpAdd: res = irb_->CreateAdd(src1, src2); break; + case kOpSub: res = irb_->CreateSub(src1, src2); break; + case kOpRsub: res = irb_->CreateSub(src2, src1); break; + case kOpMul: res = irb_->CreateMul(src1, src2); break; + case kOpOr: res = irb_->CreateOr(src1, src2); break; + case kOpAnd: res = irb_->CreateAnd(src1, src2); break; + case kOpXor: res = irb_->CreateXor(src1, src2); break; + case kOpDiv: res = GenDivModOp(true, is_long, src1, src2); break; + case kOpRem: res = GenDivModOp(false, is_long, src1, src2); break; + case kOpLsl: res = irb_->CreateShl(src1, src2); break; + case kOpLsr: res = irb_->CreateLShr(src1, src2); break; + case kOpAsr: res = irb_->CreateAShr(src1, src2); break; default: LOG(FATAL) << "Invalid op " << op; } return res; } -static void ConvertFPArithOp(CompilationUnit* cu, OpKind op, RegLocation rl_dest, +void MirConverter::ConvertFPArithOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { - ::llvm::Value* src1 = GetLLVMValue(cu, rl_src1.orig_sreg); - ::llvm::Value* src2 = GetLLVMValue(cu, rl_src2.orig_sreg); + ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg); + ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg); ::llvm::Value* res = NULL; switch(op) { - case kOpAdd: res = cu->irb->CreateFAdd(src1, src2); break; - case kOpSub: res = cu->irb->CreateFSub(src1, src2); break; - case kOpMul: res = cu->irb->CreateFMul(src1, src2); break; - case kOpDiv: res = cu->irb->CreateFDiv(src1, src2); break; - case kOpRem: res = cu->irb->CreateFRem(src1, src2); break; + case kOpAdd: res = irb_->CreateFAdd(src1, src2); break; + case kOpSub: res = irb_->CreateFSub(src1, src2); break; + case kOpMul: res = irb_->CreateFMul(src1, src2); break; + case kOpDiv: res = irb_->CreateFDiv(src1, src2); break; + case kOpRem: res = irb_->CreateFRem(src1, src2); break; default: LOG(FATAL) << "Invalid op " << op; } - DefineValue(cu, res, rl_dest.orig_sreg); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertShift(CompilationUnit* cu, art::llvm::IntrinsicHelper::IntrinsicId id, +void MirConverter::ConvertShift(art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::SmallVector< ::llvm::Value*, 2>args; - args.push_back(GetLLVMValue(cu, rl_src1.orig_sreg)); - args.push_back(GetLLVMValue(cu, rl_src2.orig_sreg)); - ::llvm::Value* res = cu->irb->CreateCall(intr, args); - DefineValue(cu, res, rl_dest.orig_sreg); + args.push_back(GetLLVMValue(rl_src1.orig_sreg)); + args.push_back(GetLLVMValue(rl_src2.orig_sreg)); + ::llvm::Value* res = irb_->CreateCall(intr, args); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertShiftLit(CompilationUnit* cu, art::llvm::IntrinsicHelper::IntrinsicId id, +void MirConverter::ConvertShiftLit(art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest, RegLocation rl_src, int shift_amount) { - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::SmallVector< ::llvm::Value*, 2>args; - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - args.push_back(cu->irb->getInt32(shift_amount)); - ::llvm::Value* res = cu->irb->CreateCall(intr, args); - DefineValue(cu, res, rl_dest.orig_sreg); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + args.push_back(irb_->getInt32(shift_amount)); + ::llvm::Value* res = irb_->CreateCall(intr, args); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertArithOp(CompilationUnit* cu, OpKind op, RegLocation rl_dest, +void MirConverter::ConvertArithOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { - ::llvm::Value* src1 = GetLLVMValue(cu, rl_src1.orig_sreg); - ::llvm::Value* src2 = GetLLVMValue(cu, rl_src2.orig_sreg); + ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg); + ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg); DCHECK_EQ(src1->getType(), src2->getType()); - ::llvm::Value* res = GenArithOp(cu, op, rl_dest.wide, src1, src2); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* res = GenArithOp(op, rl_dest.wide, src1, src2); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertArithOpLit(CompilationUnit* cu, OpKind op, RegLocation rl_dest, +void MirConverter::ConvertArithOpLit(OpKind op, RegLocation rl_dest, RegLocation rl_src1, int32_t imm) { - ::llvm::Value* src1 = GetLLVMValue(cu, rl_src1.orig_sreg); - ::llvm::Value* src2 = cu->irb->getInt32(imm); - ::llvm::Value* res = GenArithOp(cu, op, rl_dest.wide, src1, src2); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg); + ::llvm::Value* src2 = irb_->getInt32(imm); + ::llvm::Value* res = GenArithOp(op, rl_dest.wide, src1, src2); + DefineValue(res, rl_dest.orig_sreg); } /* @@ -482,21 +479,20 @@ static void ConvertArithOpLit(CompilationUnit* cu, OpKind op, RegLocation rl_des * collect and process arguments for NEW_FILLED_ARRAY and NEW_FILLED_ARRAY_RANGE. * The requirements are similar. */ -static void ConvertInvoke(CompilationUnit* cu, BasicBlock* bb, MIR* mir, +void MirConverter::ConvertInvoke(BasicBlock* bb, MIR* mir, InvokeType invoke_type, bool is_range, bool is_filled_new_array) { - Codegen* cg = cu->cg.get(); - CallInfo* info = cg->NewMemCallInfo(cu, bb, mir, invoke_type, is_range); + CallInfo* info = mir_graph_->NewMemCallInfo(bb, mir, invoke_type, is_range); ::llvm::SmallVector< ::llvm::Value*, 10> args; // Insert the invoke_type - args.push_back(cu->irb->getInt32(static_cast<int>(invoke_type))); + args.push_back(irb_->getInt32(static_cast<int>(invoke_type))); // Insert the method_idx - args.push_back(cu->irb->getInt32(info->index)); + args.push_back(irb_->getInt32(info->index)); // Insert the optimization flags - args.push_back(cu->irb->getInt32(info->opt_flags)); + args.push_back(irb_->getInt32(info->opt_flags)); // Now, insert the actual arguments for (int i = 0; i < info->num_arg_words;) { - ::llvm::Value* val = GetLLVMValue(cu, info->args[i].orig_sreg); + ::llvm::Value* val = GetLLVMValue(info->args[i].orig_sreg); args.push_back(val); i += info->args[i].wide ? 2 : 1; } @@ -525,215 +521,214 @@ static void ConvertInvoke(CompilationUnit* cu, BasicBlock* bb, MIR* mir, id = art::llvm::IntrinsicHelper::HLInvokeInt; } } - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Value* res = cu->irb->CreateCall(intr, args); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Value* res = irb_->CreateCall(intr, args); if (info->result.location != kLocInvalid) { - DefineValue(cu, res, info->result.orig_sreg); + DefineValue(res, info->result.orig_sreg); } } -static void ConvertConstObject(CompilationUnit* cu, uint32_t idx, +void MirConverter::ConvertConstObject(uint32_t idx, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest) { - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Value* index = cu->irb->getInt32(idx); - ::llvm::Value* res = cu->irb->CreateCall(intr, index); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Value* index = irb_->getInt32(idx); + ::llvm::Value* res = irb_->CreateCall(intr, index); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertCheckCast(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_src) +void MirConverter::ConvertCheckCast(uint32_t type_idx, RegLocation rl_src) { art::llvm::IntrinsicHelper::IntrinsicId id; id = art::llvm::IntrinsicHelper::HLCheckCast; - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::SmallVector< ::llvm::Value*, 2> args; - args.push_back(cu->irb->getInt32(type_idx)); - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - cu->irb->CreateCall(intr, args); + args.push_back(irb_->getInt32(type_idx)); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + irb_->CreateCall(intr, args); } -static void ConvertNewInstance(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest) +void MirConverter::ConvertNewInstance(uint32_t type_idx, RegLocation rl_dest) { art::llvm::IntrinsicHelper::IntrinsicId id; id = art::llvm::IntrinsicHelper::NewInstance; - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Value* index = cu->irb->getInt32(type_idx); - ::llvm::Value* res = cu->irb->CreateCall(intr, index); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Value* index = irb_->getInt32(type_idx); + ::llvm::Value* res = irb_->CreateCall(intr, index); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertNewArray(CompilationUnit* cu, uint32_t type_idx, +void MirConverter::ConvertNewArray(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src) { art::llvm::IntrinsicHelper::IntrinsicId id; id = art::llvm::IntrinsicHelper::NewArray; - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::SmallVector< ::llvm::Value*, 2> args; - args.push_back(cu->irb->getInt32(type_idx)); - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - ::llvm::Value* res = cu->irb->CreateCall(intr, args); - DefineValue(cu, res, rl_dest.orig_sreg); + args.push_back(irb_->getInt32(type_idx)); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + ::llvm::Value* res = irb_->CreateCall(intr, args); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertAget(CompilationUnit* cu, int opt_flags, +void MirConverter::ConvertAget(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest, RegLocation rl_array, RegLocation rl_index) { ::llvm::SmallVector< ::llvm::Value*, 3> args; - args.push_back(cu->irb->getInt32(opt_flags)); - args.push_back(GetLLVMValue(cu, rl_array.orig_sreg)); - args.push_back(GetLLVMValue(cu, rl_index.orig_sreg)); - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Value* res = cu->irb->CreateCall(intr, args); - DefineValue(cu, res, rl_dest.orig_sreg); + args.push_back(irb_->getInt32(opt_flags)); + args.push_back(GetLLVMValue(rl_array.orig_sreg)); + args.push_back(GetLLVMValue(rl_index.orig_sreg)); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Value* res = irb_->CreateCall(intr, args); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertAput(CompilationUnit* cu, int opt_flags, +void MirConverter::ConvertAput(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src, RegLocation rl_array, RegLocation rl_index) { ::llvm::SmallVector< ::llvm::Value*, 4> args; - args.push_back(cu->irb->getInt32(opt_flags)); - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - args.push_back(GetLLVMValue(cu, rl_array.orig_sreg)); - args.push_back(GetLLVMValue(cu, rl_index.orig_sreg)); - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - cu->irb->CreateCall(intr, args); + args.push_back(irb_->getInt32(opt_flags)); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + args.push_back(GetLLVMValue(rl_array.orig_sreg)); + args.push_back(GetLLVMValue(rl_index.orig_sreg)); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + irb_->CreateCall(intr, args); } -static void ConvertIget(CompilationUnit* cu, int opt_flags, +void MirConverter::ConvertIget(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest, RegLocation rl_obj, int field_index) { ::llvm::SmallVector< ::llvm::Value*, 3> args; - args.push_back(cu->irb->getInt32(opt_flags)); - args.push_back(GetLLVMValue(cu, rl_obj.orig_sreg)); - args.push_back(cu->irb->getInt32(field_index)); - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Value* res = cu->irb->CreateCall(intr, args); - DefineValue(cu, res, rl_dest.orig_sreg); + args.push_back(irb_->getInt32(opt_flags)); + args.push_back(GetLLVMValue(rl_obj.orig_sreg)); + args.push_back(irb_->getInt32(field_index)); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Value* res = irb_->CreateCall(intr, args); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertIput(CompilationUnit* cu, int opt_flags, +void MirConverter::ConvertIput(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src, RegLocation rl_obj, int field_index) { ::llvm::SmallVector< ::llvm::Value*, 4> args; - args.push_back(cu->irb->getInt32(opt_flags)); - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - args.push_back(GetLLVMValue(cu, rl_obj.orig_sreg)); - args.push_back(cu->irb->getInt32(field_index)); - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - cu->irb->CreateCall(intr, args); + args.push_back(irb_->getInt32(opt_flags)); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + args.push_back(GetLLVMValue(rl_obj.orig_sreg)); + args.push_back(irb_->getInt32(field_index)); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + irb_->CreateCall(intr, args); } -static void ConvertInstanceOf(CompilationUnit* cu, uint32_t type_idx, +void MirConverter::ConvertInstanceOf(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src) { art::llvm::IntrinsicHelper::IntrinsicId id; id = art::llvm::IntrinsicHelper::InstanceOf; - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::SmallVector< ::llvm::Value*, 2> args; - args.push_back(cu->irb->getInt32(type_idx)); - args.push_back(GetLLVMValue(cu, rl_src.orig_sreg)); - ::llvm::Value* res = cu->irb->CreateCall(intr, args); - DefineValue(cu, res, rl_dest.orig_sreg); + args.push_back(irb_->getInt32(type_idx)); + args.push_back(GetLLVMValue(rl_src.orig_sreg)); + ::llvm::Value* res = irb_->CreateCall(intr, args); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertIntToLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void MirConverter::ConvertIntToLong(RegLocation rl_dest, RegLocation rl_src) { - ::llvm::Value* res = cu->irb->CreateSExt(GetLLVMValue(cu, rl_src.orig_sreg), - cu->irb->getInt64Ty()); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* res = irb_->CreateSExt(GetLLVMValue(rl_src.orig_sreg), + irb_->getInt64Ty()); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertLongToInt(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void MirConverter::ConvertLongToInt(RegLocation rl_dest, RegLocation rl_src) { - ::llvm::Value* src = GetLLVMValue(cu, rl_src.orig_sreg); - ::llvm::Value* res = cu->irb->CreateTrunc(src, cu->irb->getInt32Ty()); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg); + ::llvm::Value* res = irb_->CreateTrunc(src, irb_->getInt32Ty()); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertFloatToDouble(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void MirConverter::ConvertFloatToDouble(RegLocation rl_dest, RegLocation rl_src) { - ::llvm::Value* src = GetLLVMValue(cu, rl_src.orig_sreg); - ::llvm::Value* res = cu->irb->CreateFPExt(src, cu->irb->getDoubleTy()); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg); + ::llvm::Value* res = irb_->CreateFPExt(src, irb_->getDoubleTy()); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertDoubleToFloat(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void MirConverter::ConvertDoubleToFloat(RegLocation rl_dest, RegLocation rl_src) { - ::llvm::Value* src = GetLLVMValue(cu, rl_src.orig_sreg); - ::llvm::Value* res = cu->irb->CreateFPTrunc(src, cu->irb->getFloatTy()); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg); + ::llvm::Value* res = irb_->CreateFPTrunc(src, irb_->getFloatTy()); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertWideComparison(CompilationUnit* cu, - art::llvm::IntrinsicHelper::IntrinsicId id, - RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) +void MirConverter::ConvertWideComparison(art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) { DCHECK_EQ(rl_src1.fp, rl_src2.fp); DCHECK_EQ(rl_src1.wide, rl_src2.wide); - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::SmallVector< ::llvm::Value*, 2> args; - args.push_back(GetLLVMValue(cu, rl_src1.orig_sreg)); - args.push_back(GetLLVMValue(cu, rl_src2.orig_sreg)); - ::llvm::Value* res = cu->irb->CreateCall(intr, args); - DefineValue(cu, res, rl_dest.orig_sreg); + args.push_back(GetLLVMValue(rl_src1.orig_sreg)); + args.push_back(GetLLVMValue(rl_src2.orig_sreg)); + ::llvm::Value* res = irb_->CreateCall(intr, args); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertIntNarrowing(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src, +void MirConverter::ConvertIntNarrowing(RegLocation rl_dest, RegLocation rl_src, art::llvm::IntrinsicHelper::IntrinsicId id) { - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::Value* res = - cu->irb->CreateCall(intr, GetLLVMValue(cu, rl_src.orig_sreg)); - DefineValue(cu, res, rl_dest.orig_sreg); + irb_->CreateCall(intr, GetLLVMValue(rl_src.orig_sreg)); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertNeg(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void MirConverter::ConvertNeg(RegLocation rl_dest, RegLocation rl_src) { - ::llvm::Value* res = cu->irb->CreateNeg(GetLLVMValue(cu, rl_src.orig_sreg)); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* res = irb_->CreateNeg(GetLLVMValue(rl_src.orig_sreg)); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertIntToFP(CompilationUnit* cu, ::llvm::Type* ty, RegLocation rl_dest, +void MirConverter::ConvertIntToFP(::llvm::Type* ty, RegLocation rl_dest, RegLocation rl_src) { ::llvm::Value* res = - cu->irb->CreateSIToFP(GetLLVMValue(cu, rl_src.orig_sreg), ty); - DefineValue(cu, res, rl_dest.orig_sreg); + irb_->CreateSIToFP(GetLLVMValue(rl_src.orig_sreg), ty); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertFPToInt(CompilationUnit* cu, art::llvm::IntrinsicHelper::IntrinsicId id, +void MirConverter::ConvertFPToInt(art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest, RegLocation rl_src) { - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Value* res = cu->irb->CreateCall(intr, GetLLVMValue(cu, rl_src.orig_sreg)); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Value* res = irb_->CreateCall(intr, GetLLVMValue(rl_src.orig_sreg)); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertNegFP(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void MirConverter::ConvertNegFP(RegLocation rl_dest, RegLocation rl_src) { ::llvm::Value* res = - cu->irb->CreateFNeg(GetLLVMValue(cu, rl_src.orig_sreg)); - DefineValue(cu, res, rl_dest.orig_sreg); + irb_->CreateFNeg(GetLLVMValue(rl_src.orig_sreg)); + DefineValue(res, rl_dest.orig_sreg); } -static void ConvertNot(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void MirConverter::ConvertNot(RegLocation rl_dest, RegLocation rl_src) { - ::llvm::Value* src = GetLLVMValue(cu, rl_src.orig_sreg); - ::llvm::Value* res = cu->irb->CreateXor(src, static_cast<uint64_t>(-1)); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg); + ::llvm::Value* res = irb_->CreateXor(src, static_cast<uint64_t>(-1)); + DefineValue(res, rl_dest.orig_sreg); } -static void EmitConstructorBarrier(CompilationUnit* cu) { - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction( +void MirConverter::EmitConstructorBarrier() { + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction( art::llvm::IntrinsicHelper::ConstructorBarrier); - cu->irb->CreateCall(intr); + irb_->CreateCall(intr); } /* @@ -741,61 +736,61 @@ static void EmitConstructorBarrier(CompilationUnit* cu) { * load/store utilities here, or target-dependent genXX() handlers * when necessary. */ -static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, +bool MirConverter::ConvertMIRNode(MIR* mir, BasicBlock* bb, ::llvm::BasicBlock* llvm_bb) { bool res = false; // Assume success RegLocation rl_src[3]; - RegLocation rl_dest = GetBadLoc(); + RegLocation rl_dest = mir_graph_->GetBadLoc(); Instruction::Code opcode = mir->dalvikInsn.opcode; int op_val = opcode; uint32_t vB = mir->dalvikInsn.vB; uint32_t vC = mir->dalvikInsn.vC; int opt_flags = mir->optimization_flags; - if (cu->verbose) { + if (cu_->verbose) { if (op_val < kMirOpFirst) { LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x" << std::hex << op_val; } else { - LOG(INFO) << extended_mir_op_names[op_val - kMirOpFirst] << " 0x" << std::hex << op_val; + LOG(INFO) << mir_graph_->extended_mir_op_names_[op_val - kMirOpFirst] << " 0x" << std::hex << op_val; } } /* Prep Src and Dest locations */ int next_sreg = 0; int next_loc = 0; - int attrs = oat_data_flow_attributes[opcode]; - rl_src[0] = rl_src[1] = rl_src[2] = GetBadLoc(); + int attrs = mir_graph_->oat_data_flow_attributes_[opcode]; + rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc(); if (attrs & DF_UA) { if (attrs & DF_A_WIDE) { - rl_src[next_loc++] = GetSrcWide(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); next_sreg+= 2; } else { - rl_src[next_loc++] = GetSrc(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); next_sreg++; } } if (attrs & DF_UB) { if (attrs & DF_B_WIDE) { - rl_src[next_loc++] = GetSrcWide(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); next_sreg+= 2; } else { - rl_src[next_loc++] = GetSrc(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); next_sreg++; } } if (attrs & DF_UC) { if (attrs & DF_C_WIDE) { - rl_src[next_loc++] = GetSrcWide(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); } else { - rl_src[next_loc++] = GetSrc(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); } } if (attrs & DF_DA) { if (attrs & DF_A_WIDE) { - rl_dest = GetDestWide(cu, mir); + rl_dest = mir_graph_->GetDestWide(mir); } else { - rl_dest = GetDest(cu, mir); + rl_dest = mir_graph_->GetDest(mir); } } @@ -819,18 +814,18 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, * Insert a dummy intrinsic copy call, which will be recognized * by the quick path and removed by the portable path. */ - ::llvm::Value* src = GetLLVMValue(cu, rl_src[0].orig_sreg); - ::llvm::Value* res = EmitCopy(cu, src, rl_dest); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Value* src = GetLLVMValue(rl_src[0].orig_sreg); + ::llvm::Value* res = EmitCopy(src, rl_dest); + DefineValue(res, rl_dest.orig_sreg); } break; case Instruction::CONST: case Instruction::CONST_4: case Instruction::CONST_16: { - ::llvm::Constant* imm_value = cu->irb->getJInt(vB); - ::llvm::Value* res = EmitConst(cu, imm_value, rl_dest); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Constant* imm_value = irb_->getJInt(vB); + ::llvm::Value* res = EmitConst(imm_value, rl_dest); + DefineValue(res, rl_dest.orig_sreg); } break; @@ -838,172 +833,172 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, case Instruction::CONST_WIDE_32: { // Sign extend to 64 bits int64_t imm = static_cast<int32_t>(vB); - ::llvm::Constant* imm_value = cu->irb->getJLong(imm); - ::llvm::Value* res = EmitConst(cu, imm_value, rl_dest); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Constant* imm_value = irb_->getJLong(imm); + ::llvm::Value* res = EmitConst(imm_value, rl_dest); + DefineValue(res, rl_dest.orig_sreg); } break; case Instruction::CONST_HIGH16: { - ::llvm::Constant* imm_value = cu->irb->getJInt(vB << 16); - ::llvm::Value* res = EmitConst(cu, imm_value, rl_dest); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Constant* imm_value = irb_->getJInt(vB << 16); + ::llvm::Value* res = EmitConst(imm_value, rl_dest); + DefineValue(res, rl_dest.orig_sreg); } break; case Instruction::CONST_WIDE: { ::llvm::Constant* imm_value = - cu->irb->getJLong(mir->dalvikInsn.vB_wide); - ::llvm::Value* res = EmitConst(cu, imm_value, rl_dest); - DefineValue(cu, res, rl_dest.orig_sreg); + irb_->getJLong(mir->dalvikInsn.vB_wide); + ::llvm::Value* res = EmitConst(imm_value, rl_dest); + DefineValue(res, rl_dest.orig_sreg); } break; case Instruction::CONST_WIDE_HIGH16: { int64_t imm = static_cast<int64_t>(vB) << 48; - ::llvm::Constant* imm_value = cu->irb->getJLong(imm); - ::llvm::Value* res = EmitConst(cu, imm_value, rl_dest); - DefineValue(cu, res, rl_dest.orig_sreg); + ::llvm::Constant* imm_value = irb_->getJLong(imm); + ::llvm::Value* res = EmitConst(imm_value, rl_dest); + DefineValue(res, rl_dest.orig_sreg); } break; case Instruction::SPUT_OBJECT: - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSputObject, + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputObject, rl_src[0]); break; case Instruction::SPUT: if (rl_src[0].fp) { - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSputFloat, + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputFloat, rl_src[0]); } else { - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSput, rl_src[0]); + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSput, rl_src[0]); } break; case Instruction::SPUT_BOOLEAN: - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSputBoolean, + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputBoolean, rl_src[0]); break; case Instruction::SPUT_BYTE: - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSputByte, rl_src[0]); + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputByte, rl_src[0]); break; case Instruction::SPUT_CHAR: - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSputChar, rl_src[0]); + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputChar, rl_src[0]); break; case Instruction::SPUT_SHORT: - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSputShort, rl_src[0]); + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputShort, rl_src[0]); break; case Instruction::SPUT_WIDE: if (rl_src[0].fp) { - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSputDouble, + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputDouble, rl_src[0]); } else { - ConvertSput(cu, vB, art::llvm::IntrinsicHelper::HLSputWide, + ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputWide, rl_src[0]); } break; case Instruction::SGET_OBJECT: - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSgetObject, rl_dest); + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetObject, rl_dest); break; case Instruction::SGET: if (rl_dest.fp) { - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSgetFloat, rl_dest); + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetFloat, rl_dest); } else { - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSget, rl_dest); + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSget, rl_dest); } break; case Instruction::SGET_BOOLEAN: - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSgetBoolean, rl_dest); + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetBoolean, rl_dest); break; case Instruction::SGET_BYTE: - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSgetByte, rl_dest); + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetByte, rl_dest); break; case Instruction::SGET_CHAR: - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSgetChar, rl_dest); + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetChar, rl_dest); break; case Instruction::SGET_SHORT: - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSgetShort, rl_dest); + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetShort, rl_dest); break; case Instruction::SGET_WIDE: if (rl_dest.fp) { - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSgetDouble, + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetDouble, rl_dest); } else { - ConvertSget(cu, vB, art::llvm::IntrinsicHelper::HLSgetWide, rl_dest); + ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetWide, rl_dest); } break; case Instruction::RETURN_WIDE: case Instruction::RETURN: case Instruction::RETURN_OBJECT: { - if (!(cu->attributes & METHOD_IS_LEAF)) { - EmitSuspendCheck(cu); + if (!mir_graph_->MethodIsLeaf()) { + EmitSuspendCheck(); } - EmitPopShadowFrame(cu); - cu->irb->CreateRet(GetLLVMValue(cu, rl_src[0].orig_sreg)); + EmitPopShadowFrame(); + irb_->CreateRet(GetLLVMValue(rl_src[0].orig_sreg)); DCHECK(bb->terminated_by_return); } break; case Instruction::RETURN_VOID: { - if (((cu->access_flags & kAccConstructor) != 0) && - cu->compiler_driver->RequiresConstructorBarrier(Thread::Current(), - cu->dex_file, - cu->class_def_idx)) { - EmitConstructorBarrier(cu); + if (((cu_->access_flags & kAccConstructor) != 0) && + cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), + cu_->dex_file, + cu_->class_def_idx)) { + EmitConstructorBarrier(); } - if (!(cu->attributes & METHOD_IS_LEAF)) { - EmitSuspendCheck(cu); + if (!mir_graph_->MethodIsLeaf()) { + EmitSuspendCheck(); } - EmitPopShadowFrame(cu); - cu->irb->CreateRetVoid(); + EmitPopShadowFrame(); + irb_->CreateRetVoid(); DCHECK(bb->terminated_by_return); } break; case Instruction::IF_EQ: - ConvertCompareAndBranch(cu, bb, mir, kCondEq, rl_src[0], rl_src[1]); + ConvertCompareAndBranch(bb, mir, kCondEq, rl_src[0], rl_src[1]); break; case Instruction::IF_NE: - ConvertCompareAndBranch(cu, bb, mir, kCondNe, rl_src[0], rl_src[1]); + ConvertCompareAndBranch(bb, mir, kCondNe, rl_src[0], rl_src[1]); break; case Instruction::IF_LT: - ConvertCompareAndBranch(cu, bb, mir, kCondLt, rl_src[0], rl_src[1]); + ConvertCompareAndBranch(bb, mir, kCondLt, rl_src[0], rl_src[1]); break; case Instruction::IF_GE: - ConvertCompareAndBranch(cu, bb, mir, kCondGe, rl_src[0], rl_src[1]); + ConvertCompareAndBranch(bb, mir, kCondGe, rl_src[0], rl_src[1]); break; case Instruction::IF_GT: - ConvertCompareAndBranch(cu, bb, mir, kCondGt, rl_src[0], rl_src[1]); + ConvertCompareAndBranch(bb, mir, kCondGt, rl_src[0], rl_src[1]); break; case Instruction::IF_LE: - ConvertCompareAndBranch(cu, bb, mir, kCondLe, rl_src[0], rl_src[1]); + ConvertCompareAndBranch(bb, mir, kCondLe, rl_src[0], rl_src[1]); break; case Instruction::IF_EQZ: - ConvertCompareZeroAndBranch(cu, bb, mir, kCondEq, rl_src[0]); + ConvertCompareZeroAndBranch(bb, mir, kCondEq, rl_src[0]); break; case Instruction::IF_NEZ: - ConvertCompareZeroAndBranch(cu, bb, mir, kCondNe, rl_src[0]); + ConvertCompareZeroAndBranch(bb, mir, kCondNe, rl_src[0]); break; case Instruction::IF_LTZ: - ConvertCompareZeroAndBranch(cu, bb, mir, kCondLt, rl_src[0]); + ConvertCompareZeroAndBranch(bb, mir, kCondLt, rl_src[0]); break; case Instruction::IF_GEZ: - ConvertCompareZeroAndBranch(cu, bb, mir, kCondGe, rl_src[0]); + ConvertCompareZeroAndBranch(bb, mir, kCondGe, rl_src[0]); break; case Instruction::IF_GTZ: - ConvertCompareZeroAndBranch(cu, bb, mir, kCondGt, rl_src[0]); + ConvertCompareZeroAndBranch(bb, mir, kCondGt, rl_src[0]); break; case Instruction::IF_LEZ: - ConvertCompareZeroAndBranch(cu, bb, mir, kCondLe, rl_src[0]); + ConvertCompareZeroAndBranch(bb, mir, kCondLe, rl_src[0]); break; case Instruction::GOTO: case Instruction::GOTO_16: case Instruction::GOTO_32: { if (bb->taken->start_offset <= bb->start_offset) { - EmitSuspendCheck(cu); + EmitSuspendCheck(); } - cu->irb->CreateBr(GetLLVMBlock(cu, bb->taken->id)); + irb_->CreateBr(GetLLVMBlock(bb->taken->id)); } break; @@ -1011,123 +1006,123 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, case Instruction::ADD_LONG_2ADDR: case Instruction::ADD_INT: case Instruction::ADD_INT_2ADDR: - ConvertArithOp(cu, kOpAdd, rl_dest, rl_src[0], rl_src[1]); + ConvertArithOp(kOpAdd, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::SUB_LONG: case Instruction::SUB_LONG_2ADDR: case Instruction::SUB_INT: case Instruction::SUB_INT_2ADDR: - ConvertArithOp(cu, kOpSub, rl_dest, rl_src[0], rl_src[1]); + ConvertArithOp(kOpSub, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::MUL_LONG: case Instruction::MUL_LONG_2ADDR: case Instruction::MUL_INT: case Instruction::MUL_INT_2ADDR: - ConvertArithOp(cu, kOpMul, rl_dest, rl_src[0], rl_src[1]); + ConvertArithOp(kOpMul, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::DIV_LONG: case Instruction::DIV_LONG_2ADDR: case Instruction::DIV_INT: case Instruction::DIV_INT_2ADDR: - ConvertArithOp(cu, kOpDiv, rl_dest, rl_src[0], rl_src[1]); + ConvertArithOp(kOpDiv, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::REM_LONG: case Instruction::REM_LONG_2ADDR: case Instruction::REM_INT: case Instruction::REM_INT_2ADDR: - ConvertArithOp(cu, kOpRem, rl_dest, rl_src[0], rl_src[1]); + ConvertArithOp(kOpRem, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::AND_LONG: case Instruction::AND_LONG_2ADDR: case Instruction::AND_INT: case Instruction::AND_INT_2ADDR: - ConvertArithOp(cu, kOpAnd, rl_dest, rl_src[0], rl_src[1]); + ConvertArithOp(kOpAnd, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::OR_LONG: case Instruction::OR_LONG_2ADDR: case Instruction::OR_INT: case Instruction::OR_INT_2ADDR: - ConvertArithOp(cu, kOpOr, rl_dest, rl_src[0], rl_src[1]); + ConvertArithOp(kOpOr, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::XOR_LONG: case Instruction::XOR_LONG_2ADDR: case Instruction::XOR_INT: case Instruction::XOR_INT_2ADDR: - ConvertArithOp(cu, kOpXor, rl_dest, rl_src[0], rl_src[1]); + ConvertArithOp(kOpXor, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::SHL_LONG: case Instruction::SHL_LONG_2ADDR: - ConvertShift(cu, art::llvm::IntrinsicHelper::SHLLong, + ConvertShift(art::llvm::IntrinsicHelper::SHLLong, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::SHL_INT: case Instruction::SHL_INT_2ADDR: - ConvertShift(cu, art::llvm::IntrinsicHelper::SHLInt, + ConvertShift(art::llvm::IntrinsicHelper::SHLInt, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::SHR_LONG: case Instruction::SHR_LONG_2ADDR: - ConvertShift(cu, art::llvm::IntrinsicHelper::SHRLong, + ConvertShift(art::llvm::IntrinsicHelper::SHRLong, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::SHR_INT: case Instruction::SHR_INT_2ADDR: - ConvertShift(cu, art::llvm::IntrinsicHelper::SHRInt, + ConvertShift(art::llvm::IntrinsicHelper::SHRInt, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::USHR_LONG: case Instruction::USHR_LONG_2ADDR: - ConvertShift(cu, art::llvm::IntrinsicHelper::USHRLong, + ConvertShift(art::llvm::IntrinsicHelper::USHRLong, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::USHR_INT: case Instruction::USHR_INT_2ADDR: - ConvertShift(cu, art::llvm::IntrinsicHelper::USHRInt, + ConvertShift(art::llvm::IntrinsicHelper::USHRInt, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::ADD_INT_LIT16: case Instruction::ADD_INT_LIT8: - ConvertArithOpLit(cu, kOpAdd, rl_dest, rl_src[0], vC); + ConvertArithOpLit(kOpAdd, rl_dest, rl_src[0], vC); break; case Instruction::RSUB_INT: case Instruction::RSUB_INT_LIT8: - ConvertArithOpLit(cu, kOpRsub, rl_dest, rl_src[0], vC); + ConvertArithOpLit(kOpRsub, rl_dest, rl_src[0], vC); break; case Instruction::MUL_INT_LIT16: case Instruction::MUL_INT_LIT8: - ConvertArithOpLit(cu, kOpMul, rl_dest, rl_src[0], vC); + ConvertArithOpLit(kOpMul, rl_dest, rl_src[0], vC); break; case Instruction::DIV_INT_LIT16: case Instruction::DIV_INT_LIT8: - ConvertArithOpLit(cu, kOpDiv, rl_dest, rl_src[0], vC); + ConvertArithOpLit(kOpDiv, rl_dest, rl_src[0], vC); break; case Instruction::REM_INT_LIT16: case Instruction::REM_INT_LIT8: - ConvertArithOpLit(cu, kOpRem, rl_dest, rl_src[0], vC); + ConvertArithOpLit(kOpRem, rl_dest, rl_src[0], vC); break; case Instruction::AND_INT_LIT16: case Instruction::AND_INT_LIT8: - ConvertArithOpLit(cu, kOpAnd, rl_dest, rl_src[0], vC); + ConvertArithOpLit(kOpAnd, rl_dest, rl_src[0], vC); break; case Instruction::OR_INT_LIT16: case Instruction::OR_INT_LIT8: - ConvertArithOpLit(cu, kOpOr, rl_dest, rl_src[0], vC); + ConvertArithOpLit(kOpOr, rl_dest, rl_src[0], vC); break; case Instruction::XOR_INT_LIT16: case Instruction::XOR_INT_LIT8: - ConvertArithOpLit(cu, kOpXor, rl_dest, rl_src[0], vC); + ConvertArithOpLit(kOpXor, rl_dest, rl_src[0], vC); break; case Instruction::SHL_INT_LIT8: - ConvertShiftLit(cu, art::llvm::IntrinsicHelper::SHLInt, + ConvertShiftLit(art::llvm::IntrinsicHelper::SHLInt, rl_dest, rl_src[0], vC & 0x1f); break; case Instruction::SHR_INT_LIT8: - ConvertShiftLit(cu, art::llvm::IntrinsicHelper::SHRInt, + ConvertShiftLit(art::llvm::IntrinsicHelper::SHRInt, rl_dest, rl_src[0], vC & 0x1f); break; case Instruction::USHR_INT_LIT8: - ConvertShiftLit(cu, art::llvm::IntrinsicHelper::USHRInt, + ConvertShiftLit(art::llvm::IntrinsicHelper::USHRInt, rl_dest, rl_src[0], vC & 0x1f); break; @@ -1135,122 +1130,122 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, case Instruction::ADD_FLOAT_2ADDR: case Instruction::ADD_DOUBLE: case Instruction::ADD_DOUBLE_2ADDR: - ConvertFPArithOp(cu, kOpAdd, rl_dest, rl_src[0], rl_src[1]); + ConvertFPArithOp(kOpAdd, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::SUB_FLOAT: case Instruction::SUB_FLOAT_2ADDR: case Instruction::SUB_DOUBLE: case Instruction::SUB_DOUBLE_2ADDR: - ConvertFPArithOp(cu, kOpSub, rl_dest, rl_src[0], rl_src[1]); + ConvertFPArithOp(kOpSub, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::MUL_FLOAT: case Instruction::MUL_FLOAT_2ADDR: case Instruction::MUL_DOUBLE: case Instruction::MUL_DOUBLE_2ADDR: - ConvertFPArithOp(cu, kOpMul, rl_dest, rl_src[0], rl_src[1]); + ConvertFPArithOp(kOpMul, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::DIV_FLOAT: case Instruction::DIV_FLOAT_2ADDR: case Instruction::DIV_DOUBLE: case Instruction::DIV_DOUBLE_2ADDR: - ConvertFPArithOp(cu, kOpDiv, rl_dest, rl_src[0], rl_src[1]); + ConvertFPArithOp(kOpDiv, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::REM_FLOAT: case Instruction::REM_FLOAT_2ADDR: case Instruction::REM_DOUBLE: case Instruction::REM_DOUBLE_2ADDR: - ConvertFPArithOp(cu, kOpRem, rl_dest, rl_src[0], rl_src[1]); + ConvertFPArithOp(kOpRem, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::INVOKE_STATIC: - ConvertInvoke(cu, bb, mir, kStatic, false /*range*/, + ConvertInvoke(bb, mir, kStatic, false /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_STATIC_RANGE: - ConvertInvoke(cu, bb, mir, kStatic, true /*range*/, + ConvertInvoke(bb, mir, kStatic, true /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_DIRECT: - ConvertInvoke(cu, bb, mir, kDirect, false /*range*/, + ConvertInvoke(bb, mir, kDirect, false /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_DIRECT_RANGE: - ConvertInvoke(cu, bb, mir, kDirect, true /*range*/, + ConvertInvoke(bb, mir, kDirect, true /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_VIRTUAL: - ConvertInvoke(cu, bb, mir, kVirtual, false /*range*/, + ConvertInvoke(bb, mir, kVirtual, false /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_VIRTUAL_RANGE: - ConvertInvoke(cu, bb, mir, kVirtual, true /*range*/, + ConvertInvoke(bb, mir, kVirtual, true /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_SUPER: - ConvertInvoke(cu, bb, mir, kSuper, false /*range*/, + ConvertInvoke(bb, mir, kSuper, false /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_SUPER_RANGE: - ConvertInvoke(cu, bb, mir, kSuper, true /*range*/, + ConvertInvoke(bb, mir, kSuper, true /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_INTERFACE: - ConvertInvoke(cu, bb, mir, kInterface, false /*range*/, + ConvertInvoke(bb, mir, kInterface, false /*range*/, false /* NewFilledArray */); break; case Instruction::INVOKE_INTERFACE_RANGE: - ConvertInvoke(cu, bb, mir, kInterface, true /*range*/, + ConvertInvoke(bb, mir, kInterface, true /*range*/, false /* NewFilledArray */); break; case Instruction::FILLED_NEW_ARRAY: - ConvertInvoke(cu, bb, mir, kInterface, false /*range*/, + ConvertInvoke(bb, mir, kInterface, false /*range*/, true /* NewFilledArray */); break; case Instruction::FILLED_NEW_ARRAY_RANGE: - ConvertInvoke(cu, bb, mir, kInterface, true /*range*/, + ConvertInvoke(bb, mir, kInterface, true /*range*/, true /* NewFilledArray */); break; case Instruction::CONST_STRING: case Instruction::CONST_STRING_JUMBO: - ConvertConstObject(cu, vB, art::llvm::IntrinsicHelper::ConstString, + ConvertConstObject(vB, art::llvm::IntrinsicHelper::ConstString, rl_dest); break; case Instruction::CONST_CLASS: - ConvertConstObject(cu, vB, art::llvm::IntrinsicHelper::ConstClass, + ConvertConstObject(vB, art::llvm::IntrinsicHelper::ConstClass, rl_dest); break; case Instruction::CHECK_CAST: - ConvertCheckCast(cu, vB, rl_src[0]); + ConvertCheckCast(vB, rl_src[0]); break; case Instruction::NEW_INSTANCE: - ConvertNewInstance(cu, vB, rl_dest); + ConvertNewInstance(vB, rl_dest); break; case Instruction::MOVE_EXCEPTION: - ConvertMoveException(cu, rl_dest); + ConvertMoveException(rl_dest); break; case Instruction::THROW: - ConvertThrow(cu, rl_src[0]); + ConvertThrow(rl_src[0]); /* * If this throw is standalone, terminate. * If it might rethrow, force termination * of the following block. */ if (bb->fall_through == NULL) { - cu->irb->CreateUnreachable(); + irb_->CreateUnreachable(); } else { bb->fall_through->fall_through = NULL; bb->fall_through->taken = NULL; @@ -1267,291 +1262,291 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, break; case Instruction::MONITOR_ENTER: - ConvertMonitorEnterExit(cu, opt_flags, + ConvertMonitorEnterExit(opt_flags, art::llvm::IntrinsicHelper::MonitorEnter, rl_src[0]); break; case Instruction::MONITOR_EXIT: - ConvertMonitorEnterExit(cu, opt_flags, + ConvertMonitorEnterExit(opt_flags, art::llvm::IntrinsicHelper::MonitorExit, rl_src[0]); break; case Instruction::ARRAY_LENGTH: - ConvertArrayLength(cu, opt_flags, rl_dest, rl_src[0]); + ConvertArrayLength(opt_flags, rl_dest, rl_src[0]); break; case Instruction::NEW_ARRAY: - ConvertNewArray(cu, vC, rl_dest, rl_src[0]); + ConvertNewArray(vC, rl_dest, rl_src[0]); break; case Instruction::INSTANCE_OF: - ConvertInstanceOf(cu, vC, rl_dest, rl_src[0]); + ConvertInstanceOf(vC, rl_dest, rl_src[0]); break; case Instruction::AGET: if (rl_dest.fp) { - ConvertAget(cu, opt_flags, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetFloat, rl_dest, rl_src[0], rl_src[1]); } else { - ConvertAget(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayGet, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGet, rl_dest, rl_src[0], rl_src[1]); } break; case Instruction::AGET_OBJECT: - ConvertAget(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayGetObject, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetObject, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::AGET_BOOLEAN: - ConvertAget(cu, opt_flags, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetBoolean, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::AGET_BYTE: - ConvertAget(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayGetByte, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetByte, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::AGET_CHAR: - ConvertAget(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayGetChar, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetChar, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::AGET_SHORT: - ConvertAget(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayGetShort, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetShort, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::AGET_WIDE: if (rl_dest.fp) { - ConvertAget(cu, opt_flags, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetDouble, rl_dest, rl_src[0], rl_src[1]); } else { - ConvertAget(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayGetWide, + ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetWide, rl_dest, rl_src[0], rl_src[1]); } break; case Instruction::APUT: if (rl_src[0].fp) { - ConvertAput(cu, opt_flags, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutFloat, rl_src[0], rl_src[1], rl_src[2]); } else { - ConvertAput(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayPut, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPut, rl_src[0], rl_src[1], rl_src[2]); } break; case Instruction::APUT_OBJECT: - ConvertAput(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayPutObject, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutObject, rl_src[0], rl_src[1], rl_src[2]); break; case Instruction::APUT_BOOLEAN: - ConvertAput(cu, opt_flags, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutBoolean, rl_src[0], rl_src[1], rl_src[2]); break; case Instruction::APUT_BYTE: - ConvertAput(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayPutByte, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutByte, rl_src[0], rl_src[1], rl_src[2]); break; case Instruction::APUT_CHAR: - ConvertAput(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayPutChar, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutChar, rl_src[0], rl_src[1], rl_src[2]); break; case Instruction::APUT_SHORT: - ConvertAput(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayPutShort, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutShort, rl_src[0], rl_src[1], rl_src[2]); break; case Instruction::APUT_WIDE: if (rl_src[0].fp) { - ConvertAput(cu, opt_flags, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutDouble, rl_src[0], rl_src[1], rl_src[2]); } else { - ConvertAput(cu, opt_flags, art::llvm::IntrinsicHelper::HLArrayPutWide, + ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutWide, rl_src[0], rl_src[1], rl_src[2]); } break; case Instruction::IGET: if (rl_dest.fp) { - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGetFloat, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetFloat, rl_dest, rl_src[0], vC); } else { - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGet, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGet, rl_dest, rl_src[0], vC); } break; case Instruction::IGET_OBJECT: - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGetObject, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetObject, rl_dest, rl_src[0], vC); break; case Instruction::IGET_BOOLEAN: - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGetBoolean, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetBoolean, rl_dest, rl_src[0], vC); break; case Instruction::IGET_BYTE: - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGetByte, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetByte, rl_dest, rl_src[0], vC); break; case Instruction::IGET_CHAR: - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGetChar, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetChar, rl_dest, rl_src[0], vC); break; case Instruction::IGET_SHORT: - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGetShort, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetShort, rl_dest, rl_src[0], vC); break; case Instruction::IGET_WIDE: if (rl_dest.fp) { - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGetDouble, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetDouble, rl_dest, rl_src[0], vC); } else { - ConvertIget(cu, opt_flags, art::llvm::IntrinsicHelper::HLIGetWide, + ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetWide, rl_dest, rl_src[0], vC); } break; case Instruction::IPUT: if (rl_src[0].fp) { - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPutFloat, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutFloat, rl_src[0], rl_src[1], vC); } else { - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPut, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPut, rl_src[0], rl_src[1], vC); } break; case Instruction::IPUT_OBJECT: - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPutObject, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutObject, rl_src[0], rl_src[1], vC); break; case Instruction::IPUT_BOOLEAN: - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPutBoolean, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutBoolean, rl_src[0], rl_src[1], vC); break; case Instruction::IPUT_BYTE: - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPutByte, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutByte, rl_src[0], rl_src[1], vC); break; case Instruction::IPUT_CHAR: - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPutChar, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutChar, rl_src[0], rl_src[1], vC); break; case Instruction::IPUT_SHORT: - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPutShort, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutShort, rl_src[0], rl_src[1], vC); break; case Instruction::IPUT_WIDE: if (rl_src[0].fp) { - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPutDouble, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutDouble, rl_src[0], rl_src[1], vC); } else { - ConvertIput(cu, opt_flags, art::llvm::IntrinsicHelper::HLIPutWide, + ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutWide, rl_src[0], rl_src[1], vC); } break; case Instruction::FILL_ARRAY_DATA: - ConvertFillArrayData(cu, vB, rl_src[0]); + ConvertFillArrayData(vB, rl_src[0]); break; case Instruction::LONG_TO_INT: - ConvertLongToInt(cu, rl_dest, rl_src[0]); + ConvertLongToInt(rl_dest, rl_src[0]); break; case Instruction::INT_TO_LONG: - ConvertIntToLong(cu, rl_dest, rl_src[0]); + ConvertIntToLong(rl_dest, rl_src[0]); break; case Instruction::INT_TO_CHAR: - ConvertIntNarrowing(cu, rl_dest, rl_src[0], + ConvertIntNarrowing(rl_dest, rl_src[0], art::llvm::IntrinsicHelper::IntToChar); break; case Instruction::INT_TO_BYTE: - ConvertIntNarrowing(cu, rl_dest, rl_src[0], + ConvertIntNarrowing(rl_dest, rl_src[0], art::llvm::IntrinsicHelper::IntToByte); break; case Instruction::INT_TO_SHORT: - ConvertIntNarrowing(cu, rl_dest, rl_src[0], + ConvertIntNarrowing(rl_dest, rl_src[0], art::llvm::IntrinsicHelper::IntToShort); break; case Instruction::INT_TO_FLOAT: case Instruction::LONG_TO_FLOAT: - ConvertIntToFP(cu, cu->irb->getFloatTy(), rl_dest, rl_src[0]); + ConvertIntToFP(irb_->getFloatTy(), rl_dest, rl_src[0]); break; case Instruction::INT_TO_DOUBLE: case Instruction::LONG_TO_DOUBLE: - ConvertIntToFP(cu, cu->irb->getDoubleTy(), rl_dest, rl_src[0]); + ConvertIntToFP(irb_->getDoubleTy(), rl_dest, rl_src[0]); break; case Instruction::FLOAT_TO_DOUBLE: - ConvertFloatToDouble(cu, rl_dest, rl_src[0]); + ConvertFloatToDouble(rl_dest, rl_src[0]); break; case Instruction::DOUBLE_TO_FLOAT: - ConvertDoubleToFloat(cu, rl_dest, rl_src[0]); + ConvertDoubleToFloat(rl_dest, rl_src[0]); break; case Instruction::NEG_LONG: case Instruction::NEG_INT: - ConvertNeg(cu, rl_dest, rl_src[0]); + ConvertNeg(rl_dest, rl_src[0]); break; case Instruction::NEG_FLOAT: case Instruction::NEG_DOUBLE: - ConvertNegFP(cu, rl_dest, rl_src[0]); + ConvertNegFP(rl_dest, rl_src[0]); break; case Instruction::NOT_LONG: case Instruction::NOT_INT: - ConvertNot(cu, rl_dest, rl_src[0]); + ConvertNot(rl_dest, rl_src[0]); break; case Instruction::FLOAT_TO_INT: - ConvertFPToInt(cu, art::llvm::IntrinsicHelper::F2I, rl_dest, rl_src[0]); + ConvertFPToInt(art::llvm::IntrinsicHelper::F2I, rl_dest, rl_src[0]); break; case Instruction::DOUBLE_TO_INT: - ConvertFPToInt(cu, art::llvm::IntrinsicHelper::D2I, rl_dest, rl_src[0]); + ConvertFPToInt(art::llvm::IntrinsicHelper::D2I, rl_dest, rl_src[0]); break; case Instruction::FLOAT_TO_LONG: - ConvertFPToInt(cu, art::llvm::IntrinsicHelper::F2L, rl_dest, rl_src[0]); + ConvertFPToInt(art::llvm::IntrinsicHelper::F2L, rl_dest, rl_src[0]); break; case Instruction::DOUBLE_TO_LONG: - ConvertFPToInt(cu, art::llvm::IntrinsicHelper::D2L, rl_dest, rl_src[0]); + ConvertFPToInt(art::llvm::IntrinsicHelper::D2L, rl_dest, rl_src[0]); break; case Instruction::CMPL_FLOAT: - ConvertWideComparison(cu, art::llvm::IntrinsicHelper::CmplFloat, + ConvertWideComparison(art::llvm::IntrinsicHelper::CmplFloat, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::CMPG_FLOAT: - ConvertWideComparison(cu, art::llvm::IntrinsicHelper::CmpgFloat, + ConvertWideComparison(art::llvm::IntrinsicHelper::CmpgFloat, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::CMPL_DOUBLE: - ConvertWideComparison(cu, art::llvm::IntrinsicHelper::CmplDouble, + ConvertWideComparison(art::llvm::IntrinsicHelper::CmplDouble, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::CMPG_DOUBLE: - ConvertWideComparison(cu, art::llvm::IntrinsicHelper::CmpgDouble, + ConvertWideComparison(art::llvm::IntrinsicHelper::CmpgDouble, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::CMP_LONG: - ConvertWideComparison(cu, art::llvm::IntrinsicHelper::CmpLong, + ConvertWideComparison(art::llvm::IntrinsicHelper::CmpLong, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::PACKED_SWITCH: - ConvertPackedSwitch(cu, bb, vB, rl_src[0]); + ConvertPackedSwitch(bb, vB, rl_src[0]); break; case Instruction::SPARSE_SWITCH: - ConvertSparseSwitch(cu, bb, vB, rl_src[0]); + ConvertSparseSwitch(bb, vB, rl_src[0]); break; default: @@ -1561,51 +1556,38 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, return res; } -static void SetDexOffset(CompilationUnit* cu, int32_t offset) +void MirConverter::SetDexOffset(int32_t offset) { - cu->current_dalvik_offset = offset; + current_dalvik_offset_ = offset; ::llvm::SmallVector< ::llvm::Value*, 1> array_ref; - array_ref.push_back(cu->irb->getInt32(offset)); - ::llvm::MDNode* node = ::llvm::MDNode::get(*cu->context, array_ref); - cu->irb->SetDexOffset(node); + array_ref.push_back(irb_->getInt32(offset)); + ::llvm::MDNode* node = ::llvm::MDNode::get(*context_, array_ref); + irb_->SetDexOffset(node); } // Attach method info as metadata to special intrinsic -static void SetMethodInfo(CompilationUnit* cu) +void MirConverter::SetMethodInfo() { // We don't want dex offset on this - cu->irb->SetDexOffset(NULL); + irb_->SetDexOffset(NULL); art::llvm::IntrinsicHelper::IntrinsicId id; id = art::llvm::IntrinsicHelper::MethodInfo; - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Instruction* inst = cu->irb->CreateCall(intr); + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Instruction* inst = irb_->CreateCall(intr); ::llvm::SmallVector< ::llvm::Value*, 2> reg_info; - reg_info.push_back(cu->irb->getInt32(cu->num_ins)); - reg_info.push_back(cu->irb->getInt32(cu->num_regs)); - reg_info.push_back(cu->irb->getInt32(cu->num_outs)); - reg_info.push_back(cu->irb->getInt32(cu->num_compiler_temps)); - reg_info.push_back(cu->irb->getInt32(cu->mir_graph->GetNumSSARegs())); - ::llvm::MDNode* reg_info_node = ::llvm::MDNode::get(*cu->context, reg_info); + reg_info.push_back(irb_->getInt32(cu_->num_ins)); + reg_info.push_back(irb_->getInt32(cu_->num_regs)); + reg_info.push_back(irb_->getInt32(cu_->num_outs)); + reg_info.push_back(irb_->getInt32(cu_->num_compiler_temps)); + reg_info.push_back(irb_->getInt32(mir_graph_->GetNumSSARegs())); + ::llvm::MDNode* reg_info_node = ::llvm::MDNode::get(*context_, reg_info); inst->setMetadata("RegInfo", reg_info_node); - int promo_size = cu->num_dalvik_registers + cu->num_compiler_temps + 1; - ::llvm::SmallVector< ::llvm::Value*, 50> pmap; - for (int i = 0; i < promo_size; i++) { - PromotionMap* p = &cu->promotion_map[i]; - int32_t map_data = ((p->first_in_pair & 0xff) << 24) | - ((p->FpReg & 0xff) << 16) | - ((p->core_reg & 0xff) << 8) | - ((p->fp_location & 0xf) << 4) | - (p->core_location & 0xf); - pmap.push_back(cu->irb->getInt32(map_data)); - } - ::llvm::MDNode* map_node = ::llvm::MDNode::get(*cu->context, pmap); - inst->setMetadata("PromotionMap", map_node); - SetDexOffset(cu, cu->current_dalvik_offset); + SetDexOffset(current_dalvik_offset_); } -static void HandlePhiNodes(CompilationUnit* cu, BasicBlock* bb, ::llvm::BasicBlock* llvm_bb) +void MirConverter::HandlePhiNodes(BasicBlock* bb, ::llvm::BasicBlock* llvm_bb) { - SetDexOffset(cu, bb->start_offset); + SetDexOffset(bb->start_offset); for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { int opcode = mir->dalvikInsn.opcode; if (opcode < kMirOpFirst) { @@ -1616,7 +1598,7 @@ static void HandlePhiNodes(CompilationUnit* cu, BasicBlock* bb, ::llvm::BasicBlo // Skip other mir Pseudos. continue; } - RegLocation rl_dest = cu->reg_location[mir->ssa_rep->defs[0]]; + RegLocation rl_dest = mir_graph_->reg_location_[mir->ssa_rep->defs[0]]; /* * The Art compiler's Phi nodes only handle 32-bit operands, * representing wide values using a matched set of Phi nodes @@ -1629,43 +1611,43 @@ static void HandlePhiNodes(CompilationUnit* cu, BasicBlock* bb, ::llvm::BasicBlo } int* incoming = reinterpret_cast<int*>(mir->dalvikInsn.vB); ::llvm::Type* phi_type = - LlvmTypeFromLocRec(cu, rl_dest); - ::llvm::PHINode* phi = cu->irb->CreatePHI(phi_type, mir->ssa_rep->num_uses); + LlvmTypeFromLocRec(rl_dest); + ::llvm::PHINode* phi = irb_->CreatePHI(phi_type, mir->ssa_rep->num_uses); for (int i = 0; i < mir->ssa_rep->num_uses; i++) { RegLocation loc; // Don't check width here. - loc = GetRawSrc(cu, mir, i); + loc = mir_graph_->GetRawSrc(mir, i); DCHECK_EQ(rl_dest.wide, loc.wide); DCHECK_EQ(rl_dest.wide & rl_dest.high_word, loc.wide & loc.high_word); DCHECK_EQ(rl_dest.fp, loc.fp); DCHECK_EQ(rl_dest.core, loc.core); DCHECK_EQ(rl_dest.ref, loc.ref); SafeMap<unsigned int, unsigned int>::iterator it; - it = cu->block_id_map.find(incoming[i]); - DCHECK(it != cu->block_id_map.end()); - DCHECK(GetLLVMValue(cu, loc.orig_sreg) != NULL); - DCHECK(GetLLVMBlock(cu, it->second) != NULL); - phi->addIncoming(GetLLVMValue(cu, loc.orig_sreg), - GetLLVMBlock(cu, it->second)); + it = mir_graph_->block_id_map_.find(incoming[i]); + DCHECK(it != mir_graph_->block_id_map_.end()); + DCHECK(GetLLVMValue(loc.orig_sreg) != NULL); + DCHECK(GetLLVMBlock(it->second) != NULL); + phi->addIncoming(GetLLVMValue(loc.orig_sreg), + GetLLVMBlock(it->second)); } - DefineValueOnly(cu, phi, rl_dest.orig_sreg); + DefineValueOnly(phi, rl_dest.orig_sreg); } } /* Extended MIR instructions like PHI */ -static void ConvertExtendedMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir, +void MirConverter::ConvertExtendedMIR(BasicBlock* bb, MIR* mir, ::llvm::BasicBlock* llvm_bb) { switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { case kMirOpPhi: { // The llvm Phi node already emitted - just DefineValue() here. - RegLocation rl_dest = cu->reg_location[mir->ssa_rep->defs[0]]; + RegLocation rl_dest = mir_graph_->reg_location_[mir->ssa_rep->defs[0]]; if (!rl_dest.high_word) { // Only consider low word of pairs. - DCHECK(GetLLVMValue(cu, rl_dest.orig_sreg) != NULL); - ::llvm::Value* phi = GetLLVMValue(cu, rl_dest.orig_sreg); - if (1) SetVregOnValue(cu, phi, rl_dest.orig_sreg); + DCHECK(GetLLVMValue(rl_dest.orig_sreg) != NULL); + ::llvm::Value* phi = GetLLVMValue(rl_dest.orig_sreg); + if (1) SetVregOnValue(phi, rl_dest.orig_sreg); } break; } @@ -1676,7 +1658,7 @@ static void ConvertExtendedMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir, case kMirOpNop: if ((mir == bb->last_mir_insn) && (bb->taken == NULL) && (bb->fall_through == NULL)) { - cu->irb->CreateUnreachable(); + irb_->CreateUnreachable(); } break; @@ -1702,18 +1684,18 @@ static void ConvertExtendedMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir, } /* Handle the content in each basic block */ -static bool BlockBitcodeConversion(CompilationUnit* cu, BasicBlock* bb) +bool MirConverter::BlockBitcodeConversion(BasicBlock* bb) { if (bb->block_type == kDead) return false; - ::llvm::BasicBlock* llvm_bb = GetLLVMBlock(cu, bb->id); + ::llvm::BasicBlock* llvm_bb = GetLLVMBlock(bb->id); if (llvm_bb == NULL) { CHECK(bb->block_type == kExitBlock); } else { - cu->irb->SetInsertPoint(llvm_bb); - SetDexOffset(cu, bb->start_offset); + irb_->SetInsertPoint(llvm_bb); + SetDexOffset(bb->start_offset); } - if (cu->verbose) { + if (cu_->verbose) { LOG(INFO) << "................................"; LOG(INFO) << "Block id " << bb->id; if (llvm_bb != NULL) { @@ -1724,36 +1706,36 @@ static bool BlockBitcodeConversion(CompilationUnit* cu, BasicBlock* bb) } if (bb->block_type == kEntryBlock) { - SetMethodInfo(cu); + SetMethodInfo(); { // Allocate shadowframe. art::llvm::IntrinsicHelper::IntrinsicId id = art::llvm::IntrinsicHelper::AllocaShadowFrame; - ::llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id); - ::llvm::Value* entries = cu->irb->getInt32(cu->num_dalvik_registers); - cu->irb->CreateCall(func, entries); + ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id); + ::llvm::Value* entries = irb_->getInt32(cu_->num_dalvik_registers); + irb_->CreateCall(func, entries); } { // Store arguments to vregs. - uint16_t arg_reg = cu->num_regs; + uint16_t arg_reg = cu_->num_regs; - ::llvm::Function::arg_iterator arg_iter(cu->func->arg_begin()); - ::llvm::Function::arg_iterator arg_end(cu->func->arg_end()); + ::llvm::Function::arg_iterator arg_iter(func_->arg_begin()); + ::llvm::Function::arg_iterator arg_end(func_->arg_end()); - const char* shorty = cu->shorty; + const char* shorty = cu_->shorty; uint32_t shorty_size = strlen(shorty); CHECK_GE(shorty_size, 1u); ++arg_iter; // skip method object - if ((cu->access_flags & kAccStatic) == 0) { - SetVregOnValue(cu, arg_iter, arg_reg); + if ((cu_->access_flags & kAccStatic) == 0) { + SetVregOnValue(arg_iter, arg_reg); ++arg_iter; ++arg_reg; } for (uint32_t i = 1; i < shorty_size; ++i, ++arg_iter) { - SetVregOnValue(cu, arg_iter, arg_reg); + SetVregOnValue(arg_iter, arg_reg); ++arg_reg; if (shorty[i] == 'J' || shorty[i] == 'D') { @@ -1779,11 +1761,11 @@ static bool BlockBitcodeConversion(CompilationUnit* cu, BasicBlock* bb) return false; } - HandlePhiNodes(cu, bb, llvm_bb); + HandlePhiNodes(bb, llvm_bb); for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { - SetDexOffset(cu, mir->offset); + SetDexOffset(mir->offset); int opcode = mir->dalvikInsn.opcode; Instruction::Format dalvik_format = @@ -1800,38 +1782,38 @@ static bool BlockBitcodeConversion(CompilationUnit* cu, BasicBlock* bb) work_half->meta.original_opcode = work_half->dalvikInsn.opcode; work_half->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); if (bb->successor_block_list.block_list_type == kCatch) { - ::llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction( + ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction( art::llvm::IntrinsicHelper::CatchTargets); ::llvm::Value* switch_key = - cu->irb->CreateCall(intr, cu->irb->getInt32(mir->offset)); + irb_->CreateCall(intr, irb_->getInt32(mir->offset)); GrowableListIterator iter; GrowableListIteratorInit(&bb->successor_block_list.blocks, &iter); // New basic block to use for work half ::llvm::BasicBlock* work_bb = - ::llvm::BasicBlock::Create(*cu->context, "", cu->func); + ::llvm::BasicBlock::Create(*context_, "", func_); ::llvm::SwitchInst* sw = - cu->irb->CreateSwitch(switch_key, work_bb, + irb_->CreateSwitch(switch_key, work_bb, bb->successor_block_list.blocks.num_used); while (true) { SuccessorBlockInfo *successor_block_info = reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iter)); if (successor_block_info == NULL) break; ::llvm::BasicBlock *target = - GetLLVMBlock(cu, successor_block_info->block->id); + GetLLVMBlock(successor_block_info->block->id); int type_index = successor_block_info->key; - sw->addCase(cu->irb->getInt32(type_index), target); + sw->addCase(irb_->getInt32(type_index), target); } llvm_bb = work_bb; - cu->irb->SetInsertPoint(llvm_bb); + irb_->SetInsertPoint(llvm_bb); } } if (opcode >= kMirOpFirst) { - ConvertExtendedMIR(cu, bb, mir, llvm_bb); + ConvertExtendedMIR(bb, mir, llvm_bb); continue; } - bool not_handled = ConvertMIRNode(cu, mir, bb, llvm_bb); + bool not_handled = ConvertMIRNode(mir, bb, llvm_bb); if (not_handled) { Instruction::Code dalvik_opcode = static_cast<Instruction::Code>(opcode); LOG(WARNING) << StringPrintf("%#06x: Op %#x (%s) / Fmt %d not handled", @@ -1842,9 +1824,9 @@ static bool BlockBitcodeConversion(CompilationUnit* cu, BasicBlock* bb) } if (bb->block_type == kEntryBlock) { - cu->entryTarget_bb = GetLLVMBlock(cu, bb->fall_through->id); + entry_target_bb_ = GetLLVMBlock(bb->fall_through->id); } else if ((bb->fall_through != NULL) && !bb->terminated_by_return) { - cu->irb->CreateBr(GetLLVMBlock(cu, bb->fall_through->id)); + irb_->CreateBr(GetLLVMBlock(bb->fall_through->id)); } return false; @@ -1872,74 +1854,74 @@ char RemapShorty(char shorty_type) { return shorty_type; } -static ::llvm::FunctionType* GetFunctionType(CompilationUnit* cu) { +::llvm::FunctionType* MirConverter::GetFunctionType() { // Get return type - ::llvm::Type* ret_type = cu->irb->getJType(RemapShorty(cu->shorty[0])); + ::llvm::Type* ret_type = irb_->getJType(RemapShorty(cu_->shorty[0])); // Get argument type std::vector< ::llvm::Type*> args_type; // method object - args_type.push_back(cu->irb->getJMethodTy()); + args_type.push_back(irb_->getJMethodTy()); // Do we have a "this"? - if ((cu->access_flags & kAccStatic) == 0) { - args_type.push_back(cu->irb->getJObjectTy()); + if ((cu_->access_flags & kAccStatic) == 0) { + args_type.push_back(irb_->getJObjectTy()); } - for (uint32_t i = 1; i < strlen(cu->shorty); ++i) { - args_type.push_back(cu->irb->getJType(RemapShorty(cu->shorty[i]))); + for (uint32_t i = 1; i < strlen(cu_->shorty); ++i) { + args_type.push_back(irb_->getJType(RemapShorty(cu_->shorty[i]))); } return ::llvm::FunctionType::get(ret_type, args_type, false); } -static bool CreateFunction(CompilationUnit* cu) { - ::llvm::FunctionType* func_type = GetFunctionType(cu); +bool MirConverter::CreateFunction() { + ::llvm::FunctionType* func_type = GetFunctionType(); if (func_type == NULL) { return false; } - cu->func = ::llvm::Function::Create(func_type, + func_ = ::llvm::Function::Create(func_type, ::llvm::Function::InternalLinkage, - cu->symbol, cu->module); + symbol_, module_); - ::llvm::Function::arg_iterator arg_iter(cu->func->arg_begin()); - ::llvm::Function::arg_iterator arg_end(cu->func->arg_end()); + ::llvm::Function::arg_iterator arg_iter(func_->arg_begin()); + ::llvm::Function::arg_iterator arg_end(func_->arg_end()); arg_iter->setName("method"); ++arg_iter; - int start_sreg = cu->num_regs; + int start_sreg = cu_->num_regs; for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) { arg_iter->setName(StringPrintf("v%i_0", start_sreg)); - start_sreg += cu->reg_location[start_sreg].wide ? 2 : 1; + start_sreg += mir_graph_->reg_location_[start_sreg].wide ? 2 : 1; } return true; } -static bool CreateLLVMBasicBlock(CompilationUnit* cu, BasicBlock* bb) +bool MirConverter::CreateLLVMBasicBlock(BasicBlock* bb) { // Skip the exit block if ((bb->block_type == kDead) ||(bb->block_type == kExitBlock)) { - cu->id_to_block_map.Put(bb->id, NULL); + id_to_block_map_.Put(bb->id, NULL); } else { int offset = bb->start_offset; bool entry_block = (bb->block_type == kEntryBlock); ::llvm::BasicBlock* llvm_bb = - ::llvm::BasicBlock::Create(*cu->context, entry_block ? "entry" : + ::llvm::BasicBlock::Create(*context_, entry_block ? "entry" : StringPrintf(kLabelFormat, bb->catch_entry ? kCatchBlock : - kNormalBlock, offset, bb->id), cu->func); + kNormalBlock, offset, bb->id), func_); if (entry_block) { - cu->entry_bb = llvm_bb; - cu->placeholder_bb = - ::llvm::BasicBlock::Create(*cu->context, "placeholder", - cu->func); + entry_bb_ = llvm_bb; + placeholder_bb_ = + ::llvm::BasicBlock::Create(*context_, "placeholder", + func_); } - cu->id_to_block_map.Put(bb->id, llvm_bb); + id_to_block_map_.Put(bb->id, llvm_bb); } return false; } @@ -1953,18 +1935,18 @@ static bool CreateLLVMBasicBlock(CompilationUnit* cu, BasicBlock* bb) * o Iterate through the MIR a basic block at a time, setting arguments * to recovered ssa name. */ -void MethodMIR2Bitcode(CompilationUnit* cu) +void MirConverter::MethodMIR2Bitcode() { - InitIR(cu); - CompilerInitGrowableList(cu, &cu->llvm_values, cu->mir_graph->GetNumSSARegs()); + InitIR(); + CompilerInitGrowableList(cu_, &llvm_values_, mir_graph_->GetNumSSARegs()); // Create the function - CreateFunction(cu); + CreateFunction(); // Create an LLVM basic block for each MIR block in dfs preorder - PreOrderDfsIterator iter(cu->mir_graph.get(), false /* not iterative */); + PreOrderDfsIterator iter(mir_graph_, false /* not iterative */); for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { - CreateLLVMBasicBlock(cu, bb); + CreateLLVMBasicBlock(bb); } /* @@ -1972,31 +1954,31 @@ void MethodMIR2Bitcode(CompilationUnit* cu) * placeholders for all non-argument values (because we haven't seen * the definition yet). */ - cu->irb->SetInsertPoint(cu->placeholder_bb); - ::llvm::Function::arg_iterator arg_iter(cu->func->arg_begin()); + irb_->SetInsertPoint(placeholder_bb_); + ::llvm::Function::arg_iterator arg_iter(func_->arg_begin()); arg_iter++; /* Skip path method */ - for (int i = 0; i < cu->mir_graph->GetNumSSARegs(); i++) { + for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) { ::llvm::Value* val; - RegLocation rl_temp = cu->reg_location[i]; - if ((cu->mir_graph->SRegToVReg(i) < 0) || rl_temp.high_word) { - InsertGrowableList(cu, &cu->llvm_values, 0); - } else if ((i < cu->num_regs) || - (i >= (cu->num_regs + cu->num_ins))) { - ::llvm::Constant* imm_value = cu->reg_location[i].wide ? - cu->irb->getJLong(0) : cu->irb->getJInt(0); - val = EmitConst(cu, imm_value, cu->reg_location[i]); - val->setName(cu->mir_graph->GetSSAString(i)); - InsertGrowableList(cu, &cu->llvm_values, reinterpret_cast<uintptr_t>(val)); + RegLocation rl_temp = mir_graph_->reg_location_[i]; + if ((mir_graph_->SRegToVReg(i) < 0) || rl_temp.high_word) { + InsertGrowableList(cu_, &llvm_values_, 0); + } else if ((i < cu_->num_regs) || + (i >= (cu_->num_regs + cu_->num_ins))) { + ::llvm::Constant* imm_value = mir_graph_->reg_location_[i].wide ? + irb_->getJLong(0) : irb_->getJInt(0); + val = EmitConst(imm_value, mir_graph_->reg_location_[i]); + val->setName(mir_graph_->GetSSAString(i)); + InsertGrowableList(cu_, &llvm_values_, reinterpret_cast<uintptr_t>(val)); } else { // Recover previously-created argument values ::llvm::Value* arg_val = arg_iter++; - InsertGrowableList(cu, &cu->llvm_values, reinterpret_cast<uintptr_t>(arg_val)); + InsertGrowableList(cu_, &llvm_values_, reinterpret_cast<uintptr_t>(arg_val)); } } - PreOrderDfsIterator iter2(cu->mir_graph.get(), false /* not iterative */); + PreOrderDfsIterator iter2(mir_graph_, false /* not iterative */); for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) { - BlockBitcodeConversion(cu, bb); + BlockBitcodeConversion(bb); } /* @@ -2012,8 +1994,8 @@ void MethodMIR2Bitcode(CompilationUnit* cu) * If any definitions remain, we link the placeholder block into the * CFG. Otherwise, it is deleted. */ - for (::llvm::BasicBlock::iterator it = cu->placeholder_bb->begin(), - it_end = cu->placeholder_bb->end(); it != it_end;) { + for (::llvm::BasicBlock::iterator it = placeholder_bb_->begin(), + it_end = placeholder_bb_->end(); it != it_end;) { ::llvm::Instruction* inst = ::llvm::dyn_cast< ::llvm::Instruction>(it++); DCHECK(inst != NULL); ::llvm::Value* val = ::llvm::dyn_cast< ::llvm::Value>(inst); @@ -2022,31 +2004,31 @@ void MethodMIR2Bitcode(CompilationUnit* cu) inst->eraseFromParent(); } } - SetDexOffset(cu, 0); - if (cu->placeholder_bb->empty()) { - cu->placeholder_bb->eraseFromParent(); + SetDexOffset(0); + if (placeholder_bb_->empty()) { + placeholder_bb_->eraseFromParent(); } else { - cu->irb->SetInsertPoint(cu->placeholder_bb); - cu->irb->CreateBr(cu->entryTarget_bb); - cu->entryTarget_bb = cu->placeholder_bb; + irb_->SetInsertPoint(placeholder_bb_); + irb_->CreateBr(entry_target_bb_); + entry_target_bb_ = placeholder_bb_; } - cu->irb->SetInsertPoint(cu->entry_bb); - cu->irb->CreateBr(cu->entryTarget_bb); + irb_->SetInsertPoint(entry_bb_); + irb_->CreateBr(entry_target_bb_); - if (cu->enable_debug & (1 << kDebugVerifyBitcode)) { - if (::llvm::verifyFunction(*cu->func, ::llvm::PrintMessageAction)) { + if (cu_->enable_debug & (1 << kDebugVerifyBitcode)) { + if (::llvm::verifyFunction(*func_, ::llvm::PrintMessageAction)) { LOG(INFO) << "Bitcode verification FAILED for " - << PrettyMethod(cu->method_idx, *cu->dex_file) - << " of size " << cu->code_item->insns_size_in_code_units_; - cu->enable_debug |= (1 << kDebugDumpBitcodeFile); + << PrettyMethod(cu_->method_idx, *cu_->dex_file) + << " of size " << cu_->code_item->insns_size_in_code_units_; + cu_->enable_debug |= (1 << kDebugDumpBitcodeFile); } } - if (cu->enable_debug & (1 << kDebugDumpBitcodeFile)) { + if (cu_->enable_debug & (1 << kDebugDumpBitcodeFile)) { // Write bitcode to file std::string errmsg; - std::string fname(PrettyMethod(cu->method_idx, *cu->dex_file)); - ReplaceSpecialChars(fname); + std::string fname(PrettyMethod(cu_->method_idx, *cu_->dex_file)); + mir_graph_->ReplaceSpecialChars(fname); // TODO: make configurable change naming mechanism to avoid fname length issues. fname = StringPrintf("/sdcard/Bitcode/%s.bc", fname.c_str()); @@ -2063,9 +2045,14 @@ void MethodMIR2Bitcode(CompilationUnit* cu) LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; } - ::llvm::WriteBitcodeToFile(cu->module, out_file->os()); + ::llvm::WriteBitcodeToFile(module_, out_file->os()); out_file->keep(); } } +Backend* PortableCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, + llvm::LlvmCompilationUnit* const llvm_compilation_unit) { + return new MirConverter(cu, mir_graph, llvm_compilation_unit); +} + } // namespace art diff --git a/src/compiler/dex/portable/mir_to_gbc.h b/src/compiler/dex/portable/mir_to_gbc.h index 48faf759f8..eb7069cf8d 100644 --- a/src/compiler/dex/portable/mir_to_gbc.h +++ b/src/compiler/dex/portable/mir_to_gbc.h @@ -17,9 +17,176 @@ #ifndef ART_SRC_COMPILER_DEX_PORTABLE_MIRTOGBC_H_ #define ART_SRC_COMPILER_DEX_PORTABLE_MIRTOGBC_H_ +#include "invoke_type.h" +#include "compiled_method.h" +#include "compiler/dex/compiler_enums.h" +#include "compiler/dex/compiler_ir.h" +#include "compiler/dex/compiler_utility.h" +#include "compiler/dex/backend.h" +#include "compiler/llvm/llvm_compilation_unit.h" +#include "safe_map.h" + namespace art { -void MethodMIR2Bitcode(CompilationUnit* cu); +struct BasicBlock; +struct CallInfo; +struct CompilationUnit; +struct MIR; +struct RegLocation; +struct RegisterInfo; +class MIRGraph; + +// Target-specific initialization. +Backend* PortableCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, + llvm::LlvmCompilationUnit* const llvm_compilation_unit); + +class MirConverter : public Backend { + + public: + // TODO: flesh out and integrate into new world order. + MirConverter(CompilationUnit* cu, MIRGraph* mir_graph, + llvm::LlvmCompilationUnit* llvm_compilation_unit) + : cu_(cu), + mir_graph_(mir_graph), + llvm_compilation_unit_(llvm_compilation_unit), + llvm_info_(llvm_compilation_unit->GetQuickContext()), + symbol_(llvm_compilation_unit->GetDexCompilationUnit()->GetSymbol()), + context_(NULL), + module_(NULL), + func_(NULL), + intrinsic_helper_(NULL), + irb_(NULL), + placeholder_bb_(NULL), + entry_bb_(NULL), + entry_target_bb_(NULL), + temp_name_(0), + current_dalvik_offset_(0) { + if (kIsDebugBuild) { + cu->enable_debug |= (1 << kDebugVerifyBitcode); + } + } + + void Materialize() { + MethodMIR2Bitcode(); + } + + CompiledMethod* GetCompiledMethod() { + return NULL; + } + + private: + ::llvm::BasicBlock* GetLLVMBlock(int id); + ::llvm::Value* GetLLVMValue(int s_reg); + void SetVregOnValue(::llvm::Value* val, int s_reg); + void DefineValueOnly(::llvm::Value* val, int s_reg); + void DefineValue(::llvm::Value* val, int s_reg); + ::llvm::Type* LlvmTypeFromLocRec(RegLocation loc); + void InitIR(); + ::llvm::BasicBlock* FindCaseTarget(uint32_t vaddr); + void ConvertPackedSwitch(BasicBlock* bb, int32_t table_offset, + RegLocation rl_src); + void ConvertSparseSwitch(BasicBlock* bb, int32_t table_offset, + RegLocation rl_src); + void ConvertSget(int32_t field_index, + art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest); + void ConvertSput(int32_t field_index, + art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src); + void ConvertFillArrayData(int32_t offset, RegLocation rl_array); + ::llvm::Value* EmitConst(::llvm::ArrayRef< ::llvm::Value*> src, + RegLocation loc); + void EmitPopShadowFrame(); + ::llvm::Value* EmitCopy(::llvm::ArrayRef< ::llvm::Value*> src, + RegLocation loc); + void ConvertMoveException(RegLocation rl_dest); + void ConvertThrow(RegLocation rl_src); + void ConvertMonitorEnterExit(int opt_flags, + art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src); + void ConvertArrayLength(int opt_flags, RegLocation rl_dest, + RegLocation rl_src); + void EmitSuspendCheck(); + ::llvm::Value* ConvertCompare(ConditionCode cc, + ::llvm::Value* src1, ::llvm::Value* src2); + void ConvertCompareAndBranch(BasicBlock* bb, MIR* mir, ConditionCode cc, + RegLocation rl_src1, RegLocation rl_src2); + void ConvertCompareZeroAndBranch(BasicBlock* bb, MIR* mir, ConditionCode cc, + RegLocation rl_src1); + ::llvm::Value* GenDivModOp(bool is_div, bool is_long, ::llvm::Value* src1, + ::llvm::Value* src2); + ::llvm::Value* GenArithOp(OpKind op, bool is_long, ::llvm::Value* src1, + ::llvm::Value* src2); + void ConvertFPArithOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2); + void ConvertShift(art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + void ConvertShiftLit(art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_dest, RegLocation rl_src, int shift_amount); + void ConvertArithOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2); + void ConvertArithOpLit(OpKind op, RegLocation rl_dest, RegLocation rl_src1, + int32_t imm); + void ConvertInvoke(BasicBlock* bb, MIR* mir, InvokeType invoke_type, + bool is_range, bool is_filled_new_array); + void ConvertConstObject(uint32_t idx, + art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest); + void ConvertCheckCast(uint32_t type_idx, RegLocation rl_src); + void ConvertNewInstance(uint32_t type_idx, RegLocation rl_dest); + void ConvertNewArray(uint32_t type_idx, RegLocation rl_dest, + RegLocation rl_src); + void ConvertAget(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_dest, RegLocation rl_array, RegLocation rl_index); + void ConvertAput(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_src, RegLocation rl_array, RegLocation rl_index); + void ConvertIget(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_dest, RegLocation rl_obj, int field_index); + void ConvertIput(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_src, RegLocation rl_obj, int field_index); + void ConvertInstanceOf(uint32_t type_idx, RegLocation rl_dest, + RegLocation rl_src); + void ConvertIntToLong(RegLocation rl_dest, RegLocation rl_src); + void ConvertLongToInt(RegLocation rl_dest, RegLocation rl_src); + void ConvertFloatToDouble(RegLocation rl_dest, RegLocation rl_src); + void ConvertDoubleToFloat(RegLocation rl_dest, RegLocation rl_src); + void ConvertWideComparison(art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + void ConvertIntNarrowing(RegLocation rl_dest, RegLocation rl_src, + art::llvm::IntrinsicHelper::IntrinsicId id); + void ConvertNeg(RegLocation rl_dest, RegLocation rl_src); + void ConvertIntToFP(::llvm::Type* ty, RegLocation rl_dest, RegLocation rl_src); + void ConvertFPToInt(art::llvm::IntrinsicHelper::IntrinsicId id, + RegLocation rl_dest, RegLocation rl_src); + void ConvertNegFP(RegLocation rl_dest, RegLocation rl_src); + void ConvertNot(RegLocation rl_dest, RegLocation rl_src); + void EmitConstructorBarrier(); + bool ConvertMIRNode(MIR* mir, BasicBlock* bb, ::llvm::BasicBlock* llvm_bb); + void SetDexOffset(int32_t offset); + void SetMethodInfo(); + void HandlePhiNodes(BasicBlock* bb, ::llvm::BasicBlock* llvm_bb); + void ConvertExtendedMIR(BasicBlock* bb, MIR* mir, ::llvm::BasicBlock* llvm_bb); + bool BlockBitcodeConversion(BasicBlock* bb); + ::llvm::FunctionType* GetFunctionType(); + bool CreateFunction(); + bool CreateLLVMBasicBlock(BasicBlock* bb); + void MethodMIR2Bitcode(); + + CompilationUnit* cu_; + MIRGraph* mir_graph_; + llvm::LlvmCompilationUnit* const llvm_compilation_unit_; + LLVMInfo* llvm_info_; + std::string symbol_; + ::llvm::LLVMContext* context_; + ::llvm::Module* module_; + ::llvm::Function* func_; + art::llvm::IntrinsicHelper* intrinsic_helper_; + art::llvm::IRBuilder* irb_; + ::llvm::BasicBlock* placeholder_bb_; + ::llvm::BasicBlock* entry_bb_; + ::llvm::BasicBlock* entry_target_bb_; + std::string bitcode_filename_; + GrowableList llvm_values_; + int32_t temp_name_; + SafeMap<int32_t, ::llvm::BasicBlock*> id_to_block_map_; // block id -> llvm bb. + int current_dalvik_offset_; +}; // Class MirConverter } // namespace art diff --git a/src/compiler/dex/quick/arm/assemble_arm.cc b/src/compiler/dex/quick/arm/assemble_arm.cc index 253d5e9b72..23a87dcec1 100644 --- a/src/compiler/dex/quick/arm/assemble_arm.cc +++ b/src/compiler/dex/quick/arm/assemble_arm.cc @@ -16,7 +16,6 @@ #include "arm_lir.h" #include "codegen_arm.h" -#include "compiler/dex/quick/codegen_util.h" namespace art { @@ -76,7 +75,7 @@ namespace art { * [!] escape. To insert "!", use "!!" */ /* NOTE: must be kept in sync with enum ArmOpcode from LIR.h */ -const ArmEncodingMap ArmCodegen::EncodingMap[kArmLast] = { +const ArmEncodingMap ArmMir2Lir::EncodingMap[kArmLast] = { ENCODING_MAP(kArm16BitData, 0x0000, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_UNARY_OP, "data", "0x!0h(!0d)", 2), @@ -1002,18 +1001,18 @@ const ArmEncodingMap ArmCodegen::EncodingMap[kArmLast] = { * discover that pc-relative displacements may not fit the selected * instruction. */ -AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t start_addr) +AssemblerStatus ArmMir2Lir::AssembleInstructions(uintptr_t start_addr) { LIR* lir; AssemblerStatus res = kSuccess; // Assume success - for (lir = cu->first_lir_insn; lir != NULL; lir = NEXT_LIR(lir)) { + for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) { if (lir->opcode < 0) { /* 1 means padding is needed */ if ((lir->opcode == kPseudoPseudoAlign4) && (lir->operands[0] == 1)) { - cu->code_buffer.push_back(PADDING_MOV_R5_R5 & 0xFF); - cu->code_buffer.push_back((PADDING_MOV_R5_R5 >> 8) & 0xFF); + code_buffer_.push_back(PADDING_MOV_R5_R5 & 0xFF); + code_buffer_.push_back((PADDING_MOV_R5_R5 >> 8) & 0xFF); } continue; } @@ -1073,7 +1072,7 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t ? lir->operands[0] : rARM_LR; // Add new Adr to generate the address. - LIR* new_adr = RawLIR(cu, lir->dalvik_offset, kThumb2Adr, + LIR* new_adr = RawLIR(lir->dalvik_offset, kThumb2Adr, base_reg, 0, 0, 0, 0, lir->target); InsertLIRBefore(lir, new_adr); @@ -1091,7 +1090,7 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t lir->operands[2] = 0; lir->operands[1] = base_reg; } - SetupResourceMasks(cu, lir); + SetupResourceMasks(lir); res = kRetryAll; } else { if ((lir->opcode == kThumb2Vldrs) || @@ -1114,7 +1113,7 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t * Make new branch instruction and insert after */ LIR* new_inst = - RawLIR(cu, lir->dalvik_offset, kThumbBCond, 0, + RawLIR(lir->dalvik_offset, kThumbBCond, 0, (lir->opcode == kThumb2Cbz) ? kArmCondEq : kArmCondNe, 0, 0, 0, lir->target); InsertLIRAfter(lir, new_inst); @@ -1123,7 +1122,7 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t /* operand[0] is src1 in both cb[n]z & CmpRI8 */ lir->operands[1] = 0; lir->target = 0; - SetupResourceMasks(cu, lir); + SetupResourceMasks(lir); res = kRetryAll; } else { lir->operands[1] = delta >> 1; @@ -1148,7 +1147,7 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t } } lir->operands[0] = reg; - SetupResourceMasks(cu, lir); + SetupResourceMasks(lir); res = kRetryAll; } } else if (lir->opcode == kThumbBCond || lir->opcode == kThumb2BCond) { @@ -1160,7 +1159,7 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t delta = target - pc; if ((lir->opcode == kThumbBCond) && (delta > 254 || delta < -256)) { lir->opcode = kThumb2BCond; - SetupResourceMasks(cu, lir); + SetupResourceMasks(lir); res = kRetryAll; } lir->operands[0] = delta >> 1; @@ -1170,7 +1169,7 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t uintptr_t target = target_lir->offset; int delta = target - pc; lir->operands[0] = delta >> 1; - if (!(cu->disable_opt & (1 << kSafeOptimizations)) && + if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && lir->operands[0] == 0) { // Useless branch lir->flags.is_nop = true; res = kRetryAll; @@ -1184,11 +1183,11 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t // Convert to Thumb2BCond w/ kArmCondAl lir->opcode = kThumb2BUncond; lir->operands[0] = 0; - SetupResourceMasks(cu, lir); + SetupResourceMasks(lir); res = kRetryAll; } else { lir->operands[0] = delta >> 1; - if (!(cu->disable_opt & (1 << kSafeOptimizations)) && + if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && lir->operands[0] == -1) { // Useless branch lir->flags.is_nop = true; res = kRetryAll; @@ -1232,12 +1231,12 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t // convert to ldimm16l, ldimm16h, add tgt, pc, operands[0] // TUNING: if this case fires often, it can be improved. Not expected to be common. LIR *new_mov16L = - RawLIR(cu, lir->dalvik_offset, kThumb2MovImm16LST, + RawLIR(lir->dalvik_offset, kThumb2MovImm16LST, lir->operands[0], 0, reinterpret_cast<uintptr_t>(lir), reinterpret_cast<uintptr_t>(tab_rec), 0, lir->target); InsertLIRBefore(lir, new_mov16L); LIR *new_mov16H = - RawLIR(cu, lir->dalvik_offset, kThumb2MovImm16HST, + RawLIR(lir->dalvik_offset, kThumb2MovImm16HST, lir->operands[0], 0, reinterpret_cast<uintptr_t>(lir), reinterpret_cast<uintptr_t>(tab_rec), 0, lir->target); InsertLIRBefore(lir, new_mov16H); @@ -1247,7 +1246,7 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t lir->opcode = kThumbAddRRHH; } lir->operands[1] = rARM_PC; - SetupResourceMasks(cu, lir); + SetupResourceMasks(lir); res = kRetryAll; } } else if (lir->opcode == kThumb2MovImm16LST) { @@ -1380,16 +1379,16 @@ AssemblerStatus ArmCodegen::AssembleInstructions(CompilationUnit* cu, uintptr_t } } if (encoder->size == 4) { - cu->code_buffer.push_back((bits >> 16) & 0xff); - cu->code_buffer.push_back((bits >> 24) & 0xff); + code_buffer_.push_back((bits >> 16) & 0xff); + code_buffer_.push_back((bits >> 24) & 0xff); } - cu->code_buffer.push_back(bits & 0xff); - cu->code_buffer.push_back((bits >> 8) & 0xff); + code_buffer_.push_back(bits & 0xff); + code_buffer_.push_back((bits >> 8) & 0xff); } return res; } -int ArmCodegen::GetInsnSize(LIR* lir) +int ArmMir2Lir::GetInsnSize(LIR* lir) { return EncodingMap[lir->opcode].size; } diff --git a/src/compiler/dex/quick/arm/call_arm.cc b/src/compiler/dex/quick/arm/call_arm.cc index a201fd8292..bb46e1f7a8 100644 --- a/src/compiler/dex/quick/arm/call_arm.cc +++ b/src/compiler/dex/quick/arm/call_arm.cc @@ -18,18 +18,16 @@ #include "arm_lir.h" #include "codegen_arm.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "oat/runtime/oat_support_entrypoints.h" namespace art { /* Return the position of an ssa name within the argument list */ -static int InPosition(CompilationUnit* cu, int s_reg) +int ArmMir2Lir::InPosition(int s_reg) { - int v_reg = cu->mir_graph->SRegToVReg(s_reg); - return v_reg - cu->num_regs; + int v_reg = mir_graph_->SRegToVReg(s_reg); + return v_reg - cu_->num_regs; } /* @@ -37,9 +35,9 @@ static int InPosition(CompilationUnit* cu, int s_reg) * there. NOTE: all live arg registers must be locked prior to this call * to avoid having them allocated as a temp by downstream utilities. */ -RegLocation ArmCodegen::ArgLoc(CompilationUnit* cu, RegLocation loc) +RegLocation ArmMir2Lir::ArgLoc(RegLocation loc) { - int arg_num = InPosition(cu, loc.s_reg_low); + int arg_num = InPosition(loc.s_reg_low); if (loc.wide) { if (arg_num == 2) { // Bad case - half in register, half in frame. Just punt @@ -67,16 +65,15 @@ RegLocation ArmCodegen::ArgLoc(CompilationUnit* cu, RegLocation loc) * the frame, we can't use the normal LoadValue() because it assumed * a proper frame - and we're frameless. */ -static RegLocation LoadArg(CompilationUnit* cu, RegLocation loc) +RegLocation ArmMir2Lir::LoadArg(RegLocation loc) { - Codegen* cg = cu->cg.get(); if (loc.location == kLocDalvikFrame) { - int start = (InPosition(cu, loc.s_reg_low) + 1) * sizeof(uint32_t); - loc.low_reg = AllocTemp(cu); - cg->LoadWordDisp(cu, rARM_SP, start, loc.low_reg); + int start = (InPosition(loc.s_reg_low) + 1) * sizeof(uint32_t); + loc.low_reg = AllocTemp(); + LoadWordDisp(rARM_SP, start, loc.low_reg); if (loc.wide) { - loc.high_reg = AllocTemp(cu); - cg->LoadWordDisp(cu, rARM_SP, start + sizeof(uint32_t), loc.high_reg); + loc.high_reg = AllocTemp(); + LoadWordDisp(rARM_SP, start + sizeof(uint32_t), loc.high_reg); } loc.location = kLocPhysReg; } @@ -84,21 +81,22 @@ static RegLocation LoadArg(CompilationUnit* cu, RegLocation loc) } /* Lock any referenced arguments that arrive in registers */ -static void LockLiveArgs(CompilationUnit* cu, MIR* mir) +void ArmMir2Lir::LockLiveArgs(MIR* mir) { - int first_in = cu->num_regs; + int first_in = cu_->num_regs; const int num_arg_regs = 3; // TODO: generalize & move to RegUtil.cc for (int i = 0; i < mir->ssa_rep->num_uses; i++) { - int v_reg = cu->mir_graph->SRegToVReg(mir->ssa_rep->uses[i]); + int v_reg = mir_graph_->SRegToVReg(mir->ssa_rep->uses[i]); int InPosition = v_reg - first_in; if (InPosition < num_arg_regs) { - LockTemp(cu, rARM_ARG1 + InPosition); + LockTemp(rARM_ARG1 + InPosition); } } } /* Find the next MIR, which may be in a following basic block */ -static MIR* GetNextMir(CompilationUnit* cu, BasicBlock** p_bb, MIR* mir) +// TODO: should this be a utility in mir_graph? +MIR* ArmMir2Lir::GetNextMir(BasicBlock** p_bb, MIR* mir) { BasicBlock* bb = *p_bb; MIR* orig_mir = mir; @@ -124,105 +122,100 @@ static MIR* GetNextMir(CompilationUnit* cu, BasicBlock** p_bb, MIR* mir) /* Used for the "verbose" listing */ //TODO: move to common code -void ArmCodegen::GenPrintLabel(CompilationUnit *cu, MIR* mir) +void ArmMir2Lir::GenPrintLabel(MIR* mir) { /* Mark the beginning of a Dalvik instruction for line tracking */ - char* inst_str = cu->verbose ? - GetDalvikDisassembly(cu, mir) : NULL; - MarkBoundary(cu, mir->offset, inst_str); + char* inst_str = cu_->verbose ? + mir_graph_->GetDalvikDisassembly(mir) : NULL; + MarkBoundary(mir->offset, inst_str); } -static MIR* SpecialIGet(CompilationUnit* cu, BasicBlock** bb, MIR* mir, - OpSize size, bool long_or_double, bool is_object) +MIR* ArmMir2Lir::SpecialIGet(BasicBlock** bb, MIR* mir, + OpSize size, bool long_or_double, bool is_object) { - Codegen* cg = cu->cg.get(); int field_offset; bool is_volatile; uint32_t field_idx = mir->dalvikInsn.vC; - bool fast_path = FastInstance(cu, field_idx, field_offset, is_volatile, false); + bool fast_path = FastInstance(field_idx, field_offset, is_volatile, false); if (!fast_path || !(mir->optimization_flags & MIR_IGNORE_NULL_CHECK)) { return NULL; } - RegLocation rl_obj = GetSrc(cu, mir, 0); - LockLiveArgs(cu, mir); - rl_obj = ArmCodegen::ArgLoc(cu, rl_obj); + RegLocation rl_obj = mir_graph_->GetSrc(mir, 0); + LockLiveArgs(mir); + rl_obj = ArmMir2Lir::ArgLoc(rl_obj); RegLocation rl_dest; if (long_or_double) { - rl_dest = GetReturnWide(cu, false); + rl_dest = GetReturnWide(false); } else { - rl_dest = GetReturn(cu, false); + rl_dest = GetReturn(false); } // Point of no return - no aborts after this - ArmCodegen::GenPrintLabel(cu, mir); - rl_obj = LoadArg(cu, rl_obj); - cg->GenIGet(cu, field_idx, mir->optimization_flags, size, rl_dest, rl_obj, - long_or_double, is_object); - return GetNextMir(cu, bb, mir); + ArmMir2Lir::GenPrintLabel(mir); + rl_obj = LoadArg(rl_obj); + GenIGet(field_idx, mir->optimization_flags, size, rl_dest, rl_obj, long_or_double, is_object); + return GetNextMir(bb, mir); } -static MIR* SpecialIPut(CompilationUnit* cu, BasicBlock** bb, MIR* mir, - OpSize size, bool long_or_double, bool is_object) +MIR* ArmMir2Lir::SpecialIPut(BasicBlock** bb, MIR* mir, + OpSize size, bool long_or_double, bool is_object) { - Codegen* cg = cu->cg.get(); int field_offset; bool is_volatile; uint32_t field_idx = mir->dalvikInsn.vC; - bool fast_path = FastInstance(cu, field_idx, field_offset, is_volatile, false); + bool fast_path = FastInstance(field_idx, field_offset, is_volatile, false); if (!fast_path || !(mir->optimization_flags & MIR_IGNORE_NULL_CHECK)) { return NULL; } RegLocation rl_src; RegLocation rl_obj; - LockLiveArgs(cu, mir); + LockLiveArgs(mir); if (long_or_double) { - rl_src = GetSrcWide(cu, mir, 0); - rl_obj = GetSrc(cu, mir, 2); + rl_src = mir_graph_->GetSrcWide(mir, 0); + rl_obj = mir_graph_->GetSrc(mir, 2); } else { - rl_src = GetSrc(cu, mir, 0); - rl_obj = GetSrc(cu, mir, 1); + rl_src = mir_graph_->GetSrc(mir, 0); + rl_obj = mir_graph_->GetSrc(mir, 1); } - rl_src = ArmCodegen::ArgLoc(cu, rl_src); - rl_obj = ArmCodegen::ArgLoc(cu, rl_obj); + rl_src = ArmMir2Lir::ArgLoc(rl_src); + rl_obj = ArmMir2Lir::ArgLoc(rl_obj); // Reject if source is split across registers & frame if (rl_obj.location == kLocInvalid) { - ResetRegPool(cu); + ResetRegPool(); return NULL; } // Point of no return - no aborts after this - ArmCodegen::GenPrintLabel(cu, mir); - rl_obj = LoadArg(cu, rl_obj); - rl_src = LoadArg(cu, rl_src); - cg->GenIPut(cu, field_idx, mir->optimization_flags, size, rl_src, rl_obj, - long_or_double, is_object); - return GetNextMir(cu, bb, mir); + ArmMir2Lir::GenPrintLabel(mir); + rl_obj = LoadArg(rl_obj); + rl_src = LoadArg(rl_src); + GenIPut(field_idx, mir->optimization_flags, size, rl_src, rl_obj, long_or_double, is_object); + return GetNextMir(bb, mir); } -static MIR* SpecialIdentity(CompilationUnit* cu, MIR* mir) +MIR* ArmMir2Lir::SpecialIdentity(MIR* mir) { - Codegen* cg = cu->cg.get(); RegLocation rl_src; RegLocation rl_dest; bool wide = (mir->ssa_rep->num_uses == 2); if (wide) { - rl_src = GetSrcWide(cu, mir, 0); - rl_dest = GetReturnWide(cu, false); + rl_src = mir_graph_->GetSrcWide(mir, 0); + rl_dest = GetReturnWide(false); } else { - rl_src = GetSrc(cu, mir, 0); - rl_dest = GetReturn(cu, false); + rl_src = mir_graph_->GetSrc(mir, 0); + rl_dest = GetReturn(false); } - LockLiveArgs(cu, mir); - rl_src = ArmCodegen::ArgLoc(cu, rl_src); + LockLiveArgs(mir); + rl_src = ArmMir2Lir::ArgLoc(rl_src); if (rl_src.location == kLocInvalid) { - ResetRegPool(cu); + ResetRegPool(); return NULL; } // Point of no return - no aborts after this - ArmCodegen::GenPrintLabel(cu, mir); - rl_src = LoadArg(cu, rl_src); + ArmMir2Lir::GenPrintLabel(mir); + rl_src = LoadArg(rl_src); if (wide) { - cg->StoreValueWide(cu, rl_dest, rl_src); + StoreValueWide(rl_dest, rl_src); } else { - cg->StoreValue(cu, rl_dest, rl_src); + StoreValue(rl_dest, rl_src); } return mir; } @@ -230,10 +223,10 @@ static MIR* SpecialIdentity(CompilationUnit* cu, MIR* mir) /* * Special-case code genration for simple non-throwing leaf methods. */ -void ArmCodegen::GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, +void ArmMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, SpecialCaseHandler special_case) { - cu->current_dalvik_offset = mir->offset; + current_dalvik_offset_ = mir->offset; MIR* next_mir = NULL; switch (special_case) { case kNullMethod: @@ -241,67 +234,67 @@ void ArmCodegen::GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, next_mir = mir; break; case kConstFunction: - ArmCodegen::GenPrintLabel(cu, mir); - LoadConstant(cu, rARM_RET0, mir->dalvikInsn.vB); - next_mir = GetNextMir(cu, &bb, mir); + ArmMir2Lir::GenPrintLabel(mir); + LoadConstant(rARM_RET0, mir->dalvikInsn.vB); + next_mir = GetNextMir(&bb, mir); break; case kIGet: - next_mir = SpecialIGet(cu, &bb, mir, kWord, false, false); + next_mir = SpecialIGet(&bb, mir, kWord, false, false); break; case kIGetBoolean: case kIGetByte: - next_mir = SpecialIGet(cu, &bb, mir, kUnsignedByte, false, false); + next_mir = SpecialIGet(&bb, mir, kUnsignedByte, false, false); break; case kIGetObject: - next_mir = SpecialIGet(cu, &bb, mir, kWord, false, true); + next_mir = SpecialIGet(&bb, mir, kWord, false, true); break; case kIGetChar: - next_mir = SpecialIGet(cu, &bb, mir, kUnsignedHalf, false, false); + next_mir = SpecialIGet(&bb, mir, kUnsignedHalf, false, false); break; case kIGetShort: - next_mir = SpecialIGet(cu, &bb, mir, kSignedHalf, false, false); + next_mir = SpecialIGet(&bb, mir, kSignedHalf, false, false); break; case kIGetWide: - next_mir = SpecialIGet(cu, &bb, mir, kLong, true, false); + next_mir = SpecialIGet(&bb, mir, kLong, true, false); break; case kIPut: - next_mir = SpecialIPut(cu, &bb, mir, kWord, false, false); + next_mir = SpecialIPut(&bb, mir, kWord, false, false); break; case kIPutBoolean: case kIPutByte: - next_mir = SpecialIPut(cu, &bb, mir, kUnsignedByte, false, false); + next_mir = SpecialIPut(&bb, mir, kUnsignedByte, false, false); break; case kIPutObject: - next_mir = SpecialIPut(cu, &bb, mir, kWord, false, true); + next_mir = SpecialIPut(&bb, mir, kWord, false, true); break; case kIPutChar: - next_mir = SpecialIPut(cu, &bb, mir, kUnsignedHalf, false, false); + next_mir = SpecialIPut(&bb, mir, kUnsignedHalf, false, false); break; case kIPutShort: - next_mir = SpecialIPut(cu, &bb, mir, kSignedHalf, false, false); + next_mir = SpecialIPut(&bb, mir, kSignedHalf, false, false); break; case kIPutWide: - next_mir = SpecialIPut(cu, &bb, mir, kLong, true, false); + next_mir = SpecialIPut(&bb, mir, kLong, true, false); break; case kIdentity: - next_mir = SpecialIdentity(cu, mir); + next_mir = SpecialIdentity(mir); break; default: return; } if (next_mir != NULL) { - cu->current_dalvik_offset = next_mir->offset; + current_dalvik_offset_ = next_mir->offset; if (special_case != kIdentity) { - ArmCodegen::GenPrintLabel(cu, next_mir); + ArmMir2Lir::GenPrintLabel(next_mir); } - NewLIR1(cu, kThumbBx, rARM_LR); - cu->core_spill_mask = 0; - cu->num_core_spills = 0; - cu->fp_spill_mask = 0; - cu->num_fp_spills = 0; - cu->frame_size = 0; - cu->core_vmap_table.clear(); - cu->fp_vmap_table.clear(); + 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(); } } @@ -324,28 +317,28 @@ void ArmCodegen::GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, * add rARM_PC, r_disp ; This is the branch from which we compute displacement * cbnz r_idx, lp */ -void ArmCodegen::GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, +void ArmMir2Lir::GenSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; - if (cu->verbose) { + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + if (cu_->verbose) { DumpSparseSwitchTable(table); } // Add the table to the list - we'll process it later SwitchTable *tab_rec = - static_cast<SwitchTable*>(NewMem(cu, sizeof(SwitchTable), true, kAllocData)); + static_cast<SwitchTable*>(NewMem(cu_, sizeof(SwitchTable), true, kAllocData)); tab_rec->table = table; - tab_rec->vaddr = cu->current_dalvik_offset; + tab_rec->vaddr = current_dalvik_offset_; int size = table[1]; - tab_rec->targets = static_cast<LIR**>(NewMem(cu, size * sizeof(LIR*), true, kAllocLIR)); - InsertGrowableList(cu, &cu->switch_tables, reinterpret_cast<uintptr_t>(tab_rec)); + tab_rec->targets = static_cast<LIR**>(NewMem(cu_, size * sizeof(LIR*), true, kAllocLIR)); + InsertGrowableList(cu_, &switch_tables_, reinterpret_cast<uintptr_t>(tab_rec)); // Get the switch value - rl_src = LoadValue(cu, rl_src, kCoreReg); - int rBase = AllocTemp(cu); + rl_src = LoadValue(rl_src, kCoreReg); + int rBase = AllocTemp(); /* Allocate key and disp temps */ - int r_key = AllocTemp(cu); - int r_disp = AllocTemp(cu); + int r_key = AllocTemp(); + int r_disp = AllocTemp(); // Make sure r_key's register number is less than r_disp's number for ldmia if (r_key > r_disp) { int tmp = r_disp; @@ -353,69 +346,69 @@ void ArmCodegen::GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_o r_key = tmp; } // Materialize a pointer to the switch table - NewLIR3(cu, kThumb2Adr, rBase, 0, reinterpret_cast<uintptr_t>(tab_rec)); + NewLIR3(kThumb2Adr, rBase, 0, reinterpret_cast<uintptr_t>(tab_rec)); // Set up r_idx - int r_idx = AllocTemp(cu); - LoadConstant(cu, r_idx, size); + int r_idx = AllocTemp(); + LoadConstant(r_idx, size); // Establish loop branch target - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); // Load next key/disp - NewLIR2(cu, kThumb2LdmiaWB, rBase, (1 << r_key) | (1 << r_disp)); - OpRegReg(cu, kOpCmp, r_key, rl_src.low_reg); + NewLIR2(kThumb2LdmiaWB, rBase, (1 << r_key) | (1 << r_disp)); + OpRegReg(kOpCmp, r_key, rl_src.low_reg); // Go if match. NOTE: No instruction set switch here - must stay Thumb2 - OpIT(cu, kCondEq, ""); - LIR* switch_branch = NewLIR1(cu, kThumb2AddPCR, r_disp); + OpIT(kCondEq, ""); + LIR* switch_branch = NewLIR1(kThumb2AddPCR, r_disp); tab_rec->anchor = switch_branch; // Needs to use setflags encoding here - NewLIR3(cu, kThumb2SubsRRI12, r_idx, r_idx, 1); - OpCondBranch(cu, kCondNe, target); + NewLIR3(kThumb2SubsRRI12, r_idx, r_idx, 1); + OpCondBranch(kCondNe, target); } -void ArmCodegen::GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, +void ArmMir2Lir::GenPackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; - if (cu->verbose) { + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + if (cu_->verbose) { DumpPackedSwitchTable(table); } // Add the table to the list - we'll process it later SwitchTable *tab_rec = - static_cast<SwitchTable*>(NewMem(cu, sizeof(SwitchTable), true, kAllocData)); + static_cast<SwitchTable*>(NewMem(cu_, sizeof(SwitchTable), true, kAllocData)); tab_rec->table = table; - tab_rec->vaddr = cu->current_dalvik_offset; + tab_rec->vaddr = current_dalvik_offset_; int size = table[1]; - tab_rec->targets = static_cast<LIR**>(NewMem(cu, size * sizeof(LIR*), true, kAllocLIR)); - InsertGrowableList(cu, &cu->switch_tables, reinterpret_cast<uintptr_t>(tab_rec)); + tab_rec->targets = static_cast<LIR**>(NewMem(cu_, size * sizeof(LIR*), true, kAllocLIR)); + InsertGrowableList(cu_, &switch_tables_, reinterpret_cast<uintptr_t>(tab_rec)); // Get the switch value - rl_src = LoadValue(cu, rl_src, kCoreReg); - int table_base = AllocTemp(cu); + rl_src = LoadValue(rl_src, kCoreReg); + int table_base = AllocTemp(); // Materialize a pointer to the switch table - NewLIR3(cu, kThumb2Adr, table_base, 0, reinterpret_cast<uintptr_t>(tab_rec)); + NewLIR3(kThumb2Adr, table_base, 0, reinterpret_cast<uintptr_t>(tab_rec)); int low_key = s4FromSwitchData(&table[2]); int keyReg; // Remove the bias, if necessary if (low_key == 0) { keyReg = rl_src.low_reg; } else { - keyReg = AllocTemp(cu); - OpRegRegImm(cu, kOpSub, keyReg, rl_src.low_reg, low_key); + keyReg = AllocTemp(); + OpRegRegImm(kOpSub, keyReg, rl_src.low_reg, low_key); } // Bounds check - if < 0 or >= size continue following switch - OpRegImm(cu, kOpCmp, keyReg, size-1); - LIR* branch_over = OpCondBranch(cu, kCondHi, NULL); + OpRegImm(kOpCmp, keyReg, size-1); + LIR* branch_over = OpCondBranch(kCondHi, NULL); // Load the displacement from the switch table - int disp_reg = AllocTemp(cu); - LoadBaseIndexed(cu, table_base, keyReg, disp_reg, 2, kWord); + int disp_reg = AllocTemp(); + LoadBaseIndexed(table_base, keyReg, disp_reg, 2, kWord); // ..and go! NOTE: No instruction set switch here - must stay Thumb2 - LIR* switch_branch = NewLIR1(cu, kThumb2AddPCR, disp_reg); + LIR* switch_branch = NewLIR1(kThumb2AddPCR, disp_reg); tab_rec->anchor = switch_branch; /* branch_over target here */ - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); branch_over->target = target; } @@ -429,30 +422,30 @@ void ArmCodegen::GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_o * * Total size is 4+(width * size + 1)/2 16-bit code units. */ -void ArmCodegen::GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, RegLocation rl_src) +void ArmMir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; // Add the table to the list - we'll process it later FillArrayData *tab_rec = - static_cast<FillArrayData*>(NewMem(cu, sizeof(FillArrayData), true, kAllocData)); + static_cast<FillArrayData*>(NewMem(cu_, sizeof(FillArrayData), true, kAllocData)); tab_rec->table = table; - tab_rec->vaddr = cu->current_dalvik_offset; + tab_rec->vaddr = current_dalvik_offset_; uint16_t width = tab_rec->table[1]; uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16); tab_rec->size = (size * width) + 8; - InsertGrowableList(cu, &cu->fill_array_data, reinterpret_cast<uintptr_t>(tab_rec)); + InsertGrowableList(cu_, &fill_array_data_, reinterpret_cast<uintptr_t>(tab_rec)); // Making a call - use explicit registers - FlushAllRegs(cu); /* Everything to home location */ - LoadValueDirectFixed(cu, rl_src, r0); - LoadWordDisp(cu, rARM_SELF, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), + FlushAllRegs(); /* Everything to home location */ + LoadValueDirectFixed(rl_src, r0); + LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), rARM_LR); // Materialize a pointer to the fill data image - NewLIR3(cu, kThumb2Adr, r1, 0, reinterpret_cast<uintptr_t>(tab_rec)); - ClobberCalleeSave(cu); - LIR* call_inst = OpReg(cu, kOpBlx, rARM_LR); - MarkSafepointPC(cu, call_inst); + NewLIR3(kThumb2Adr, r1, 0, reinterpret_cast<uintptr_t>(tab_rec)); + ClobberCalleeSave(); + LIR* call_inst = OpReg(kOpBlx, rARM_LR); + MarkSafepointPC(call_inst); } /* @@ -481,33 +474,33 @@ void ArmCodegen::GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, Re * preserved. * */ -void ArmCodegen::GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation rl_src) +void ArmMir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) { - FlushAllRegs(cu); + FlushAllRegs(); DCHECK_EQ(LW_SHAPE_THIN, 0); - LoadValueDirectFixed(cu, rl_src, r0); // Get obj - LockCallTemps(cu); // Prepare for explicit register usage - GenNullCheck(cu, rl_src.s_reg_low, r0, opt_flags); - LoadWordDisp(cu, rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2); - NewLIR3(cu, kThumb2Ldrex, r1, r0, + LoadValueDirectFixed(rl_src, r0); // Get obj + LockCallTemps(); // Prepare for explicit register usage + GenNullCheck(rl_src.s_reg_low, r0, opt_flags); + LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2); + NewLIR3(kThumb2Ldrex, r1, r0, mirror::Object::MonitorOffset().Int32Value() >> 2); // Get object->lock // Align owner - OpRegImm(cu, kOpLsl, r2, LW_LOCK_OWNER_SHIFT); + OpRegImm(kOpLsl, r2, LW_LOCK_OWNER_SHIFT); // Is lock unheld on lock or held by us (==thread_id) on unlock? - NewLIR4(cu, kThumb2Bfi, r2, r1, 0, LW_LOCK_OWNER_SHIFT - 1); - NewLIR3(cu, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); - OpRegImm(cu, kOpCmp, r1, 0); - OpIT(cu, kCondEq, ""); - NewLIR4(cu, kThumb2Strex, r1, r2, r0, + NewLIR4(kThumb2Bfi, r2, r1, 0, LW_LOCK_OWNER_SHIFT - 1); + NewLIR3(kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); + OpRegImm(kOpCmp, r1, 0); + OpIT(kCondEq, ""); + NewLIR4(kThumb2Strex, r1, r2, r0, mirror::Object::MonitorOffset().Int32Value() >> 2); - OpRegImm(cu, kOpCmp, r1, 0); - OpIT(cu, kCondNe, "T"); + OpRegImm(kOpCmp, r1, 0); + OpIT(kCondNe, "T"); // Go expensive route - artLockObjectFromCode(self, obj); - LoadWordDisp(cu, rARM_SELF, ENTRYPOINT_OFFSET(pLockObjectFromCode), rARM_LR); - ClobberCalleeSave(cu); - LIR* call_inst = OpReg(cu, kOpBlx, rARM_LR); - MarkSafepointPC(cu, call_inst); - GenMemBarrier(cu, kLoadLoad); + LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pLockObjectFromCode), rARM_LR); + ClobberCalleeSave(); + LIR* call_inst = OpReg(kOpBlx, rARM_LR); + MarkSafepointPC(call_inst); + GenMemBarrier(kLoadLoad); } /* @@ -516,140 +509,140 @@ void ArmCodegen::GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation * a zero recursion count, it's safe to punch it back to the * initial, unlock thin state with a store word. */ -void ArmCodegen::GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation rl_src) +void ArmMir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) { DCHECK_EQ(LW_SHAPE_THIN, 0); - FlushAllRegs(cu); - LoadValueDirectFixed(cu, rl_src, r0); // Get obj - LockCallTemps(cu); // Prepare for explicit register usage - GenNullCheck(cu, rl_src.s_reg_low, r0, opt_flags); - LoadWordDisp(cu, r0, mirror::Object::MonitorOffset().Int32Value(), r1); // Get lock - LoadWordDisp(cu, rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2); + FlushAllRegs(); + LoadValueDirectFixed(rl_src, r0); // Get obj + LockCallTemps(); // Prepare for explicit register usage + GenNullCheck(rl_src.s_reg_low, r0, opt_flags); + LoadWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r1); // Get lock + LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2); // Is lock unheld on lock or held by us (==thread_id) on unlock? - OpRegRegImm(cu, kOpAnd, r3, r1, + OpRegRegImm(kOpAnd, r3, r1, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); // Align owner - OpRegImm(cu, kOpLsl, r2, LW_LOCK_OWNER_SHIFT); - NewLIR3(cu, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); - OpRegReg(cu, kOpSub, r1, r2); - OpIT(cu, kCondEq, "EE"); - StoreWordDisp(cu, r0, mirror::Object::MonitorOffset().Int32Value(), r3); + OpRegImm(kOpLsl, r2, LW_LOCK_OWNER_SHIFT); + NewLIR3(kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); + OpRegReg(kOpSub, r1, r2); + OpIT(kCondEq, "EE"); + StoreWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r3); // Go expensive route - UnlockObjectFromCode(obj); - LoadWordDisp(cu, rARM_SELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rARM_LR); - ClobberCalleeSave(cu); - LIR* call_inst = OpReg(cu, kOpBlx, rARM_LR); - MarkSafepointPC(cu, call_inst); - GenMemBarrier(cu, kStoreLoad); + LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rARM_LR); + ClobberCalleeSave(); + LIR* call_inst = OpReg(kOpBlx, rARM_LR); + MarkSafepointPC(call_inst); + GenMemBarrier(kStoreLoad); } -void ArmCodegen::GenMoveException(CompilationUnit* cu, RegLocation rl_dest) +void ArmMir2Lir::GenMoveException(RegLocation rl_dest) { int ex_offset = Thread::ExceptionOffset().Int32Value(); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int reset_reg = AllocTemp(cu); - LoadWordDisp(cu, rARM_SELF, ex_offset, rl_result.low_reg); - LoadConstant(cu, reset_reg, 0); - StoreWordDisp(cu, rARM_SELF, ex_offset, reset_reg); - FreeTemp(cu, reset_reg); - StoreValue(cu, rl_dest, rl_result); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + int reset_reg = AllocTemp(); + LoadWordDisp(rARM_SELF, ex_offset, rl_result.low_reg); + LoadConstant(reset_reg, 0); + StoreWordDisp(rARM_SELF, ex_offset, reset_reg); + FreeTemp(reset_reg); + StoreValue(rl_dest, rl_result); } /* * Mark garbage collection card. Skip if the value we're storing is null. */ -void ArmCodegen::MarkGCCard(CompilationUnit* cu, int val_reg, int tgt_addr_reg) +void ArmMir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg) { - int reg_card_base = AllocTemp(cu); - int reg_card_no = AllocTemp(cu); - LIR* branch_over = OpCmpImmBranch(cu, kCondEq, val_reg, 0, NULL); - LoadWordDisp(cu, rARM_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base); - OpRegRegImm(cu, kOpLsr, reg_card_no, tgt_addr_reg, CardTable::kCardShift); - StoreBaseIndexed(cu, reg_card_base, reg_card_no, reg_card_base, 0, + int reg_card_base = AllocTemp(); + int reg_card_no = AllocTemp(); + LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL); + LoadWordDisp(rARM_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base); + OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, CardTable::kCardShift); + StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte); - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); branch_over->target = target; - FreeTemp(cu, reg_card_base); - FreeTemp(cu, reg_card_no); + FreeTemp(reg_card_base); + FreeTemp(reg_card_no); } -void ArmCodegen::GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl_method) +void ArmMir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) { - int spill_count = cu->num_core_spills + cu->num_fp_spills; + int spill_count = num_core_spills_ + num_fp_spills_; /* * On entry, r0, r1, r2 & r3 are live. Let the register allocation * mechanism know so it doesn't try to use any of them when * expanding the frame or flushing. This leaves the utility * code with a single temp: r12. This should be enough. */ - LockTemp(cu, r0); - LockTemp(cu, r1); - LockTemp(cu, r2); - LockTemp(cu, r3); + LockTemp(r0); + LockTemp(r1); + LockTemp(r2); + LockTemp(r3); /* * We can safely skip the stack overflow check if we're * a leaf *and* our frame size < fudge factor. */ - bool skip_overflow_check = ((cu->attributes & METHOD_IS_LEAF) && - (static_cast<size_t>(cu->frame_size) < + bool skip_overflow_check = (mir_graph_->MethodIsLeaf() && + (static_cast<size_t>(frame_size_) < Thread::kStackOverflowReservedBytes)); - NewLIR0(cu, kPseudoMethodEntry); + NewLIR0(kPseudoMethodEntry); if (!skip_overflow_check) { /* Load stack limit */ - LoadWordDisp(cu, rARM_SELF, Thread::StackEndOffset().Int32Value(), r12); + LoadWordDisp(rARM_SELF, Thread::StackEndOffset().Int32Value(), r12); } /* Spill core callee saves */ - NewLIR1(cu, kThumb2Push, cu->core_spill_mask); + NewLIR1(kThumb2Push, core_spill_mask_); /* Need to spill any FP regs? */ - if (cu->num_fp_spills) { + if (num_fp_spills_) { /* * NOTE: fp spills are a little different from core spills in that * they are pushed as a contiguous block. When promoting from * the fp set, we must allocate all singles from s16..highest-promoted */ - NewLIR1(cu, kThumb2VPushCS, cu->num_fp_spills); + NewLIR1(kThumb2VPushCS, num_fp_spills_); } if (!skip_overflow_check) { - OpRegRegImm(cu, kOpSub, rARM_LR, rARM_SP, cu->frame_size - (spill_count * 4)); - GenRegRegCheck(cu, kCondCc, rARM_LR, r12, kThrowStackOverflow); - OpRegCopy(cu, rARM_SP, rARM_LR); // Establish stack + OpRegRegImm(kOpSub, rARM_LR, rARM_SP, frame_size_ - (spill_count * 4)); + GenRegRegCheck(kCondCc, rARM_LR, r12, kThrowStackOverflow); + OpRegCopy(rARM_SP, rARM_LR); // Establish stack } else { - OpRegImm(cu, kOpSub, rARM_SP, cu->frame_size - (spill_count * 4)); + OpRegImm(kOpSub, rARM_SP, frame_size_ - (spill_count * 4)); } - FlushIns(cu, ArgLocs, rl_method); + FlushIns(ArgLocs, rl_method); - FreeTemp(cu, r0); - FreeTemp(cu, r1); - FreeTemp(cu, r2); - FreeTemp(cu, r3); + FreeTemp(r0); + FreeTemp(r1); + FreeTemp(r2); + FreeTemp(r3); } -void ArmCodegen::GenExitSequence(CompilationUnit* cu) +void ArmMir2Lir::GenExitSequence() { - int spill_count = cu->num_core_spills + cu->num_fp_spills; + int spill_count = num_core_spills_ + num_fp_spills_; /* * In the exit path, r0/r1 are live - make sure they aren't * allocated by the register utilities as temps. */ - LockTemp(cu, r0); - LockTemp(cu, r1); + LockTemp(r0); + LockTemp(r1); - NewLIR0(cu, kPseudoMethodExit); - OpRegImm(cu, kOpAdd, rARM_SP, cu->frame_size - (spill_count * 4)); + NewLIR0(kPseudoMethodExit); + OpRegImm(kOpAdd, rARM_SP, frame_size_ - (spill_count * 4)); /* Need to restore any FP callee saves? */ - if (cu->num_fp_spills) { - NewLIR1(cu, kThumb2VPopCS, cu->num_fp_spills); + if (num_fp_spills_) { + NewLIR1(kThumb2VPopCS, num_fp_spills_); } - if (cu->core_spill_mask & (1 << rARM_LR)) { + if (core_spill_mask_ & (1 << rARM_LR)) { /* Unspill rARM_LR to rARM_PC */ - cu->core_spill_mask &= ~(1 << rARM_LR); - cu->core_spill_mask |= (1 << rARM_PC); + core_spill_mask_ &= ~(1 << rARM_LR); + core_spill_mask_ |= (1 << rARM_PC); } - NewLIR1(cu, kThumb2Pop, cu->core_spill_mask); - if (!(cu->core_spill_mask & (1 << rARM_PC))) { + NewLIR1(kThumb2Pop, core_spill_mask_); + if (!(core_spill_mask_ & (1 << rARM_PC))) { /* We didn't pop to rARM_PC, so must do a bv rARM_LR */ - NewLIR1(cu, kThumbBx, rARM_LR); + NewLIR1(kThumbBx, rARM_LR); } } diff --git a/src/compiler/dex/quick/arm/codegen_arm.h b/src/compiler/dex/quick/arm/codegen_arm.h index 29aef0e110..df9451ab42 100644 --- a/src/compiler/dex/quick/arm/codegen_arm.h +++ b/src/compiler/dex/quick/arm/codegen_arm.h @@ -21,64 +21,60 @@ namespace art { -class ArmCodegen : public Codegen { +class ArmMir2Lir : public Mir2Lir { public: + + ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph); + // Required for target - codegen helpers. - virtual bool SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode, - RegLocation rl_src, RegLocation rl_dest, int lit); - virtual int LoadHelper(CompilationUnit* cu, int offset); - virtual LIR* LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest, - OpSize size, int s_reg); - virtual LIR* LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo, - int r_dest_hi, int s_reg); - virtual LIR* LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest, int scale, - OpSize size); - virtual LIR* LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, - int displacement, int r_dest, int r_dest_hi, OpSize size, - int s_reg); - virtual LIR* LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value); - virtual LIR* LoadConstantWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi, int64_t value); - virtual LIR* StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src, - OpSize size); - virtual LIR* StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_src_lo, - int r_src_hi); - virtual LIR* StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src, int scale, - OpSize size); - virtual LIR* StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, - int displacement, int r_src, int r_src_hi, OpSize size, - int s_reg); - virtual void MarkGCCard(CompilationUnit* cu, int val_reg, int tgt_addr_reg); + virtual bool SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src, + RegLocation rl_dest, int lit); + virtual int LoadHelper(int offset); + virtual LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg); + virtual LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi, + int s_reg); + virtual LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size); + virtual LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_dest, int r_dest_hi, OpSize size, int s_reg); + virtual LIR* LoadConstantNoClobber(int r_dest, int value); + virtual LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value); + virtual LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size); + virtual LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi); + virtual LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size); + virtual LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_src, int r_src_hi, OpSize size, int s_reg); + virtual void MarkGCCard(int val_reg, int tgt_addr_reg); // Required for target - register utilities. virtual bool IsFpReg(int reg); virtual bool SameRegType(int reg1, int reg2); - virtual int AllocTypedTemp(CompilationUnit* cu, bool fp_hint, int reg_class); - virtual int AllocTypedTempPair(CompilationUnit* cu, bool fp_hint, int reg_class); + virtual int AllocTypedTemp(bool fp_hint, int reg_class); + virtual int AllocTypedTempPair(bool fp_hint, int reg_class); virtual int S2d(int low_reg, int high_reg); virtual int TargetReg(SpecialTargetRegister reg); - virtual RegisterInfo* GetRegInfo(CompilationUnit* cu, int reg); - virtual RegLocation GetReturnAlt(CompilationUnit* cu); - virtual RegLocation GetReturnWideAlt(CompilationUnit* cu); + virtual RegisterInfo* GetRegInfo(int reg); + virtual RegLocation GetReturnAlt(); + virtual RegLocation GetReturnWideAlt(); virtual RegLocation LocCReturn(); virtual RegLocation LocCReturnDouble(); virtual RegLocation LocCReturnFloat(); virtual RegLocation LocCReturnWide(); virtual uint32_t FpRegMask(); - virtual uint64_t GetRegMaskCommon(CompilationUnit* cu, int reg); - virtual void AdjustSpillMask(CompilationUnit* cu); - virtual void ClobberCalleeSave(CompilationUnit *cu); - virtual void FlushReg(CompilationUnit* cu, int reg); - virtual void FlushRegWide(CompilationUnit* cu, int reg1, int reg2); - virtual void FreeCallTemps(CompilationUnit* cu); - virtual void FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, RegLocation rl_free); - virtual void LockCallTemps(CompilationUnit* cu); - virtual void MarkPreservedSingle(CompilationUnit* cu, int v_reg, int reg); - virtual void CompilerInitializeRegAlloc(CompilationUnit* cu); + virtual uint64_t GetRegMaskCommon(int reg); + virtual void AdjustSpillMask(); + virtual void ClobberCalleeSave(); + virtual void FlushReg(int reg); + virtual void FlushRegWide(int reg1, int reg2); + virtual void FreeCallTemps(); + virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free); + virtual void LockCallTemps(); + virtual void MarkPreservedSingle(int v_reg, int reg); + virtual void CompilerInitializeRegAlloc(); // Required for target - miscellaneous. - virtual AssemblerStatus AssembleInstructions(CompilationUnit* cu, uintptr_t start_addr); + virtual AssemblerStatus AssembleInstructions(uintptr_t start_addr); virtual void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix); - virtual void SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir); + virtual void SetupTargetResourceMasks(LIR* lir); virtual const char* GetTargetInstFmt(int opcode); virtual const char* GetTargetInstName(int opcode); virtual std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr); @@ -88,129 +84,111 @@ class ArmCodegen : public Codegen { virtual bool IsUnconditionalBranch(LIR* lir); // Required for target - Dalvik-level generators. - virtual void GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, + virtual void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); - virtual void GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, - RegLocation rl_index, RegLocation rl_src, int scale); - virtual void GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, + virtual void GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index, + RegLocation rl_src, int scale); + virtual void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale); - virtual void GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, + virtual void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale); - virtual void GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_shift); - virtual void GenMulLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenAndLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenArithOpDouble(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest, + virtual void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_shift); + virtual void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenAndLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2); + virtual void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); - virtual void GenCmpFP(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); - virtual void GenConversion(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src); - virtual bool GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier); - virtual bool GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min); - virtual bool GenInlinedSqrt(CompilationUnit* cu, CallInfo* info); - virtual void GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenOrLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual LIR* GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code, int reg1, int base, - int offset, ThrowKind kind); - virtual RegLocation GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int reg_hi, - bool is_div); - virtual RegLocation GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int lit, - bool is_div); - virtual void GenCmpLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi); - virtual void GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, - RegLocation rl_method); - virtual void GenExitSequence(CompilationUnit* cu); - virtual void GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, - RegLocation rl_src); - virtual void GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, bool gt_bias, - bool is_double); - virtual void GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir); - virtual void GenSelect(CompilationUnit* cu, BasicBlock* bb, MIR* mir); - virtual void GenMemBarrier(CompilationUnit* cu, MemBarrierKind barrier_kind); - virtual void GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation rl_src); - virtual void GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation rl_src); - virtual void GenMoveException(CompilationUnit* cu, RegLocation rl_dest); - virtual void GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src, - RegLocation rl_result, int lit, int first_bit, - int second_bit); - virtual void GenNegDouble(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenNegFloat(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, - RegLocation rl_src); - virtual void GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, - RegLocation rl_src); - virtual void GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, - SpecialCaseHandler special_case); + virtual void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2); + virtual void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src); + virtual bool GenInlinedCas32(CallInfo* info, bool need_write_barrier); + virtual bool GenInlinedMinMaxInt(CallInfo* info, bool is_min); + virtual bool GenInlinedSqrt(CallInfo* info); + virtual void GenNegLong(RegLocation rl_dest, RegLocation rl_src); + virtual void GenOrLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenXorLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset, + ThrowKind kind); + virtual RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div); + virtual RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div); + virtual void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenDivZeroCheck(int reg_lo, int reg_hi); + virtual void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method); + virtual void GenExitSequence(); + virtual void GenFillArrayData(uint32_t table_offset, RegLocation rl_src); + virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double); + virtual void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir); + virtual void GenSelect(BasicBlock* bb, MIR* mir); + virtual void GenMemBarrier(MemBarrierKind barrier_kind); + virtual void GenMonitorEnter(int opt_flags, RegLocation rl_src); + virtual void GenMonitorExit(int opt_flags, RegLocation rl_src); + virtual void GenMoveException(RegLocation rl_dest); + virtual void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit, + int first_bit, int second_bit); + virtual void GenNegDouble(RegLocation rl_dest, RegLocation rl_src); + virtual void GenNegFloat(RegLocation rl_dest, RegLocation rl_src); + virtual void GenPackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src); + virtual void GenSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src); + virtual void GenSpecialCase(BasicBlock* bb, MIR* mir, SpecialCaseHandler special_case); // Required for target - single operation generators. - virtual LIR* OpUnconditionalBranch(CompilationUnit* cu, LIR* target); - virtual LIR* OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, int src2, - LIR* target); - virtual LIR* OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg, int check_value, - LIR* target); - virtual LIR* OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target); - virtual LIR* OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, - LIR* target); - virtual LIR* OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpIT(CompilationUnit* cu, ConditionCode cond, const char* guide); - virtual LIR* OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp); - virtual LIR* OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target); - virtual LIR* OpReg(CompilationUnit* cu, OpKind op, int r_dest_src); - virtual LIR* OpRegCopy(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpRegCopyNoInsert(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value); - virtual LIR* OpRegMem(CompilationUnit* cu, OpKind op, int r_dest, int rBase, int offset); - virtual LIR* OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2); - virtual LIR* OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value); - virtual LIR* OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, - int r_src2); - virtual LIR* OpTestSuspend(CompilationUnit* cu, LIR* target); - virtual LIR* OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset); - virtual LIR* OpVldm(CompilationUnit* cu, int rBase, int count); - virtual LIR* OpVstm(CompilationUnit* cu, int rBase, int count); - virtual void OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, - int offset); - virtual void OpRegCopyWide(CompilationUnit* cu, int dest_lo, int dest_hi, int src_lo, - int src_hi); - virtual void OpTlsCmp(CompilationUnit* cu, int offset, int val); + virtual LIR* OpUnconditionalBranch(LIR* target); + virtual LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target); + virtual LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target); + virtual LIR* OpCondBranch(ConditionCode cc, LIR* target); + virtual LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target); + virtual LIR* OpFpRegCopy(int r_dest, int r_src); + virtual LIR* OpIT(ConditionCode cond, const char* guide); + virtual LIR* OpMem(OpKind op, int rBase, int disp); + virtual LIR* OpPcRelLoad(int reg, LIR* target); + virtual LIR* OpReg(OpKind op, int r_dest_src); + virtual LIR* OpRegCopy(int r_dest, int r_src); + virtual LIR* OpRegCopyNoInsert(int r_dest, int r_src); + virtual LIR* OpRegImm(OpKind op, int r_dest_src1, int value); + virtual LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset); + virtual LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2); + virtual LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value); + virtual LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2); + virtual LIR* OpTestSuspend(LIR* target); + virtual LIR* OpThreadMem(OpKind op, int thread_offset); + virtual LIR* OpVldm(int rBase, int count); + virtual LIR* OpVstm(int rBase, int count); + virtual void OpLea(int rBase, int reg1, int reg2, int scale, int offset); + virtual void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi); + virtual void OpTlsCmp(int offset, int val); - static RegLocation ArgLoc(CompilationUnit* cu, RegLocation loc); - LIR* LoadBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_dest, - int r_dest_hi, OpSize size, int s_reg); - LIR* StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_src, - int r_src_hi, OpSize size); - static void GenPrintLabel(CompilationUnit *cu, MIR* mir); - static LIR* OpRegRegRegShift(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, - int r_src2, int shift); - static LIR* OpRegRegShift(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2, - int shift); + RegLocation ArgLoc(RegLocation loc); + LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size, + int s_reg); + LIR* StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size); + void GenPrintLabel(MIR* mir); + LIR* OpRegRegRegShift(OpKind op, int r_dest, int r_src1, int r_src2, int shift); + LIR* OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, int shift); static const ArmEncodingMap EncodingMap[kArmLast]; - static int EncodeShift(int code, int amount); - static int ModifiedImmediate(uint32_t value); - static ArmConditionCode ArmConditionEncoding(ConditionCode code); + int EncodeShift(int code, int amount); + int ModifiedImmediate(uint32_t value); + ArmConditionCode ArmConditionEncoding(ConditionCode code); bool InexpensiveConstantInt(int32_t value); bool InexpensiveConstantFloat(int32_t value); bool InexpensiveConstantLong(int64_t value); bool InexpensiveConstantDouble(int64_t value); private: - void GenFusedLongCmpImmBranch(CompilationUnit* cu, BasicBlock* bb, RegLocation rl_src1, - int64_t val, ConditionCode ccode); + void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, int64_t val, + ConditionCode ccode); + int InPosition(int s_reg); + RegLocation LoadArg(RegLocation loc); + void LockLiveArgs(MIR* mir); + MIR* GetNextMir(BasicBlock** p_bb, MIR* mir); + MIR* SpecialIGet(BasicBlock** bb, MIR* mir, OpSize size, bool long_or_double, bool is_object); + MIR* SpecialIPut(BasicBlock** bb, MIR* mir, OpSize size, bool long_or_double, bool is_object); + MIR* SpecialIdentity(MIR* mir); + LIR* LoadFPConstantValue(int r_dest, int value); + bool BadOverlap(RegLocation rl_src, RegLocation rl_dest); }; } // namespace art diff --git a/src/compiler/dex/quick/arm/fp_arm.cc b/src/compiler/dex/quick/arm/fp_arm.cc index cc65217b03..4bf8738949 100644 --- a/src/compiler/dex/quick/arm/fp_arm.cc +++ b/src/compiler/dex/quick/arm/fp_arm.cc @@ -16,12 +16,10 @@ #include "arm_lir.h" #include "codegen_arm.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" namespace art { -void ArmCodegen::GenArithOpFloat(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, +void ArmMir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { int op = kThumbBkpt; @@ -50,25 +48,25 @@ void ArmCodegen::GenArithOpFloat(CompilationUnit* cu, Instruction::Code opcode, break; case Instruction::REM_FLOAT_2ADDR: case Instruction::REM_FLOAT: - FlushAllRegs(cu); // Send everything to home location - CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false); - rl_result = GetReturn(cu, true); - StoreValue(cu, rl_dest, rl_result); + FlushAllRegs(); // Send everything to home location + CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false); + rl_result = GetReturn(true); + StoreValue(rl_dest, rl_result); return; case Instruction::NEG_FLOAT: - GenNegFloat(cu, rl_dest, rl_src1); + GenNegFloat(rl_dest, rl_src1); return; default: LOG(FATAL) << "Unexpected opcode: " << opcode; } - rl_src1 = LoadValue(cu, rl_src1, kFPReg); - rl_src2 = LoadValue(cu, rl_src2, kFPReg); - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR3(cu, op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); - StoreValue(cu, rl_dest, rl_result); + rl_src1 = LoadValue(rl_src1, kFPReg); + rl_src2 = LoadValue(rl_src2, kFPReg); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR3(op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); + StoreValue(rl_dest, rl_result); } -void ArmCodegen::GenArithOpDouble(CompilationUnit* cu, Instruction::Code opcode, +void ArmMir2Lir::GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { int op = kThumbBkpt; @@ -93,31 +91,31 @@ void ArmCodegen::GenArithOpDouble(CompilationUnit* cu, Instruction::Code opcode, break; case Instruction::REM_DOUBLE_2ADDR: case Instruction::REM_DOUBLE: - FlushAllRegs(cu); // Send everything to home location - CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false); - rl_result = GetReturnWide(cu, true); - StoreValueWide(cu, rl_dest, rl_result); + FlushAllRegs(); // Send everything to home location + CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false); + rl_result = GetReturnWide(true); + StoreValueWide(rl_dest, rl_result); return; case Instruction::NEG_DOUBLE: - GenNegDouble(cu, rl_dest, rl_src1); + GenNegDouble(rl_dest, rl_src1); return; default: LOG(FATAL) << "Unexpected opcode: " << opcode; } - rl_src1 = LoadValueWide(cu, rl_src1, kFPReg); + rl_src1 = LoadValueWide(rl_src1, kFPReg); DCHECK(rl_src1.wide); - rl_src2 = LoadValueWide(cu, rl_src2, kFPReg); + rl_src2 = LoadValueWide(rl_src2, kFPReg); DCHECK(rl_src2.wide); - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); + rl_result = EvalLoc(rl_dest, kFPReg, true); DCHECK(rl_dest.wide); DCHECK(rl_result.wide); - NewLIR3(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg), + NewLIR3(op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg), S2d(rl_src2.low_reg, rl_src2.high_reg)); - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void ArmCodegen::GenConversion(CompilationUnit* cu, Instruction::Code opcode, +void ArmMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) { int op = kThumbBkpt; @@ -144,60 +142,59 @@ void ArmCodegen::GenConversion(CompilationUnit* cu, Instruction::Code opcode, op = kThumb2VcvtDI; break; case Instruction::LONG_TO_DOUBLE: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src); return; case Instruction::FLOAT_TO_LONG: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src); return; case Instruction::LONG_TO_FLOAT: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src); return; case Instruction::DOUBLE_TO_LONG: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src); return; default: LOG(FATAL) << "Unexpected opcode: " << opcode; } if (rl_src.wide) { - rl_src = LoadValueWide(cu, rl_src, kFPReg); + rl_src = LoadValueWide(rl_src, kFPReg); src_reg = S2d(rl_src.low_reg, rl_src.high_reg); } else { - rl_src = LoadValue(cu, rl_src, kFPReg); + rl_src = LoadValue(rl_src, kFPReg); src_reg = rl_src.low_reg; } if (rl_dest.wide) { - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg); - StoreValueWide(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg); + StoreValueWide(rl_dest, rl_result); } else { - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, op, rl_result.low_reg, src_reg); - StoreValue(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(op, rl_result.low_reg, src_reg); + StoreValue(rl_dest, rl_result); } } -void ArmCodegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, bool gt_bias, +void ArmMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) { - LIR* label_list = cu->block_label_list; - LIR* target = &label_list[bb->taken->id]; + LIR* target = &block_label_list_[bb->taken->id]; RegLocation rl_src1; RegLocation rl_src2; if (is_double) { - rl_src1 = GetSrcWide(cu, mir, 0); - rl_src2 = GetSrcWide(cu, mir, 2); - rl_src1 = LoadValueWide(cu, rl_src1, kFPReg); - rl_src2 = LoadValueWide(cu, rl_src2, kFPReg); - NewLIR2(cu, kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg), + rl_src1 = mir_graph_->GetSrcWide(mir, 0); + rl_src2 = mir_graph_->GetSrcWide(mir, 2); + rl_src1 = LoadValueWide(rl_src1, kFPReg); + rl_src2 = LoadValueWide(rl_src2, kFPReg); + NewLIR2(kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg), S2d(rl_src2.low_reg, rl_src2.high_reg)); } else { - rl_src1 = GetSrc(cu, mir, 0); - rl_src2 = GetSrc(cu, mir, 1); - rl_src1 = LoadValue(cu, rl_src1, kFPReg); - rl_src2 = LoadValue(cu, rl_src2, kFPReg); - NewLIR2(cu, kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg); + rl_src1 = mir_graph_->GetSrc(mir, 0); + rl_src2 = mir_graph_->GetSrc(mir, 1); + rl_src1 = LoadValue(rl_src1, kFPReg); + rl_src2 = LoadValue(rl_src2, kFPReg); + NewLIR2(kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg); } - NewLIR0(cu, kThumb2Fmstat); + NewLIR0(kThumb2Fmstat); ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); switch(ccode) { case kCondEq: @@ -226,11 +223,11 @@ void ArmCodegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* m default: LOG(FATAL) << "Unexpected ccode: " << ccode; } - OpCondBranch(cu, ccode, target); + OpCondBranch(ccode, target); } -void ArmCodegen::GenCmpFP(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, +void ArmMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { bool is_double = false; @@ -258,78 +255,78 @@ void ArmCodegen::GenCmpFP(CompilationUnit* cu, Instruction::Code opcode, RegLoca LOG(FATAL) << "Unexpected opcode: " << opcode; } if (is_double) { - rl_src1 = LoadValueWide(cu, rl_src1, kFPReg); - rl_src2 = LoadValueWide(cu, rl_src2, kFPReg); + rl_src1 = LoadValueWide(rl_src1, kFPReg); + rl_src2 = LoadValueWide(rl_src2, kFPReg); // In case result vreg is also a src vreg, break association to avoid useless copy by EvalLoc() - ClobberSReg(cu, rl_dest.s_reg_low); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - LoadConstant(cu, rl_result.low_reg, default_result); - NewLIR2(cu, kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg), + ClobberSReg(rl_dest.s_reg_low); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + LoadConstant(rl_result.low_reg, default_result); + NewLIR2(kThumb2Vcmpd, S2d(rl_src1.low_reg, rl_src2.high_reg), S2d(rl_src2.low_reg, rl_src2.high_reg)); } else { - rl_src1 = LoadValue(cu, rl_src1, kFPReg); - rl_src2 = LoadValue(cu, rl_src2, kFPReg); + rl_src1 = LoadValue(rl_src1, kFPReg); + rl_src2 = LoadValue(rl_src2, kFPReg); // In case result vreg is also a srcvreg, break association to avoid useless copy by EvalLoc() - ClobberSReg(cu, rl_dest.s_reg_low); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - LoadConstant(cu, rl_result.low_reg, default_result); - NewLIR2(cu, kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg); + ClobberSReg(rl_dest.s_reg_low); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + LoadConstant(rl_result.low_reg, default_result); + NewLIR2(kThumb2Vcmps, rl_src1.low_reg, rl_src2.low_reg); } DCHECK(!ARM_FPREG(rl_result.low_reg)); - NewLIR0(cu, kThumb2Fmstat); + NewLIR0(kThumb2Fmstat); - OpIT(cu, (default_result == -1) ? kCondGt : kCondMi, ""); - NewLIR2(cu, kThumb2MovImmShift, rl_result.low_reg, + OpIT((default_result == -1) ? kCondGt : kCondMi, ""); + NewLIR2(kThumb2MovImmShift, rl_result.low_reg, ModifiedImmediate(-default_result)); // Must not alter ccodes - GenBarrier(cu); + GenBarrier(); - OpIT(cu, kCondEq, ""); - LoadConstant(cu, rl_result.low_reg, 0); - GenBarrier(cu); + OpIT(kCondEq, ""); + LoadConstant(rl_result.low_reg, 0); + GenBarrier(); - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } -void ArmCodegen::GenNegFloat(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void ArmMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { RegLocation rl_result; - rl_src = LoadValue(cu, rl_src, kFPReg); - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, kThumb2Vnegs, rl_result.low_reg, rl_src.low_reg); - StoreValue(cu, rl_dest, rl_result); + rl_src = LoadValue(rl_src, kFPReg); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(kThumb2Vnegs, rl_result.low_reg, rl_src.low_reg); + StoreValue(rl_dest, rl_result); } -void ArmCodegen::GenNegDouble(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void ArmMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { RegLocation rl_result; - rl_src = LoadValueWide(cu, rl_src, kFPReg); - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, kThumb2Vnegd, S2d(rl_result.low_reg, rl_result.high_reg), + rl_src = LoadValueWide(rl_src, kFPReg); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(kThumb2Vnegd, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src.low_reg, rl_src.high_reg)); - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -bool ArmCodegen::GenInlinedSqrt(CompilationUnit* cu, CallInfo* info) { - DCHECK_EQ(cu->instruction_set, kThumb2); +bool ArmMir2Lir::GenInlinedSqrt(CallInfo* info) { + DCHECK_EQ(cu_->instruction_set, kThumb2); LIR *branch; RegLocation rl_src = info->args[0]; - RegLocation rl_dest = InlineTargetWide(cu, info); // double place for result - rl_src = LoadValueWide(cu, rl_src, kFPReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, kThumb2Vsqrtd, S2d(rl_result.low_reg, rl_result.high_reg), + RegLocation rl_dest = InlineTargetWide(info); // double place for result + rl_src = LoadValueWide(rl_src, kFPReg); + RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(kThumb2Vsqrtd, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src.low_reg, rl_src.high_reg)); - NewLIR2(cu, kThumb2Vcmpd, S2d(rl_result.low_reg, rl_result.high_reg), + NewLIR2(kThumb2Vcmpd, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_result.low_reg, rl_result.high_reg)); - NewLIR0(cu, kThumb2Fmstat); - branch = NewLIR2(cu, kThumbBCond, 0, kArmCondEq); - ClobberCalleeSave(cu); - LockCallTemps(cu); // Using fixed registers - int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pSqrt)); - NewLIR3(cu, kThumb2Fmrrd, r0, r1, S2d(rl_src.low_reg, rl_src.high_reg)); - NewLIR1(cu, kThumbBlxR, r_tgt); - NewLIR3(cu, kThumb2Fmdrr, S2d(rl_result.low_reg, rl_result.high_reg), r0, r1); - branch->target = NewLIR0(cu, kPseudoTargetLabel); - StoreValueWide(cu, rl_dest, rl_result); + NewLIR0(kThumb2Fmstat); + branch = NewLIR2(kThumbBCond, 0, kArmCondEq); + ClobberCalleeSave(); + LockCallTemps(); // Using fixed registers + int r_tgt = LoadHelper(ENTRYPOINT_OFFSET(pSqrt)); + NewLIR3(kThumb2Fmrrd, r0, r1, S2d(rl_src.low_reg, rl_src.high_reg)); + NewLIR1(kThumbBlxR, r_tgt); + NewLIR3(kThumb2Fmdrr, S2d(rl_result.low_reg, rl_result.high_reg), r0, r1); + branch->target = NewLIR0(kPseudoTargetLabel); + StoreValueWide(rl_dest, rl_result); return true; } diff --git a/src/compiler/dex/quick/arm/int_arm.cc b/src/compiler/dex/quick/arm/int_arm.cc index 0ebc94321e..4133aea6aa 100644 --- a/src/compiler/dex/quick/arm/int_arm.cc +++ b/src/compiler/dex/quick/arm/int_arm.cc @@ -18,17 +18,15 @@ #include "arm_lir.h" #include "codegen_arm.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "oat/runtime/oat_support_entrypoints.h" namespace art { -LIR* ArmCodegen::OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, +LIR* ArmMir2Lir::OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target) { - OpRegReg(cu, kOpCmp, src1, src2); - return OpCondBranch(cu, cond, target); + OpRegReg(kOpCmp, src1, src2); + return OpCondBranch(cond, target); } /* @@ -41,7 +39,7 @@ LIR* ArmCodegen::OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, * met, and an "E" means the instruction is executed if the condition * is not met. */ -LIR* ArmCodegen::OpIT(CompilationUnit* cu, ConditionCode ccode, const char* guide) +LIR* ArmMir2Lir::OpIT(ConditionCode ccode, const char* guide) { int mask; int mask3 = 0; @@ -67,7 +65,7 @@ LIR* ArmCodegen::OpIT(CompilationUnit* cu, ConditionCode ccode, const char* guid } mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) | (1 << (3 - strlen(guide))); - return NewLIR2(cu, kThumb2It, code, mask); + return NewLIR2(kThumb2It, code, mask); } /* @@ -85,52 +83,51 @@ LIR* ArmCodegen::OpIT(CompilationUnit* cu, ConditionCode ccode, const char* guid * neg rX * done: */ -void ArmCodegen::GenCmpLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void ArmMir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LIR* target1; LIR* target2; - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); - rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg); - int t_reg = AllocTemp(cu); - LoadConstant(cu, t_reg, -1); - OpRegReg(cu, kOpCmp, rl_src1.high_reg, rl_src2.high_reg); - LIR* branch1 = OpCondBranch(cu, kCondLt, NULL); - LIR* branch2 = OpCondBranch(cu, kCondGt, NULL); - OpRegRegReg(cu, kOpSub, t_reg, rl_src1.low_reg, rl_src2.low_reg); - LIR* branch3 = OpCondBranch(cu, kCondEq, NULL); - - OpIT(cu, kCondHi, "E"); - NewLIR2(cu, kThumb2MovImmShift, t_reg, ModifiedImmediate(-1)); - LoadConstant(cu, t_reg, 1); - GenBarrier(cu); - - target2 = NewLIR0(cu, kPseudoTargetLabel); - OpRegReg(cu, kOpNeg, t_reg, t_reg); - - target1 = NewLIR0(cu, kPseudoTargetLabel); + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); + int t_reg = AllocTemp(); + LoadConstant(t_reg, -1); + OpRegReg(kOpCmp, rl_src1.high_reg, rl_src2.high_reg); + LIR* branch1 = OpCondBranch(kCondLt, NULL); + LIR* branch2 = OpCondBranch(kCondGt, NULL); + OpRegRegReg(kOpSub, t_reg, rl_src1.low_reg, rl_src2.low_reg); + LIR* branch3 = OpCondBranch(kCondEq, NULL); + + OpIT(kCondHi, "E"); + NewLIR2(kThumb2MovImmShift, t_reg, ModifiedImmediate(-1)); + LoadConstant(t_reg, 1); + GenBarrier(); + + target2 = NewLIR0(kPseudoTargetLabel); + OpRegReg(kOpNeg, t_reg, t_reg); + + target1 = NewLIR0(kPseudoTargetLabel); RegLocation rl_temp = LocCReturn(); // Just using as template, will change rl_temp.low_reg = t_reg; - StoreValue(cu, rl_dest, rl_temp); - FreeTemp(cu, t_reg); + StoreValue(rl_dest, rl_temp); + FreeTemp(t_reg); branch1->target = target1; branch2->target = target2; branch3->target = branch1->target; } -void ArmCodegen::GenFusedLongCmpImmBranch(CompilationUnit* cu, BasicBlock* bb, RegLocation rl_src1, +void ArmMir2Lir::GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, int64_t val, ConditionCode ccode) { int32_t val_lo = Low32Bits(val); int32_t val_hi = High32Bits(val); DCHECK(ModifiedImmediate(val_lo) >= 0); DCHECK(ModifiedImmediate(val_hi) >= 0); - LIR* label_list = cu->block_label_list; - LIR* taken = &label_list[bb->taken->id]; - LIR* not_taken = &label_list[bb->fall_through->id]; - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); + LIR* taken = &block_label_list_[bb->taken->id]; + LIR* not_taken = &block_label_list_[bb->fall_through->id]; + rl_src1 = LoadValueWide(rl_src1, kCoreReg); int32_t low_reg = rl_src1.low_reg; int32_t high_reg = rl_src1.high_reg; @@ -147,51 +144,51 @@ void ArmCodegen::GenFusedLongCmpImmBranch(CompilationUnit* cu, BasicBlock* bb, R condition = kCondNe; } if (val == 0) { - int t_reg = AllocTemp(cu); - NewLIR4(cu, kThumb2OrrRRRs, t_reg, low_reg, high_reg, 0); - FreeTemp(cu, t_reg); - OpCondBranch(cu, condition, taken); + int t_reg = AllocTemp(); + NewLIR4(kThumb2OrrRRRs, t_reg, low_reg, high_reg, 0); + FreeTemp(t_reg); + OpCondBranch(condition, taken); return; } - OpCmpImmBranch(cu, kCondNe, high_reg, val_hi, target); + OpCmpImmBranch(kCondNe, high_reg, val_hi, target); break; case kCondLt: - OpCmpImmBranch(cu, kCondLt, high_reg, val_hi, taken); - OpCmpImmBranch(cu, kCondGt, high_reg, val_hi, not_taken); + OpCmpImmBranch(kCondLt, high_reg, val_hi, taken); + OpCmpImmBranch(kCondGt, high_reg, val_hi, not_taken); ccode = kCondCc; break; case kCondLe: - OpCmpImmBranch(cu, kCondLt, high_reg, val_hi, taken); - OpCmpImmBranch(cu, kCondGt, high_reg, val_hi, not_taken); + OpCmpImmBranch(kCondLt, high_reg, val_hi, taken); + OpCmpImmBranch(kCondGt, high_reg, val_hi, not_taken); ccode = kCondLs; break; case kCondGt: - OpCmpImmBranch(cu, kCondGt, high_reg, val_hi, taken); - OpCmpImmBranch(cu, kCondLt, high_reg, val_hi, not_taken); + OpCmpImmBranch(kCondGt, high_reg, val_hi, taken); + OpCmpImmBranch(kCondLt, high_reg, val_hi, not_taken); ccode = kCondHi; break; case kCondGe: - OpCmpImmBranch(cu, kCondGt, high_reg, val_hi, taken); - OpCmpImmBranch(cu, kCondLt, high_reg, val_hi, not_taken); + OpCmpImmBranch(kCondGt, high_reg, val_hi, taken); + OpCmpImmBranch(kCondLt, high_reg, val_hi, not_taken); ccode = kCondCs; break; default: LOG(FATAL) << "Unexpected ccode: " << ccode; } - OpCmpImmBranch(cu, ccode, low_reg, val_lo, taken); + OpCmpImmBranch(ccode, low_reg, val_lo, taken); } -void ArmCodegen::GenSelect(CompilationUnit* cu, BasicBlock* bb, MIR* mir) +void ArmMir2Lir::GenSelect(BasicBlock* bb, MIR* mir) { RegLocation rl_result; - RegLocation rl_src = GetSrc(cu, mir, 0); + RegLocation rl_src = mir_graph_->GetSrc(mir, 0); // Temporary debugging code int dest_sreg = mir->ssa_rep->defs[0]; - if ((dest_sreg < 0) || (dest_sreg >= cu->mir_graph->GetNumSSARegs())) { + if ((dest_sreg < 0) || (dest_sreg >= mir_graph_->GetNumSSARegs())) { LOG(INFO) << "Bad target sreg: " << dest_sreg << ", in " - << PrettyMethod(cu->method_idx,*cu->dex_file); + << PrettyMethod(cu_->method_idx,*cu_->dex_file); LOG(INFO) << "at dex offset 0x" << std::hex << mir->offset; - LOG(INFO) << "vreg = " << cu->mir_graph->SRegToVReg(dest_sreg); + LOG(INFO) << "vreg = " << mir_graph_->SRegToVReg(dest_sreg); LOG(INFO) << "num uses = " << mir->ssa_rep->num_uses; if (mir->ssa_rep->num_uses == 1) { LOG(INFO) << "CONST case, vals = " << mir->dalvikInsn.vB << ", " << mir->dalvikInsn.vC; @@ -202,58 +199,58 @@ void ArmCodegen::GenSelect(CompilationUnit* cu, BasicBlock* bb, MIR* mir) CHECK(false) << "Invalid target sreg on Select."; } // End temporary debugging code - RegLocation rl_dest = GetDest(cu, mir); - rl_src = LoadValue(cu, rl_src, kCoreReg); + RegLocation rl_dest = mir_graph_->GetDest(mir); + rl_src = LoadValue(rl_src, kCoreReg); if (mir->ssa_rep->num_uses == 1) { // CONST case int true_val = mir->dalvikInsn.vB; int false_val = mir->dalvikInsn.vC; - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_result = EvalLoc(rl_dest, kCoreReg, true); if ((true_val == 1) && (false_val == 0)) { - OpRegRegImm(cu, kOpRsub, rl_result.low_reg, rl_src.low_reg, 1); - OpIT(cu, kCondCc, ""); - LoadConstant(cu, rl_result.low_reg, 0); - GenBarrier(cu); // Add a scheduling barrier to keep the IT shadow intact + OpRegRegImm(kOpRsub, rl_result.low_reg, rl_src.low_reg, 1); + OpIT(kCondCc, ""); + LoadConstant(rl_result.low_reg, 0); + GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact } else if (InexpensiveConstantInt(true_val) && InexpensiveConstantInt(false_val)) { - OpRegImm(cu, kOpCmp, rl_src.low_reg, 0); - OpIT(cu, kCondEq, "E"); - LoadConstant(cu, rl_result.low_reg, true_val); - LoadConstant(cu, rl_result.low_reg, false_val); - GenBarrier(cu); // Add a scheduling barrier to keep the IT shadow intact + OpRegImm(kOpCmp, rl_src.low_reg, 0); + OpIT(kCondEq, "E"); + LoadConstant(rl_result.low_reg, true_val); + LoadConstant(rl_result.low_reg, false_val); + GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact } else { // Unlikely case - could be tuned. - int t_reg1 = AllocTemp(cu); - int t_reg2 = AllocTemp(cu); - LoadConstant(cu, t_reg1, true_val); - LoadConstant(cu, t_reg2, false_val); - OpRegImm(cu, kOpCmp, rl_src.low_reg, 0); - OpIT(cu, kCondEq, "E"); - OpRegCopy(cu, rl_result.low_reg, t_reg1); - OpRegCopy(cu, rl_result.low_reg, t_reg2); - GenBarrier(cu); // Add a scheduling barrier to keep the IT shadow intact + int t_reg1 = AllocTemp(); + int t_reg2 = AllocTemp(); + LoadConstant(t_reg1, true_val); + LoadConstant(t_reg2, false_val); + OpRegImm(kOpCmp, rl_src.low_reg, 0); + OpIT(kCondEq, "E"); + OpRegCopy(rl_result.low_reg, t_reg1); + OpRegCopy(rl_result.low_reg, t_reg2); + GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact } } else { // MOVE case - RegLocation rl_true = cu->reg_location[mir->ssa_rep->uses[1]]; - RegLocation rl_false = cu->reg_location[mir->ssa_rep->uses[2]]; - rl_true = LoadValue(cu, rl_true, kCoreReg); - rl_false = LoadValue(cu, rl_false, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegImm(cu, kOpCmp, rl_src.low_reg, 0); - OpIT(cu, kCondEq, "E"); - LIR* l1 = OpRegCopy(cu, rl_result.low_reg, rl_true.low_reg); + RegLocation rl_true = mir_graph_->reg_location_[mir->ssa_rep->uses[1]]; + RegLocation rl_false = mir_graph_->reg_location_[mir->ssa_rep->uses[2]]; + rl_true = LoadValue(rl_true, kCoreReg); + rl_false = LoadValue(rl_false, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegImm(kOpCmp, rl_src.low_reg, 0); + OpIT(kCondEq, "E"); + LIR* l1 = OpRegCopy(rl_result.low_reg, rl_true.low_reg); l1->flags.is_nop = false; // Make sure this instruction isn't optimized away - LIR* l2 = OpRegCopy(cu, rl_result.low_reg, rl_false.low_reg); + LIR* l2 = OpRegCopy(rl_result.low_reg, rl_false.low_reg); l2->flags.is_nop = false; // Make sure this instruction isn't optimized away - GenBarrier(cu); // Add a scheduling barrier to keep the IT shadow intact + GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } -void ArmCodegen::GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir) +void ArmMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) { - RegLocation rl_src1 = GetSrcWide(cu, mir, 0); - RegLocation rl_src2 = GetSrcWide(cu, mir, 2); + RegLocation rl_src1 = mir_graph_->GetSrcWide(mir, 0); + RegLocation rl_src2 = mir_graph_->GetSrcWide(mir, 2); // Normalize such that if either operand is constant, src2 will be constant. ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); if (rl_src1.is_const) { @@ -263,60 +260,59 @@ void ArmCodegen::GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* ccode = FlipComparisonOrder(ccode); } if (rl_src2.is_const) { - RegLocation rl_temp = UpdateLocWide(cu, rl_src2); + RegLocation rl_temp = UpdateLocWide(rl_src2); // Do special compare/branch against simple const operand if not already in registers. - int64_t val = cu->mir_graph->ConstantValueWide(rl_src2); + int64_t val = mir_graph_->ConstantValueWide(rl_src2); if ((rl_temp.location != kLocPhysReg) && ((ModifiedImmediate(Low32Bits(val)) >= 0) && (ModifiedImmediate(High32Bits(val)) >= 0))) { - GenFusedLongCmpImmBranch(cu, bb, rl_src1, val, ccode); + GenFusedLongCmpImmBranch(bb, rl_src1, val, ccode); return; } } - LIR* label_list = cu->block_label_list; - LIR* taken = &label_list[bb->taken->id]; - LIR* not_taken = &label_list[bb->fall_through->id]; - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); - rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg); - OpRegReg(cu, kOpCmp, rl_src1.high_reg, rl_src2.high_reg); + LIR* taken = &block_label_list_[bb->taken->id]; + LIR* not_taken = &block_label_list_[bb->fall_through->id]; + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); + OpRegReg(kOpCmp, rl_src1.high_reg, rl_src2.high_reg); switch(ccode) { case kCondEq: - OpCondBranch(cu, kCondNe, not_taken); + OpCondBranch(kCondNe, not_taken); break; case kCondNe: - OpCondBranch(cu, kCondNe, taken); + OpCondBranch(kCondNe, taken); break; case kCondLt: - OpCondBranch(cu, kCondLt, taken); - OpCondBranch(cu, kCondGt, not_taken); + OpCondBranch(kCondLt, taken); + OpCondBranch(kCondGt, not_taken); ccode = kCondCc; break; case kCondLe: - OpCondBranch(cu, kCondLt, taken); - OpCondBranch(cu, kCondGt, not_taken); + OpCondBranch(kCondLt, taken); + OpCondBranch(kCondGt, not_taken); ccode = kCondLs; break; case kCondGt: - OpCondBranch(cu, kCondGt, taken); - OpCondBranch(cu, kCondLt, not_taken); + OpCondBranch(kCondGt, taken); + OpCondBranch(kCondLt, not_taken); ccode = kCondHi; break; case kCondGe: - OpCondBranch(cu, kCondGt, taken); - OpCondBranch(cu, kCondLt, not_taken); + OpCondBranch(kCondGt, taken); + OpCondBranch(kCondLt, not_taken); ccode = kCondCs; break; default: LOG(FATAL) << "Unexpected ccode: " << ccode; } - OpRegReg(cu, kOpCmp, rl_src1.low_reg, rl_src2.low_reg); - OpCondBranch(cu, ccode, taken); + OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg); + OpCondBranch(ccode, taken); } /* * Generate a register comparison to an immediate and branch. Caller * is responsible for setting branch target field. */ -LIR* ArmCodegen::OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg, int check_value, +LIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target) { LIR* branch; @@ -324,31 +320,31 @@ LIR* ArmCodegen::OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg ArmConditionCode arm_cond = ArmConditionEncoding(cond); if ((ARM_LOWREG(reg)) && (check_value == 0) && ((arm_cond == kArmCondEq) || (arm_cond == kArmCondNe))) { - branch = NewLIR2(cu, (arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz, + branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz, reg, 0); } else { mod_imm = ModifiedImmediate(check_value); if (ARM_LOWREG(reg) && ((check_value & 0xff) == check_value)) { - NewLIR2(cu, kThumbCmpRI8, reg, check_value); + NewLIR2(kThumbCmpRI8, reg, check_value); } else if (mod_imm >= 0) { - NewLIR2(cu, kThumb2CmpRI12, reg, mod_imm); + NewLIR2(kThumb2CmpRI12, reg, mod_imm); } else { - int t_reg = AllocTemp(cu); - LoadConstant(cu, t_reg, check_value); - OpRegReg(cu, kOpCmp, reg, t_reg); + int t_reg = AllocTemp(); + LoadConstant(t_reg, check_value); + OpRegReg(kOpCmp, reg, t_reg); } - branch = NewLIR2(cu, kThumbBCond, 0, arm_cond); + branch = NewLIR2(kThumbBCond, 0, arm_cond); } branch->target = target; return branch; } -LIR* ArmCodegen::OpRegCopyNoInsert(CompilationUnit* cu, int r_dest, int r_src) +LIR* ArmMir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) { LIR* res; int opcode; if (ARM_FPREG(r_dest) || ARM_FPREG(r_src)) - return OpFpRegCopy(cu, r_dest, r_src); + return OpFpRegCopy(r_dest, r_src); if (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src)) opcode = kThumbMovRR; else if (!ARM_LOWREG(r_dest) && !ARM_LOWREG(r_src)) @@ -357,21 +353,21 @@ LIR* ArmCodegen::OpRegCopyNoInsert(CompilationUnit* cu, int r_dest, int r_src) opcode = kThumbMovRR_H2L; else opcode = kThumbMovRR_L2H; - res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src); - if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) { + res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src); + if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) { res->flags.is_nop = true; } return res; } -LIR* ArmCodegen::OpRegCopy(CompilationUnit* cu, int r_dest, int r_src) +LIR* ArmMir2Lir::OpRegCopy(int r_dest, int r_src) { - LIR* res = OpRegCopyNoInsert(cu, r_dest, r_src); - AppendLIR(cu, res); + LIR* res = OpRegCopyNoInsert(r_dest, r_src); + AppendLIR(res); return res; } -void ArmCodegen::OpRegCopyWide(CompilationUnit* cu, int dest_lo, int dest_hi, int src_lo, +void ArmMir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi) { bool dest_fp = ARM_FPREG(dest_lo) && ARM_FPREG(dest_hi); @@ -380,21 +376,21 @@ void ArmCodegen::OpRegCopyWide(CompilationUnit* cu, int dest_lo, int dest_hi, in DCHECK_EQ(ARM_FPREG(dest_lo), ARM_FPREG(dest_hi)); if (dest_fp) { if (src_fp) { - OpRegCopy(cu, S2d(dest_lo, dest_hi), S2d(src_lo, src_hi)); + OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi)); } else { - NewLIR3(cu, kThumb2Fmdrr, S2d(dest_lo, dest_hi), src_lo, src_hi); + NewLIR3(kThumb2Fmdrr, S2d(dest_lo, dest_hi), src_lo, src_hi); } } else { if (src_fp) { - NewLIR3(cu, kThumb2Fmrrd, dest_lo, dest_hi, S2d(src_lo, src_hi)); + NewLIR3(kThumb2Fmrrd, dest_lo, dest_hi, S2d(src_lo, src_hi)); } else { // Handle overlap if (src_hi == dest_lo) { - OpRegCopy(cu, dest_hi, src_hi); - OpRegCopy(cu, dest_lo, src_lo); + OpRegCopy(dest_hi, src_hi); + OpRegCopy(dest_lo, src_lo); } else { - OpRegCopy(cu, dest_lo, src_lo); - OpRegCopy(cu, dest_hi, src_hi); + OpRegCopy(dest_lo, src_lo); + OpRegCopy(dest_hi, src_hi); } } } @@ -427,7 +423,7 @@ static const MagicTable magic_table[] = { }; // Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4) -bool ArmCodegen::SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode, +bool ArmMir2Lir::SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src, RegLocation rl_dest, int lit) { if ((lit < 0) || (lit >= static_cast<int>(sizeof(magic_table)/sizeof(magic_table[0])))) { @@ -442,122 +438,122 @@ bool ArmCodegen::SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvi return false; } - int r_magic = AllocTemp(cu); - LoadConstant(cu, r_magic, magic_table[lit].magic); - rl_src = LoadValue(cu, rl_src, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int r_hi = AllocTemp(cu); - int r_lo = AllocTemp(cu); - NewLIR4(cu, kThumb2Smull, r_lo, r_hi, r_magic, rl_src.low_reg); + int r_magic = AllocTemp(); + LoadConstant(r_magic, magic_table[lit].magic); + rl_src = LoadValue(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + int r_hi = AllocTemp(); + int r_lo = AllocTemp(); + NewLIR4(kThumb2Smull, r_lo, r_hi, r_magic, rl_src.low_reg); switch(pattern) { case Divide3: - OpRegRegRegShift(cu, kOpSub, rl_result.low_reg, r_hi, + OpRegRegRegShift(kOpSub, rl_result.low_reg, r_hi, rl_src.low_reg, EncodeShift(kArmAsr, 31)); break; case Divide5: - OpRegRegImm(cu, kOpAsr, r_lo, rl_src.low_reg, 31); - OpRegRegRegShift(cu, kOpRsub, rl_result.low_reg, r_lo, r_hi, + OpRegRegImm(kOpAsr, r_lo, rl_src.low_reg, 31); + OpRegRegRegShift(kOpRsub, rl_result.low_reg, r_lo, r_hi, EncodeShift(kArmAsr, magic_table[lit].shift)); break; case Divide7: - OpRegReg(cu, kOpAdd, r_hi, rl_src.low_reg); - OpRegRegImm(cu, kOpAsr, r_lo, rl_src.low_reg, 31); - OpRegRegRegShift(cu, kOpRsub, rl_result.low_reg, r_lo, r_hi, + OpRegReg(kOpAdd, r_hi, rl_src.low_reg); + OpRegRegImm(kOpAsr, r_lo, rl_src.low_reg, 31); + OpRegRegRegShift(kOpRsub, rl_result.low_reg, r_lo, r_hi, EncodeShift(kArmAsr, magic_table[lit].shift)); break; default: LOG(FATAL) << "Unexpected pattern: " << pattern; } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); return true; } -LIR* ArmCodegen::GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code, +LIR* ArmMir2Lir::GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset, ThrowKind kind) { LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm"; return NULL; } -RegLocation ArmCodegen::GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg1, int lit, +RegLocation ArmMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit, bool is_div) { LOG(FATAL) << "Unexpected use of GenDivRemLit for Arm"; return rl_dest; } -RegLocation ArmCodegen::GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg1, int reg2, +RegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, int reg1, int reg2, bool is_div) { LOG(FATAL) << "Unexpected use of GenDivRem for Arm"; return rl_dest; } -bool ArmCodegen::GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min) +bool ArmMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) { - DCHECK_EQ(cu->instruction_set, kThumb2); + DCHECK_EQ(cu_->instruction_set, kThumb2); RegLocation rl_src1 = info->args[0]; RegLocation rl_src2 = info->args[1]; - rl_src1 = LoadValue(cu, rl_src1, kCoreReg); - rl_src2 = LoadValue(cu, rl_src2, kCoreReg); - RegLocation rl_dest = InlineTarget(cu, info); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegReg(cu, kOpCmp, rl_src1.low_reg, rl_src2.low_reg); - OpIT(cu, (is_min) ? kCondGt : kCondLt, "E"); - OpRegReg(cu, kOpMov, rl_result.low_reg, rl_src2.low_reg); - OpRegReg(cu, kOpMov, rl_result.low_reg, rl_src1.low_reg); - GenBarrier(cu); - StoreValue(cu, rl_dest, rl_result); + rl_src1 = LoadValue(rl_src1, kCoreReg); + rl_src2 = LoadValue(rl_src2, kCoreReg); + RegLocation rl_dest = InlineTarget(info); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg); + OpIT((is_min) ? kCondGt : kCondLt, "E"); + OpRegReg(kOpMov, rl_result.low_reg, rl_src2.low_reg); + OpRegReg(kOpMov, rl_result.low_reg, rl_src1.low_reg); + GenBarrier(); + StoreValue(rl_dest, rl_result); return true; } -void ArmCodegen::OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, int offset) +void ArmMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) { LOG(FATAL) << "Unexpected use of OpLea for Arm"; } -void ArmCodegen::OpTlsCmp(CompilationUnit* cu, int offset, int val) +void ArmMir2Lir::OpTlsCmp(int offset, int val) { LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm"; } -bool ArmCodegen::GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier) { - DCHECK_EQ(cu->instruction_set, kThumb2); +bool ArmMir2Lir::GenInlinedCas32(CallInfo* info, bool need_write_barrier) { + DCHECK_EQ(cu_->instruction_set, kThumb2); // Unused - RegLocation rl_src_unsafe = info->args[0]; RegLocation rl_src_obj= info->args[1]; // Object - known non-null RegLocation rl_src_offset= info->args[2]; // long low rl_src_offset.wide = 0; // ignore high half in info->args[3] RegLocation rl_src_expected= info->args[4]; // int or Object RegLocation rl_src_new_value= info->args[5]; // int or Object - RegLocation rl_dest = InlineTarget(cu, info); // boolean place for result + RegLocation rl_dest = InlineTarget(info); // boolean place for result // Release store semantics, get the barrier out of the way. TODO: revisit - GenMemBarrier(cu, kStoreLoad); + GenMemBarrier(kStoreLoad); - RegLocation rl_object = LoadValue(cu, rl_src_obj, kCoreReg); - RegLocation rl_new_value = LoadValue(cu, rl_src_new_value, kCoreReg); + RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg); + RegLocation rl_new_value = LoadValue(rl_src_new_value, kCoreReg); - if (need_write_barrier && !cu->mir_graph->IsConstantNullRef(rl_new_value)) { + if (need_write_barrier && !mir_graph_->IsConstantNullRef(rl_new_value)) { // Mark card for object assuming new value is stored. - MarkGCCard(cu, rl_new_value.low_reg, rl_object.low_reg); + MarkGCCard(rl_new_value.low_reg, rl_object.low_reg); } - RegLocation rl_offset = LoadValue(cu, rl_src_offset, kCoreReg); + RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg); - int r_ptr = AllocTemp(cu); - OpRegRegReg(cu, kOpAdd, r_ptr, rl_object.low_reg, rl_offset.low_reg); + int r_ptr = AllocTemp(); + OpRegRegReg(kOpAdd, r_ptr, rl_object.low_reg, rl_offset.low_reg); // Free now unneeded rl_object and rl_offset to give more temps. - ClobberSReg(cu, rl_object.s_reg_low); - FreeTemp(cu, rl_object.low_reg); - ClobberSReg(cu, rl_offset.s_reg_low); - FreeTemp(cu, rl_offset.low_reg); + ClobberSReg(rl_object.s_reg_low); + FreeTemp(rl_object.low_reg); + ClobberSReg(rl_offset.s_reg_low); + FreeTemp(rl_offset.low_reg); - int r_old_value = AllocTemp(cu); - NewLIR3(cu, kThumb2Ldrex, r_old_value, r_ptr, 0); // r_old_value := [r_ptr] + int r_old_value = AllocTemp(); + NewLIR3(kThumb2Ldrex, r_old_value, r_ptr, 0); // r_old_value := [r_ptr] - RegLocation rl_expected = LoadValue(cu, rl_src_expected, kCoreReg); + RegLocation rl_expected = LoadValue(rl_src_expected, kCoreReg); // if (r_old_value == rExpected) { // [r_ptr] <- r_new_value && r_result := success ? 0 : 1 @@ -565,70 +561,70 @@ bool ArmCodegen::GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_ // } else { // r_result := 0 // } - OpRegReg(cu, kOpCmp, r_old_value, rl_expected.low_reg); - FreeTemp(cu, r_old_value); // Now unneeded. - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpIT(cu, kCondEq, "TE"); - NewLIR4(cu, kThumb2Strex, rl_result.low_reg, rl_new_value.low_reg, r_ptr, 0); - FreeTemp(cu, r_ptr); // Now unneeded. - OpRegImm(cu, kOpXor, rl_result.low_reg, 1); - OpRegReg(cu, kOpXor, rl_result.low_reg, rl_result.low_reg); + OpRegReg(kOpCmp, r_old_value, rl_expected.low_reg); + FreeTemp(r_old_value); // Now unneeded. + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpIT(kCondEq, "TE"); + NewLIR4(kThumb2Strex, rl_result.low_reg, rl_new_value.low_reg, r_ptr, 0); + FreeTemp(r_ptr); // Now unneeded. + OpRegImm(kOpXor, rl_result.low_reg, 1); + OpRegReg(kOpXor, rl_result.low_reg, rl_result.low_reg); - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); return true; } -LIR* ArmCodegen::OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target) +LIR* ArmMir2Lir::OpPcRelLoad(int reg, LIR* target) { - return RawLIR(cu, cu->current_dalvik_offset, kThumb2LdrPcRel12, reg, 0, 0, 0, 0, target); + return RawLIR(current_dalvik_offset_, kThumb2LdrPcRel12, reg, 0, 0, 0, 0, target); } -LIR* ArmCodegen::OpVldm(CompilationUnit* cu, int rBase, int count) +LIR* ArmMir2Lir::OpVldm(int rBase, int count) { - return NewLIR3(cu, kThumb2Vldms, rBase, fr0, count); + return NewLIR3(kThumb2Vldms, rBase, fr0, count); } -LIR* ArmCodegen::OpVstm(CompilationUnit* cu, int rBase, int count) +LIR* ArmMir2Lir::OpVstm(int rBase, int count) { - return NewLIR3(cu, kThumb2Vstms, rBase, fr0, count); + return NewLIR3(kThumb2Vstms, rBase, fr0, count); } -void ArmCodegen::GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src, +void ArmMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit, int first_bit, int second_bit) { - OpRegRegRegShift(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg, + OpRegRegRegShift(kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg, EncodeShift(kArmLsl, second_bit - first_bit)); if (first_bit != 0) { - OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit); + OpRegRegImm(kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit); } } -void ArmCodegen::GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi) +void ArmMir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) { - int t_reg = AllocTemp(cu); - NewLIR4(cu, kThumb2OrrRRRs, t_reg, reg_lo, reg_hi, 0); - FreeTemp(cu, t_reg); - GenCheck(cu, kCondEq, kThrowDivZero); + int t_reg = AllocTemp(); + NewLIR4(kThumb2OrrRRRs, t_reg, reg_lo, reg_hi, 0); + FreeTemp(t_reg); + GenCheck(kCondEq, kThrowDivZero); } // Test suspend flag, return target of taken suspend branch -LIR* ArmCodegen::OpTestSuspend(CompilationUnit* cu, LIR* target) +LIR* ArmMir2Lir::OpTestSuspend(LIR* target) { - NewLIR2(cu, kThumbSubRI8, rARM_SUSPEND, 1); - return OpCondBranch(cu, (target == NULL) ? kCondEq : kCondNe, target); + NewLIR2(kThumbSubRI8, rARM_SUSPEND, 1); + return OpCondBranch((target == NULL) ? kCondEq : kCondNe, target); } // Decrement register and branch on condition -LIR* ArmCodegen::OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, LIR* target) +LIR* ArmMir2Lir::OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) { // Combine sub & test using sub setflags encoding here - NewLIR3(cu, kThumb2SubsRRI12, reg, reg, 1); - return OpCondBranch(cu, c_code, target); + NewLIR3(kThumb2SubsRRI12, reg, reg, 1); + return OpCondBranch(c_code, target); } -void ArmCodegen::GenMemBarrier(CompilationUnit* cu, MemBarrierKind barrier_kind) +void ArmMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { #if ANDROID_SMP != 0 int dmb_flavor; @@ -643,29 +639,29 @@ void ArmCodegen::GenMemBarrier(CompilationUnit* cu, MemBarrierKind barrier_kind) dmb_flavor = kSY; // quiet gcc. break; } - LIR* dmb = NewLIR1(cu, kThumb2Dmb, dmb_flavor); + LIR* dmb = NewLIR1(kThumb2Dmb, dmb_flavor); dmb->def_mask = ENCODE_ALL; #endif } -void ArmCodegen::GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void ArmMir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) { - rl_src = LoadValueWide(cu, rl_src, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int z_reg = AllocTemp(cu); - LoadConstantNoClobber(cu, z_reg, 0); + rl_src = LoadValueWide(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + int z_reg = AllocTemp(); + LoadConstantNoClobber(z_reg, 0); // Check for destructive overlap if (rl_result.low_reg == rl_src.high_reg) { - int t_reg = AllocTemp(cu); - OpRegRegReg(cu, kOpSub, rl_result.low_reg, z_reg, rl_src.low_reg); - OpRegRegReg(cu, kOpSbc, rl_result.high_reg, z_reg, t_reg); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + OpRegRegReg(kOpSub, rl_result.low_reg, z_reg, rl_src.low_reg); + OpRegRegReg(kOpSbc, rl_result.high_reg, z_reg, t_reg); + FreeTemp(t_reg); } else { - OpRegRegReg(cu, kOpSub, rl_result.low_reg, z_reg, rl_src.low_reg); - OpRegRegReg(cu, kOpSbc, rl_result.high_reg, z_reg, rl_src.high_reg); + OpRegRegReg(kOpSub, rl_result.low_reg, z_reg, rl_src.low_reg); + OpRegRegReg(kOpSbc, rl_result.high_reg, z_reg, rl_src.high_reg); } - FreeTemp(cu, z_reg); - StoreValueWide(cu, rl_dest, rl_result); + FreeTemp(z_reg); + StoreValueWide(rl_dest, rl_result); } @@ -674,14 +670,14 @@ void ArmCodegen::GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocatio * is not usual for dx to generate, but it is legal (for now). In a future rev of * dex, we'll want to make this case illegal. */ -static bool BadOverlap(CompilationUnit* cu, RegLocation rl_src, RegLocation rl_dest) +bool ArmMir2Lir::BadOverlap(RegLocation rl_src, RegLocation rl_dest) { DCHECK(rl_src.wide); DCHECK(rl_dest.wide); - return (abs(cu->mir_graph->SRegToVReg(rl_src.s_reg_low) - cu->mir_graph->SRegToVReg(rl_dest.s_reg_low)) == 1); + return (abs(mir_graph_->SRegToVReg(rl_src.s_reg_low) - mir_graph_->SRegToVReg(rl_dest.s_reg_low)) == 1); } -void ArmCodegen::GenMulLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void ArmMir2Lir::GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { /* @@ -694,92 +690,92 @@ void ArmCodegen::GenMulLong(CompilationUnit* cu, RegLocation rl_dest, RegLocatio * overlap with either operand and send that case to a runtime handler. */ RegLocation rl_result; - if (BadOverlap(cu, rl_src1, rl_dest) || (BadOverlap(cu, rl_src2, rl_dest))) { + if (BadOverlap(rl_src1, rl_dest) || (BadOverlap(rl_src2, rl_dest))) { int func_offset = ENTRYPOINT_OFFSET(pLmul); - FlushAllRegs(cu); - CallRuntimeHelperRegLocationRegLocation(cu, func_offset, rl_src1, rl_src2, false); - rl_result = GetReturnWide(cu, false); - StoreValueWide(cu, rl_dest, rl_result); + FlushAllRegs(); + CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_src2, false); + rl_result = GetReturnWide(false); + StoreValueWide(rl_dest, rl_result); return; } // Temporarily add LR to the temp pool, and assign it to tmp1 - MarkTemp(cu, rARM_LR); - FreeTemp(cu, rARM_LR); + MarkTemp(rARM_LR); + FreeTemp(rARM_LR); int tmp1 = rARM_LR; - LockTemp(cu, rARM_LR); + LockTemp(rARM_LR); - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); - rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg); + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); bool special_case = true; // If operands are the same, or any pair has been promoted we're not the special case. if ((rl_src1.s_reg_low == rl_src2.s_reg_low) || - (!IsTemp(cu, rl_src1.low_reg) && !IsTemp(cu, rl_src1.high_reg)) || - (!IsTemp(cu, rl_src2.low_reg) && !IsTemp(cu, rl_src2.high_reg))) { + (!IsTemp(rl_src1.low_reg) && !IsTemp(rl_src1.high_reg)) || + (!IsTemp(rl_src2.low_reg) && !IsTemp(rl_src2.high_reg))) { special_case = false; } // Tuning: if rl_dest has been promoted and is *not* either operand, could use directly. - int res_lo = AllocTemp(cu); + int res_lo = AllocTemp(); int res_hi; if (rl_src1.low_reg == rl_src2.low_reg) { - res_hi = AllocTemp(cu); - NewLIR3(cu, kThumb2MulRRR, tmp1, rl_src1.low_reg, rl_src1.high_reg); - NewLIR4(cu, kThumb2Umull, res_lo, res_hi, rl_src1.low_reg, rl_src1.low_reg); - OpRegRegRegShift(cu, kOpAdd, res_hi, res_hi, tmp1, EncodeShift(kArmLsl, 1)); + res_hi = AllocTemp(); + NewLIR3(kThumb2MulRRR, tmp1, rl_src1.low_reg, rl_src1.high_reg); + NewLIR4(kThumb2Umull, res_lo, res_hi, rl_src1.low_reg, rl_src1.low_reg); + OpRegRegRegShift(kOpAdd, res_hi, res_hi, tmp1, EncodeShift(kArmLsl, 1)); } else { // In the special case, all temps are now allocated - NewLIR3(cu, kThumb2MulRRR, tmp1, rl_src2.low_reg, rl_src1.high_reg); + NewLIR3(kThumb2MulRRR, tmp1, rl_src2.low_reg, rl_src1.high_reg); if (special_case) { DCHECK_NE(rl_src1.low_reg, rl_src2.low_reg); DCHECK_NE(rl_src1.high_reg, rl_src2.high_reg); - FreeTemp(cu, rl_src1.high_reg); + FreeTemp(rl_src1.high_reg); } - res_hi = AllocTemp(cu); + res_hi = AllocTemp(); - NewLIR4(cu, kThumb2Umull, res_lo, res_hi, rl_src2.low_reg, rl_src1.low_reg); - NewLIR4(cu, kThumb2Mla, tmp1, rl_src1.low_reg, rl_src2.high_reg, tmp1); - NewLIR4(cu, kThumb2AddRRR, res_hi, tmp1, res_hi, 0); + NewLIR4(kThumb2Umull, res_lo, res_hi, rl_src2.low_reg, rl_src1.low_reg); + NewLIR4(kThumb2Mla, tmp1, rl_src1.low_reg, rl_src2.high_reg, tmp1); + NewLIR4(kThumb2AddRRR, res_hi, tmp1, res_hi, 0); if (special_case) { - FreeTemp(cu, rl_src1.low_reg); - Clobber(cu, rl_src1.low_reg); - Clobber(cu, rl_src1.high_reg); + FreeTemp(rl_src1.low_reg); + Clobber(rl_src1.low_reg); + Clobber(rl_src1.high_reg); } } - FreeTemp(cu, tmp1); - rl_result = GetReturnWide(cu, false); // Just using as a template. + FreeTemp(tmp1); + rl_result = GetReturnWide(false); // Just using as a template. rl_result.low_reg = res_lo; rl_result.high_reg = res_hi; - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); // Now, restore lr to its non-temp status. - Clobber(cu, rARM_LR); - UnmarkTemp(cu, rARM_LR); + Clobber(rARM_LR); + UnmarkTemp(rARM_LR); } -void ArmCodegen::GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void ArmMir2Lir::GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenAddLong for Arm"; } -void ArmCodegen::GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void ArmMir2Lir::GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenSubLong for Arm"; } -void ArmCodegen::GenAndLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void ArmMir2Lir::GenAndLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenAndLong for Arm"; } -void ArmCodegen::GenOrLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void ArmMir2Lir::GenOrLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenOrLong for Arm"; } -void ArmCodegen::GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void ArmMir2Lir::GenXorLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of genXoLong for Arm"; @@ -788,7 +784,7 @@ void ArmCodegen::GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocatio /* * Generate array load */ -void ArmCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, +void ArmMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); @@ -796,9 +792,9 @@ void ArmCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, Re int data_offset; RegLocation rl_result; bool constant_index = rl_index.is_const; - rl_array = LoadValue(cu, rl_array, kCoreReg); + rl_array = LoadValue(rl_array, kCoreReg); if (!constant_index) { - rl_index = LoadValue(cu, rl_index, kCoreReg); + rl_index = LoadValue(rl_index, kCoreReg); } if (rl_dest.wide) { @@ -809,18 +805,18 @@ void ArmCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, Re // If index is constant, just fold it into the data offset if (constant_index) { - data_offset += cu->mir_graph->ConstantValue(rl_index) << scale; + data_offset += mir_graph_->ConstantValue(rl_index) << scale; } /* null object? */ - GenNullCheck(cu, rl_array.s_reg_low, rl_array.low_reg, opt_flags); + GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags); bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK)); int reg_len = INVALID_REG; if (needs_range_check) { - reg_len = AllocTemp(cu); + reg_len = AllocTemp(); /* Get len */ - LoadWordDisp(cu, rl_array.low_reg, len_offset, reg_len); + LoadWordDisp(rl_array.low_reg, len_offset, reg_len); } if (rl_dest.wide || rl_dest.fp || constant_index) { int reg_ptr; @@ -828,50 +824,50 @@ void ArmCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, Re reg_ptr = rl_array.low_reg; // NOTE: must not alter reg_ptr in constant case. } else { // No special indexed operation, lea + load w/ displacement - reg_ptr = AllocTemp(cu); - OpRegRegRegShift(cu, kOpAdd, reg_ptr, rl_array.low_reg, rl_index.low_reg, + reg_ptr = AllocTemp(); + OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.low_reg, rl_index.low_reg, EncodeShift(kArmLsl, scale)); - FreeTemp(cu, rl_index.low_reg); + FreeTemp(rl_index.low_reg); } - rl_result = EvalLoc(cu, rl_dest, reg_class, true); + rl_result = EvalLoc(rl_dest, reg_class, true); if (needs_range_check) { if (constant_index) { - GenImmedCheck(cu, kCondLs, reg_len, cu->mir_graph->ConstantValue(rl_index), kThrowConstantArrayBounds); + GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds); } else { - GenRegRegCheck(cu, kCondLs, reg_len, rl_index.low_reg, kThrowArrayBounds); + GenRegRegCheck(kCondLs, reg_len, rl_index.low_reg, kThrowArrayBounds); } - FreeTemp(cu, reg_len); + FreeTemp(reg_len); } if (rl_dest.wide) { - LoadBaseDispWide(cu, reg_ptr, data_offset, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); + LoadBaseDispWide(reg_ptr, data_offset, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); if (!constant_index) { - FreeTemp(cu, reg_ptr); + FreeTemp(reg_ptr); } - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } else { - LoadBaseDisp(cu, reg_ptr, data_offset, rl_result.low_reg, size, INVALID_SREG); + LoadBaseDisp(reg_ptr, data_offset, rl_result.low_reg, size, INVALID_SREG); if (!constant_index) { - FreeTemp(cu, reg_ptr); + FreeTemp(reg_ptr); } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } } else { // Offset base, then use indexed load - int reg_ptr = AllocTemp(cu); - OpRegRegImm(cu, kOpAdd, reg_ptr, rl_array.low_reg, data_offset); - FreeTemp(cu, rl_array.low_reg); - rl_result = EvalLoc(cu, rl_dest, reg_class, true); + int reg_ptr = AllocTemp(); + OpRegRegImm(kOpAdd, reg_ptr, rl_array.low_reg, data_offset); + FreeTemp(rl_array.low_reg); + rl_result = EvalLoc(rl_dest, reg_class, true); if (needs_range_check) { // TODO: change kCondCS to a more meaningful name, is the sense of // carry-set/clear flipped? - GenRegRegCheck(cu, kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); - FreeTemp(cu, reg_len); + GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); + FreeTemp(reg_len); } - LoadBaseIndexed(cu, reg_ptr, rl_index.low_reg, rl_result.low_reg, scale, size); - FreeTemp(cu, reg_ptr); - StoreValue(cu, rl_dest, rl_result); + LoadBaseIndexed(reg_ptr, rl_index.low_reg, rl_result.low_reg, scale, size); + FreeTemp(reg_ptr); + StoreValue(rl_dest, rl_result); } } @@ -879,7 +875,7 @@ void ArmCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, Re * Generate array store * */ -void ArmCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, +void ArmMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); @@ -895,73 +891,73 @@ void ArmCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, Re // If index is constant, just fold it into the data offset. if (constant_index) { - data_offset += cu->mir_graph->ConstantValue(rl_index) << scale; + data_offset += mir_graph_->ConstantValue(rl_index) << scale; } - rl_array = LoadValue(cu, rl_array, kCoreReg); + rl_array = LoadValue(rl_array, kCoreReg); if (!constant_index) { - rl_index = LoadValue(cu, rl_index, kCoreReg); + rl_index = LoadValue(rl_index, kCoreReg); } int reg_ptr; if (constant_index) { reg_ptr = rl_array.low_reg; - } else if (IsTemp(cu, rl_array.low_reg)) { - Clobber(cu, rl_array.low_reg); + } else if (IsTemp(rl_array.low_reg)) { + Clobber(rl_array.low_reg); reg_ptr = rl_array.low_reg; } else { - reg_ptr = AllocTemp(cu); + reg_ptr = AllocTemp(); } /* null object? */ - GenNullCheck(cu, rl_array.s_reg_low, rl_array.low_reg, opt_flags); + GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags); bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK)); int reg_len = INVALID_REG; if (needs_range_check) { - reg_len = AllocTemp(cu); + reg_len = AllocTemp(); //NOTE: max live temps(4) here. /* Get len */ - LoadWordDisp(cu, rl_array.low_reg, len_offset, reg_len); + LoadWordDisp(rl_array.low_reg, len_offset, reg_len); } /* at this point, reg_ptr points to array, 2 live temps */ if (rl_src.wide || rl_src.fp || constant_index) { if (rl_src.wide) { - rl_src = LoadValueWide(cu, rl_src, reg_class); + rl_src = LoadValueWide(rl_src, reg_class); } else { - rl_src = LoadValue(cu, rl_src, reg_class); + rl_src = LoadValue(rl_src, reg_class); } if (!constant_index) { - OpRegRegRegShift(cu, kOpAdd, reg_ptr, rl_array.low_reg, rl_index.low_reg, + OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.low_reg, rl_index.low_reg, EncodeShift(kArmLsl, scale)); } if (needs_range_check) { if (constant_index) { - GenImmedCheck(cu, kCondLs, reg_len, cu->mir_graph->ConstantValue(rl_index), kThrowConstantArrayBounds); + GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds); } else { - GenRegRegCheck(cu, kCondLs, reg_len, rl_index.low_reg, kThrowArrayBounds); + GenRegRegCheck(kCondLs, reg_len, rl_index.low_reg, kThrowArrayBounds); } - FreeTemp(cu, reg_len); + FreeTemp(reg_len); } if (rl_src.wide) { - StoreBaseDispWide(cu, reg_ptr, data_offset, rl_src.low_reg, rl_src.high_reg); + StoreBaseDispWide(reg_ptr, data_offset, rl_src.low_reg, rl_src.high_reg); } else { - StoreBaseDisp(cu, reg_ptr, data_offset, rl_src.low_reg, size); + StoreBaseDisp(reg_ptr, data_offset, rl_src.low_reg, size); } } else { /* reg_ptr -> array data */ - OpRegRegImm(cu, kOpAdd, reg_ptr, rl_array.low_reg, data_offset); - rl_src = LoadValue(cu, rl_src, reg_class); + OpRegRegImm(kOpAdd, reg_ptr, rl_array.low_reg, data_offset); + rl_src = LoadValue(rl_src, reg_class); if (needs_range_check) { - GenRegRegCheck(cu, kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); - FreeTemp(cu, reg_len); + GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); + FreeTemp(reg_len); } - StoreBaseIndexed(cu, reg_ptr, rl_index.low_reg, rl_src.low_reg, + StoreBaseIndexed(reg_ptr, rl_index.low_reg, rl_src.low_reg, scale, size); } if (!constant_index) { - FreeTemp(cu, reg_ptr); + FreeTemp(reg_ptr); } } @@ -969,144 +965,144 @@ void ArmCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, Re * Generate array store * */ -void ArmCodegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, +void ArmMir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(); - FlushAllRegs(cu); // Use explicit registers - LockCallTemps(cu); + FlushAllRegs(); // Use explicit registers + LockCallTemps(); int r_value = TargetReg(kArg0); // Register holding value int r_array_class = TargetReg(kArg1); // Register holding array's Class int r_array = TargetReg(kArg2); // Register holding array int r_index = TargetReg(kArg3); // Register holding index into array - LoadValueDirectFixed(cu, rl_array, r_array); // Grab array - LoadValueDirectFixed(cu, rl_src, r_value); // Grab value - LoadValueDirectFixed(cu, rl_index, r_index); // Grab index + LoadValueDirectFixed(rl_array, r_array); // Grab array + LoadValueDirectFixed(rl_src, r_value); // Grab value + LoadValueDirectFixed(rl_index, r_index); // Grab index - GenNullCheck(cu, rl_array.s_reg_low, r_array, opt_flags); // NPE? + GenNullCheck(rl_array.s_reg_low, r_array, opt_flags); // NPE? // Store of null? - LIR* null_value_check = OpCmpImmBranch(cu, kCondEq, r_value, 0, NULL); + LIR* null_value_check = OpCmpImmBranch(kCondEq, r_value, 0, NULL); // Get the array's class. - LoadWordDisp(cu, r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); - CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, + LoadWordDisp(r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); + CallRuntimeHelperRegReg(ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, r_array_class, true); // Redo LoadValues in case they didn't survive the call. - LoadValueDirectFixed(cu, rl_array, r_array); // Reload array - LoadValueDirectFixed(cu, rl_index, r_index); // Reload index - LoadValueDirectFixed(cu, rl_src, r_value); // Reload value + LoadValueDirectFixed(rl_array, r_array); // Reload array + LoadValueDirectFixed(rl_index, r_index); // Reload index + LoadValueDirectFixed(rl_src, r_value); // Reload value r_array_class = INVALID_REG; // Branch here if value to be stored == null - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); null_value_check->target = target; bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK)); int reg_len = INVALID_REG; if (needs_range_check) { reg_len = TargetReg(kArg1); - LoadWordDisp(cu, r_array, len_offset, reg_len); // Get len + LoadWordDisp(r_array, len_offset, reg_len); // Get len } /* r_ptr -> array data */ - int r_ptr = AllocTemp(cu); - OpRegRegImm(cu, kOpAdd, r_ptr, r_array, data_offset); + int r_ptr = AllocTemp(); + OpRegRegImm(kOpAdd, r_ptr, r_array, data_offset); if (needs_range_check) { - GenRegRegCheck(cu, kCondCs, r_index, reg_len, kThrowArrayBounds); + GenRegRegCheck(kCondCs, r_index, reg_len, kThrowArrayBounds); } - StoreBaseIndexed(cu, r_ptr, r_index, r_value, scale, kWord); - FreeTemp(cu, r_ptr); - FreeTemp(cu, r_index); - if (!cu->mir_graph->IsConstantNullRef(rl_src)) { - MarkGCCard(cu, r_value, r_array); + StoreBaseIndexed(r_ptr, r_index, r_value, scale, kWord); + FreeTemp(r_ptr); + FreeTemp(r_index); + if (!mir_graph_->IsConstantNullRef(rl_src)) { + MarkGCCard(r_value, r_array); } } -void ArmCodegen::GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, +void ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift) { - rl_src = LoadValueWide(cu, rl_src, kCoreReg); + rl_src = LoadValueWide(rl_src, kCoreReg); // Per spec, we only care about low 6 bits of shift amount. - int shift_amount = cu->mir_graph->ConstantValue(rl_shift) & 0x3f; + int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f; if (shift_amount == 0) { - StoreValueWide(cu, rl_dest, rl_src); + StoreValueWide(rl_dest, rl_src); return; } - if (BadOverlap(cu, rl_src, rl_dest)) { - GenShiftOpLong(cu, opcode, rl_dest, rl_src, rl_shift); + if (BadOverlap(rl_src, rl_dest)) { + GenShiftOpLong(opcode, rl_dest, rl_src, rl_shift); return; } - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); switch(opcode) { case Instruction::SHL_LONG: case Instruction::SHL_LONG_2ADDR: if (shift_amount == 1) { - OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg); - OpRegRegReg(cu, kOpAdc, rl_result.high_reg, rl_src.high_reg, rl_src.high_reg); + OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg); + OpRegRegReg(kOpAdc, rl_result.high_reg, rl_src.high_reg, rl_src.high_reg); } else if (shift_amount == 32) { - OpRegCopy(cu, rl_result.high_reg, rl_src.low_reg); - LoadConstant(cu, rl_result.low_reg, 0); + OpRegCopy(rl_result.high_reg, rl_src.low_reg); + LoadConstant(rl_result.low_reg, 0); } else if (shift_amount > 31) { - OpRegRegImm(cu, kOpLsl, rl_result.high_reg, rl_src.low_reg, shift_amount - 32); - LoadConstant(cu, rl_result.low_reg, 0); + OpRegRegImm(kOpLsl, rl_result.high_reg, rl_src.low_reg, shift_amount - 32); + LoadConstant(rl_result.low_reg, 0); } else { - OpRegRegImm(cu, kOpLsl, rl_result.high_reg, rl_src.high_reg, shift_amount); - OpRegRegRegShift(cu, kOpOr, rl_result.high_reg, rl_result.high_reg, rl_src.low_reg, + OpRegRegImm(kOpLsl, rl_result.high_reg, rl_src.high_reg, shift_amount); + OpRegRegRegShift(kOpOr, rl_result.high_reg, rl_result.high_reg, rl_src.low_reg, EncodeShift(kArmLsr, 32 - shift_amount)); - OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_src.low_reg, shift_amount); + OpRegRegImm(kOpLsl, rl_result.low_reg, rl_src.low_reg, shift_amount); } break; case Instruction::SHR_LONG: case Instruction::SHR_LONG_2ADDR: if (shift_amount == 32) { - OpRegCopy(cu, rl_result.low_reg, rl_src.high_reg); - OpRegRegImm(cu, kOpAsr, rl_result.high_reg, rl_src.high_reg, 31); + OpRegCopy(rl_result.low_reg, rl_src.high_reg); + OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, 31); } else if (shift_amount > 31) { - OpRegRegImm(cu, kOpAsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32); - OpRegRegImm(cu, kOpAsr, rl_result.high_reg, rl_src.high_reg, 31); + OpRegRegImm(kOpAsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32); + OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, 31); } else { - int t_reg = AllocTemp(cu); - OpRegRegImm(cu, kOpLsr, t_reg, rl_src.low_reg, shift_amount); - OpRegRegRegShift(cu, kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg, + int t_reg = AllocTemp(); + OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, shift_amount); + OpRegRegRegShift(kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg, EncodeShift(kArmLsl, 32 - shift_amount)); - FreeTemp(cu, t_reg); - OpRegRegImm(cu, kOpAsr, rl_result.high_reg, rl_src.high_reg, shift_amount); + FreeTemp(t_reg); + OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, shift_amount); } break; case Instruction::USHR_LONG: case Instruction::USHR_LONG_2ADDR: if (shift_amount == 32) { - OpRegCopy(cu, rl_result.low_reg, rl_src.high_reg); - LoadConstant(cu, rl_result.high_reg, 0); + OpRegCopy(rl_result.low_reg, rl_src.high_reg); + LoadConstant(rl_result.high_reg, 0); } else if (shift_amount > 31) { - OpRegRegImm(cu, kOpLsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32); - LoadConstant(cu, rl_result.high_reg, 0); + OpRegRegImm(kOpLsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32); + LoadConstant(rl_result.high_reg, 0); } else { - int t_reg = AllocTemp(cu); - OpRegRegImm(cu, kOpLsr, t_reg, rl_src.low_reg, shift_amount); - OpRegRegRegShift(cu, kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg, + int t_reg = AllocTemp(); + OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, shift_amount); + OpRegRegRegShift(kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg, EncodeShift(kArmLsl, 32 - shift_amount)); - FreeTemp(cu, t_reg); - OpRegRegImm(cu, kOpLsr, rl_result.high_reg, rl_src.high_reg, shift_amount); + FreeTemp(t_reg); + OpRegRegImm(kOpLsr, rl_result.high_reg, rl_src.high_reg, shift_amount); } break; default: LOG(FATAL) << "Unexpected case"; } - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void ArmCodegen::GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode, +void ArmMir2Lir::GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { if ((opcode == Instruction::SUB_LONG_2ADDR) || (opcode == Instruction::SUB_LONG)) { if (!rl_src2.is_const) { // Don't bother with special handling for subtract from immediate. - GenArithOpLong(cu, opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); return; } } else { @@ -1118,12 +1114,12 @@ void ArmCodegen::GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode rl_src2 = rl_temp; } } - if (BadOverlap(cu, rl_src1, rl_dest)) { - GenArithOpLong(cu, opcode, rl_dest, rl_src1, rl_src2); + if (BadOverlap(rl_src1, rl_dest)) { + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); return; } DCHECK(rl_src2.is_const); - int64_t val = cu->mir_graph->ConstantValueWide(rl_src2); + int64_t val = mir_graph_->ConstantValueWide(rl_src2); uint32_t val_lo = Low32Bits(val); uint32_t val_hi = High32Bits(val); int32_t mod_imm_lo = ModifiedImmediate(val_lo); @@ -1136,54 +1132,54 @@ void ArmCodegen::GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode case Instruction::SUB_LONG: case Instruction::SUB_LONG_2ADDR: if ((mod_imm_lo < 0) || (mod_imm_hi < 0)) { - GenArithOpLong(cu, opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); return; } break; default: break; } - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); // NOTE: once we've done the EvalLoc on dest, we can no longer bail. switch (opcode) { case Instruction::ADD_LONG: case Instruction::ADD_LONG_2ADDR: - NewLIR3(cu, kThumb2AddRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo); - NewLIR3(cu, kThumb2AdcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi); + NewLIR3(kThumb2AddRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo); + NewLIR3(kThumb2AdcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi); break; case Instruction::OR_LONG: case Instruction::OR_LONG_2ADDR: if ((val_lo != 0) || (rl_result.low_reg != rl_src1.low_reg)) { - OpRegRegImm(cu, kOpOr, rl_result.low_reg, rl_src1.low_reg, val_lo); + OpRegRegImm(kOpOr, rl_result.low_reg, rl_src1.low_reg, val_lo); } if ((val_hi != 0) || (rl_result.high_reg != rl_src1.high_reg)) { - OpRegRegImm(cu, kOpOr, rl_result.high_reg, rl_src1.high_reg, val_hi); + OpRegRegImm(kOpOr, rl_result.high_reg, rl_src1.high_reg, val_hi); } break; case Instruction::XOR_LONG: case Instruction::XOR_LONG_2ADDR: - OpRegRegImm(cu, kOpXor, rl_result.low_reg, rl_src1.low_reg, val_lo); - OpRegRegImm(cu, kOpXor, rl_result.high_reg, rl_src1.high_reg, val_hi); + OpRegRegImm(kOpXor, rl_result.low_reg, rl_src1.low_reg, val_lo); + OpRegRegImm(kOpXor, rl_result.high_reg, rl_src1.high_reg, val_hi); break; case Instruction::AND_LONG: case Instruction::AND_LONG_2ADDR: if ((val_lo != 0xffffffff) || (rl_result.low_reg != rl_src1.low_reg)) { - OpRegRegImm(cu, kOpAnd, rl_result.low_reg, rl_src1.low_reg, val_lo); + OpRegRegImm(kOpAnd, rl_result.low_reg, rl_src1.low_reg, val_lo); } if ((val_hi != 0xffffffff) || (rl_result.high_reg != rl_src1.high_reg)) { - OpRegRegImm(cu, kOpAnd, rl_result.high_reg, rl_src1.high_reg, val_hi); + OpRegRegImm(kOpAnd, rl_result.high_reg, rl_src1.high_reg, val_hi); } break; case Instruction::SUB_LONG_2ADDR: case Instruction::SUB_LONG: - NewLIR3(cu, kThumb2SubRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo); - NewLIR3(cu, kThumb2SbcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi); + NewLIR3(kThumb2SubRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo); + NewLIR3(kThumb2SbcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi); break; default: LOG(FATAL) << "Unexpected opcode " << opcode; } - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } } // namespace art diff --git a/src/compiler/dex/quick/arm/target_arm.cc b/src/compiler/dex/quick/arm/target_arm.cc index 6d8102f27c..43bbb6993b 100644 --- a/src/compiler/dex/quick/arm/target_arm.cc +++ b/src/compiler/dex/quick/arm/target_arm.cc @@ -18,9 +18,7 @@ #include "arm_lir.h" #include "codegen_arm.h" -#include "compiler/dex/quick/codegen_util.h" #include "compiler/dex/compiler_internals.h" -#include "compiler/dex/quick/ralloc_util.h" namespace art { @@ -35,32 +33,32 @@ static int core_temps[] = {r0, r1, r2, r3, r12}; static int fp_temps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15}; -RegLocation ArmCodegen::LocCReturn() +RegLocation ArmMir2Lir::LocCReturn() { RegLocation res = ARM_LOC_C_RETURN; return res; } -RegLocation ArmCodegen::LocCReturnWide() +RegLocation ArmMir2Lir::LocCReturnWide() { RegLocation res = ARM_LOC_C_RETURN_WIDE; return res; } -RegLocation ArmCodegen::LocCReturnFloat() +RegLocation ArmMir2Lir::LocCReturnFloat() { RegLocation res = ARM_LOC_C_RETURN_FLOAT; return res; } -RegLocation ArmCodegen::LocCReturnDouble() +RegLocation ArmMir2Lir::LocCReturnDouble() { RegLocation res = ARM_LOC_C_RETURN_DOUBLE; return res; } // Return a target-dependent special register. -int ArmCodegen::TargetReg(SpecialTargetRegister reg) { +int ArmMir2Lir::TargetReg(SpecialTargetRegister reg) { int res = INVALID_REG; switch (reg) { case kSelf: res = rARM_SELF; break; @@ -86,19 +84,19 @@ int ArmCodegen::TargetReg(SpecialTargetRegister reg) { // Create a double from a pair of singles. -int ArmCodegen::S2d(int low_reg, int high_reg) +int ArmMir2Lir::S2d(int low_reg, int high_reg) { return ARM_S2D(low_reg, high_reg); } // Return mask to strip off fp reg flags and bias. -uint32_t ArmCodegen::FpRegMask() +uint32_t ArmMir2Lir::FpRegMask() { return ARM_FP_REG_MASK; } // True if both regs single, both core or both double. -bool ArmCodegen::SameRegType(int reg1, int reg2) +bool ArmMir2Lir::SameRegType(int reg1, int reg2) { return (ARM_REGTYPE(reg1) == ARM_REGTYPE(reg2)); } @@ -106,7 +104,7 @@ bool ArmCodegen::SameRegType(int reg1, int reg2) /* * Decode the register id. */ -uint64_t ArmCodegen::GetRegMaskCommon(CompilationUnit* cu, int reg) +uint64_t ArmMir2Lir::GetRegMaskCommon(int reg) { uint64_t seed; int shift; @@ -123,17 +121,17 @@ uint64_t ArmCodegen::GetRegMaskCommon(CompilationUnit* cu, int reg) return (seed << shift); } -uint64_t ArmCodegen::GetPCUseDefEncoding() +uint64_t ArmMir2Lir::GetPCUseDefEncoding() { return ENCODE_ARM_REG_PC; } -void ArmCodegen::SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir) +void ArmMir2Lir::SetupTargetResourceMasks(LIR* lir) { - DCHECK_EQ(cu->instruction_set, kThumb2); + DCHECK_EQ(cu_->instruction_set, kThumb2); // Thumb2 specific setup - uint64_t flags = ArmCodegen::EncodingMap[lir->opcode].flags; + uint64_t flags = ArmMir2Lir::EncodingMap[lir->opcode].flags; int opcode = lir->opcode; if (flags & REG_DEF_SP) { @@ -158,7 +156,7 @@ void ArmCodegen::SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir) if (flags & REG_DEF_FPCS_LIST2) { for (int i = 0; i < lir->operands[2]; i++) { - SetupRegMask(cu, &lir->def_mask, lir->operands[1] + i); + SetupRegMask(&lir->def_mask, lir->operands[1] + i); } } @@ -185,12 +183,12 @@ void ArmCodegen::SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir) if (flags & REG_USE_FPCS_LIST2) { for (int i = 0; i < lir->operands[2]; i++) { - SetupRegMask(cu, &lir->use_mask, lir->operands[1] + i); + SetupRegMask(&lir->use_mask, lir->operands[1] + i); } } /* Fixup for kThumbPush/lr and kThumbPop/pc */ if (opcode == kThumbPush || opcode == kThumbPop) { - uint64_t r8Mask = GetRegMaskCommon(cu, r8); + uint64_t r8Mask = GetRegMaskCommon(r8); if ((opcode == kThumbPush) && (lir->use_mask & r8Mask)) { lir->use_mask &= ~r8Mask; lir->use_mask |= ENCODE_ARM_REG_LR; @@ -204,7 +202,7 @@ void ArmCodegen::SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir) } } -ArmConditionCode ArmCodegen::ArmConditionEncoding(ConditionCode ccode) +ArmConditionCode ArmMir2Lir::ArmConditionEncoding(ConditionCode ccode) { ArmConditionCode res; switch (ccode) { @@ -317,7 +315,7 @@ const char* cc_names[] = {"eq","ne","cs","cc","mi","pl","vs","vc", * Interpret a format string and build a string no longer than size * See format key in Assemble.c. */ -std::string ArmCodegen::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) +std::string ArmMir2Lir::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) { std::string buf; int i; @@ -456,7 +454,7 @@ std::string ArmCodegen::BuildInsnString(const char* fmt, LIR* lir, unsigned char return buf; } -void ArmCodegen::DumpResourceMask(LIR* arm_lir, uint64_t mask, const char* prefix) +void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, uint64_t mask, const char* prefix) { char buf[256]; buf[0] = 0; @@ -502,98 +500,98 @@ void ArmCodegen::DumpResourceMask(LIR* arm_lir, uint64_t mask, const char* prefi } } -bool ArmCodegen::IsUnconditionalBranch(LIR* lir) +bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) { return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond)); } -bool InitArmCodegen(CompilationUnit* cu) -{ - cu->cg.reset(new ArmCodegen()); +ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph) : Mir2Lir(cu, mir_graph) { + // Sanity check - make sure encoding map lines up. for (int i = 0; i < kArmLast; i++) { - if (ArmCodegen::EncodingMap[i].opcode != i) { - LOG(FATAL) << "Encoding order for " << ArmCodegen::EncodingMap[i].name + if (ArmMir2Lir::EncodingMap[i].opcode != i) { + LOG(FATAL) << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name << " is wrong: expecting " << i << ", seeing " - << static_cast<int>(ArmCodegen::EncodingMap[i].opcode); + << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode); } } - return true; +} + +Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph) { + return new ArmMir2Lir(cu, mir_graph); } /* * Alloc a pair of core registers, or a double. Low reg in low byte, * high reg in next byte. */ -int ArmCodegen::AllocTypedTempPair(CompilationUnit* cu, bool fp_hint, int reg_class) +int ArmMir2Lir::AllocTypedTempPair(bool fp_hint, int reg_class) { int high_reg; int low_reg; int res = 0; if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { - low_reg = AllocTempDouble(cu); + low_reg = AllocTempDouble(); high_reg = low_reg + 1; } else { - low_reg = AllocTemp(cu); - high_reg = AllocTemp(cu); + low_reg = AllocTemp(); + high_reg = AllocTemp(); } res = (low_reg & 0xff) | ((high_reg & 0xff) << 8); return res; } -int ArmCodegen::AllocTypedTemp(CompilationUnit* cu, bool fp_hint, int reg_class) +int ArmMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) { if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) - return AllocTempFloat(cu); - return AllocTemp(cu); + return AllocTempFloat(); + return AllocTemp(); } -void ArmCodegen::CompilerInitializeRegAlloc(CompilationUnit* cu) +void ArmMir2Lir::CompilerInitializeRegAlloc() { int num_regs = sizeof(core_regs)/sizeof(*core_regs); int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs); int num_temps = sizeof(core_temps)/sizeof(*core_temps); int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs); int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps); - RegisterPool *pool = - static_cast<RegisterPool*>(NewMem(cu, sizeof(*pool), true, kAllocRegAlloc)); - cu->reg_pool = pool; - pool->num_core_regs = num_regs; - pool->core_regs = reinterpret_cast<RegisterInfo*> - (NewMem(cu, num_regs * sizeof(*cu->reg_pool->core_regs), true, kAllocRegAlloc)); - pool->num_fp_regs = num_fp_regs; - pool->FPRegs = static_cast<RegisterInfo*> - (NewMem(cu, num_fp_regs * sizeof(*cu->reg_pool->FPRegs), true, kAllocRegAlloc)); - CompilerInitPool(pool->core_regs, core_regs, pool->num_core_regs); - CompilerInitPool(pool->FPRegs, FpRegs, pool->num_fp_regs); + reg_pool_ = static_cast<RegisterPool*>(NewMem(cu_, sizeof(*reg_pool_), true, kAllocRegAlloc)); + reg_pool_->num_core_regs = num_regs; + reg_pool_->core_regs = reinterpret_cast<RegisterInfo*> + (NewMem(cu_, num_regs * sizeof(*reg_pool_->core_regs), true, kAllocRegAlloc)); + reg_pool_->num_fp_regs = num_fp_regs; + reg_pool_->FPRegs = static_cast<RegisterInfo*> + (NewMem(cu_, num_fp_regs * sizeof(*reg_pool_->FPRegs), true, kAllocRegAlloc)); + CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs); + CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs); // Keep special registers from being allocated for (int i = 0; i < num_reserved; i++) { if (NO_SUSPEND && (ReservedRegs[i] == rARM_SUSPEND)) { //To measure cost of suspend check continue; } - MarkInUse(cu, ReservedRegs[i]); + MarkInUse(ReservedRegs[i]); } // Mark temp regs - all others not in use can be used for promotion for (int i = 0; i < num_temps; i++) { - MarkTemp(cu, core_temps[i]); + MarkTemp(core_temps[i]); } for (int i = 0; i < num_fp_temps; i++) { - MarkTemp(cu, fp_temps[i]); + MarkTemp(fp_temps[i]); } // Start allocation at r2 in an attempt to avoid clobbering return values - pool->next_core_reg = r2; + reg_pool_->next_core_reg = r2; } -void ArmCodegen::FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, +void ArmMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) { if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) && (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) { // No overlap, free both - FreeTemp(cu, rl_free.low_reg); - FreeTemp(cu, rl_free.high_reg); + FreeTemp(rl_free.low_reg); + FreeTemp(rl_free.high_reg); } } /* @@ -602,10 +600,10 @@ void ArmCodegen::FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, * machinery is in place, always spill lr. */ -void ArmCodegen::AdjustSpillMask(CompilationUnit* cu) +void ArmMir2Lir::AdjustSpillMask() { - cu->core_spill_mask |= (1 << rARM_LR); - cu->num_core_spills++; + core_spill_mask_ |= (1 << rARM_LR); + num_core_spills_++; } /* @@ -614,26 +612,26 @@ void ArmCodegen::AdjustSpillMask(CompilationUnit* cu) * include any holes in the mask. Associate holes with * Dalvik register INVALID_VREG (0xFFFFU). */ -void ArmCodegen::MarkPreservedSingle(CompilationUnit* cu, int v_reg, int reg) +void ArmMir2Lir::MarkPreservedSingle(int v_reg, int reg) { DCHECK_GE(reg, ARM_FP_REG_MASK + ARM_FP_CALLEE_SAVE_BASE); reg = (reg & ARM_FP_REG_MASK) - ARM_FP_CALLEE_SAVE_BASE; // Ensure fp_vmap_table is large enough - int table_size = cu->fp_vmap_table.size(); + int table_size = fp_vmap_table_.size(); for (int i = table_size; i < (reg + 1); i++) { - cu->fp_vmap_table.push_back(INVALID_VREG); + fp_vmap_table_.push_back(INVALID_VREG); } // Add the current mapping - cu->fp_vmap_table[reg] = v_reg; + fp_vmap_table_[reg] = v_reg; // Size of fp_vmap_table is high-water mark, use to set mask - cu->num_fp_spills = cu->fp_vmap_table.size(); - cu->fp_spill_mask = ((1 << cu->num_fp_spills) - 1) << ARM_FP_CALLEE_SAVE_BASE; + num_fp_spills_ = fp_vmap_table_.size(); + fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE; } -void ArmCodegen::FlushRegWide(CompilationUnit* cu, int reg1, int reg2) +void ArmMir2Lir::FlushRegWide(int reg1, int reg2) { - RegisterInfo* info1 = GetRegInfo(cu, reg1); - RegisterInfo* info2 = GetRegInfo(cu, reg2); + RegisterInfo* info1 = GetRegInfo(reg1); + RegisterInfo* info2 = GetRegInfo(reg2); DCHECK(info1 && info2 && info1->pair && info2->pair && (info1->partner == info2->reg) && (info2->partner == info1->reg)); @@ -645,121 +643,121 @@ void ArmCodegen::FlushRegWide(CompilationUnit* cu, int reg1, int reg2) info1->dirty = false; info2->dirty = false; - if (cu->mir_graph->SRegToVReg(info2->s_reg) < - cu->mir_graph->SRegToVReg(info1->s_reg)) + if (mir_graph_->SRegToVReg(info2->s_reg) < + mir_graph_->SRegToVReg(info1->s_reg)) info1 = info2; - int v_reg = cu->mir_graph->SRegToVReg(info1->s_reg); - StoreBaseDispWide(cu, rARM_SP, VRegOffset(cu, v_reg), info1->reg, info1->partner); + int v_reg = mir_graph_->SRegToVReg(info1->s_reg); + StoreBaseDispWide(rARM_SP, VRegOffset(v_reg), info1->reg, info1->partner); } } -void ArmCodegen::FlushReg(CompilationUnit* cu, int reg) +void ArmMir2Lir::FlushReg(int reg) { - RegisterInfo* info = GetRegInfo(cu, reg); + RegisterInfo* info = GetRegInfo(reg); if (info->live && info->dirty) { info->dirty = false; - int v_reg = cu->mir_graph->SRegToVReg(info->s_reg); - StoreBaseDisp(cu, rARM_SP, VRegOffset(cu, v_reg), reg, kWord); + int v_reg = mir_graph_->SRegToVReg(info->s_reg); + StoreBaseDisp(rARM_SP, VRegOffset(v_reg), reg, kWord); } } /* Give access to the target-dependent FP register encoding to common code */ -bool ArmCodegen::IsFpReg(int reg) { +bool ArmMir2Lir::IsFpReg(int reg) { return ARM_FPREG(reg); } /* Clobber all regs that might be used by an external C call */ -void ArmCodegen::ClobberCalleeSave(CompilationUnit *cu) -{ - Clobber(cu, r0); - Clobber(cu, r1); - Clobber(cu, r2); - Clobber(cu, r3); - Clobber(cu, r12); - Clobber(cu, r14lr); - Clobber(cu, fr0); - Clobber(cu, fr1); - Clobber(cu, fr2); - Clobber(cu, fr3); - Clobber(cu, fr4); - Clobber(cu, fr5); - Clobber(cu, fr6); - Clobber(cu, fr7); - Clobber(cu, fr8); - Clobber(cu, fr9); - Clobber(cu, fr10); - Clobber(cu, fr11); - Clobber(cu, fr12); - Clobber(cu, fr13); - Clobber(cu, fr14); - Clobber(cu, fr15); -} - -RegLocation ArmCodegen::GetReturnWideAlt(CompilationUnit* cu) +void ArmMir2Lir::ClobberCalleeSave() +{ + Clobber(r0); + Clobber(r1); + Clobber(r2); + Clobber(r3); + Clobber(r12); + Clobber(r14lr); + Clobber(fr0); + Clobber(fr1); + Clobber(fr2); + Clobber(fr3); + Clobber(fr4); + Clobber(fr5); + Clobber(fr6); + Clobber(fr7); + Clobber(fr8); + Clobber(fr9); + Clobber(fr10); + Clobber(fr11); + Clobber(fr12); + Clobber(fr13); + Clobber(fr14); + Clobber(fr15); +} + +RegLocation ArmMir2Lir::GetReturnWideAlt() { RegLocation res = LocCReturnWide(); res.low_reg = r2; res.high_reg = r3; - Clobber(cu, r2); - Clobber(cu, r3); - MarkInUse(cu, r2); - MarkInUse(cu, r3); - MarkPair(cu, res.low_reg, res.high_reg); + Clobber(r2); + Clobber(r3); + MarkInUse(r2); + MarkInUse(r3); + MarkPair(res.low_reg, res.high_reg); return res; } -RegLocation ArmCodegen::GetReturnAlt(CompilationUnit* cu) +RegLocation ArmMir2Lir::GetReturnAlt() { RegLocation res = LocCReturn(); res.low_reg = r1; - Clobber(cu, r1); - MarkInUse(cu, r1); + Clobber(r1); + MarkInUse(r1); return res; } -RegisterInfo* ArmCodegen::GetRegInfo(CompilationUnit* cu, int reg) +ArmMir2Lir::RegisterInfo* ArmMir2Lir::GetRegInfo(int reg) { - return ARM_FPREG(reg) ? &cu->reg_pool->FPRegs[reg & ARM_FP_REG_MASK] - : &cu->reg_pool->core_regs[reg]; + return ARM_FPREG(reg) ? ®_pool_->FPRegs[reg & ARM_FP_REG_MASK] + : ®_pool_->core_regs[reg]; } /* To be used when explicitly managing register use */ -void ArmCodegen::LockCallTemps(CompilationUnit* cu) +void ArmMir2Lir::LockCallTemps() { - LockTemp(cu, r0); - LockTemp(cu, r1); - LockTemp(cu, r2); - LockTemp(cu, r3); + LockTemp(r0); + LockTemp(r1); + LockTemp(r2); + LockTemp(r3); } /* To be used when explicitly managing register use */ -void ArmCodegen::FreeCallTemps(CompilationUnit* cu) +void ArmMir2Lir::FreeCallTemps() { - FreeTemp(cu, r0); - FreeTemp(cu, r1); - FreeTemp(cu, r2); - FreeTemp(cu, r3); + FreeTemp(r0); + FreeTemp(r1); + FreeTemp(r2); + FreeTemp(r3); } -int ArmCodegen::LoadHelper(CompilationUnit* cu, int offset) +int ArmMir2Lir::LoadHelper(int offset) { - LoadWordDisp(cu, rARM_SELF, offset, rARM_LR); + LoadWordDisp(rARM_SELF, offset, rARM_LR); return rARM_LR; } -uint64_t ArmCodegen::GetTargetInstFlags(int opcode) +uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) { - return ArmCodegen::EncodingMap[opcode].flags; + return ArmMir2Lir::EncodingMap[opcode].flags; } -const char* ArmCodegen::GetTargetInstName(int opcode) +const char* ArmMir2Lir::GetTargetInstName(int opcode) { - return ArmCodegen::EncodingMap[opcode].name; + return ArmMir2Lir::EncodingMap[opcode].name; } -const char* ArmCodegen::GetTargetInstFmt(int opcode) +const char* ArmMir2Lir::GetTargetInstFmt(int opcode) { - return ArmCodegen::EncodingMap[opcode].fmt; + return ArmMir2Lir::EncodingMap[opcode].fmt; } } // namespace art diff --git a/src/compiler/dex/quick/arm/utility_arm.cc b/src/compiler/dex/quick/arm/utility_arm.cc index 33e821060c..c689f72436 100644 --- a/src/compiler/dex/quick/arm/utility_arm.cc +++ b/src/compiler/dex/quick/arm/utility_arm.cc @@ -16,8 +16,7 @@ #include "arm_lir.h" #include "codegen_arm.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" +#include "compiler/dex/quick/mir_to_lir.h" namespace art { @@ -71,31 +70,31 @@ static int EncodeImmDouble(int64_t value) return res; } -static LIR* LoadFPConstantValue(CompilationUnit* cu, int r_dest, int value) +LIR* ArmMir2Lir::LoadFPConstantValue(int r_dest, int value) { DCHECK(ARM_SINGLEREG(r_dest)); if (value == 0) { // TODO: we need better info about the target CPU. a vector exclusive or // would probably be better here if we could rely on its existance. // Load an immediate +2.0 (which encodes to 0) - NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, 0); + NewLIR2(kThumb2Vmovs_IMM8, r_dest, 0); // +0.0 = +2.0 - +2.0 - return NewLIR3(cu, kThumb2Vsubs, r_dest, r_dest, r_dest); + return NewLIR3(kThumb2Vsubs, r_dest, r_dest, r_dest); } else { int encoded_imm = EncodeImmSingle(value); if (encoded_imm >= 0) { - return NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, encoded_imm); + return NewLIR2(kThumb2Vmovs_IMM8, r_dest, encoded_imm); } } - LIR* data_target = ScanLiteralPool(cu->literal_list, value, 0); + LIR* data_target = ScanLiteralPool(literal_list_, value, 0); if (data_target == NULL) { - data_target = AddWordData(cu, &cu->literal_list, value); + data_target = AddWordData(&literal_list_, value); } - LIR* load_pc_rel = RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrs, + LIR* load_pc_rel = RawLIR(current_dalvik_offset_, kThumb2Vldrs, r_dest, r15pc, 0, 0, 0, data_target); - SetMemRefType(cu, load_pc_rel, true, kLiteral); + SetMemRefType(load_pc_rel, true, kLiteral); load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target); - AppendLIR(cu, load_pc_rel); + AppendLIR(load_pc_rel); return load_pc_rel; } @@ -122,7 +121,7 @@ static int LeadingZeros(uint32_t val) * Determine whether value can be encoded as a Thumb2 modified * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form. */ -int ArmCodegen::ModifiedImmediate(uint32_t value) +int ArmMir2Lir::ModifiedImmediate(uint32_t value) { int z_leading; int z_trailing; @@ -152,22 +151,22 @@ int ArmCodegen::ModifiedImmediate(uint32_t value) return value | ((0x8 + z_leading) << 7); /* [01000..11111]:bcdefgh */ } -bool ArmCodegen::InexpensiveConstantInt(int32_t value) +bool ArmMir2Lir::InexpensiveConstantInt(int32_t value) { return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0); } -bool ArmCodegen::InexpensiveConstantFloat(int32_t value) +bool ArmMir2Lir::InexpensiveConstantFloat(int32_t value) { return EncodeImmSingle(value) >= 0; } -bool ArmCodegen::InexpensiveConstantLong(int64_t value) +bool ArmMir2Lir::InexpensiveConstantLong(int64_t value) { return InexpensiveConstantInt(High32Bits(value)) && InexpensiveConstantInt(Low32Bits(value)); } -bool ArmCodegen::InexpensiveConstantDouble(int64_t value) +bool ArmMir2Lir::InexpensiveConstantDouble(int64_t value) { return EncodeImmDouble(value) >= 0; } @@ -180,57 +179,57 @@ bool ArmCodegen::InexpensiveConstantDouble(int64_t value) * 1) r_dest is freshly returned from AllocTemp or * 2) The codegen is under fixed register usage */ -LIR* ArmCodegen::LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value) +LIR* ArmMir2Lir::LoadConstantNoClobber(int r_dest, int value) { LIR* res; int mod_imm; if (ARM_FPREG(r_dest)) { - return LoadFPConstantValue(cu, r_dest, value); + return LoadFPConstantValue(r_dest, value); } /* See if the value can be constructed cheaply */ if (ARM_LOWREG(r_dest) && (value >= 0) && (value <= 255)) { - return NewLIR2(cu, kThumbMovImm, r_dest, value); + return NewLIR2(kThumbMovImm, r_dest, value); } /* Check Modified immediate special cases */ mod_imm = ModifiedImmediate(value); if (mod_imm >= 0) { - res = NewLIR2(cu, kThumb2MovImmShift, r_dest, mod_imm); + res = NewLIR2(kThumb2MovImmShift, r_dest, mod_imm); return res; } mod_imm = ModifiedImmediate(~value); if (mod_imm >= 0) { - res = NewLIR2(cu, kThumb2MvnImm12, r_dest, mod_imm); + res = NewLIR2(kThumb2MvnImm12, r_dest, mod_imm); return res; } /* 16-bit immediate? */ if ((value & 0xffff) == value) { - res = NewLIR2(cu, kThumb2MovImm16, r_dest, value); + res = NewLIR2(kThumb2MovImm16, r_dest, value); return res; } /* Do a low/high pair */ - res = NewLIR2(cu, kThumb2MovImm16, r_dest, Low16Bits(value)); - NewLIR2(cu, kThumb2MovImm16H, r_dest, High16Bits(value)); + res = NewLIR2(kThumb2MovImm16, r_dest, Low16Bits(value)); + NewLIR2(kThumb2MovImm16H, r_dest, High16Bits(value)); return res; } -LIR* ArmCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target) +LIR* ArmMir2Lir::OpUnconditionalBranch(LIR* target) { - LIR* res = NewLIR1(cu, kThumbBUncond, 0 /* offset to be patched during assembly*/); + LIR* res = NewLIR1(kThumbBUncond, 0 /* offset to be patched during assembly*/); res->target = target; return res; } -LIR* ArmCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target) +LIR* ArmMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) { - LIR* branch = NewLIR2(cu, kThumb2BCond, 0 /* offset to be patched */, + LIR* branch = NewLIR2(kThumb2BCond, 0 /* offset to be patched */, ArmConditionEncoding(cc)); branch->target = target; return branch; } -LIR* ArmCodegen::OpReg(CompilationUnit* cu, OpKind op, int r_dest_src) +LIR* ArmMir2Lir::OpReg(OpKind op, int r_dest_src) { ArmOpcode opcode = kThumbBkpt; switch (op) { @@ -240,10 +239,10 @@ LIR* ArmCodegen::OpReg(CompilationUnit* cu, OpKind op, int r_dest_src) default: LOG(FATAL) << "Bad opcode " << op; } - return NewLIR1(cu, opcode, r_dest_src); + return NewLIR1(opcode, r_dest_src); } -LIR* ArmCodegen::OpRegRegShift(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2, +LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, int shift) { bool thumb_form = ((shift == 0) && ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2)); @@ -332,39 +331,39 @@ LIR* ArmCodegen::OpRegRegShift(CompilationUnit* cu, OpKind op, int r_dest_src1, break; case kOp2Byte: DCHECK_EQ(shift, 0); - return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 8); + return NewLIR4(kThumb2Sbfx, r_dest_src1, r_src2, 0, 8); case kOp2Short: DCHECK_EQ(shift, 0); - return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 16); + return NewLIR4(kThumb2Sbfx, r_dest_src1, r_src2, 0, 16); case kOp2Char: DCHECK_EQ(shift, 0); - return NewLIR4(cu, kThumb2Ubfx, r_dest_src1, r_src2, 0, 16); + return NewLIR4(kThumb2Ubfx, r_dest_src1, r_src2, 0, 16); default: LOG(FATAL) << "Bad opcode: " << op; break; } DCHECK_GE(static_cast<int>(opcode), 0); if (EncodingMap[opcode].flags & IS_BINARY_OP) - return NewLIR2(cu, opcode, r_dest_src1, r_src2); + return NewLIR2(opcode, r_dest_src1, r_src2); else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) { if (EncodingMap[opcode].field_loc[2].kind == kFmtShift) - return NewLIR3(cu, opcode, r_dest_src1, r_src2, shift); + return NewLIR3(opcode, r_dest_src1, r_src2, shift); else - return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_src2); + return NewLIR3(opcode, r_dest_src1, r_dest_src1, r_src2); } else if (EncodingMap[opcode].flags & IS_QUAD_OP) - return NewLIR4(cu, opcode, r_dest_src1, r_dest_src1, r_src2, shift); + return NewLIR4(opcode, r_dest_src1, r_dest_src1, r_src2, shift); else { LOG(FATAL) << "Unexpected encoding operand count"; return NULL; } } -LIR* ArmCodegen::OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2) +LIR* ArmMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) { - return OpRegRegShift(cu, op, r_dest_src1, r_src2, 0); + return OpRegRegShift(op, r_dest_src1, r_src2, 0); } -LIR* ArmCodegen::OpRegRegRegShift(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, +LIR* ArmMir2Lir::OpRegRegRegShift(OpKind op, int r_dest, int r_src1, int r_src2, int shift) { ArmOpcode opcode = kThumbBkpt; @@ -424,19 +423,19 @@ LIR* ArmCodegen::OpRegRegRegShift(CompilationUnit* cu, OpKind op, int r_dest, in } DCHECK_GE(static_cast<int>(opcode), 0); if (EncodingMap[opcode].flags & IS_QUAD_OP) - return NewLIR4(cu, opcode, r_dest, r_src1, r_src2, shift); + return NewLIR4(opcode, r_dest, r_src1, r_src2, shift); else { DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP); - return NewLIR3(cu, opcode, r_dest, r_src1, r_src2); + return NewLIR3(opcode, r_dest, r_src1, r_src2); } } -LIR* ArmCodegen::OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int r_src2) +LIR* ArmMir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2) { - return OpRegRegRegShift(cu, op, r_dest, r_src1, r_src2, 0); + return OpRegRegRegShift(op, r_dest, r_src1, r_src2, 0); } -LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value) +LIR* ArmMir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src1, int value) { LIR* res; bool neg = (value < 0); @@ -450,28 +449,28 @@ LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_s switch (op) { case kOpLsl: if (all_low_regs) - return NewLIR3(cu, kThumbLslRRI5, r_dest, r_src1, value); + return NewLIR3(kThumbLslRRI5, r_dest, r_src1, value); else - return NewLIR3(cu, kThumb2LslRRI5, r_dest, r_src1, value); + return NewLIR3(kThumb2LslRRI5, r_dest, r_src1, value); case kOpLsr: if (all_low_regs) - return NewLIR3(cu, kThumbLsrRRI5, r_dest, r_src1, value); + return NewLIR3(kThumbLsrRRI5, r_dest, r_src1, value); else - return NewLIR3(cu, kThumb2LsrRRI5, r_dest, r_src1, value); + return NewLIR3(kThumb2LsrRRI5, r_dest, r_src1, value); case kOpAsr: if (all_low_regs) - return NewLIR3(cu, kThumbAsrRRI5, r_dest, r_src1, value); + return NewLIR3(kThumbAsrRRI5, r_dest, r_src1, value); else - return NewLIR3(cu, kThumb2AsrRRI5, r_dest, r_src1, value); + return NewLIR3(kThumb2AsrRRI5, r_dest, r_src1, value); case kOpRor: - return NewLIR3(cu, kThumb2RorRRI5, r_dest, r_src1, value); + return NewLIR3(kThumb2RorRRI5, r_dest, r_src1, value); case kOpAdd: if (ARM_LOWREG(r_dest) && (r_src1 == r13sp) && (value <= 1020) && ((value & 0x3)==0)) { - return NewLIR3(cu, kThumbAddSpRel, r_dest, r_src1, value >> 2); + return NewLIR3(kThumbAddSpRel, r_dest, r_src1, value >> 2); } else if (ARM_LOWREG(r_dest) && (r_src1 == r15pc) && (value <= 1020) && ((value & 0x3)==0)) { - return NewLIR3(cu, kThumbAddPcRel, r_dest, r_src1, value >> 2); + return NewLIR3(kThumbAddPcRel, r_dest, r_src1, value >> 2); } // Note: intentional fallthrough case kOpSub: @@ -480,13 +479,13 @@ LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_s opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3; else opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3; - return NewLIR3(cu, opcode, r_dest, r_src1, abs_value); + return NewLIR3(opcode, r_dest, r_src1, abs_value); } else if ((abs_value & 0xff) == abs_value) { if (op == kOpAdd) opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12; else opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12; - return NewLIR3(cu, opcode, r_dest, r_src1, abs_value); + return NewLIR3(opcode, r_dest, r_src1, abs_value); } if (mod_imm_neg >= 0) { op = (op == kOpAdd) ? kOpSub : kOpAdd; @@ -533,12 +532,12 @@ LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_s int mod_imm = ModifiedImmediate(value); LIR* res; if (mod_imm >= 0) { - res = NewLIR2(cu, kThumb2CmpRI12, r_src1, mod_imm); + res = NewLIR2(kThumb2CmpRI12, r_src1, mod_imm); } else { - int r_tmp = AllocTemp(cu); - res = LoadConstant(cu, r_tmp, value); - OpRegReg(cu, kOpCmp, r_src1, r_tmp); - FreeTemp(cu, r_tmp); + int r_tmp = AllocTemp(); + res = LoadConstant(r_tmp, value); + OpRegReg(kOpCmp, r_src1, r_tmp); + FreeTemp(r_tmp); } return res; } @@ -547,21 +546,21 @@ LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_s } if (mod_imm >= 0) { - return NewLIR3(cu, opcode, r_dest, r_src1, mod_imm); + return NewLIR3(opcode, r_dest, r_src1, mod_imm); } else { - int r_scratch = AllocTemp(cu); - LoadConstant(cu, r_scratch, value); + int r_scratch = AllocTemp(); + LoadConstant(r_scratch, value); if (EncodingMap[alt_opcode].flags & IS_QUAD_OP) - res = NewLIR4(cu, alt_opcode, r_dest, r_src1, r_scratch, 0); + res = NewLIR4(alt_opcode, r_dest, r_src1, r_scratch, 0); else - res = NewLIR3(cu, alt_opcode, r_dest, r_src1, r_scratch); - FreeTemp(cu, r_scratch); + res = NewLIR3(alt_opcode, r_dest, r_src1, r_scratch); + FreeTemp(r_scratch); return res; } } /* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */ -LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value) +LIR* ArmMir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value) { bool neg = (value < 0); int abs_value = (neg) ? -value : value; @@ -571,7 +570,7 @@ LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int v case kOpAdd: if ( !neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */ DCHECK_EQ((value & 0x3), 0); - return NewLIR1(cu, kThumbAddSpI7, value >> 2); + return NewLIR1(kThumbAddSpI7, value >> 2); } else if (short_form) { opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8; } @@ -579,7 +578,7 @@ LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int v case kOpSub: if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */ DCHECK_EQ((value & 0x3), 0); - return NewLIR1(cu, kThumbSubSpI7, value >> 2); + return NewLIR1(kThumbSubSpI7, value >> 2); } else if (short_form) { opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8; } @@ -600,13 +599,13 @@ LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int v break; } if (short_form) - return NewLIR2(cu, opcode, r_dest_src1, abs_value); + return NewLIR2(opcode, r_dest_src1, abs_value); else { - return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value); + return OpRegRegImm(op, r_dest_src1, r_dest_src1, value); } } -LIR* ArmCodegen::LoadConstantWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi, int64_t value) +LIR* ArmMir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) { LIR* res = NULL; int32_t val_lo = Low32Bits(value); @@ -617,46 +616,46 @@ LIR* ArmCodegen::LoadConstantWide(CompilationUnit* cu, int r_dest_lo, int r_dest // TODO: we need better info about the target CPU. a vector exclusive or // would probably be better here if we could rely on its existance. // Load an immediate +2.0 (which encodes to 0) - NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, 0); + NewLIR2(kThumb2Vmovd_IMM8, target_reg, 0); // +0.0 = +2.0 - +2.0 - res = NewLIR3(cu, kThumb2Vsubd, target_reg, target_reg, target_reg); + res = NewLIR3(kThumb2Vsubd, target_reg, target_reg, target_reg); } else { int encoded_imm = EncodeImmDouble(value); if (encoded_imm >= 0) { - res = NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, encoded_imm); + res = NewLIR2(kThumb2Vmovd_IMM8, target_reg, encoded_imm); } } } else { if ((InexpensiveConstantInt(val_lo) && (InexpensiveConstantInt(val_hi)))) { - res = LoadConstantNoClobber(cu, r_dest_lo, val_lo); - LoadConstantNoClobber(cu, r_dest_hi, val_hi); + res = LoadConstantNoClobber(r_dest_lo, val_lo); + LoadConstantNoClobber(r_dest_hi, val_hi); } } if (res == NULL) { // No short form - load from the literal pool. - LIR* data_target = ScanLiteralPoolWide(cu->literal_list, val_lo, val_hi); + LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi); if (data_target == NULL) { - data_target = AddWideData(cu, &cu->literal_list, val_lo, val_hi); + data_target = AddWideData(&literal_list_, val_lo, val_hi); } if (ARM_FPREG(r_dest_lo)) { - res = RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrd, + res = RawLIR(current_dalvik_offset_, kThumb2Vldrd, target_reg, r15pc, 0, 0, 0, data_target); } else { - res = RawLIR(cu, cu->current_dalvik_offset, kThumb2LdrdPcRel8, + res = RawLIR(current_dalvik_offset_, kThumb2LdrdPcRel8, r_dest_lo, r_dest_hi, r15pc, 0, 0, data_target); } - SetMemRefType(cu, res, true, kLiteral); + SetMemRefType(res, true, kLiteral); res->alias_info = reinterpret_cast<uintptr_t>(data_target); - AppendLIR(cu, res); + AppendLIR(res); } return res; } -int ArmCodegen::EncodeShift(int code, int amount) { +int ArmMir2Lir::EncodeShift(int code, int amount) { return ((amount & 0x1f) << 2) | code; } -LIR* ArmCodegen::LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest, +LIR* ArmMir2Lir::LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size) { bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest); @@ -685,15 +684,15 @@ LIR* ArmCodegen::LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, in switch (size) { case kDouble: // fall-through case kSingle: - reg_ptr = AllocTemp(cu); + reg_ptr = AllocTemp(); if (scale) { - NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index, + NewLIR4(kThumb2AddRRR, reg_ptr, rBase, r_index, EncodeShift(kArmLsl, scale)); } else { - OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index); + OpRegRegReg(kOpAdd, reg_ptr, rBase, r_index); } - load = NewLIR3(cu, opcode, r_dest, reg_ptr, 0); - FreeTemp(cu, reg_ptr); + load = NewLIR3(opcode, r_dest, reg_ptr, 0); + FreeTemp(reg_ptr); return load; case kWord: opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR; @@ -714,14 +713,14 @@ LIR* ArmCodegen::LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, in LOG(FATAL) << "Bad size: " << size; } if (thumb_form) - load = NewLIR3(cu, opcode, r_dest, rBase, r_index); + load = NewLIR3(opcode, r_dest, rBase, r_index); else - load = NewLIR4(cu, opcode, r_dest, rBase, r_index, scale); + load = NewLIR4(opcode, r_dest, rBase, r_index, scale); return load; } -LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src, +LIR* ArmMir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size) { bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src); @@ -750,15 +749,15 @@ LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, i switch (size) { case kDouble: // fall-through case kSingle: - reg_ptr = AllocTemp(cu); + reg_ptr = AllocTemp(); if (scale) { - NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index, + NewLIR4(kThumb2AddRRR, reg_ptr, rBase, r_index, EncodeShift(kArmLsl, scale)); } else { - OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index); + OpRegRegReg(kOpAdd, reg_ptr, rBase, r_index); } - store = NewLIR3(cu, opcode, r_src, reg_ptr, 0); - FreeTemp(cu, reg_ptr); + store = NewLIR3(opcode, r_src, reg_ptr, 0); + FreeTemp(reg_ptr); return store; case kWord: opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR; @@ -775,9 +774,9 @@ LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, i LOG(FATAL) << "Bad size: " << size; } if (thumb_form) - store = NewLIR3(cu, opcode, r_src, rBase, r_index); + store = NewLIR3(opcode, r_src, rBase, r_index); else - store = NewLIR4(cu, opcode, r_src, rBase, r_index, scale); + store = NewLIR4(opcode, r_src, rBase, r_index, scale); return store; } @@ -787,10 +786,9 @@ LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, i * on base (which must have an associated s_reg and MIR). If not * performing null check, incoming MIR can be null. */ -LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_dest, +LIR* ArmMir2Lir::LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size, int s_reg) { - Codegen* cg = cu->cg.get(); LIR* load = NULL; ArmOpcode opcode = kThumbBkpt; bool short_form = false; @@ -806,7 +804,7 @@ LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displaceme if (ARM_FPREG(r_dest)) { if (ARM_SINGLEREG(r_dest)) { DCHECK(ARM_FPREG(r_dest_hi)); - r_dest = cg->S2d(r_dest, r_dest_hi); + r_dest = S2d(r_dest, r_dest_hi); } opcode = kThumb2Vldrd; if (displacement <= 1020) { @@ -816,11 +814,11 @@ LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displaceme break; } else { if (displacement <= 1020) { - load = NewLIR4(cu, kThumb2LdrdI8, r_dest, r_dest_hi, rBase, displacement >> 2); + load = NewLIR4(kThumb2LdrdI8, r_dest, r_dest_hi, rBase, displacement >> 2); } else { - load = LoadBaseDispBody(cu, rBase, displacement, r_dest, + load = LoadBaseDispBody(rBase, displacement, r_dest, -1, kWord, s_reg); - LoadBaseDispBody(cu, rBase, displacement + 4, r_dest_hi, + LoadBaseDispBody(rBase, displacement + 4, r_dest_hi, -1, kWord, INVALID_SREG); } already_generated = true; @@ -893,38 +891,37 @@ LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displaceme if (!already_generated) { if (short_form) { - load = NewLIR3(cu, opcode, r_dest, rBase, encoded_disp); + load = NewLIR3(opcode, r_dest, rBase, encoded_disp); } else { - int reg_offset = AllocTemp(cu); - cg->LoadConstant(cu, reg_offset, encoded_disp); - load = cg->LoadBaseIndexed(cu, rBase, reg_offset, r_dest, 0, size); - FreeTemp(cu, reg_offset); + int reg_offset = AllocTemp(); + LoadConstant(reg_offset, encoded_disp); + load = LoadBaseIndexed(rBase, reg_offset, r_dest, 0, size); + FreeTemp(reg_offset); } } // TODO: in future may need to differentiate Dalvik accesses w/ spills if (rBase == rARM_SP) { - AnnotateDalvikRegAccess(cu, load, displacement >> 2, true /* is_load */, is64bit); + AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, is64bit); } return load; } -LIR* ArmCodegen::LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest, +LIR* ArmMir2Lir::LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg) { - return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1, size, s_reg); + return LoadBaseDispBody(rBase, displacement, r_dest, -1, size, s_reg); } -LIR* ArmCodegen::LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo, +LIR* ArmMir2Lir::LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi, int s_reg) { - return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg); + return LoadBaseDispBody(rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg); } -LIR* ArmCodegen::StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacement, +LIR* ArmMir2Lir::StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size) { - Codegen* cg = cu->cg.get(); LIR* store = NULL; ArmOpcode opcode = kThumbBkpt; bool short_form = false; @@ -939,16 +936,16 @@ LIR* ArmCodegen::StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacem is64bit = true; if (!ARM_FPREG(r_src)) { if (displacement <= 1020) { - store = NewLIR4(cu, kThumb2StrdI8, r_src, r_src_hi, rBase, displacement >> 2); + store = NewLIR4(kThumb2StrdI8, r_src, r_src_hi, rBase, displacement >> 2); } else { - store = StoreBaseDispBody(cu, rBase, displacement, r_src, -1, kWord); - StoreBaseDispBody(cu, rBase, displacement + 4, r_src_hi, -1, kWord); + store = StoreBaseDispBody(rBase, displacement, r_src, -1, kWord); + StoreBaseDispBody(rBase, displacement + 4, r_src_hi, -1, kWord); } already_generated = true; } else { if (ARM_SINGLEREG(r_src)) { DCHECK(ARM_FPREG(r_src_hi)); - r_src = cg->S2d(r_src, r_src_hi); + r_src = S2d(r_src, r_src_hi); } opcode = kThumb2Vstrd; if (displacement <= 1020) { @@ -1010,35 +1007,35 @@ LIR* ArmCodegen::StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacem } if (!already_generated) { if (short_form) { - store = NewLIR3(cu, opcode, r_src, rBase, encoded_disp); + store = NewLIR3(opcode, r_src, rBase, encoded_disp); } else { - int r_scratch = AllocTemp(cu); - cg->LoadConstant(cu, r_scratch, encoded_disp); - store = cg->StoreBaseIndexed(cu, rBase, r_scratch, r_src, 0, size); - FreeTemp(cu, r_scratch); + int r_scratch = AllocTemp(); + LoadConstant(r_scratch, encoded_disp); + store = StoreBaseIndexed(rBase, r_scratch, r_src, 0, size); + FreeTemp(r_scratch); } } // TODO: In future, may need to differentiate Dalvik & spill accesses if (rBase == rARM_SP) { - AnnotateDalvikRegAccess(cu, store, displacement >> 2, false /* is_load */, is64bit); + AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, is64bit); } return store; } -LIR* ArmCodegen::StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src, +LIR* ArmMir2Lir::StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size) { - return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size); + return StoreBaseDispBody(rBase, displacement, r_src, -1, size); } -LIR* ArmCodegen::StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement, +LIR* ArmMir2Lir::StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi) { - return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong); + return StoreBaseDispBody(rBase, displacement, r_src_lo, r_src_hi, kLong); } -LIR* ArmCodegen::OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src) +LIR* ArmMir2Lir::OpFpRegCopy(int r_dest, int r_src) { int opcode; DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src)); @@ -1052,26 +1049,26 @@ LIR* ArmCodegen::OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src) opcode = kThumb2Fmrs; } } - LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src); - if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) { + LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src); + if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) { res->flags.is_nop = true; } return res; } -LIR* ArmCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset) +LIR* ArmMir2Lir::OpThreadMem(OpKind op, int thread_offset) { LOG(FATAL) << "Unexpected use of OpThreadMem for Arm"; return NULL; } -LIR* ArmCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp) +LIR* ArmMir2Lir::OpMem(OpKind op, int rBase, int disp) { LOG(FATAL) << "Unexpected use of OpMem for Arm"; return NULL; } -LIR* ArmCodegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, +LIR* ArmMir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, int r_src, int r_src_hi, OpSize size, int s_reg) { @@ -1079,13 +1076,13 @@ LIR* ArmCodegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_inde return NULL; } -LIR* ArmCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, int offset) +LIR* ArmMir2Lir::OpRegMem(OpKind op, int r_dest, int rBase, int offset) { LOG(FATAL) << "Unexpected use of OpRegMem for Arm"; return NULL; } -LIR* ArmCodegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, +LIR* ArmMir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, int r_dest, int r_dest_hi, OpSize size, int s_reg) { diff --git a/src/compiler/dex/quick/codegen.h b/src/compiler/dex/quick/codegen.h deleted file mode 100644 index 272ccadfb9..0000000000 --- a/src/compiler/dex/quick/codegen.h +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_SRC_COMPILER_DEX_QUICK_CODEGEN_H_ -#define ART_SRC_COMPILER_DEX_QUICK_CODEGEN_H_ - -#include "invoke_type.h" -#include "compiler/dex/compiler_enums.h" -#include "compiler/dex/compiler_ir.h" - -namespace art { - -// Set to 1 to measure cost of suspend check. -#define NO_SUSPEND 0 - -#define IS_BINARY_OP (1ULL << kIsBinaryOp) -#define IS_BRANCH (1ULL << kIsBranch) -#define IS_IT (1ULL << kIsIT) -#define IS_LOAD (1ULL << kMemLoad) -#define IS_QUAD_OP (1ULL << kIsQuadOp) -#define IS_QUIN_OP (1ULL << kIsQuinOp) -#define IS_SEXTUPLE_OP (1ULL << kIsSextupleOp) -#define IS_STORE (1ULL << kMemStore) -#define IS_TERTIARY_OP (1ULL << kIsTertiaryOp) -#define IS_UNARY_OP (1ULL << kIsUnaryOp) -#define NEEDS_FIXUP (1ULL << kPCRelFixup) -#define NO_OPERAND (1ULL << kNoOperand) -#define REG_DEF0 (1ULL << kRegDef0) -#define REG_DEF1 (1ULL << kRegDef1) -#define REG_DEFA (1ULL << kRegDefA) -#define REG_DEFD (1ULL << kRegDefD) -#define REG_DEF_FPCS_LIST0 (1ULL << kRegDefFPCSList0) -#define REG_DEF_FPCS_LIST2 (1ULL << kRegDefFPCSList2) -#define REG_DEF_LIST0 (1ULL << kRegDefList0) -#define REG_DEF_LIST1 (1ULL << kRegDefList1) -#define REG_DEF_LR (1ULL << kRegDefLR) -#define REG_DEF_SP (1ULL << kRegDefSP) -#define REG_USE0 (1ULL << kRegUse0) -#define REG_USE1 (1ULL << kRegUse1) -#define REG_USE2 (1ULL << kRegUse2) -#define REG_USE3 (1ULL << kRegUse3) -#define REG_USE4 (1ULL << kRegUse4) -#define REG_USEA (1ULL << kRegUseA) -#define REG_USEC (1ULL << kRegUseC) -#define REG_USED (1ULL << kRegUseD) -#define REG_USE_FPCS_LIST0 (1ULL << kRegUseFPCSList0) -#define REG_USE_FPCS_LIST2 (1ULL << kRegUseFPCSList2) -#define REG_USE_LIST0 (1ULL << kRegUseList0) -#define REG_USE_LIST1 (1ULL << kRegUseList1) -#define REG_USE_LR (1ULL << kRegUseLR) -#define REG_USE_PC (1ULL << kRegUsePC) -#define REG_USE_SP (1ULL << kRegUseSP) -#define SETS_CCODES (1ULL << kSetsCCodes) -#define USES_CCODES (1ULL << kUsesCCodes) - -// Common combo register usage patterns. -#define REG_DEF01 (REG_DEF0 | REG_DEF1) -#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2) -#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01) -#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0) -#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12) -#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1) -#define REG_DEF0_USE2 (REG_DEF0 | REG_USE2) -#define REG_DEFAD_USEAD (REG_DEFAD_USEA | REG_USED) -#define REG_DEFAD_USEA (REG_DEFA_USEA | REG_DEFD) -#define REG_DEFA_USEA (REG_DEFA | REG_USEA) -#define REG_USE012 (REG_USE01 | REG_USE2) -#define REG_USE014 (REG_USE01 | REG_USE4) -#define REG_USE01 (REG_USE0 | REG_USE1) -#define REG_USE02 (REG_USE0 | REG_USE2) -#define REG_USE12 (REG_USE1 | REG_USE2) -#define REG_USE23 (REG_USE2 | REG_USE3) - -struct BasicBlock; -struct CallInfo; -struct CompilationUnit; -struct LIR; -struct MIR; -struct RegLocation; -struct RegisterInfo; - -typedef int (*NextCallInsn)(CompilationUnit*, CallInfo*, int, uint32_t dex_idx, - uint32_t method_idx, uintptr_t direct_code, - uintptr_t direct_method, InvokeType type); - -// Target-specific initialization. -bool InitArmCodegen(CompilationUnit* cu); -bool InitMipsCodegen(CompilationUnit* cu); -bool InitX86Codegen(CompilationUnit* cu); - -class Codegen { - - public: - - struct SwitchTable { - int offset; - const uint16_t* table; // Original dex table. - int vaddr; // Dalvik offset of switch opcode. - LIR* anchor; // Reference instruction for relative offsets. - LIR** targets; // Array of case targets. - }; - - struct FillArrayData { - int offset; - const uint16_t* table; // Original dex table. - int size; - int vaddr; // Dalvik offset of FILL_ARRAY_DATA opcode. - }; - - virtual ~Codegen(){}; - - // Shared by all targets - implemented in ralloc_util.cc - void SimpleRegAlloc(CompilationUnit* cu); - - // Shared by all targets - implemented in gen_common.cc. - void HandleSuspendLaunchPads(CompilationUnit *cu); - void HandleIntrinsicLaunchPads(CompilationUnit *cu); - void HandleThrowLaunchPads(CompilationUnit *cu); - void GenBarrier(CompilationUnit* cu); - LIR* GenCheck(CompilationUnit* cu, ConditionCode c_code, ThrowKind kind); - LIR* GenImmedCheck(CompilationUnit* cu, ConditionCode c_code, int reg, int imm_val, - ThrowKind kind); - LIR* GenNullCheck(CompilationUnit* cu, int s_reg, int m_reg, int opt_flags); - LIR* GenRegRegCheck(CompilationUnit* cu, ConditionCode c_code, int reg1, int reg2, - ThrowKind kind); - void GenCompareAndBranch(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_src1, - RegLocation rl_src2, LIR* taken, LIR* fall_through); - void GenCompareZeroAndBranch(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_src, - LIR* taken, LIR* fall_through); - void GenIntToLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - void GenIntNarrowing(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src); - void GenNewArray(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest, - RegLocation rl_src); - void GenFilledNewArray(CompilationUnit* cu, CallInfo* info); - void GenSput(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_src, - bool is_long_or_double, bool is_object); - void GenSget(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_dest, - bool is_long_or_double, bool is_object); - void GenShowTarget(CompilationUnit* cu); - void GenIGet(CompilationUnit* cu, uint32_t field_idx, int opt_flags, OpSize size, - RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double, bool is_object); - void GenIPut(CompilationUnit* cu, uint32_t field_idx, int opt_flags, OpSize size, - RegLocation rl_src, RegLocation rl_obj, bool is_long_or_double, bool is_object); - void GenConstClass(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest); - void GenConstString(CompilationUnit* cu, uint32_t string_idx, RegLocation rl_dest); - void GenNewInstance(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest); - void GenThrow(CompilationUnit* cu, RegLocation rl_src); - void GenInstanceof(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest, - RegLocation rl_src); - void GenCheckCast(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_src); - void GenLong3Addr(CompilationUnit* cu, OpKind first_op, OpKind second_op, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); - void GenShiftOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_shift); - void GenArithOpInt(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); - void GenArithOpIntLit(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src, int lit); - void GenArithOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); - void GenConversionCall(CompilationUnit* cu, int func_offset, RegLocation rl_dest, - RegLocation rl_src); - void GenSuspendTest(CompilationUnit* cu, int opt_flags); - void GenSuspendTestAndBranch(CompilationUnit* cu, int opt_flags, LIR* target); - - // Shared by all targets - implemented in gen_invoke.cc. - int CallHelperSetup(CompilationUnit* cu, int helper_offset); - LIR* CallHelper(CompilationUnit* cu, int r_tgt, int helper_offset, bool safepoint_pc); - void CallRuntimeHelperImm(CompilationUnit* cu, int helper_offset, int arg0, bool safepoint_pc); - void CallRuntimeHelperReg(CompilationUnit* cu, int helper_offset, int arg0, bool safepoint_pc); - void CallRuntimeHelperRegLocation(CompilationUnit* cu, int helper_offset, RegLocation arg0, - bool safepoint_pc); - void CallRuntimeHelperImmImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1, - bool safepoint_pc); - void CallRuntimeHelperImmRegLocation(CompilationUnit* cu, int helper_offset, int arg0, - RegLocation arg1, bool safepoint_pc); - void CallRuntimeHelperRegLocationImm(CompilationUnit* cu, int helper_offset, RegLocation arg0, - int arg1, bool safepoint_pc); - void CallRuntimeHelperImmReg(CompilationUnit* cu, int helper_offset, int arg0, int arg1, - bool safepoint_pc); - void CallRuntimeHelperRegImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1, - bool safepoint_pc); - void CallRuntimeHelperImmMethod(CompilationUnit* cu, int helper_offset, int arg0, - bool safepoint_pc); - void CallRuntimeHelperRegLocationRegLocation(CompilationUnit* cu, int helper_offset, - RegLocation arg0, RegLocation arg1, - bool safepoint_pc); - void CallRuntimeHelperRegReg(CompilationUnit* cu, int helper_offset, int arg0, int arg1, - bool safepoint_pc); - void CallRuntimeHelperRegRegImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1, - int arg2, bool safepoint_pc); - void CallRuntimeHelperImmMethodRegLocation(CompilationUnit* cu, int helper_offset, int arg0, - RegLocation arg2, bool safepoint_pc); - void CallRuntimeHelperImmMethodImm(CompilationUnit* cu, int helper_offset, int arg0, int arg2, - bool safepoint_pc); - void CallRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cu, int helper_offset, - int arg0, RegLocation arg1, RegLocation arg2, - bool safepoint_pc); - void GenInvoke(CompilationUnit* cu, CallInfo* info); - void FlushIns(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl_method); - int GenDalvikArgsNoRange(CompilationUnit* cu, CallInfo* info, int call_state, LIR** pcrLabel, - NextCallInsn next_call_insn, uint32_t dex_idx, uint32_t method_idx, - uintptr_t direct_code, uintptr_t direct_method, InvokeType type, - bool skip_this); - int GenDalvikArgsRange(CompilationUnit* cu, CallInfo* info, int call_state, LIR** pcrLabel, - NextCallInsn next_call_insn, uint32_t dex_idx, uint32_t method_idx, - uintptr_t direct_code, uintptr_t direct_method, InvokeType type, - bool skip_this); - RegLocation InlineTarget(CompilationUnit* cu, CallInfo* info); - RegLocation InlineTargetWide(CompilationUnit* cu, CallInfo* info); - CallInfo* NewMemCallInfo(CompilationUnit* cu, BasicBlock* bb, MIR* mir, InvokeType type, - bool is_range); - bool GenInlinedCharAt(CompilationUnit* cu, CallInfo* info); - bool GenInlinedStringIsEmptyOrLength(CompilationUnit* cu, CallInfo* info, bool is_empty); - bool GenInlinedAbsInt(CompilationUnit *cu, CallInfo* info); - bool GenInlinedAbsLong(CompilationUnit *cu, CallInfo* info); - bool GenInlinedFloatCvt(CompilationUnit *cu, CallInfo* info); - bool GenInlinedDoubleCvt(CompilationUnit *cu, CallInfo* info); - bool GenInlinedIndexOf(CompilationUnit* cu, CallInfo* info, bool zero_based); - bool GenInlinedStringCompareTo(CompilationUnit* cu, CallInfo* info); - bool GenInlinedCurrentThread(CompilationUnit* cu, CallInfo* info); - bool GenInlinedUnsafeGet(CompilationUnit* cu, CallInfo* info, bool is_long, bool is_volatile); - bool GenInlinedUnsafePut(CompilationUnit* cu, CallInfo* info, bool is_long, bool is_object, - bool is_volatile, bool is_ordered); - bool GenIntrinsic(CompilationUnit* cu, CallInfo* info); - - // Shared by all targets - implemented in gen_loadstore.cc. - RegLocation LoadCurrMethod(CompilationUnit *cu); - void LoadCurrMethodDirect(CompilationUnit *cu, int r_tgt); - LIR* LoadConstant(CompilationUnit* cu, int r_dest, int value); - LIR* LoadWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest); - RegLocation LoadValue(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind); - RegLocation LoadValueWide(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind); - void LoadValueDirect(CompilationUnit* cu, RegLocation rl_src, int r_dest); - void LoadValueDirectFixed(CompilationUnit* cu, RegLocation rl_src, int r_dest); - void LoadValueDirectWide(CompilationUnit* cu, RegLocation rl_src, int reg_lo, int reg_hi); - void LoadValueDirectWideFixed(CompilationUnit* cu, RegLocation rl_src, int reg_lo, int reg_hi); - LIR* StoreWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_src); - void StoreValue(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - void StoreValueWide(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - - // Required for target - codegen helpers. - virtual bool SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode, - RegLocation rl_src, RegLocation rl_dest, int lit) = 0; - virtual int LoadHelper(CompilationUnit* cu, int offset) = 0; - virtual LIR* LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest, - OpSize size, int s_reg) = 0; - virtual LIR* LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo, - int r_dest_hi, int s_reg) = 0; - virtual LIR* LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest, int scale, - OpSize size) = 0; - virtual LIR* LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, - int displacement, int r_dest, int r_dest_hi, OpSize size, - int s_reg) = 0; - virtual LIR* LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value) = 0; - virtual LIR* LoadConstantWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi, - int64_t value) = 0; - virtual LIR* StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src, - OpSize size) = 0; - virtual LIR* StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_src_lo, - int r_src_hi) = 0; - virtual LIR* StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src, int scale, - OpSize size) = 0; - virtual LIR* StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, - int displacement, int r_src, int r_src_hi, OpSize size, - int s_reg) = 0; - virtual void MarkGCCard(CompilationUnit* cu, int val_reg, int tgt_addr_reg) = 0; - - // Required for target - register utilities. - virtual bool IsFpReg(int reg) = 0; - virtual bool SameRegType(int reg1, int reg2) = 0; - virtual int AllocTypedTemp(CompilationUnit* cu, bool fp_hint, int reg_class) = 0; - virtual int AllocTypedTempPair(CompilationUnit* cu, bool fp_hint, int reg_class) = 0; - virtual int S2d(int low_reg, int high_reg) = 0; - virtual int TargetReg(SpecialTargetRegister reg) = 0; - virtual RegisterInfo* GetRegInfo(CompilationUnit* cu, int reg) = 0; - virtual RegLocation GetReturnAlt(CompilationUnit* cu) = 0; - virtual RegLocation GetReturnWideAlt(CompilationUnit* cu) = 0; - virtual RegLocation LocCReturn() = 0; - virtual RegLocation LocCReturnDouble() = 0; - virtual RegLocation LocCReturnFloat() = 0; - virtual RegLocation LocCReturnWide() = 0; - virtual uint32_t FpRegMask() = 0; - virtual uint64_t GetRegMaskCommon(CompilationUnit* cu, int reg) = 0; - virtual void AdjustSpillMask(CompilationUnit* cu) = 0; - virtual void ClobberCalleeSave(CompilationUnit *cu) = 0; - virtual void FlushReg(CompilationUnit* cu, int reg) = 0; - virtual void FlushRegWide(CompilationUnit* cu, int reg1, int reg2) = 0; - virtual void FreeCallTemps(CompilationUnit* cu) = 0; - virtual void FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, RegLocation rl_free) = 0; - virtual void LockCallTemps(CompilationUnit* cu) = 0; - virtual void MarkPreservedSingle(CompilationUnit* cu, int v_reg, int reg) = 0; - virtual void CompilerInitializeRegAlloc(CompilationUnit* cu) = 0; - - // Required for target - miscellaneous. - virtual AssemblerStatus AssembleInstructions(CompilationUnit* cu, uintptr_t start_addr) = 0; - virtual void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix) = 0; - virtual void SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir) = 0; - virtual const char* GetTargetInstFmt(int opcode) = 0; - virtual const char* GetTargetInstName(int opcode) = 0; - virtual std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) = 0; - virtual uint64_t GetPCUseDefEncoding() = 0; - virtual uint64_t GetTargetInstFlags(int opcode) = 0; - virtual int GetInsnSize(LIR* lir) = 0; - virtual bool IsUnconditionalBranch(LIR* lir) = 0; - - // Required for target - Dalvik-level generators. - virtual void GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2) = 0; - virtual void GenMulLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) = 0; - virtual void GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) = 0; - virtual void GenAndLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) = 0; - virtual void GenArithOpDouble(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) = 0; - virtual void GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2) = 0; - virtual void GenCmpFP(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2) = 0; - virtual void GenConversion(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src) = 0; - virtual bool GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier) = 0; - virtual bool GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min) = 0; - virtual bool GenInlinedSqrt(CompilationUnit* cu, CallInfo* info) = 0; - virtual void GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) = 0; - virtual void GenOrLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) = 0; - virtual void GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) = 0; - virtual void GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) = 0; - virtual LIR* GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code, int reg1, int base, - int offset, ThrowKind kind) = 0; - virtual RegLocation GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int reg_hi, - bool is_div) = 0; - virtual RegLocation GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int lit, - bool is_div) = 0; - virtual void GenCmpLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) = 0; - virtual void GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi) = 0; - virtual void GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, - RegLocation rl_method) = 0; - virtual void GenExitSequence(CompilationUnit* cu) = 0; - virtual void GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, - RegLocation rl_src) = 0; - virtual void GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, bool gt_bias, - bool is_double) = 0; - virtual void GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir) = 0; - virtual void GenSelect(CompilationUnit* cu, BasicBlock* bb, MIR* mir) = 0; - virtual void GenMemBarrier(CompilationUnit* cu, MemBarrierKind barrier_kind) = 0; - virtual void GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation rl_src) = 0; - virtual void GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation rl_src) = 0; - virtual void GenMoveException(CompilationUnit* cu, RegLocation rl_dest) = 0; - virtual void GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src, - RegLocation rl_result, int lit, int first_bit, - int second_bit) = 0; - virtual void GenNegDouble(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) = 0; - virtual void GenNegFloat(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) = 0; - virtual void GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, - RegLocation rl_src) = 0; - virtual void GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, - RegLocation rl_src) = 0; - virtual void GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, - SpecialCaseHandler special_case) = 0; - virtual void GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, - RegLocation rl_index, RegLocation rl_src, int scale) = 0; - virtual void GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, - RegLocation rl_index, RegLocation rl_dest, int scale) = 0; - virtual void GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, - RegLocation rl_index, RegLocation rl_src, int scale) = 0; - virtual void GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_shift) = 0; - - // Required for target - single operation generators. - virtual LIR* OpUnconditionalBranch(CompilationUnit* cu, LIR* target) = 0; - virtual LIR* OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, int src2, - LIR* target) = 0; - virtual LIR* OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg, int check_value, - LIR* target) = 0; - virtual LIR* OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target) = 0; - virtual LIR* OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, - LIR* target) = 0; - virtual LIR* OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src) = 0; - virtual LIR* OpIT(CompilationUnit* cu, ConditionCode cond, const char* guide) = 0; - virtual LIR* OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp) = 0; - virtual LIR* OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target) = 0; - virtual LIR* OpReg(CompilationUnit* cu, OpKind op, int r_dest_src) = 0; - virtual LIR* OpRegCopy(CompilationUnit* cu, int r_dest, int r_src) = 0; - virtual LIR* OpRegCopyNoInsert(CompilationUnit* cu, int r_dest, int r_src) = 0; - virtual LIR* OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value) = 0; - virtual LIR* OpRegMem(CompilationUnit* cu, OpKind op, int r_dest, int rBase, int offset) = 0; - virtual LIR* OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2) = 0; - virtual LIR* OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value) = 0; - virtual LIR* OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, - int r_src2) = 0; - virtual LIR* OpTestSuspend(CompilationUnit* cu, LIR* target) = 0; - virtual LIR* OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset) = 0; - virtual LIR* OpVldm(CompilationUnit* cu, int rBase, int count) = 0; - virtual LIR* OpVstm(CompilationUnit* cu, int rBase, int count) = 0; - virtual void OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, - int offset) = 0; - virtual void OpRegCopyWide(CompilationUnit* cu, int dest_lo, int dest_hi, int src_lo, - int src_hi) = 0; - virtual void OpTlsCmp(CompilationUnit* cu, int offset, int val) = 0; - virtual bool InexpensiveConstantInt(int32_t value) = 0; - virtual bool InexpensiveConstantFloat(int32_t value) = 0; - virtual bool InexpensiveConstantLong(int64_t value) = 0; - virtual bool InexpensiveConstantDouble(int64_t value) = 0; - - // Temp workaround - void Workaround7250540(CompilationUnit* cu, RegLocation rl_dest, int value); - }; // Class Codegen - -} // namespace art - -#endif // ART_SRC_COMPILER_DEX_QUICK_CODEGEN_H_ diff --git a/src/compiler/dex/quick/codegen_util.cc b/src/compiler/dex/quick/codegen_util.cc index b5152df994..91422eab77 100644 --- a/src/compiler/dex/quick/codegen_util.cc +++ b/src/compiler/dex/quick/codegen_util.cc @@ -19,58 +19,54 @@ #include "gc_map.h" #include "verifier/dex_gc_map.h" #include "verifier/method_verifier.h" -#include "ralloc_util.h" -#include "codegen_util.h" namespace art { -bool IsInexpensiveConstant(CompilationUnit* cu, RegLocation rl_src) +bool Mir2Lir::IsInexpensiveConstant(RegLocation rl_src) { bool res = false; if (rl_src.is_const) { if (rl_src.wide) { if (rl_src.fp) { - res = cu->cg->InexpensiveConstantDouble(cu->mir_graph->ConstantValueWide(rl_src)); + res = InexpensiveConstantDouble(mir_graph_->ConstantValueWide(rl_src)); } else { - res = cu->cg->InexpensiveConstantLong(cu->mir_graph->ConstantValueWide(rl_src)); + res = InexpensiveConstantLong(mir_graph_->ConstantValueWide(rl_src)); } } else { if (rl_src.fp) { - res = cu->cg->InexpensiveConstantFloat(cu->mir_graph->ConstantValue(rl_src)); + res = InexpensiveConstantFloat(mir_graph_->ConstantValue(rl_src)); } else { - res = cu->cg->InexpensiveConstantInt(cu->mir_graph->ConstantValue(rl_src)); + res = InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src)); } } } return res; } -void MarkSafepointPC(CompilationUnit* cu, LIR* inst) +void Mir2Lir::MarkSafepointPC(LIR* inst) { inst->def_mask = ENCODE_ALL; - LIR* safepoint_pc = NewLIR0(cu, kPseudoSafepointPC); + LIR* safepoint_pc = NewLIR0(kPseudoSafepointPC); DCHECK_EQ(safepoint_pc->def_mask, ENCODE_ALL); } -bool FastInstance(CompilationUnit* cu, uint32_t field_idx, - int& field_offset, bool& is_volatile, bool is_put) +bool Mir2Lir::FastInstance(uint32_t field_idx, int& field_offset, bool& is_volatile, bool is_put) { - return cu->compiler_driver->ComputeInstanceFieldInfo( - field_idx, cu->mir_graph->GetCurrentDexCompilationUnit(), field_offset, is_volatile, is_put); + return cu_->compiler_driver->ComputeInstanceFieldInfo( + field_idx, mir_graph_->GetCurrentDexCompilationUnit(), field_offset, is_volatile, is_put); } /* Convert an instruction to a NOP */ -void NopLIR( LIR* lir) +void Mir2Lir::NopLIR( LIR* lir) { lir->flags.is_nop = true; } -void SetMemRefType(CompilationUnit* cu, LIR* lir, bool is_load, int mem_type) +void Mir2Lir::SetMemRefType(LIR* lir, bool is_load, int mem_type) { uint64_t *mask_ptr; uint64_t mask = ENCODE_MEM;; - Codegen* cg = cu->cg.get(); - DCHECK(cg->GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE)); + DCHECK(GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE)); if (is_load) { mask_ptr = &lir->use_mask; } else { @@ -92,7 +88,7 @@ void SetMemRefType(CompilationUnit* cu, LIR* lir, bool is_load, int mem_type) break; case kMustNotAlias: /* Currently only loads can be marked as kMustNotAlias */ - DCHECK(!(cg->GetTargetInstFlags(lir->opcode) & IS_STORE)); + DCHECK(!(GetTargetInstFlags(lir->opcode) & IS_STORE)); *mask_ptr |= ENCODE_MUST_NOT_ALIAS; break; default: @@ -103,9 +99,10 @@ void SetMemRefType(CompilationUnit* cu, LIR* lir, bool is_load, int mem_type) /* * Mark load/store instructions that access Dalvik registers through the stack. */ -void AnnotateDalvikRegAccess(CompilationUnit* cu, LIR* lir, int reg_id, bool is_load, bool is64bit) +void Mir2Lir::AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load, + bool is64bit) { - SetMemRefType(cu, lir, is_load, kDalvikReg); + SetMemRefType(lir, is_load, kDalvikReg); /* * Store the Dalvik register id in alias_info. Mark the MSB if it is a 64-bit @@ -117,38 +114,36 @@ void AnnotateDalvikRegAccess(CompilationUnit* cu, LIR* lir, int reg_id, bool is_ /* * Mark the corresponding bit(s). */ -void SetupRegMask(CompilationUnit* cu, uint64_t* mask, int reg) +void Mir2Lir::SetupRegMask(uint64_t* mask, int reg) { - Codegen* cg = cu->cg.get(); - *mask |= cg->GetRegMaskCommon(cu, reg); + *mask |= GetRegMaskCommon(reg); } /* * Set up the proper fields in the resource mask */ -void SetupResourceMasks(CompilationUnit* cu, LIR* lir) +void Mir2Lir::SetupResourceMasks(LIR* lir) { int opcode = lir->opcode; - Codegen* cg = cu->cg.get(); if (opcode <= 0) { lir->use_mask = lir->def_mask = 0; return; } - uint64_t flags = cg->GetTargetInstFlags(opcode); + uint64_t flags = GetTargetInstFlags(opcode); if (flags & NEEDS_FIXUP) { lir->flags.pcRelFixup = true; } /* Get the starting size of the instruction's template */ - lir->flags.size = cg->GetInsnSize(lir); + lir->flags.size = GetInsnSize(lir); /* Set up the mask for resources that are updated */ if (flags & (IS_LOAD | IS_STORE)) { /* Default to heap - will catch specialized classes later */ - SetMemRefType(cu, lir, flags & IS_LOAD, kHeapRef); + SetMemRefType(lir, flags & IS_LOAD, kHeapRef); } /* @@ -161,11 +156,11 @@ void SetupResourceMasks(CompilationUnit* cu, LIR* lir) } if (flags & REG_DEF0) { - SetupRegMask(cu, &lir->def_mask, lir->operands[0]); + SetupRegMask(&lir->def_mask, lir->operands[0]); } if (flags & REG_DEF1) { - SetupRegMask(cu, &lir->def_mask, lir->operands[1]); + SetupRegMask(&lir->def_mask, lir->operands[1]); } @@ -178,7 +173,7 @@ void SetupResourceMasks(CompilationUnit* cu, LIR* lir) for (i = 0; i < 4; i++) { if (flags & (1 << (kRegUse0 + i))) { - SetupRegMask(cu, &lir->use_mask, lir->operands[i]); + SetupRegMask(&lir->use_mask, lir->operands[i]); } } } @@ -188,7 +183,7 @@ void SetupResourceMasks(CompilationUnit* cu, LIR* lir) } // Handle target-specific actions - cg->SetupTargetResourceMasks(cu, lir); + SetupTargetResourceMasks(lir); } /* @@ -197,18 +192,17 @@ void SetupResourceMasks(CompilationUnit* cu, LIR* lir) #define DUMP_RESOURCE_MASK(X) /* Pretty-print a LIR instruction */ -void DumpLIRInsn(CompilationUnit* cu, LIR* lir, unsigned char* base_addr) +void Mir2Lir::DumpLIRInsn(LIR* lir, unsigned char* base_addr) { int offset = lir->offset; int dest = lir->operands[0]; - const bool dump_nop = (cu->enable_debug & (1 << kDebugShowNops)); - Codegen* cg = cu->cg.get(); + const bool dump_nop = (cu_->enable_debug & (1 << kDebugShowNops)); /* Handle pseudo-ops individually, and all regular insns as a group */ switch (lir->opcode) { case kPseudoMethodEntry: LOG(INFO) << "-------- method entry " - << PrettyMethod(cu->method_idx, *cu->dex_file); + << PrettyMethod(cu_->method_idx, *cu_->dex_file); break; case kPseudoMethodExit: LOG(INFO) << "-------- Method_Exit"; @@ -264,9 +258,9 @@ void DumpLIRInsn(CompilationUnit* cu, LIR* lir, unsigned char* base_addr) if (lir->flags.is_nop && !dump_nop) { break; } else { - std::string op_name(cg->BuildInsnString(cg->GetTargetInstName(lir->opcode), + std::string op_name(BuildInsnString(GetTargetInstName(lir->opcode), lir, base_addr)); - std::string op_operands(cg->BuildInsnString(cg->GetTargetInstFmt(lir->opcode), + std::string op_operands(BuildInsnString(GetTargetInstFmt(lir->opcode), lir, base_addr)); LOG(INFO) << StringPrintf("%05x: %-9s%s%s", reinterpret_cast<unsigned int>(base_addr + offset), @@ -284,38 +278,37 @@ void DumpLIRInsn(CompilationUnit* cu, LIR* lir, unsigned char* base_addr) } } -void DumpPromotionMap(CompilationUnit *cu) +void Mir2Lir::DumpPromotionMap() { - Codegen* cg = cu->cg.get(); - int num_regs = cu->num_dalvik_registers + cu->num_compiler_temps + 1; + int num_regs = cu_->num_dalvik_registers + cu_->num_compiler_temps + 1; for (int i = 0; i < num_regs; i++) { - PromotionMap v_reg_map = cu->promotion_map[i]; + PromotionMap v_reg_map = promotion_map_[i]; std::string buf; if (v_reg_map.fp_location == kLocPhysReg) { - StringAppendF(&buf, " : s%d", v_reg_map.FpReg & cg->FpRegMask()); + StringAppendF(&buf, " : s%d", v_reg_map.FpReg & FpRegMask()); } std::string buf3; - if (i < cu->num_dalvik_registers) { + if (i < cu_->num_dalvik_registers) { StringAppendF(&buf3, "%02d", i); - } else if (i == cu->method_sreg) { + } else if (i == mir_graph_->GetMethodSReg()) { buf3 = "Method*"; } else { - StringAppendF(&buf3, "ct%d", i - cu->num_dalvik_registers); + StringAppendF(&buf3, "ct%d", i - cu_->num_dalvik_registers); } LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(), v_reg_map.core_location == kLocPhysReg ? "r" : "SP+", v_reg_map.core_location == kLocPhysReg ? - v_reg_map.core_reg : SRegOffset(cu, i), + v_reg_map.core_reg : SRegOffset(i), buf.c_str()); } } /* Dump a mapping table */ -static void DumpMappingTable(const char* table_name, const std::string& descriptor, - const std::string& name, const std::string& signature, - const std::vector<uint32_t>& v) { +void Mir2Lir::DumpMappingTable(const char* table_name, const std::string& descriptor, + const std::string& name, const std::string& signature, + const std::vector<uint32_t>& v) { if (v.size() > 0) { std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name, descriptor.c_str(), name.c_str(), signature.c_str(), v.size())); @@ -330,49 +323,49 @@ static void DumpMappingTable(const char* table_name, const std::string& descript } /* Dump instructions and constant pool contents */ -void CodegenDump(CompilationUnit* cu) +void Mir2Lir::CodegenDump() { LOG(INFO) << "Dumping LIR insns for " - << PrettyMethod(cu->method_idx, *cu->dex_file); + << PrettyMethod(cu_->method_idx, *cu_->dex_file); LIR* lir_insn; - int insns_size = cu->code_item->insns_size_in_code_units_; - - LOG(INFO) << "Regs (excluding ins) : " << cu->num_regs; - LOG(INFO) << "Ins : " << cu->num_ins; - LOG(INFO) << "Outs : " << cu->num_outs; - LOG(INFO) << "CoreSpills : " << cu->num_core_spills; - LOG(INFO) << "FPSpills : " << cu->num_fp_spills; - LOG(INFO) << "CompilerTemps : " << cu->num_compiler_temps; - LOG(INFO) << "Frame size : " << cu->frame_size; - LOG(INFO) << "code size is " << cu->total_size << + int insns_size = cu_->code_item->insns_size_in_code_units_; + + LOG(INFO) << "Regs (excluding ins) : " << cu_->num_regs; + LOG(INFO) << "Ins : " << cu_->num_ins; + LOG(INFO) << "Outs : " << cu_->num_outs; + LOG(INFO) << "CoreSpills : " << num_core_spills_; + LOG(INFO) << "FPSpills : " << num_fp_spills_; + LOG(INFO) << "CompilerTemps : " << cu_->num_compiler_temps; + LOG(INFO) << "Frame size : " << frame_size_; + LOG(INFO) << "code size is " << total_size_ << " bytes, Dalvik size is " << insns_size * 2; LOG(INFO) << "expansion factor: " - << static_cast<float>(cu->total_size) / static_cast<float>(insns_size * 2); - DumpPromotionMap(cu); - for (lir_insn = cu->first_lir_insn; lir_insn != NULL; lir_insn = lir_insn->next) { - DumpLIRInsn(cu, lir_insn, 0); + << static_cast<float>(total_size_) / static_cast<float>(insns_size * 2); + DumpPromotionMap(); + for (lir_insn = first_lir_insn_; lir_insn != NULL; lir_insn = lir_insn->next) { + DumpLIRInsn(lir_insn, 0); } - for (lir_insn = cu->literal_list; lir_insn != NULL; lir_insn = lir_insn->next) { + for (lir_insn = literal_list_; lir_insn != NULL; lir_insn = lir_insn->next) { LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lir_insn->offset, lir_insn->offset, lir_insn->operands[0]); } const DexFile::MethodId& method_id = - cu->dex_file->GetMethodId(cu->method_idx); - std::string signature(cu->dex_file->GetMethodSignature(method_id)); - std::string name(cu->dex_file->GetMethodName(method_id)); - std::string descriptor(cu->dex_file->GetMethodDeclaringClassDescriptor(method_id)); + cu_->dex_file->GetMethodId(cu_->method_idx); + std::string signature(cu_->dex_file->GetMethodSignature(method_id)); + std::string name(cu_->dex_file->GetMethodName(method_id)); + std::string descriptor(cu_->dex_file->GetMethodDeclaringClassDescriptor(method_id)); // Dump mapping tables - DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cu->pc2dexMappingTable); - DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cu->dex2pcMappingTable); + DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, pc2dex_mapping_table_); + DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, dex2pc_mapping_table_); } -LIR* RawLIR(CompilationUnit* cu, int dalvik_offset, int opcode, int op0, - int op1, int op2, int op3, int op4, LIR* target) +LIR* Mir2Lir::RawLIR(int dalvik_offset, int opcode, int op0, + int op1, int op2, int op3, int op4, LIR* target) { - LIR* insn = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR)); + LIR* insn = static_cast<LIR*>(NewMem(cu_, sizeof(LIR), true, kAllocLIR)); insn->dalvik_offset = dalvik_offset; insn->opcode = opcode; insn->operands[0] = op0; @@ -381,7 +374,7 @@ LIR* RawLIR(CompilationUnit* cu, int dalvik_offset, int opcode, int op0, insn->operands[3] = op3; insn->operands[4] = op4; insn->target = target; - SetupResourceMasks(cu, insn); + SetupResourceMasks(insn); if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) || (opcode == kPseudoExportedPC)) { // Always make labels scheduling barriers @@ -394,80 +387,70 @@ LIR* RawLIR(CompilationUnit* cu, int dalvik_offset, int opcode, int op0, * The following are building blocks to construct low-level IRs with 0 - 4 * operands. */ -LIR* NewLIR0(CompilationUnit* cu, int opcode) +LIR* Mir2Lir::NewLIR0(int opcode) { - Codegen* cg = cu->cg.get(); - DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & NO_OPERAND)) - << cg->GetTargetInstName(opcode) << " " << opcode << " " - << PrettyMethod(cu->method_idx, *cu->dex_file) << " " - << cu->current_dalvik_offset; - LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode); - AppendLIR(cu, insn); + DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & NO_OPERAND)) + << GetTargetInstName(opcode) << " " << opcode << " " + << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " + << current_dalvik_offset_; + LIR* insn = RawLIR(current_dalvik_offset_, opcode); + AppendLIR(insn); return insn; } -LIR* NewLIR1(CompilationUnit* cu, int opcode, - int dest) +LIR* Mir2Lir::NewLIR1(int opcode, int dest) { - Codegen* cg = cu->cg.get(); - DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_UNARY_OP)) - << cg->GetTargetInstName(opcode) << " " << opcode << " " - << PrettyMethod(cu->method_idx, *cu->dex_file) << " " - << cu->current_dalvik_offset; - LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest); - AppendLIR(cu, insn); + DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_UNARY_OP)) + << GetTargetInstName(opcode) << " " << opcode << " " + << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " + << current_dalvik_offset_; + LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest); + AppendLIR(insn); return insn; } -LIR* NewLIR2(CompilationUnit* cu, int opcode, - int dest, int src1) +LIR* Mir2Lir::NewLIR2(int opcode, int dest, int src1) { - Codegen* cg = cu->cg.get(); - DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_BINARY_OP)) - << cg->GetTargetInstName(opcode) << " " << opcode << " " - << PrettyMethod(cu->method_idx, *cu->dex_file) << " " - << cu->current_dalvik_offset; - LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1); - AppendLIR(cu, insn); + DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_BINARY_OP)) + << GetTargetInstName(opcode) << " " << opcode << " " + << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " + << current_dalvik_offset_; + LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1); + AppendLIR(insn); return insn; } -LIR* NewLIR3(CompilationUnit* cu, int opcode, - int dest, int src1, int src2) +LIR* Mir2Lir::NewLIR3(int opcode, int dest, int src1, int src2) { - Codegen* cg = cu->cg.get(); - DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_TERTIARY_OP)) - << cg->GetTargetInstName(opcode) << " " << opcode << " " - << PrettyMethod(cu->method_idx, *cu->dex_file) << " " - << cu->current_dalvik_offset; - LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2); - AppendLIR(cu, insn); + DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_TERTIARY_OP)) + << GetTargetInstName(opcode) << " " << opcode << " " + << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " + << current_dalvik_offset_; + LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2); + AppendLIR(insn); return insn; } -LIR* NewLIR4(CompilationUnit* cu, int opcode, - int dest, int src1, int src2, int info) +LIR* Mir2Lir::NewLIR4(int opcode, int dest, int src1, int src2, int info) { - Codegen* cg = cu->cg.get(); - DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_QUAD_OP)) - << cg->GetTargetInstName(opcode) << " " << opcode << " " - << PrettyMethod(cu->method_idx, *cu->dex_file) << " " - << cu->current_dalvik_offset; - LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2, info); - AppendLIR(cu, insn); + DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_QUAD_OP)) + << GetTargetInstName(opcode) << " " << opcode << " " + << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " + << current_dalvik_offset_; + LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2, info); + AppendLIR(insn); return insn; } -LIR* NewLIR5(CompilationUnit* cu, int opcode, - int dest, int src1, int src2, int info1, int info2) +LIR* Mir2Lir::NewLIR5(int opcode, int dest, int src1, int src2, int info1, + int info2) { - Codegen* cg = cu->cg.get(); - DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_QUIN_OP)) - << cg->GetTargetInstName(opcode) << " " << opcode << " " - << PrettyMethod(cu->method_idx, *cu->dex_file) << " " - << cu->current_dalvik_offset; - LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2, info1, info2); - AppendLIR(cu, insn); + DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_QUIN_OP)) + << GetTargetInstName(opcode) << " " << opcode << " " + << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " + << current_dalvik_offset_; + LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2, info1, info2); + AppendLIR(insn); return insn; } @@ -475,7 +458,7 @@ LIR* NewLIR5(CompilationUnit* cu, int opcode, * Search the existing constants in the literal pool for an exact or close match * within specified delta (greater or equal to 0). */ -LIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta) +LIR* Mir2Lir::ScanLiteralPool(LIR* data_target, int value, unsigned int delta) { while (data_target) { if ((static_cast<unsigned>(value - data_target->operands[0])) <= delta) @@ -486,7 +469,7 @@ LIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta) } /* Search the existing constants in the literal pool for an exact wide match */ -LIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi) +LIR* Mir2Lir::ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi) { bool lo_match = false; LIR* lo_target = NULL; @@ -512,11 +495,11 @@ LIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi) */ /* Add a 32-bit constant to the constant pool */ -LIR* AddWordData(CompilationUnit* cu, LIR* *constant_list_p, int value) +LIR* Mir2Lir::AddWordData(LIR* *constant_list_p, int value) { /* Add the constant to the literal pool */ if (constant_list_p) { - LIR* new_value = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocData)); + LIR* new_value = static_cast<LIR*>(NewMem(cu_, sizeof(LIR), true, kAllocData)); new_value->operands[0] = value; new_value->next = *constant_list_p; *constant_list_p = new_value; @@ -526,11 +509,10 @@ LIR* AddWordData(CompilationUnit* cu, LIR* *constant_list_p, int value) } /* Add a 64-bit constant to the constant pool or mixed with code */ -LIR* AddWideData(CompilationUnit* cu, LIR* *constant_list_p, - int val_lo, int val_hi) +LIR* Mir2Lir::AddWideData(LIR* *constant_list_p, int val_lo, int val_hi) { - AddWordData(cu, constant_list_p, val_hi); - return AddWordData(cu, constant_list_p, val_lo); + AddWordData(constant_list_p, val_hi); + return AddWordData(constant_list_p, val_lo); } static void PushWord(std::vector<uint8_t>&buf, int data) { @@ -547,57 +529,57 @@ static void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) { } /* Write the literal pool to the output stream */ -static void InstallLiteralPools(CompilationUnit* cu) +void Mir2Lir::InstallLiteralPools() { - AlignBuffer(cu->code_buffer, cu->data_offset); - LIR* data_lir = cu->literal_list; + AlignBuffer(code_buffer_, data_offset_); + LIR* data_lir = literal_list_; while (data_lir != NULL) { - PushWord(cu->code_buffer, data_lir->operands[0]); + PushWord(code_buffer_, data_lir->operands[0]); data_lir = NEXT_LIR(data_lir); } // Push code and method literals, record offsets for the compiler to patch. - data_lir = cu->code_literal_list; + data_lir = code_literal_list_; while (data_lir != NULL) { uint32_t target = data_lir->operands[0]; - cu->compiler_driver->AddCodePatch(cu->dex_file, - cu->method_idx, - cu->invoke_type, + cu_->compiler_driver->AddCodePatch(cu_->dex_file, + cu_->method_idx, + cu_->invoke_type, target, static_cast<InvokeType>(data_lir->operands[1]), - cu->code_buffer.size()); - const DexFile::MethodId& id = cu->dex_file->GetMethodId(target); + code_buffer_.size()); + const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target); // unique based on target to ensure code deduplication works uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id); - PushWord(cu->code_buffer, unique_patch_value); + PushWord(code_buffer_, unique_patch_value); data_lir = NEXT_LIR(data_lir); } - data_lir = cu->method_literal_list; + data_lir = method_literal_list_; while (data_lir != NULL) { uint32_t target = data_lir->operands[0]; - cu->compiler_driver->AddMethodPatch(cu->dex_file, - cu->method_idx, - cu->invoke_type, + cu_->compiler_driver->AddMethodPatch(cu_->dex_file, + cu_->method_idx, + cu_->invoke_type, target, static_cast<InvokeType>(data_lir->operands[1]), - cu->code_buffer.size()); - const DexFile::MethodId& id = cu->dex_file->GetMethodId(target); + code_buffer_.size()); + const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target); // unique based on target to ensure code deduplication works uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id); - PushWord(cu->code_buffer, unique_patch_value); + PushWord(code_buffer_, unique_patch_value); data_lir = NEXT_LIR(data_lir); } } /* Write the switch tables to the output stream */ -static void InstallSwitchTables(CompilationUnit* cu) +void Mir2Lir::InstallSwitchTables() { GrowableListIterator iterator; - GrowableListIteratorInit(&cu->switch_tables, &iterator); + GrowableListIteratorInit(&switch_tables_, &iterator); while (true) { - Codegen::SwitchTable* tab_rec = - reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext( &iterator)); + Mir2Lir::SwitchTable* tab_rec = + reinterpret_cast<Mir2Lir::SwitchTable*>(GrowableListIteratorNext( &iterator)); if (tab_rec == NULL) break; - AlignBuffer(cu->code_buffer, tab_rec->offset); + AlignBuffer(code_buffer_, tab_rec->offset); /* * For Arm, our reference point is the address of the bx * instruction that does the launch, so we have to subtract @@ -605,7 +587,7 @@ static void InstallSwitchTables(CompilationUnit* cu) * is a label, so we can use the offset as-is. */ int bx_offset = INVALID_OFFSET; - switch (cu->instruction_set) { + switch (cu_->instruction_set) { case kThumb2: bx_offset = tab_rec->anchor->offset + 4; break; @@ -615,22 +597,22 @@ static void InstallSwitchTables(CompilationUnit* cu) case kMips: bx_offset = tab_rec->anchor->offset; break; - default: LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set; + default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set; } - if (cu->verbose) { + if (cu_->verbose) { LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset; } if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2])); for (int elems = 0; elems < tab_rec->table[1]; elems++) { int disp = tab_rec->targets[elems]->offset - bx_offset; - if (cu->verbose) { + if (cu_->verbose) { LOG(INFO) << " Case[" << elems << "] key: 0x" << std::hex << keys[elems] << ", disp: 0x" << std::hex << disp; } - PushWord(cu->code_buffer, keys[elems]); - PushWord(cu->code_buffer, + PushWord(code_buffer_, keys[elems]); + PushWord(code_buffer_, tab_rec->targets[elems]->offset - bx_offset); } } else { @@ -638,29 +620,29 @@ static void InstallSwitchTables(CompilationUnit* cu) static_cast<int>(Instruction::kPackedSwitchSignature)); for (int elems = 0; elems < tab_rec->table[1]; elems++) { int disp = tab_rec->targets[elems]->offset - bx_offset; - if (cu->verbose) { + if (cu_->verbose) { LOG(INFO) << " Case[" << elems << "] disp: 0x" << std::hex << disp; } - PushWord(cu->code_buffer, tab_rec->targets[elems]->offset - bx_offset); + PushWord(code_buffer_, tab_rec->targets[elems]->offset - bx_offset); } } } } /* Write the fill array dta to the output stream */ -static void InstallFillArrayData(CompilationUnit* cu) +void Mir2Lir::InstallFillArrayData() { GrowableListIterator iterator; - GrowableListIteratorInit(&cu->fill_array_data, &iterator); + GrowableListIteratorInit(&fill_array_data_, &iterator); while (true) { - Codegen::FillArrayData *tab_rec = - reinterpret_cast<Codegen::FillArrayData*>(GrowableListIteratorNext( &iterator)); + Mir2Lir::FillArrayData *tab_rec = + reinterpret_cast<Mir2Lir::FillArrayData*>(GrowableListIteratorNext( &iterator)); if (tab_rec == NULL) break; - AlignBuffer(cu->code_buffer, tab_rec->offset); + AlignBuffer(code_buffer_, tab_rec->offset); for (int i = 0; i < (tab_rec->size + 1) / 2; i++) { - cu->code_buffer.push_back( tab_rec->table[i] & 0xFF); - cu->code_buffer.push_back( (tab_rec->table[i] >> 8) & 0xFF); + code_buffer_.push_back( tab_rec->table[i] & 0xFF); + code_buffer_.push_back( (tab_rec->table[i] >> 8) & 0xFF); } } } @@ -675,15 +657,15 @@ static int AssignLiteralOffsetCommon(LIR* lir, int offset) } // Make sure we have a code address for every declared catch entry -static bool VerifyCatchEntries(CompilationUnit* cu) +bool Mir2Lir::VerifyCatchEntries() { bool success = true; - for (std::set<uint32_t>::const_iterator it = cu->mir_graph->catches_.begin(); - it != cu->mir_graph->catches_.end(); ++it) { + for (std::set<uint32_t>::const_iterator it = mir_graph_->catches_.begin(); + it != mir_graph_->catches_.end(); ++it) { uint32_t dex_pc = *it; bool found = false; - for (size_t i = 0; i < cu->dex2pcMappingTable.size(); i += 2) { - if (dex_pc == cu->dex2pcMappingTable[i+1]) { + for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) { + if (dex_pc == dex2pc_mapping_table_[i+1]) { found = true; break; } @@ -694,46 +676,44 @@ static bool VerifyCatchEntries(CompilationUnit* cu) } } // Now, try in the other direction - for (size_t i = 0; i < cu->dex2pcMappingTable.size(); i += 2) { - uint32_t dex_pc = cu->dex2pcMappingTable[i+1]; - if (cu->mir_graph->catches_.find(dex_pc) == cu->mir_graph->catches_.end()) { + for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) { + uint32_t dex_pc = dex2pc_mapping_table_[i+1]; + if (mir_graph_->catches_.find(dex_pc) == mir_graph_->catches_.end()) { LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc; success = false; } } if (!success) { - LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu->method_idx, *cu->dex_file); - LOG(INFO) << "Entries @ decode: " << cu->mir_graph->catches_.size() << ", Entries in table: " - << cu->dex2pcMappingTable.size()/2; + LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); + LOG(INFO) << "Entries @ decode: " << mir_graph_->catches_.size() << ", Entries in table: " + << dex2pc_mapping_table_.size()/2; } return success; } -static void CreateMappingTables(CompilationUnit* cu) +void Mir2Lir::CreateMappingTables() { - for (LIR* tgt_lir = cu->first_lir_insn; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) { + for (LIR* tgt_lir = first_lir_insn_; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) { if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) { - cu->pc2dexMappingTable.push_back(tgt_lir->offset); - cu->pc2dexMappingTable.push_back(tgt_lir->dalvik_offset); + pc2dex_mapping_table_.push_back(tgt_lir->offset); + pc2dex_mapping_table_.push_back(tgt_lir->dalvik_offset); } if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) { - cu->dex2pcMappingTable.push_back(tgt_lir->offset); - cu->dex2pcMappingTable.push_back(tgt_lir->dalvik_offset); + dex2pc_mapping_table_.push_back(tgt_lir->offset); + dex2pc_mapping_table_.push_back(tgt_lir->dalvik_offset); } } if (kIsDebugBuild) { - DCHECK(VerifyCatchEntries(cu)); + DCHECK(VerifyCatchEntries()); } - cu->combined_mapping_table.push_back(cu->pc2dexMappingTable.size() + - cu->dex2pcMappingTable.size()); - cu->combined_mapping_table.push_back(cu->pc2dexMappingTable.size()); - cu->combined_mapping_table.insert(cu->combined_mapping_table.end(), - cu->pc2dexMappingTable.begin(), - cu->pc2dexMappingTable.end()); - cu->combined_mapping_table.insert(cu->combined_mapping_table.end(), - cu->dex2pcMappingTable.begin(), - cu->dex2pcMappingTable.end()); + combined_mapping_table_.push_back(pc2dex_mapping_table_.size() + + dex2pc_mapping_table_.size()); + combined_mapping_table_.push_back(pc2dex_mapping_table_.size()); + combined_mapping_table_.insert(combined_mapping_table_.end(), pc2dex_mapping_table_.begin(), + pc2dex_mapping_table_.end()); + combined_mapping_table_.insert(combined_mapping_table_.end(), dex2pc_mapping_table_.begin(), + dex2pc_mapping_table_.end()); } class NativePcToReferenceMapBuilder { @@ -814,8 +794,8 @@ class NativePcToReferenceMapBuilder { std::vector<uint8_t>* const table_; }; -static void CreateNativeGcMap(CompilationUnit* cu) { - const std::vector<uint32_t>& mapping_table = cu->pc2dexMappingTable; +void Mir2Lir::CreateNativeGcMap() { + const std::vector<uint32_t>& mapping_table = pc2dex_mapping_table_; uint32_t max_native_offset = 0; for (size_t i = 0; i < mapping_table.size(); i += 2) { uint32_t native_offset = mapping_table[i + 0]; @@ -823,11 +803,11 @@ static void CreateNativeGcMap(CompilationUnit* cu) { max_native_offset = native_offset; } } - CompilerDriver::MethodReference method_ref(cu->dex_file, cu->method_idx); + CompilerDriver::MethodReference method_ref(cu_->dex_file, cu_->method_idx); const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref); verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4); // Compute native offset to references size. - NativePcToReferenceMapBuilder native_gc_map_builder(&cu->native_gc_map, + NativePcToReferenceMapBuilder native_gc_map_builder(&native_gc_map_, mapping_table.size() / 2, max_native_offset, dex_gc_map.RegWidth()); @@ -841,21 +821,21 @@ static void CreateNativeGcMap(CompilationUnit* cu) { } /* Determine the offset of each literal field */ -static int AssignLiteralOffset(CompilationUnit* cu, int offset) +int Mir2Lir::AssignLiteralOffset(int offset) { - offset = AssignLiteralOffsetCommon(cu->literal_list, offset); - offset = AssignLiteralOffsetCommon(cu->code_literal_list, offset); - offset = AssignLiteralOffsetCommon(cu->method_literal_list, offset); + offset = AssignLiteralOffsetCommon(literal_list_, offset); + offset = AssignLiteralOffsetCommon(code_literal_list_, offset); + offset = AssignLiteralOffsetCommon(method_literal_list_, offset); return offset; } -static int AssignSwitchTablesOffset(CompilationUnit* cu, int offset) +int Mir2Lir::AssignSwitchTablesOffset(int offset) { GrowableListIterator iterator; - GrowableListIteratorInit(&cu->switch_tables, &iterator); + GrowableListIteratorInit(&switch_tables_, &iterator); while (true) { - Codegen::SwitchTable *tab_rec = - reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext(&iterator)); + Mir2Lir::SwitchTable *tab_rec = + reinterpret_cast<Mir2Lir::SwitchTable*>(GrowableListIteratorNext(&iterator)); if (tab_rec == NULL) break; tab_rec->offset = offset; if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { @@ -869,13 +849,13 @@ static int AssignSwitchTablesOffset(CompilationUnit* cu, int offset) return offset; } -static int AssignFillArrayDataOffset(CompilationUnit* cu, int offset) +int Mir2Lir::AssignFillArrayDataOffset(int offset) { GrowableListIterator iterator; - GrowableListIteratorInit(&cu->fill_array_data, &iterator); + GrowableListIteratorInit(&fill_array_data_, &iterator); while (true) { - Codegen::FillArrayData *tab_rec = - reinterpret_cast<Codegen::FillArrayData*>(GrowableListIteratorNext(&iterator)); + Mir2Lir::FillArrayData *tab_rec = + reinterpret_cast<Mir2Lir::FillArrayData*>(GrowableListIteratorNext(&iterator)); if (tab_rec == NULL) break; tab_rec->offset = offset; offset += tab_rec->size; @@ -886,12 +866,12 @@ static int AssignFillArrayDataOffset(CompilationUnit* cu, int offset) } // LIR offset assignment. -static int AssignInsnOffsets(CompilationUnit* cu) +int Mir2Lir::AssignInsnOffsets() { LIR* lir; int offset = 0; - for (lir = cu->first_lir_insn; lir != NULL; lir = NEXT_LIR(lir)) { + for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) { lir->offset = offset; if (lir->opcode >= 0) { if (!lir->flags.is_nop) { @@ -915,23 +895,23 @@ static int AssignInsnOffsets(CompilationUnit* cu) * Walk the compilation unit and assign offsets to instructions * and literals and compute the total size of the compiled unit. */ -static void AssignOffsets(CompilationUnit* cu) +void Mir2Lir::AssignOffsets() { - int offset = AssignInsnOffsets(cu); + int offset = AssignInsnOffsets(); /* Const values have to be word aligned */ offset = (offset + 3) & ~3; /* Set up offsets for literals */ - cu->data_offset = offset; + data_offset_ = offset; - offset = AssignLiteralOffset(cu, offset); + offset = AssignLiteralOffset(offset); - offset = AssignSwitchTablesOffset(cu, offset); + offset = AssignSwitchTablesOffset(offset); - offset = AssignFillArrayDataOffset(cu, offset); + offset = AssignFillArrayDataOffset(offset); - cu->total_size = offset; + total_size_ = offset; } /* @@ -939,10 +919,9 @@ static void AssignOffsets(CompilationUnit* cu) * before sending them off to the assembler. If out-of-range branch distance is * seen rearrange the instructions a bit to correct it. */ -void AssembleLIR(CompilationUnit* cu) +void Mir2Lir::AssembleLIR() { - Codegen* cg = cu->cg.get(); - AssignOffsets(cu); + AssignOffsets(); int assembler_retries = 0; /* * Assemble here. Note that we generate code with optimistic assumptions @@ -950,34 +929,34 @@ void AssembleLIR(CompilationUnit* cu) */ while (true) { - AssemblerStatus res = cg->AssembleInstructions(cu, 0); + AssemblerStatus res = AssembleInstructions(0); if (res == kSuccess) { break; } else { assembler_retries++; if (assembler_retries > MAX_ASSEMBLER_RETRIES) { - CodegenDump(cu); + CodegenDump(); LOG(FATAL) << "Assembler error - too many retries"; } // Redo offsets and try again - AssignOffsets(cu); - cu->code_buffer.clear(); + AssignOffsets(); + code_buffer_.clear(); } } // Install literals - InstallLiteralPools(cu); + InstallLiteralPools(); // Install switch tables - InstallSwitchTables(cu); + InstallSwitchTables(); // Install fill array data - InstallFillArrayData(cu); + InstallFillArrayData(); // Create the mapping table and native offset to reference map. - CreateMappingTables(cu); + CreateMappingTables(); - CreateNativeGcMap(cu); + CreateNativeGcMap(); } /* @@ -987,14 +966,14 @@ void AssembleLIR(CompilationUnit* cu) * all resource flags on this to prevent code motion across * target boundaries. KeyVal is just there for debugging. */ -static LIR* InsertCaseLabel(CompilationUnit* cu, int vaddr, int keyVal) +LIR* Mir2Lir::InsertCaseLabel(int vaddr, int keyVal) { SafeMap<unsigned int, LIR*>::iterator it; - it = cu->boundary_map.find(vaddr); - if (it == cu->boundary_map.end()) { + it = boundary_map_.find(vaddr); + if (it == boundary_map_.end()) { LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr; } - LIR* new_label = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR)); + LIR* new_label = static_cast<LIR*>(NewMem(cu_, sizeof(LIR), true, kAllocLIR)); new_label->dalvik_offset = vaddr; new_label->opcode = kPseudoCaseLabel; new_label->operands[0] = keyVal; @@ -1002,7 +981,7 @@ static LIR* InsertCaseLabel(CompilationUnit* cu, int vaddr, int keyVal) return new_label; } -static void MarkPackedCaseLabels(CompilationUnit* cu, Codegen::SwitchTable *tab_rec) +void Mir2Lir::MarkPackedCaseLabels(Mir2Lir::SwitchTable *tab_rec) { const uint16_t* table = tab_rec->table; int base_vaddr = tab_rec->vaddr; @@ -1010,11 +989,11 @@ static void MarkPackedCaseLabels(CompilationUnit* cu, Codegen::SwitchTable *tab_ int entries = table[1]; int low_key = s4FromSwitchData(&table[2]); for (int i = 0; i < entries; i++) { - tab_rec->targets[i] = InsertCaseLabel(cu, base_vaddr + targets[i], i + low_key); + tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], i + low_key); } } -static void MarkSparseCaseLabels(CompilationUnit* cu, Codegen::SwitchTable *tab_rec) +void Mir2Lir::MarkSparseCaseLabels(Mir2Lir::SwitchTable *tab_rec) { const uint16_t* table = tab_rec->table; int base_vaddr = tab_rec->vaddr; @@ -1022,29 +1001,29 @@ static void MarkSparseCaseLabels(CompilationUnit* cu, Codegen::SwitchTable *tab_ const int* keys = reinterpret_cast<const int*>(&table[2]); const int* targets = &keys[entries]; for (int i = 0; i < entries; i++) { - tab_rec->targets[i] = InsertCaseLabel(cu, base_vaddr + targets[i], keys[i]); + tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], keys[i]); } } -void ProcessSwitchTables(CompilationUnit* cu) +void Mir2Lir::ProcessSwitchTables() { GrowableListIterator iterator; - GrowableListIteratorInit(&cu->switch_tables, &iterator); + GrowableListIteratorInit(&switch_tables_, &iterator); while (true) { - Codegen::SwitchTable *tab_rec = - reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext(&iterator)); + Mir2Lir::SwitchTable *tab_rec = + reinterpret_cast<Mir2Lir::SwitchTable*>(GrowableListIteratorNext(&iterator)); if (tab_rec == NULL) break; if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) { - MarkPackedCaseLabels(cu, tab_rec); + MarkPackedCaseLabels(tab_rec); } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { - MarkSparseCaseLabels(cu, tab_rec); + MarkSparseCaseLabels(tab_rec); } else { LOG(FATAL) << "Invalid switch table"; } } } -void DumpSparseSwitchTable(const uint16_t* table) +void Mir2Lir::DumpSparseSwitchTable(const uint16_t* table) /* * Sparse switch data format: * ushort ident = 0x0200 magic value @@ -1066,7 +1045,7 @@ void DumpSparseSwitchTable(const uint16_t* table) } } -void DumpPackedSwitchTable(const uint16_t* table) +void Mir2Lir::DumpPackedSwitchTable(const uint16_t* table) /* * Packed switch data format: * ushort ident = 0x0100 magic value @@ -1095,16 +1074,16 @@ void DumpPackedSwitchTable(const uint16_t* table) * which we split a single Dalvik instruction, only the first MIR op * associated with a Dalvik PC should be entered into the map. */ -LIR* MarkBoundary(CompilationUnit* cu, int offset, const char* inst_str) +LIR* Mir2Lir::MarkBoundary(int offset, const char* inst_str) { - LIR* res = NewLIR1(cu, kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str)); - if (cu->boundary_map.find(offset) == cu->boundary_map.end()) { - cu->boundary_map.Put(offset, res); + LIR* res = NewLIR1(kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str)); + if (boundary_map_.find(offset) == boundary_map_.end()) { + boundary_map_.Put(offset, res); } return res; } -bool EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2) +bool Mir2Lir::EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2) { bool is_taken; switch (opcode) { @@ -1128,7 +1107,7 @@ bool EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2) } // Convert relation of src1/src2 to src2/src1 -ConditionCode FlipComparisonOrder(ConditionCode before) { +ConditionCode Mir2Lir::FlipComparisonOrder(ConditionCode before) { ConditionCode res; switch (before) { case kCondEq: res = kCondEq; break; @@ -1144,4 +1123,161 @@ ConditionCode FlipComparisonOrder(ConditionCode before) { return res; } +Mir2Lir::Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph) + : literal_list_(NULL), + method_literal_list_(NULL), + code_literal_list_(NULL), + cu_(cu), + mir_graph_(mir_graph), + data_offset_(0), + total_size_(0), + block_label_list_(NULL), + live_sreg_(0), + num_core_spills_(0), + num_fp_spills_(0), + frame_size_(0), + core_spill_mask_(0), + fp_spill_mask_(0), + first_lir_insn_(NULL), + last_lir_insn_(NULL) + { + + CompilerInitGrowableList(cu_, &switch_tables_, 4, kListSwitchTables); + CompilerInitGrowableList(cu_, &fill_array_data_, 4, kListFillArrayData); + CompilerInitGrowableList(cu_, &throw_launchpads_, 2048, kListThrowLaunchPads); + CompilerInitGrowableList(cu_, &intrinsic_launchpads_, 4, kListMisc); + CompilerInitGrowableList(cu_, &suspend_launchpads_, 2048, kListSuspendLaunchPads); + promotion_map_ = static_cast<PromotionMap*> + (NewMem(cu_, (cu_->num_dalvik_registers + cu_->num_compiler_temps + 1) * + sizeof(promotion_map_[0]), true, kAllocRegAlloc)); +} + +void Mir2Lir::Materialize() { + CompilerInitializeRegAlloc(); // Needs to happen after SSA naming + + /* Allocate Registers using simple local allocation scheme */ + SimpleRegAlloc(); + + //FIXME: re-enable by retrieving from mir_graph + SpecialCaseHandler special_case = kNoHandler; + + if (special_case != kNoHandler) { + /* + * Custom codegen for special cases. If for any reason the + * special codegen doesn't succeed, first_lir_insn_ will + * set to NULL; + */ + SpecialMIR2LIR(special_case); + } + + /* Convert MIR to LIR, etc. */ + if (first_lir_insn_ == NULL) { + MethodMIR2LIR(); + } + + /* Method is not empty */ + if (first_lir_insn_) { + + // mark the targets of switch statement case labels + ProcessSwitchTables(); + + /* Convert LIR into machine code. */ + AssembleLIR(); + + if (cu_->verbose) { + CodegenDump(); + } + + } + +} + +CompiledMethod* Mir2Lir::GetCompiledMethod() { + // Combine vmap tables - core regs, then fp regs - into vmap_table + std::vector<uint16_t> vmap_table; + // Core regs may have been inserted out of order - sort first + std::sort(core_vmap_table_.begin(), core_vmap_table_.end()); + for (size_t i = 0 ; i < core_vmap_table_.size(); i++) { + // Copy, stripping out the phys register sort key + vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]); + } + // If we have a frame, push a marker to take place of lr + if (frame_size_ > 0) { + vmap_table.push_back(INVALID_VREG); + } else { + DCHECK_EQ(__builtin_popcount(core_spill_mask_), 0); + DCHECK_EQ(__builtin_popcount(fp_spill_mask_), 0); + } + // Combine vmap tables - core regs, then fp regs. fp regs already sorted + for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) { + vmap_table.push_back(fp_vmap_table_[i]); + } + CompiledMethod* result = + new CompiledMethod(cu_->instruction_set, code_buffer_, + frame_size_, core_spill_mask_, fp_spill_mask_, + combined_mapping_table_, vmap_table, native_gc_map_); + return result; +} + +int Mir2Lir::ComputeFrameSize() { + /* Figure out the frame size */ + static const uint32_t kAlignMask = kStackAlignment - 1; + uint32_t size = (num_core_spills_ + num_fp_spills_ + + 1 /* filler word */ + cu_->num_regs + cu_->num_outs + + cu_->num_compiler_temps + 1 /* cur_method* */) + * sizeof(uint32_t); + /* Align and set */ + return (size + kAlignMask) & ~(kAlignMask); +} + +/* + * Append an LIR instruction to the LIR list maintained by a compilation + * unit + */ +void Mir2Lir::AppendLIR(LIR* lir) +{ + if (first_lir_insn_ == NULL) { + DCHECK(last_lir_insn_ == NULL); + last_lir_insn_ = first_lir_insn_ = lir; + lir->prev = lir->next = NULL; + } else { + last_lir_insn_->next = lir; + lir->prev = last_lir_insn_; + lir->next = NULL; + last_lir_insn_ = lir; + } +} + +/* + * Insert an LIR instruction before the current instruction, which cannot be the + * first instruction. + * + * prev_lir <-> new_lir <-> current_lir + */ +void Mir2Lir::InsertLIRBefore(LIR* current_lir, LIR* new_lir) +{ + DCHECK(current_lir->prev != NULL); + LIR *prev_lir = current_lir->prev; + + prev_lir->next = new_lir; + new_lir->prev = prev_lir; + new_lir->next = current_lir; + current_lir->prev = new_lir; +} + +/* + * Insert an LIR instruction after the current instruction, which cannot be the + * first instruction. + * + * current_lir -> new_lir -> old_next + */ +void Mir2Lir::InsertLIRAfter(LIR* current_lir, LIR* new_lir) +{ + new_lir->prev = current_lir; + new_lir->next = current_lir->next; + current_lir->next = new_lir; + new_lir->next->prev = new_lir; +} + + } // namespace art diff --git a/src/compiler/dex/quick/codegen_util.h b/src/compiler/dex/quick/codegen_util.h deleted file mode 100644 index 7fd26f337a..0000000000 --- a/src/compiler/dex/quick/codegen_util.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_SRC_COMPILER_DEX_QUICK_CODEGENUTIL_H_ -#define ART_SRC_COMPILER_DEX_QUICK_CODEGENUTIL_H_ - -#include <stdint.h> - -#include "compiler/dex/compiler_enums.h" -#include "compiler/dex/compiler_ir.h" - -namespace art { - -class CompilationUnit; -struct LIR; - -void MarkSafepointPC(CompilationUnit* cu, LIR* inst); -bool FastInstance(CompilationUnit* cu, uint32_t field_idx, - int& field_offset, bool& is_volatile, bool is_put); -void SetupResourceMasks(CompilationUnit* cu, LIR* lir); -inline int32_t s4FromSwitchData(const void* switch_data) { return *reinterpret_cast<const int32_t*>(switch_data); } -inline RegisterClass oat_reg_class_by_size(OpSize size) { return (size == kUnsignedHalf || size == kSignedHalf || size == kUnsignedByte || size == kSignedByte ) ? kCoreReg : kAnyReg; } -void AssembleLIR(CompilationUnit* cu); -void SetMemRefType(CompilationUnit* cu, LIR* lir, bool is_load, int mem_type); -void AnnotateDalvikRegAccess(CompilationUnit* cu, LIR* lir, int reg_id, bool is_load, bool is64bit); -uint64_t GetRegMaskCommon(CompilationUnit* cu, int reg); -void SetupRegMask(CompilationUnit* cu, uint64_t* mask, int reg); -void SetupResourceMasks(CompilationUnit* cu, LIR* lir); -void DumpLIRInsn(CompilationUnit* cu, LIR* arg, unsigned char* base_addr); -void DumpPromotionMap(CompilationUnit *cu); -void CodegenDump(CompilationUnit* cu); -LIR* RawLIR(CompilationUnit* cu, int dalvik_offset, int opcode, int op0 = 0, int op1 = 0, - int op2 = 0, int op3 = 0, int op4 = 0, LIR* target = NULL); -LIR* NewLIR0(CompilationUnit* cu, int opcode); -LIR* NewLIR1(CompilationUnit* cu, int opcode, int dest); -LIR* NewLIR2(CompilationUnit* cu, int opcode, int dest, int src1); -LIR* NewLIR3(CompilationUnit* cu, int opcode, int dest, int src1, int src2); -LIR* NewLIR4(CompilationUnit* cu, int opcode, int dest, int src1, int src2, int info); -LIR* NewLIR5(CompilationUnit* cu, int opcode, int dest, int src1, int src2, int info1, int info2); -LIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta); -LIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi); -LIR* AddWordData(CompilationUnit* cu, LIR* *constant_list_p, int value); -LIR* AddWideData(CompilationUnit* cu, LIR* *constant_list_p, int val_lo, int val_hi); -void ProcessSwitchTables(CompilationUnit* cu); -void DumpSparseSwitchTable(const uint16_t* table); -void DumpPackedSwitchTable(const uint16_t* table); -LIR* MarkBoundary(CompilationUnit* cu, int offset, const char* inst_str); -void NopLIR(LIR* lir); -bool EvaluateBranch(Instruction::Code opcode, int src1, int src2); -bool IsInexpensiveConstant(CompilationUnit* cu, RegLocation rl_src); -ConditionCode FlipComparisonOrder(ConditionCode before); - -} // namespace art - -#endif // ART_SRC_COMPILER_DEX_QUICK_CODEGENUTIL_H_ diff --git a/src/compiler/dex/quick/gen_common.cc b/src/compiler/dex/quick/gen_common.cc index 652a44817a..c13e79715a 100644 --- a/src/compiler/dex/quick/gen_common.cc +++ b/src/compiler/dex/quick/gen_common.cc @@ -14,11 +14,9 @@ * limitations under the License. */ -#include "compiler/dex/quick/codegen_util.h" #include "compiler/dex/compiler_ir.h" #include "compiler/dex/compiler_internals.h" #include "oat/runtime/oat_support_entrypoints.h" -#include "ralloc_util.h" namespace art { @@ -32,66 +30,62 @@ namespace art { * Generate an kPseudoBarrier marker to indicate the boundary of special * blocks. */ -void Codegen::GenBarrier(CompilationUnit* cu) +void Mir2Lir::GenBarrier() { - LIR* barrier = NewLIR0(cu, kPseudoBarrier); + LIR* barrier = NewLIR0(kPseudoBarrier); /* Mark all resources as being clobbered */ barrier->def_mask = -1; } // FIXME: need to do some work to split out targets with // condition codes and those without -LIR* Codegen::GenCheck(CompilationUnit* cu, ConditionCode c_code, ThrowKind kind) +LIR* Mir2Lir::GenCheck(ConditionCode c_code, ThrowKind kind) { - DCHECK_NE(cu->instruction_set, kMips); - LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind, - cu->current_dalvik_offset); - LIR* branch = OpCondBranch(cu, c_code, tgt); + DCHECK_NE(cu_->instruction_set, kMips); + LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_); + LIR* branch = OpCondBranch(c_code, tgt); // Remember branch target - will process later - InsertGrowableList(cu, &cu->throw_launchpads, reinterpret_cast<uintptr_t>(tgt)); + InsertGrowableList(cu_, &throw_launchpads_, reinterpret_cast<uintptr_t>(tgt)); return branch; } -LIR* Codegen::GenImmedCheck(CompilationUnit* cu, ConditionCode c_code, int reg, int imm_val, - ThrowKind kind) +LIR* Mir2Lir::GenImmedCheck(ConditionCode c_code, int reg, int imm_val, ThrowKind kind) { - LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind, - cu->current_dalvik_offset, reg, imm_val); + LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, reg, imm_val); LIR* branch; if (c_code == kCondAl) { - branch = OpUnconditionalBranch(cu, tgt); + branch = OpUnconditionalBranch(tgt); } else { - branch = OpCmpImmBranch(cu, c_code, reg, imm_val, tgt); + branch = OpCmpImmBranch(c_code, reg, imm_val, tgt); } // Remember branch target - will process later - InsertGrowableList(cu, &cu->throw_launchpads, reinterpret_cast<uintptr_t>(tgt)); + InsertGrowableList(cu_, &throw_launchpads_, reinterpret_cast<uintptr_t>(tgt)); return branch; } /* Perform null-check on a register. */ -LIR* Codegen::GenNullCheck(CompilationUnit* cu, int s_reg, int m_reg, int opt_flags) +LIR* Mir2Lir::GenNullCheck(int s_reg, int m_reg, int opt_flags) { - if (!(cu->disable_opt & (1 << kNullCheckElimination)) && + if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && opt_flags & MIR_IGNORE_NULL_CHECK) { return NULL; } - return GenImmedCheck(cu, kCondEq, m_reg, 0, kThrowNullPointer); + return GenImmedCheck(kCondEq, m_reg, 0, kThrowNullPointer); } /* Perform check on two registers */ -LIR* Codegen::GenRegRegCheck(CompilationUnit* cu, ConditionCode c_code, int reg1, int reg2, +LIR* Mir2Lir::GenRegRegCheck(ConditionCode c_code, int reg1, int reg2, ThrowKind kind) { - LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind, - cu->current_dalvik_offset, reg1, reg2); - LIR* branch = OpCmpBranch(cu, c_code, reg1, reg2, tgt); + LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, reg1, reg2); + LIR* branch = OpCmpBranch(c_code, reg1, reg2, tgt); // Remember branch target - will process later - InsertGrowableList(cu, &cu->throw_launchpads, reinterpret_cast<uintptr_t>(tgt)); + InsertGrowableList(cu_, &throw_launchpads_, reinterpret_cast<uintptr_t>(tgt)); return branch; } -void Codegen::GenCompareAndBranch(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_src1, RegLocation rl_src2, LIR* taken, +void Mir2Lir::GenCompareAndBranch(Instruction::Code opcode, RegLocation rl_src1, + RegLocation rl_src2, LIR* taken, LIR* fall_through) { ConditionCode cond; @@ -127,29 +121,29 @@ void Codegen::GenCompareAndBranch(CompilationUnit* cu, Instruction::Code opcode, cond = FlipComparisonOrder(cond); } - rl_src1 = LoadValue(cu, rl_src1, kCoreReg); + rl_src1 = LoadValue(rl_src1, kCoreReg); // Is this really an immediate comparison? if (rl_src2.is_const) { // If it's already live in a register or not easily materialized, just keep going - RegLocation rl_temp = UpdateLoc(cu, rl_src2); + RegLocation rl_temp = UpdateLoc(rl_src2); if ((rl_temp.location == kLocDalvikFrame) && - InexpensiveConstantInt(cu->mir_graph->ConstantValue(rl_src2))) { + InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src2))) { // OK - convert this to a compare immediate and branch - OpCmpImmBranch(cu, cond, rl_src1.low_reg, cu->mir_graph->ConstantValue(rl_src2), taken); - OpUnconditionalBranch(cu, fall_through); + OpCmpImmBranch(cond, rl_src1.low_reg, mir_graph_->ConstantValue(rl_src2), taken); + OpUnconditionalBranch(fall_through); return; } } - rl_src2 = LoadValue(cu, rl_src2, kCoreReg); - OpCmpBranch(cu, cond, rl_src1.low_reg, rl_src2.low_reg, taken); - OpUnconditionalBranch(cu, fall_through); + rl_src2 = LoadValue(rl_src2, kCoreReg); + OpCmpBranch(cond, rl_src1.low_reg, rl_src2.low_reg, taken); + OpUnconditionalBranch(fall_through); } -void Codegen::GenCompareZeroAndBranch(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_src, LIR* taken, LIR* fall_through) +void Mir2Lir::GenCompareZeroAndBranch(Instruction::Code opcode, RegLocation rl_src, LIR* taken, + LIR* fall_through) { ConditionCode cond; - rl_src = LoadValue(cu, rl_src, kCoreReg); + rl_src = LoadValue(rl_src, kCoreReg); switch (opcode) { case Instruction::IF_EQZ: cond = kCondEq; @@ -173,27 +167,27 @@ void Codegen::GenCompareZeroAndBranch(CompilationUnit* cu, Instruction::Code opc cond = static_cast<ConditionCode>(0); LOG(FATAL) << "Unexpected opcode " << opcode; } - OpCmpImmBranch(cu, cond, rl_src.low_reg, 0, taken); - OpUnconditionalBranch(cu, fall_through); + OpCmpImmBranch(cond, rl_src.low_reg, 0, taken); + OpUnconditionalBranch(fall_through); } -void Codegen::GenIntToLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void Mir2Lir::GenIntToLong(RegLocation rl_dest, RegLocation rl_src) { - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); if (rl_src.location == kLocPhysReg) { - OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg); + OpRegCopy(rl_result.low_reg, rl_src.low_reg); } else { - LoadValueDirect(cu, rl_src, rl_result.low_reg); + LoadValueDirect(rl_src, rl_result.low_reg); } - OpRegRegImm(cu, kOpAsr, rl_result.high_reg, rl_result.low_reg, 31); - StoreValueWide(cu, rl_dest, rl_result); + OpRegRegImm(kOpAsr, rl_result.high_reg, rl_result.low_reg, 31); + StoreValueWide(rl_dest, rl_result); } -void Codegen::GenIntNarrowing(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, +void Mir2Lir::GenIntNarrowing(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) { - rl_src = LoadValue(cu, rl_src, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src = LoadValue(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); OpKind op = kOpInvalid; switch (opcode) { case Instruction::INT_TO_BYTE: @@ -208,8 +202,8 @@ void Codegen::GenIntNarrowing(CompilationUnit* cu, Instruction::Code opcode, Reg default: LOG(ERROR) << "Bad int conversion type"; } - OpRegReg(cu, op, rl_result.low_reg, rl_src.low_reg); - StoreValue(cu, rl_dest, rl_result); + OpRegReg(op, rl_result.low_reg, rl_src.low_reg); + StoreValue(rl_dest, rl_result); } /* @@ -217,21 +211,20 @@ void Codegen::GenIntNarrowing(CompilationUnit* cu, Instruction::Code opcode, Reg * Array::AllocFromCode(type_idx, method, count); * Note: AllocFromCode will handle checks for errNegativeArraySize. */ -void Codegen::GenNewArray(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest, +void Mir2Lir::GenNewArray(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src) { - FlushAllRegs(cu); /* Everything to home location */ + FlushAllRegs(); /* Everything to home location */ int func_offset; - if (cu->compiler_driver->CanAccessTypeWithoutChecks(cu->method_idx, - *cu->dex_file, - type_idx)) { + if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *cu_->dex_file, + type_idx)) { func_offset = ENTRYPOINT_OFFSET(pAllocArrayFromCode); } else { func_offset= ENTRYPOINT_OFFSET(pAllocArrayFromCodeWithAccessCheck); } - CallRuntimeHelperImmMethodRegLocation(cu, func_offset, type_idx, rl_src, true); - RegLocation rl_result = GetReturn(cu, false); - StoreValue(cu, rl_dest, rl_result); + CallRuntimeHelperImmMethodRegLocation(func_offset, type_idx, rl_src, true); + RegLocation rl_result = GetReturn(false); + StoreValue(rl_dest, rl_result); } /* @@ -240,22 +233,21 @@ void Codegen::GenNewArray(CompilationUnit* cu, uint32_t type_idx, RegLocation rl * code throws runtime exception "bad Filled array req" for 'D' and 'J'. * Current code also throws internal unimp if not 'L', '[' or 'I'. */ -void Codegen::GenFilledNewArray(CompilationUnit* cu, CallInfo* info) +void Mir2Lir::GenFilledNewArray(CallInfo* info) { int elems = info->num_arg_words; int type_idx = info->index; - FlushAllRegs(cu); /* Everything to home location */ + FlushAllRegs(); /* Everything to home location */ int func_offset; - if (cu->compiler_driver->CanAccessTypeWithoutChecks(cu->method_idx, - *cu->dex_file, - type_idx)) { + if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *cu_->dex_file, + type_idx)) { func_offset = ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCode); } else { func_offset = ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCodeWithAccessCheck); } - CallRuntimeHelperImmMethodImm(cu, func_offset, type_idx, elems, true); - FreeTemp(cu, TargetReg(kArg2)); - FreeTemp(cu, TargetReg(kArg1)); + CallRuntimeHelperImmMethodImm(func_offset, type_idx, elems, true); + FreeTemp(TargetReg(kArg2)); + FreeTemp(TargetReg(kArg1)); /* * NOTE: the implicit target for Instruction::FILLED_NEW_ARRAY is the * return region. Because AllocFromCode placed the new array @@ -263,7 +255,7 @@ void Codegen::GenFilledNewArray(CompilationUnit* cu, CallInfo* info) * added, it may be necessary to additionally copy all return * values to a home location in thread-local storage */ - LockTemp(cu, TargetReg(kRet0)); + LockTemp(TargetReg(kRet0)); // TODO: use the correct component size, currently all supported types // share array alignment with ints (see comment at head of function) @@ -280,9 +272,9 @@ void Codegen::GenFilledNewArray(CompilationUnit* cu, CallInfo* info) * home location. */ for (int i = 0; i < elems; i++) { - RegLocation loc = UpdateLoc(cu, info->args[i]); + RegLocation loc = UpdateLoc(info->args[i]); if (loc.location == kLocPhysReg) { - StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, loc.s_reg_low), + StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.low_reg, kWord); } } @@ -291,83 +283,82 @@ void Codegen::GenFilledNewArray(CompilationUnit* cu, CallInfo* info) * this is an uncommon operation and isn't especially performance * critical. */ - int r_src = AllocTemp(cu); - int r_dst = AllocTemp(cu); - int r_idx = AllocTemp(cu); + int r_src = AllocTemp(); + int r_dst = AllocTemp(); + int r_idx = AllocTemp(); int r_val = INVALID_REG; - switch(cu->instruction_set) { + switch(cu_->instruction_set) { case kThumb2: r_val = TargetReg(kLr); break; case kX86: - FreeTemp(cu, TargetReg(kRet0)); - r_val = AllocTemp(cu); + FreeTemp(TargetReg(kRet0)); + r_val = AllocTemp(); break; case kMips: - r_val = AllocTemp(cu); + r_val = AllocTemp(); break; - default: LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set; + default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set; } // Set up source pointer RegLocation rl_first = info->args[0]; - OpRegRegImm(cu, kOpAdd, r_src, TargetReg(kSp), - SRegOffset(cu, rl_first.s_reg_low)); + OpRegRegImm(kOpAdd, r_src, TargetReg(kSp), SRegOffset(rl_first.s_reg_low)); // Set up the target pointer - OpRegRegImm(cu, kOpAdd, r_dst, TargetReg(kRet0), + OpRegRegImm(kOpAdd, r_dst, TargetReg(kRet0), mirror::Array::DataOffset(component_size).Int32Value()); // Set up the loop counter (known to be > 0) - LoadConstant(cu, r_idx, elems - 1); + LoadConstant(r_idx, elems - 1); // Generate the copy loop. Going backwards for convenience - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); // Copy next element - LoadBaseIndexed(cu, r_src, r_idx, r_val, 2, kWord); - StoreBaseIndexed(cu, r_dst, r_idx, r_val, 2, kWord); - FreeTemp(cu, r_val); - OpDecAndBranch(cu, kCondGe, r_idx, target); - if (cu->instruction_set == kX86) { + LoadBaseIndexed(r_src, r_idx, r_val, 2, kWord); + StoreBaseIndexed(r_dst, r_idx, r_val, 2, kWord); + FreeTemp(r_val); + OpDecAndBranch(kCondGe, r_idx, target); + if (cu_->instruction_set == kX86) { // Restore the target pointer - OpRegRegImm(cu, kOpAdd, TargetReg(kRet0), r_dst, + OpRegRegImm(kOpAdd, TargetReg(kRet0), r_dst, -mirror::Array::DataOffset(component_size).Int32Value()); } } else if (!info->is_range) { // TUNING: interleave for (int i = 0; i < elems; i++) { - RegLocation rl_arg = LoadValue(cu, info->args[i], kCoreReg); - StoreBaseDisp(cu, TargetReg(kRet0), + RegLocation rl_arg = LoadValue(info->args[i], kCoreReg); + StoreBaseDisp(TargetReg(kRet0), mirror::Array::DataOffset(component_size).Int32Value() + i * 4, rl_arg.low_reg, kWord); // If the LoadValue caused a temp to be allocated, free it - if (IsTemp(cu, rl_arg.low_reg)) { - FreeTemp(cu, rl_arg.low_reg); + if (IsTemp(rl_arg.low_reg)) { + FreeTemp(rl_arg.low_reg); } } } if (info->result.location != kLocInvalid) { - StoreValue(cu, info->result, GetReturn(cu, false /* not fp */)); + StoreValue(info->result, GetReturn(false /* not fp */)); } } -void Codegen::GenSput(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_src, - bool is_long_or_double, bool is_object) +void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_double, + bool is_object) { int field_offset; int ssb_index; bool is_volatile; bool is_referrers_class; - bool fast_path = cu->compiler_driver->ComputeStaticFieldInfo( - field_idx, cu->mir_graph->GetCurrentDexCompilationUnit(), field_offset, ssb_index, + bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo( + field_idx, mir_graph_->GetCurrentDexCompilationUnit(), field_offset, ssb_index, is_referrers_class, is_volatile, true); if (fast_path && !SLOW_FIELD_PATH) { DCHECK_GE(field_offset, 0); int rBase; if (is_referrers_class) { // Fast path, static storage base is this method's class - RegLocation rl_method = LoadCurrMethod(cu); - rBase = AllocTemp(cu); - LoadWordDisp(cu, rl_method.low_reg, + RegLocation rl_method = LoadCurrMethod(); + rBase = AllocTemp(); + LoadWordDisp(rl_method.low_reg, mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), rBase); - if (IsTemp(cu, rl_method.low_reg)) { - FreeTemp(cu, rl_method.low_reg); + if (IsTemp(rl_method.low_reg)) { + FreeTemp(rl_method.low_reg); } } else { // Medium path, static storage base in a different class which requires checks that the other @@ -375,82 +366,82 @@ void Codegen::GenSput(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_sr // TODO: remove initialized check now that we are initializing classes in the compiler driver. DCHECK_GE(ssb_index, 0); // May do runtime call so everything to home locations. - FlushAllRegs(cu); + FlushAllRegs(); // Using fixed register to sync with possible call to runtime support. int r_method = TargetReg(kArg1); - LockTemp(cu, r_method); - LoadCurrMethodDirect(cu, r_method); + LockTemp(r_method); + LoadCurrMethodDirect(r_method); rBase = TargetReg(kArg0); - LockTemp(cu, rBase); - LoadWordDisp(cu, r_method, + LockTemp(rBase); + LoadWordDisp(r_method, mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(), rBase); - LoadWordDisp(cu, rBase, + LoadWordDisp(rBase, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + sizeof(int32_t*) * ssb_index, rBase); // rBase now points at appropriate static storage base (Class*) // or NULL if not initialized. Check for NULL and call helper if NULL. // TUNING: fast path should fall through - LIR* branch_over = OpCmpImmBranch(cu, kCondNe, rBase, 0, NULL); - LoadConstant(cu, TargetReg(kArg0), ssb_index); - CallRuntimeHelperImm(cu, ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true); - if (cu->instruction_set == kMips) { + LIR* branch_over = OpCmpImmBranch(kCondNe, rBase, 0, NULL); + LoadConstant(TargetReg(kArg0), ssb_index); + CallRuntimeHelperImm(ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true); + if (cu_->instruction_set == kMips) { // For Arm, kRet0 = kArg0 = rBase, for Mips, we need to copy - OpRegCopy(cu, rBase, TargetReg(kRet0)); + OpRegCopy(rBase, TargetReg(kRet0)); } - LIR* skip_target = NewLIR0(cu, kPseudoTargetLabel); + LIR* skip_target = NewLIR0(kPseudoTargetLabel); branch_over->target = skip_target; - FreeTemp(cu, r_method); + FreeTemp(r_method); } // rBase now holds static storage base if (is_long_or_double) { - rl_src = LoadValueWide(cu, rl_src, kAnyReg); + rl_src = LoadValueWide(rl_src, kAnyReg); } else { - rl_src = LoadValue(cu, rl_src, kAnyReg); + rl_src = LoadValue(rl_src, kAnyReg); } if (is_volatile) { - GenMemBarrier(cu, kStoreStore); + GenMemBarrier(kStoreStore); } if (is_long_or_double) { - StoreBaseDispWide(cu, rBase, field_offset, rl_src.low_reg, + StoreBaseDispWide(rBase, field_offset, rl_src.low_reg, rl_src.high_reg); } else { - StoreWordDisp(cu, rBase, field_offset, rl_src.low_reg); + StoreWordDisp(rBase, field_offset, rl_src.low_reg); } if (is_volatile) { - GenMemBarrier(cu, kStoreLoad); + GenMemBarrier(kStoreLoad); } - if (is_object && !cu->mir_graph->IsConstantNullRef(rl_src)) { - MarkGCCard(cu, rl_src.low_reg, rBase); + if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) { + MarkGCCard(rl_src.low_reg, rBase); } - FreeTemp(cu, rBase); + FreeTemp(rBase); } else { - FlushAllRegs(cu); // Everything to home locations + FlushAllRegs(); // Everything to home locations int setter_offset = is_long_or_double ? ENTRYPOINT_OFFSET(pSet64Static) : (is_object ? ENTRYPOINT_OFFSET(pSetObjStatic) : ENTRYPOINT_OFFSET(pSet32Static)); - CallRuntimeHelperImmRegLocation(cu, setter_offset, field_idx, rl_src, true); + CallRuntimeHelperImmRegLocation(setter_offset, field_idx, rl_src, true); } } -void Codegen::GenSget(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_dest, +void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest, bool is_long_or_double, bool is_object) { int field_offset; int ssb_index; bool is_volatile; bool is_referrers_class; - bool fast_path = cu->compiler_driver->ComputeStaticFieldInfo( - field_idx, cu->mir_graph->GetCurrentDexCompilationUnit(), field_offset, ssb_index, + bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo( + field_idx, mir_graph_->GetCurrentDexCompilationUnit(), field_offset, ssb_index, is_referrers_class, is_volatile, false); if (fast_path && !SLOW_FIELD_PATH) { DCHECK_GE(field_offset, 0); int rBase; if (is_referrers_class) { // Fast path, static storage base is this method's class - RegLocation rl_method = LoadCurrMethod(cu); - rBase = AllocTemp(cu); - LoadWordDisp(cu, rl_method.low_reg, + RegLocation rl_method = LoadCurrMethod(); + rBase = AllocTemp(); + LoadWordDisp(rl_method.low_reg, mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), rBase); } else { // Medium path, static storage base in a different class which requires checks that the other @@ -458,128 +449,127 @@ void Codegen::GenSget(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_de // TODO: remove initialized check now that we are initializing classes in the compiler driver. DCHECK_GE(ssb_index, 0); // May do runtime call so everything to home locations. - FlushAllRegs(cu); + FlushAllRegs(); // Using fixed register to sync with possible call to runtime support. int r_method = TargetReg(kArg1); - LockTemp(cu, r_method); - LoadCurrMethodDirect(cu, r_method); + LockTemp(r_method); + LoadCurrMethodDirect(r_method); rBase = TargetReg(kArg0); - LockTemp(cu, rBase); - LoadWordDisp(cu, r_method, + LockTemp(rBase); + LoadWordDisp(r_method, mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(), rBase); - LoadWordDisp(cu, rBase, - mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + + LoadWordDisp(rBase, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + sizeof(int32_t*) * ssb_index, rBase); // rBase now points at appropriate static storage base (Class*) // or NULL if not initialized. Check for NULL and call helper if NULL. // TUNING: fast path should fall through - LIR* branch_over = OpCmpImmBranch(cu, kCondNe, rBase, 0, NULL); - CallRuntimeHelperImm(cu, ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true); - if (cu->instruction_set == kMips) { + LIR* branch_over = OpCmpImmBranch(kCondNe, rBase, 0, NULL); + CallRuntimeHelperImm(ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true); + if (cu_->instruction_set == kMips) { // For Arm, kRet0 = kArg0 = rBase, for Mips, we need to copy - OpRegCopy(cu, rBase, TargetReg(kRet0)); + OpRegCopy(rBase, TargetReg(kRet0)); } - LIR* skip_target = NewLIR0(cu, kPseudoTargetLabel); + LIR* skip_target = NewLIR0(kPseudoTargetLabel); branch_over->target = skip_target; - FreeTemp(cu, r_method); + FreeTemp(r_method); } // rBase now holds static storage base - RegLocation rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); + RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true); if (is_volatile) { - GenMemBarrier(cu, kLoadLoad); + GenMemBarrier(kLoadLoad); } if (is_long_or_double) { - LoadBaseDispWide(cu, rBase, field_offset, rl_result.low_reg, + LoadBaseDispWide(rBase, field_offset, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); } else { - LoadWordDisp(cu, rBase, field_offset, rl_result.low_reg); + LoadWordDisp(rBase, field_offset, rl_result.low_reg); } - FreeTemp(cu, rBase); + FreeTemp(rBase); if (is_long_or_double) { - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } else { - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } } else { - FlushAllRegs(cu); // Everything to home locations + FlushAllRegs(); // Everything to home locations int getterOffset = is_long_or_double ? ENTRYPOINT_OFFSET(pGet64Static) : (is_object ? ENTRYPOINT_OFFSET(pGetObjStatic) : ENTRYPOINT_OFFSET(pGet32Static)); - CallRuntimeHelperImm(cu, getterOffset, field_idx, true); + CallRuntimeHelperImm(getterOffset, field_idx, true); if (is_long_or_double) { - RegLocation rl_result = GetReturnWide(cu, rl_dest.fp); - StoreValueWide(cu, rl_dest, rl_result); + RegLocation rl_result = GetReturnWide(rl_dest.fp); + StoreValueWide(rl_dest, rl_result); } else { - RegLocation rl_result = GetReturn(cu, rl_dest.fp); - StoreValue(cu, rl_dest, rl_result); + RegLocation rl_result = GetReturn(rl_dest.fp); + StoreValue(rl_dest, rl_result); } } } // Debugging routine - if null target, branch to DebugMe -void Codegen::GenShowTarget(CompilationUnit* cu) +void Mir2Lir::GenShowTarget() { - DCHECK_NE(cu->instruction_set, kX86) << "unimplemented GenShowTarget"; - LIR* branch_over = OpCmpImmBranch(cu, kCondNe, TargetReg(kInvokeTgt), 0, NULL); - LoadWordDisp(cu, TargetReg(kSelf), ENTRYPOINT_OFFSET(pDebugMe), TargetReg(kInvokeTgt)); - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + DCHECK_NE(cu_->instruction_set, kX86) << "unimplemented GenShowTarget"; + LIR* branch_over = OpCmpImmBranch(kCondNe, TargetReg(kInvokeTgt), 0, NULL); + LoadWordDisp(TargetReg(kSelf), ENTRYPOINT_OFFSET(pDebugMe), TargetReg(kInvokeTgt)); + LIR* target = NewLIR0(kPseudoTargetLabel); branch_over->target = target; } -void Codegen::HandleSuspendLaunchPads(CompilationUnit *cu) +void Mir2Lir::HandleSuspendLaunchPads() { - LIR** suspend_label = reinterpret_cast<LIR**>(cu->suspend_launchpads.elem_list); - int num_elems = cu->suspend_launchpads.num_used; + LIR** suspend_label = reinterpret_cast<LIR**>(suspend_launchpads_.elem_list); + int num_elems = suspend_launchpads_.num_used; int helper_offset = ENTRYPOINT_OFFSET(pTestSuspendFromCode); for (int i = 0; i < num_elems; i++) { - ResetRegPool(cu); - ResetDefTracking(cu); + ResetRegPool(); + ResetDefTracking(); LIR* lab = suspend_label[i]; LIR* resume_lab = reinterpret_cast<LIR*>(lab->operands[0]); - cu->current_dalvik_offset = lab->operands[1]; - AppendLIR(cu, lab); - int r_tgt = CallHelperSetup(cu, helper_offset); - CallHelper(cu, r_tgt, helper_offset, true /* MarkSafepointPC */); - OpUnconditionalBranch(cu, resume_lab); + current_dalvik_offset_ = lab->operands[1]; + AppendLIR(lab); + int r_tgt = CallHelperSetup(helper_offset); + CallHelper(r_tgt, helper_offset, true /* MarkSafepointPC */); + OpUnconditionalBranch(resume_lab); } } -void Codegen::HandleIntrinsicLaunchPads(CompilationUnit *cu) +void Mir2Lir::HandleIntrinsicLaunchPads() { - LIR** intrinsic_label = reinterpret_cast<LIR**>(cu->intrinsic_launchpads.elem_list); - int num_elems = cu->intrinsic_launchpads.num_used; + LIR** intrinsic_label = reinterpret_cast<LIR**>(intrinsic_launchpads_.elem_list); + int num_elems = intrinsic_launchpads_.num_used; for (int i = 0; i < num_elems; i++) { - ResetRegPool(cu); - ResetDefTracking(cu); + ResetRegPool(); + ResetDefTracking(); LIR* lab = intrinsic_label[i]; CallInfo* info = reinterpret_cast<CallInfo*>(lab->operands[0]); - cu->current_dalvik_offset = info->offset; - AppendLIR(cu, lab); + current_dalvik_offset_ = info->offset; + AppendLIR(lab); // NOTE: GenInvoke handles MarkSafepointPC - GenInvoke(cu, info); + GenInvoke(info); LIR* resume_lab = reinterpret_cast<LIR*>(lab->operands[2]); if (resume_lab != NULL) { - OpUnconditionalBranch(cu, resume_lab); + OpUnconditionalBranch(resume_lab); } } } -void Codegen::HandleThrowLaunchPads(CompilationUnit *cu) +void Mir2Lir::HandleThrowLaunchPads() { - LIR** throw_label = reinterpret_cast<LIR**>(cu->throw_launchpads.elem_list); - int num_elems = cu->throw_launchpads.num_used; + LIR** throw_label = reinterpret_cast<LIR**>(throw_launchpads_.elem_list); + int num_elems = throw_launchpads_.num_used; for (int i = 0; i < num_elems; i++) { - ResetRegPool(cu); - ResetDefTracking(cu); + ResetRegPool(); + ResetDefTracking(); LIR* lab = throw_label[i]; - cu->current_dalvik_offset = lab->operands[1]; - AppendLIR(cu, lab); + current_dalvik_offset_ = lab->operands[1]; + AppendLIR(lab); int func_offset = 0; int v1 = lab->operands[2]; int v2 = lab->operands[3]; - bool target_x86 = (cu->instruction_set == kX86); + bool target_x86 = (cu_->instruction_set == kX86); switch (lab->operands[0]) { case kThrowNullPointer: func_offset = ENTRYPOINT_OFFSET(pThrowNullPointerFromCode); @@ -587,44 +577,44 @@ void Codegen::HandleThrowLaunchPads(CompilationUnit *cu) case kThrowConstantArrayBounds: // v1 is length reg (for Arm/Mips), v2 constant index // v1 holds the constant array index. Mips/Arm uses v2 for length, x86 reloads. if (target_x86) { - OpRegMem(cu, kOpMov, TargetReg(kArg1), v1, mirror::Array::LengthOffset().Int32Value()); + OpRegMem(kOpMov, TargetReg(kArg1), v1, mirror::Array::LengthOffset().Int32Value()); } else { - OpRegCopy(cu, TargetReg(kArg1), v1); + OpRegCopy(TargetReg(kArg1), v1); } // Make sure the following LoadConstant doesn't mess with kArg1. - LockTemp(cu, TargetReg(kArg1)); - LoadConstant(cu, TargetReg(kArg0), v2); + LockTemp(TargetReg(kArg1)); + LoadConstant(TargetReg(kArg0), v2); func_offset = ENTRYPOINT_OFFSET(pThrowArrayBoundsFromCode); break; case kThrowArrayBounds: // Move v1 (array index) to kArg0 and v2 (array length) to kArg1 if (v2 != TargetReg(kArg0)) { - OpRegCopy(cu, TargetReg(kArg0), v1); + OpRegCopy(TargetReg(kArg0), v1); if (target_x86) { // x86 leaves the array pointer in v2, so load the array length that the handler expects - OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); + OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); } else { - OpRegCopy(cu, TargetReg(kArg1), v2); + OpRegCopy(TargetReg(kArg1), v2); } } else { if (v1 == TargetReg(kArg1)) { // Swap v1 and v2, using kArg2 as a temp - OpRegCopy(cu, TargetReg(kArg2), v1); + OpRegCopy(TargetReg(kArg2), v1); if (target_x86) { // x86 leaves the array pointer in v2; load the array length that the handler expects - OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); + OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); } else { - OpRegCopy(cu, TargetReg(kArg1), v2); + OpRegCopy(TargetReg(kArg1), v2); } - OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2)); + OpRegCopy(TargetReg(kArg0), TargetReg(kArg2)); } else { if (target_x86) { // x86 leaves the array pointer in v2; load the array length that the handler expects - OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); + OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value()); } else { - OpRegCopy(cu, TargetReg(kArg1), v2); + OpRegCopy(TargetReg(kArg1), v2); } - OpRegCopy(cu, TargetReg(kArg0), v1); + OpRegCopy(TargetReg(kArg0), v1); } } func_offset = ENTRYPOINT_OFFSET(pThrowArrayBoundsFromCode); @@ -633,7 +623,7 @@ void Codegen::HandleThrowLaunchPads(CompilationUnit *cu) func_offset = ENTRYPOINT_OFFSET(pThrowDivZeroFromCode); break; case kThrowNoSuchMethod: - OpRegCopy(cu, TargetReg(kArg0), v1); + OpRegCopy(TargetReg(kArg0), v1); func_offset = ENTRYPOINT_OFFSET(pThrowNoSuchMethodFromCode); break; @@ -641,239 +631,239 @@ void Codegen::HandleThrowLaunchPads(CompilationUnit *cu) func_offset = ENTRYPOINT_OFFSET(pThrowStackOverflowFromCode); // Restore stack alignment if (target_x86) { - OpRegImm(cu, kOpAdd, TargetReg(kSp), cu->frame_size); + OpRegImm(kOpAdd, TargetReg(kSp), frame_size_); } else { - OpRegImm(cu, kOpAdd, TargetReg(kSp), (cu->num_core_spills + cu->num_fp_spills) * 4); + OpRegImm(kOpAdd, TargetReg(kSp), (num_core_spills_ + num_fp_spills_) * 4); } break; default: LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0]; } - ClobberCalleeSave(cu); - int r_tgt = CallHelperSetup(cu, func_offset); - CallHelper(cu, r_tgt, func_offset, true /* MarkSafepointPC */); + ClobberCalleeSave(); + int r_tgt = CallHelperSetup(func_offset); + CallHelper(r_tgt, func_offset, true /* MarkSafepointPC */); } } -void Codegen::GenIGet(CompilationUnit* cu, uint32_t field_idx, int opt_flags, OpSize size, +void Mir2Lir::GenIGet(uint32_t field_idx, int opt_flags, OpSize size, RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double, bool is_object) { int field_offset; bool is_volatile; - bool fast_path = FastInstance(cu, field_idx, field_offset, is_volatile, false); + bool fast_path = FastInstance(field_idx, field_offset, is_volatile, false); if (fast_path && !SLOW_FIELD_PATH) { RegLocation rl_result; RegisterClass reg_class = oat_reg_class_by_size(size); DCHECK_GE(field_offset, 0); - rl_obj = LoadValue(cu, rl_obj, kCoreReg); + rl_obj = LoadValue(rl_obj, kCoreReg); if (is_long_or_double) { DCHECK(rl_dest.wide); - GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); - if (cu->instruction_set == kX86) { - rl_result = EvalLoc(cu, rl_dest, reg_class, true); - GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); - LoadBaseDispWide(cu, rl_obj.low_reg, field_offset, rl_result.low_reg, + GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); + if (cu_->instruction_set == kX86) { + rl_result = EvalLoc(rl_dest, reg_class, true); + GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); + LoadBaseDispWide(rl_obj.low_reg, field_offset, rl_result.low_reg, rl_result.high_reg, rl_obj.s_reg_low); if (is_volatile) { - GenMemBarrier(cu, kLoadLoad); + GenMemBarrier(kLoadLoad); } } else { - int reg_ptr = AllocTemp(cu); - OpRegRegImm(cu, kOpAdd, reg_ptr, rl_obj.low_reg, field_offset); - rl_result = EvalLoc(cu, rl_dest, reg_class, true); - LoadBaseDispWide(cu, reg_ptr, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); + int reg_ptr = AllocTemp(); + OpRegRegImm(kOpAdd, reg_ptr, rl_obj.low_reg, field_offset); + rl_result = EvalLoc(rl_dest, reg_class, true); + LoadBaseDispWide(reg_ptr, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); if (is_volatile) { - GenMemBarrier(cu, kLoadLoad); + GenMemBarrier(kLoadLoad); } - FreeTemp(cu, reg_ptr); + FreeTemp(reg_ptr); } - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } else { - rl_result = EvalLoc(cu, rl_dest, reg_class, true); - GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); - LoadBaseDisp(cu, rl_obj.low_reg, field_offset, rl_result.low_reg, + rl_result = EvalLoc(rl_dest, reg_class, true); + GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); + LoadBaseDisp(rl_obj.low_reg, field_offset, rl_result.low_reg, kWord, rl_obj.s_reg_low); if (is_volatile) { - GenMemBarrier(cu, kLoadLoad); + GenMemBarrier(kLoadLoad); } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } } else { int getterOffset = is_long_or_double ? ENTRYPOINT_OFFSET(pGet64Instance) : (is_object ? ENTRYPOINT_OFFSET(pGetObjInstance) : ENTRYPOINT_OFFSET(pGet32Instance)); - CallRuntimeHelperImmRegLocation(cu, getterOffset, field_idx, rl_obj, true); + CallRuntimeHelperImmRegLocation(getterOffset, field_idx, rl_obj, true); if (is_long_or_double) { - RegLocation rl_result = GetReturnWide(cu, rl_dest.fp); - StoreValueWide(cu, rl_dest, rl_result); + RegLocation rl_result = GetReturnWide(rl_dest.fp); + StoreValueWide(rl_dest, rl_result); } else { - RegLocation rl_result = GetReturn(cu, rl_dest.fp); - StoreValue(cu, rl_dest, rl_result); + RegLocation rl_result = GetReturn(rl_dest.fp); + StoreValue(rl_dest, rl_result); } } } -void Codegen::GenIPut(CompilationUnit* cu, uint32_t field_idx, int opt_flags, OpSize size, +void Mir2Lir::GenIPut(uint32_t field_idx, int opt_flags, OpSize size, RegLocation rl_src, RegLocation rl_obj, bool is_long_or_double, bool is_object) { int field_offset; bool is_volatile; - bool fast_path = FastInstance(cu, field_idx, field_offset, is_volatile, + bool fast_path = FastInstance(field_idx, field_offset, is_volatile, true); if (fast_path && !SLOW_FIELD_PATH) { RegisterClass reg_class = oat_reg_class_by_size(size); DCHECK_GE(field_offset, 0); - rl_obj = LoadValue(cu, rl_obj, kCoreReg); + rl_obj = LoadValue(rl_obj, kCoreReg); if (is_long_or_double) { int reg_ptr; - rl_src = LoadValueWide(cu, rl_src, kAnyReg); - GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); - reg_ptr = AllocTemp(cu); - OpRegRegImm(cu, kOpAdd, reg_ptr, rl_obj.low_reg, field_offset); + rl_src = LoadValueWide(rl_src, kAnyReg); + GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); + reg_ptr = AllocTemp(); + OpRegRegImm(kOpAdd, reg_ptr, rl_obj.low_reg, field_offset); if (is_volatile) { - GenMemBarrier(cu, kStoreStore); + GenMemBarrier(kStoreStore); } - StoreBaseDispWide(cu, reg_ptr, 0, rl_src.low_reg, rl_src.high_reg); + StoreBaseDispWide(reg_ptr, 0, rl_src.low_reg, rl_src.high_reg); if (is_volatile) { - GenMemBarrier(cu, kLoadLoad); + GenMemBarrier(kLoadLoad); } - FreeTemp(cu, reg_ptr); + FreeTemp(reg_ptr); } else { - rl_src = LoadValue(cu, rl_src, reg_class); - GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); + rl_src = LoadValue(rl_src, reg_class); + GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); if (is_volatile) { - GenMemBarrier(cu, kStoreStore); + GenMemBarrier(kStoreStore); } - StoreBaseDisp(cu, rl_obj.low_reg, field_offset, rl_src.low_reg, kWord); + StoreBaseDisp(rl_obj.low_reg, field_offset, rl_src.low_reg, kWord); if (is_volatile) { - GenMemBarrier(cu, kLoadLoad); + GenMemBarrier(kLoadLoad); } - if (is_object && !cu->mir_graph->IsConstantNullRef(rl_src)) { - MarkGCCard(cu, rl_src.low_reg, rl_obj.low_reg); + if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) { + MarkGCCard(rl_src.low_reg, rl_obj.low_reg); } } } else { int setter_offset = is_long_or_double ? ENTRYPOINT_OFFSET(pSet64Instance) : (is_object ? ENTRYPOINT_OFFSET(pSetObjInstance) : ENTRYPOINT_OFFSET(pSet32Instance)); - CallRuntimeHelperImmRegLocationRegLocation(cu, setter_offset, field_idx, rl_obj, rl_src, true); + CallRuntimeHelperImmRegLocationRegLocation(setter_offset, field_idx, rl_obj, rl_src, true); } } -void Codegen::GenConstClass(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest) +void Mir2Lir::GenConstClass(uint32_t type_idx, RegLocation rl_dest) { - RegLocation rl_method = LoadCurrMethod(cu); - int res_reg = AllocTemp(cu); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - if (!cu->compiler_driver->CanAccessTypeWithoutChecks(cu->method_idx, - *cu->dex_file, + RegLocation rl_method = LoadCurrMethod(); + int res_reg = AllocTemp(); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + if (!cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, + *cu_->dex_file, type_idx)) { // Call out to helper which resolves type and verifies access. // Resolved type returned in kRet0. - CallRuntimeHelperImmReg(cu, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode), + CallRuntimeHelperImmReg(ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode), type_idx, rl_method.low_reg, true); - RegLocation rl_result = GetReturn(cu, false); - StoreValue(cu, rl_dest, rl_result); + RegLocation rl_result = GetReturn(false); + StoreValue(rl_dest, rl_result); } else { // We're don't need access checks, load type from dex cache int32_t dex_cache_offset = mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(); - LoadWordDisp(cu, rl_method.low_reg, dex_cache_offset, res_reg); + LoadWordDisp(rl_method.low_reg, dex_cache_offset, res_reg); int32_t offset_of_type = mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*) * type_idx); - LoadWordDisp(cu, res_reg, offset_of_type, rl_result.low_reg); - if (!cu->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu->dex_file, + LoadWordDisp(res_reg, offset_of_type, rl_result.low_reg); + if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx) || SLOW_TYPE_PATH) { // Slow path, at runtime test if type is null and if so initialize - FlushAllRegs(cu); - LIR* branch1 = OpCmpImmBranch(cu, kCondEq, rl_result.low_reg, 0, NULL); + FlushAllRegs(); + LIR* branch1 = OpCmpImmBranch(kCondEq, rl_result.low_reg, 0, NULL); // Resolved, store and hop over following code - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); /* * Because we have stores of the target value on two paths, * clobber temp tracking for the destination using the ssa name */ - ClobberSReg(cu, rl_dest.s_reg_low); - LIR* branch2 = OpUnconditionalBranch(cu,0); + ClobberSReg(rl_dest.s_reg_low); + LIR* branch2 = OpUnconditionalBranch(0); // TUNING: move slow path to end & remove unconditional branch - LIR* target1 = NewLIR0(cu, kPseudoTargetLabel); + LIR* target1 = NewLIR0(kPseudoTargetLabel); // Call out to helper, which will return resolved type in kArg0 - CallRuntimeHelperImmReg(cu, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, + CallRuntimeHelperImmReg(ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, rl_method.low_reg, true); - RegLocation rl_result = GetReturn(cu, false); - StoreValue(cu, rl_dest, rl_result); + RegLocation rl_result = GetReturn(false); + StoreValue(rl_dest, rl_result); /* * Because we have stores of the target value on two paths, * clobber temp tracking for the destination using the ssa name */ - ClobberSReg(cu, rl_dest.s_reg_low); + ClobberSReg(rl_dest.s_reg_low); // Rejoin code paths - LIR* target2 = NewLIR0(cu, kPseudoTargetLabel); + LIR* target2 = NewLIR0(kPseudoTargetLabel); branch1->target = target1; branch2->target = target2; } else { // Fast path, we're done - just store result - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } } } -void Codegen::GenConstString(CompilationUnit* cu, uint32_t string_idx, RegLocation rl_dest) +void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) { /* NOTE: Most strings should be available at compile time */ int32_t offset_of_string = mirror::Array::DataOffset(sizeof(mirror::String*)).Int32Value() + (sizeof(mirror::String*) * string_idx); - if (!cu->compiler_driver->CanAssumeStringIsPresentInDexCache( - *cu->dex_file, string_idx) || SLOW_STRING_PATH) { + if (!cu_->compiler_driver->CanAssumeStringIsPresentInDexCache( + *cu_->dex_file, string_idx) || SLOW_STRING_PATH) { // slow path, resolve string if not in dex cache - FlushAllRegs(cu); - LockCallTemps(cu); // Using explicit registers - LoadCurrMethodDirect(cu, TargetReg(kArg2)); - LoadWordDisp(cu, TargetReg(kArg2), + FlushAllRegs(); + LockCallTemps(); // Using explicit registers + LoadCurrMethodDirect(TargetReg(kArg2)); + LoadWordDisp(TargetReg(kArg2), mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), TargetReg(kArg0)); // Might call out to helper, which will return resolved string in kRet0 - int r_tgt = CallHelperSetup(cu, ENTRYPOINT_OFFSET(pResolveStringFromCode)); - LoadWordDisp(cu, TargetReg(kArg0), offset_of_string, TargetReg(kRet0)); - LoadConstant(cu, TargetReg(kArg1), string_idx); - if (cu->instruction_set == kThumb2) { - OpRegImm(cu, kOpCmp, TargetReg(kRet0), 0); // Is resolved? - GenBarrier(cu); + int r_tgt = CallHelperSetup(ENTRYPOINT_OFFSET(pResolveStringFromCode)); + LoadWordDisp(TargetReg(kArg0), offset_of_string, TargetReg(kRet0)); + LoadConstant(TargetReg(kArg1), string_idx); + if (cu_->instruction_set == kThumb2) { + OpRegImm(kOpCmp, TargetReg(kRet0), 0); // Is resolved? + GenBarrier(); // For testing, always force through helper if (!EXERCISE_SLOWEST_STRING_PATH) { - OpIT(cu, kCondEq, "T"); + OpIT(kCondEq, "T"); } - OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2)); // .eq - LIR* call_inst = OpReg(cu, kOpBlx, r_tgt); // .eq, helper(Method*, string_idx) - MarkSafepointPC(cu, call_inst); - FreeTemp(cu, r_tgt); - } else if (cu->instruction_set == kMips) { - LIR* branch = OpCmpImmBranch(cu, kCondNe, TargetReg(kRet0), 0, NULL); - OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2)); // .eq - LIR* call_inst = OpReg(cu, kOpBlx, r_tgt); - MarkSafepointPC(cu, call_inst); - FreeTemp(cu, r_tgt); - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + OpRegCopy(TargetReg(kArg0), TargetReg(kArg2)); // .eq + LIR* call_inst = OpReg(kOpBlx, r_tgt); // .eq, helper(Method*, string_idx) + MarkSafepointPC(call_inst); + FreeTemp(r_tgt); + } else if (cu_->instruction_set == kMips) { + LIR* branch = OpCmpImmBranch(kCondNe, TargetReg(kRet0), 0, NULL); + OpRegCopy(TargetReg(kArg0), TargetReg(kArg2)); // .eq + LIR* call_inst = OpReg(kOpBlx, r_tgt); + MarkSafepointPC(call_inst); + FreeTemp(r_tgt); + LIR* target = NewLIR0(kPseudoTargetLabel); branch->target = target; } else { - DCHECK_EQ(cu->instruction_set, kX86); - CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pResolveStringFromCode), TargetReg(kArg2), TargetReg(kArg1), true); + DCHECK_EQ(cu_->instruction_set, kX86); + CallRuntimeHelperRegReg(ENTRYPOINT_OFFSET(pResolveStringFromCode), TargetReg(kArg2), TargetReg(kArg1), true); } - GenBarrier(cu); - StoreValue(cu, rl_dest, GetReturn(cu, false)); + GenBarrier(); + StoreValue(rl_dest, GetReturn(false)); } else { - RegLocation rl_method = LoadCurrMethod(cu); - int res_reg = AllocTemp(cu); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - LoadWordDisp(cu, rl_method.low_reg, + RegLocation rl_method = LoadCurrMethod(); + int res_reg = AllocTemp(); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + LoadWordDisp(rl_method.low_reg, mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), res_reg); - LoadWordDisp(cu, res_reg, offset_of_string, rl_result.low_reg); - StoreValue(cu, rl_dest, rl_result); + LoadWordDisp(res_reg, offset_of_string, rl_result.low_reg); + StoreValue(rl_dest, rl_result); } } @@ -881,188 +871,188 @@ void Codegen::GenConstString(CompilationUnit* cu, uint32_t string_idx, RegLocati * Let helper function take care of everything. Will * call Class::NewInstanceFromCode(type_idx, method); */ -void Codegen::GenNewInstance(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest) +void Mir2Lir::GenNewInstance(uint32_t type_idx, RegLocation rl_dest) { - FlushAllRegs(cu); /* Everything to home location */ + FlushAllRegs(); /* Everything to home location */ // alloc will always check for resolution, do we also need to verify // access because the verifier was unable to? int func_offset; - if (cu->compiler_driver->CanAccessInstantiableTypeWithoutChecks( - cu->method_idx, *cu->dex_file, type_idx)) { + if (cu_->compiler_driver->CanAccessInstantiableTypeWithoutChecks( + cu_->method_idx, *cu_->dex_file, type_idx)) { func_offset = ENTRYPOINT_OFFSET(pAllocObjectFromCode); } else { func_offset = ENTRYPOINT_OFFSET(pAllocObjectFromCodeWithAccessCheck); } - CallRuntimeHelperImmMethod(cu, func_offset, type_idx, true); - RegLocation rl_result = GetReturn(cu, false); - StoreValue(cu, rl_dest, rl_result); + CallRuntimeHelperImmMethod(func_offset, type_idx, true); + RegLocation rl_result = GetReturn(false); + StoreValue(rl_dest, rl_result); } -void Codegen::GenThrow(CompilationUnit* cu, RegLocation rl_src) +void Mir2Lir::GenThrow(RegLocation rl_src) { - FlushAllRegs(cu); - CallRuntimeHelperRegLocation(cu, ENTRYPOINT_OFFSET(pDeliverException), rl_src, true); + FlushAllRegs(); + CallRuntimeHelperRegLocation(ENTRYPOINT_OFFSET(pDeliverException), rl_src, true); } -void Codegen::GenInstanceof(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest, +void Mir2Lir::GenInstanceof(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src) { - FlushAllRegs(cu); + FlushAllRegs(); // May generate a call - use explicit registers - LockCallTemps(cu); - LoadCurrMethodDirect(cu, TargetReg(kArg1)); // kArg1 <= current Method* + LockCallTemps(); + LoadCurrMethodDirect(TargetReg(kArg1)); // kArg1 <= current Method* int class_reg = TargetReg(kArg2); // kArg2 will hold the Class* - if (!cu->compiler_driver->CanAccessTypeWithoutChecks(cu->method_idx, - *cu->dex_file, + if (!cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, + *cu_->dex_file, type_idx)) { // Check we have access to type_idx and if not throw IllegalAccessError, // returns Class* in kArg0 - CallRuntimeHelperImm(cu, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode), + CallRuntimeHelperImm(ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode), type_idx, true); - OpRegCopy(cu, class_reg, TargetReg(kRet0)); // Align usage with fast path - LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0)); // kArg0 <= ref + OpRegCopy(class_reg, TargetReg(kRet0)); // Align usage with fast path + LoadValueDirectFixed(rl_src, TargetReg(kArg0)); // kArg0 <= ref } else { // Load dex cache entry into class_reg (kArg2) - LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0)); // kArg0 <= ref - LoadWordDisp(cu, TargetReg(kArg1), + LoadValueDirectFixed(rl_src, TargetReg(kArg0)); // kArg0 <= ref + LoadWordDisp(TargetReg(kArg1), mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg); int32_t offset_of_type = mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*) * type_idx); - LoadWordDisp(cu, class_reg, offset_of_type, class_reg); - if (!cu->compiler_driver->CanAssumeTypeIsPresentInDexCache( - *cu->dex_file, type_idx)) { + LoadWordDisp(class_reg, offset_of_type, class_reg); + if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache( + *cu_->dex_file, type_idx)) { // Need to test presence of type in dex cache at runtime - LIR* hop_branch = OpCmpImmBranch(cu, kCondNe, class_reg, 0, NULL); + LIR* hop_branch = OpCmpImmBranch(kCondNe, class_reg, 0, NULL); // Not resolved // Call out to helper, which will return resolved type in kRet0 - CallRuntimeHelperImm(cu, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, true); - OpRegCopy(cu, TargetReg(kArg2), TargetReg(kRet0)); // Align usage with fast path - LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0)); /* reload Ref */ + CallRuntimeHelperImm(ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, true); + OpRegCopy(TargetReg(kArg2), TargetReg(kRet0)); // Align usage with fast path + LoadValueDirectFixed(rl_src, TargetReg(kArg0)); /* reload Ref */ // Rejoin code paths - LIR* hop_target = NewLIR0(cu, kPseudoTargetLabel); + LIR* hop_target = NewLIR0(kPseudoTargetLabel); hop_branch->target = hop_target; } } /* kArg0 is ref, kArg2 is class. If ref==null, use directly as bool result */ - RegLocation rl_result = GetReturn(cu, false); - if (cu->instruction_set == kMips) { - LoadConstant(cu, rl_result.low_reg, 0); // store false result for if branch is taken + RegLocation rl_result = GetReturn(false); + if (cu_->instruction_set == kMips) { + LoadConstant(rl_result.low_reg, 0); // store false result for if branch is taken } - LIR* branch1 = OpCmpImmBranch(cu, kCondEq, TargetReg(kArg0), 0, NULL); + LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0), 0, NULL); /* load object->klass_ */ DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0); - LoadWordDisp(cu, TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1)); + LoadWordDisp(TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1)); /* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class */ LIR* call_inst; LIR* branchover = NULL; - if (cu->instruction_set == kThumb2) { + if (cu_->instruction_set == kThumb2) { /* Uses conditional nullification */ - int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); - OpRegReg(cu, kOpCmp, TargetReg(kArg1), TargetReg(kArg2)); // Same? - OpIT(cu, kCondEq, "EE"); // if-convert the test - LoadConstant(cu, TargetReg(kArg0), 1); // .eq case - load true - OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2)); // .ne case - arg0 <= class - call_inst = OpReg(cu, kOpBlx, r_tgt); // .ne case: helper(class, ref->class) - FreeTemp(cu, r_tgt); + int r_tgt = LoadHelper(ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); + OpRegReg(kOpCmp, TargetReg(kArg1), TargetReg(kArg2)); // Same? + OpIT(kCondEq, "EE"); // if-convert the test + LoadConstant(TargetReg(kArg0), 1); // .eq case - load true + OpRegCopy(TargetReg(kArg0), TargetReg(kArg2)); // .ne case - arg0 <= class + call_inst = OpReg(kOpBlx, r_tgt); // .ne case: helper(class, ref->class) + FreeTemp(r_tgt); } else { /* Uses branchovers */ - LoadConstant(cu, rl_result.low_reg, 1); // assume true - branchover = OpCmpBranch(cu, kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL); - if (cu->instruction_set != kX86) { - int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); - OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2)); // .ne case - arg0 <= class - call_inst = OpReg(cu, kOpBlx, r_tgt); // .ne case: helper(class, ref->class) - FreeTemp(cu, r_tgt); + LoadConstant(rl_result.low_reg, 1); // assume true + branchover = OpCmpBranch(kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL); + if (cu_->instruction_set != kX86) { + int r_tgt = LoadHelper(ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); + OpRegCopy(TargetReg(kArg0), TargetReg(kArg2)); // .ne case - arg0 <= class + call_inst = OpReg(kOpBlx, r_tgt); // .ne case: helper(class, ref->class) + FreeTemp(r_tgt); } else { - OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2)); - call_inst = OpThreadMem(cu, kOpBlx, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); + OpRegCopy(TargetReg(kArg0), TargetReg(kArg2)); + call_inst = OpThreadMem(kOpBlx, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); } } - MarkSafepointPC(cu, call_inst); - ClobberCalleeSave(cu); + MarkSafepointPC(call_inst); + ClobberCalleeSave(); /* branch targets here */ - LIR* target = NewLIR0(cu, kPseudoTargetLabel); - StoreValue(cu, rl_dest, rl_result); + LIR* target = NewLIR0(kPseudoTargetLabel); + StoreValue(rl_dest, rl_result); branch1->target = target; - if (cu->instruction_set != kThumb2) { + if (cu_->instruction_set != kThumb2) { branchover->target = target; } } -void Codegen::GenCheckCast(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_src) +void Mir2Lir::GenCheckCast(uint32_t type_idx, RegLocation rl_src) { - FlushAllRegs(cu); + FlushAllRegs(); // May generate a call - use explicit registers - LockCallTemps(cu); - LoadCurrMethodDirect(cu, TargetReg(kArg1)); // kArg1 <= current Method* + LockCallTemps(); + LoadCurrMethodDirect(TargetReg(kArg1)); // kArg1 <= current Method* int class_reg = TargetReg(kArg2); // kArg2 will hold the Class* - if (!cu->compiler_driver->CanAccessTypeWithoutChecks(cu->method_idx, - *cu->dex_file, + if (!cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, + *cu_->dex_file, type_idx)) { // Check we have access to type_idx and if not throw IllegalAccessError, // returns Class* in kRet0 // InitializeTypeAndVerifyAccess(idx, method) - CallRuntimeHelperImmReg(cu, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode), + CallRuntimeHelperImmReg(ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode), type_idx, TargetReg(kArg1), true); - OpRegCopy(cu, class_reg, TargetReg(kRet0)); // Align usage with fast path + OpRegCopy(class_reg, TargetReg(kRet0)); // Align usage with fast path } else { // Load dex cache entry into class_reg (kArg2) - LoadWordDisp(cu, TargetReg(kArg1), + LoadWordDisp(TargetReg(kArg1), mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg); int32_t offset_of_type = mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*) * type_idx); - LoadWordDisp(cu, class_reg, offset_of_type, class_reg); - if (!cu->compiler_driver->CanAssumeTypeIsPresentInDexCache( - *cu->dex_file, type_idx)) { + LoadWordDisp(class_reg, offset_of_type, class_reg); + if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache( + *cu_->dex_file, type_idx)) { // Need to test presence of type in dex cache at runtime - LIR* hop_branch = OpCmpImmBranch(cu, kCondNe, class_reg, 0, NULL); + LIR* hop_branch = OpCmpImmBranch(kCondNe, class_reg, 0, NULL); // Not resolved // Call out to helper, which will return resolved type in kArg0 // InitializeTypeFromCode(idx, method) - CallRuntimeHelperImmReg(cu, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, TargetReg(kArg1), + CallRuntimeHelperImmReg(ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, TargetReg(kArg1), true); - OpRegCopy(cu, class_reg, TargetReg(kRet0)); // Align usage with fast path + OpRegCopy(class_reg, TargetReg(kRet0)); // Align usage with fast path // Rejoin code paths - LIR* hop_target = NewLIR0(cu, kPseudoTargetLabel); + LIR* hop_target = NewLIR0(kPseudoTargetLabel); hop_branch->target = hop_target; } } // At this point, class_reg (kArg2) has class - LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0)); // kArg0 <= ref + LoadValueDirectFixed(rl_src, TargetReg(kArg0)); // kArg0 <= ref /* Null is OK - continue */ - LIR* branch1 = OpCmpImmBranch(cu, kCondEq, TargetReg(kArg0), 0, NULL); + LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0), 0, NULL); /* load object->klass_ */ DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0); - LoadWordDisp(cu, TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1)); + LoadWordDisp(TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1)); /* kArg1 now contains object->klass_ */ LIR* branch2; - if (cu->instruction_set == kThumb2) { - int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pCheckCastFromCode)); - OpRegReg(cu, kOpCmp, TargetReg(kArg1), class_reg); - branch2 = OpCondBranch(cu, kCondEq, NULL); /* If eq, trivial yes */ - OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg1)); - OpRegCopy(cu, TargetReg(kArg1), TargetReg(kArg2)); - ClobberCalleeSave(cu); - LIR* call_inst = OpReg(cu, kOpBlx, r_tgt); - MarkSafepointPC(cu, call_inst); - FreeTemp(cu, r_tgt); + if (cu_->instruction_set == kThumb2) { + int r_tgt = LoadHelper(ENTRYPOINT_OFFSET(pCheckCastFromCode)); + OpRegReg(kOpCmp, TargetReg(kArg1), class_reg); + branch2 = OpCondBranch(kCondEq, NULL); /* If eq, trivial yes */ + OpRegCopy(TargetReg(kArg0), TargetReg(kArg1)); + OpRegCopy(TargetReg(kArg1), TargetReg(kArg2)); + ClobberCalleeSave(); + LIR* call_inst = OpReg(kOpBlx, r_tgt); + MarkSafepointPC(call_inst); + FreeTemp(r_tgt); } else { - branch2 = OpCmpBranch(cu, kCondEq, TargetReg(kArg1), class_reg, NULL); - CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pCheckCastFromCode), TargetReg(kArg1), TargetReg(kArg2), true); + branch2 = OpCmpBranch(kCondEq, TargetReg(kArg1), class_reg, NULL); + CallRuntimeHelperRegReg(ENTRYPOINT_OFFSET(pCheckCastFromCode), TargetReg(kArg1), TargetReg(kArg2), true); } /* branch target here */ - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); branch1->target = target; branch2->target = target; } -void Codegen::GenLong3Addr(CompilationUnit* cu, OpKind first_op, OpKind second_op, - RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) +void Mir2Lir::GenLong3Addr(OpKind first_op, OpKind second_op, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2) { RegLocation rl_result; - if (cu->instruction_set == kThumb2) { + if (cu_->instruction_set == kThumb2) { /* * NOTE: This is the one place in the code in which we might have * as many as six live temporary registers. There are 5 in the normal @@ -1071,22 +1061,22 @@ void Codegen::GenLong3Addr(CompilationUnit* cu, OpKind first_op, OpKind second_o * lr is used explicitly elsewhere in the code generator and cannot * normally be used as a general temp register. */ - MarkTemp(cu, TargetReg(kLr)); // Add lr to the temp pool - FreeTemp(cu, TargetReg(kLr)); // and make it available + MarkTemp(TargetReg(kLr)); // Add lr to the temp pool + FreeTemp(TargetReg(kLr)); // and make it available } - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); - rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); // The longs may overlap - use intermediate temp if so if ((rl_result.low_reg == rl_src1.high_reg) || (rl_result.low_reg == rl_src2.high_reg)){ - int t_reg = AllocTemp(cu); - OpRegRegReg(cu, first_op, t_reg, rl_src1.low_reg, rl_src2.low_reg); - OpRegRegReg(cu, second_op, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg); - OpRegCopy(cu, rl_result.low_reg, t_reg); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + OpRegRegReg(first_op, t_reg, rl_src1.low_reg, rl_src2.low_reg); + OpRegRegReg(second_op, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg); + OpRegCopy(rl_result.low_reg, t_reg); + FreeTemp(t_reg); } else { - OpRegRegReg(cu, first_op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); - OpRegRegReg(cu, second_op, rl_result.high_reg, rl_src1.high_reg, + OpRegRegReg(first_op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); + OpRegRegReg(second_op, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg); } /* @@ -1096,17 +1086,17 @@ void Codegen::GenLong3Addr(CompilationUnit* cu, OpKind first_op, OpKind second_o * free any temps from rl_src1 & rl_src2 that aren't still live in rl_result. * Remove when spill is functional. */ - FreeRegLocTemps(cu, rl_result, rl_src1); - FreeRegLocTemps(cu, rl_result, rl_src2); - StoreValueWide(cu, rl_dest, rl_result); - if (cu->instruction_set == kThumb2) { - Clobber(cu, TargetReg(kLr)); - UnmarkTemp(cu, TargetReg(kLr)); // Remove lr from the temp pool + FreeRegLocTemps(rl_result, rl_src1); + FreeRegLocTemps(rl_result, rl_src2); + StoreValueWide(rl_dest, rl_result); + if (cu_->instruction_set == kThumb2) { + Clobber(TargetReg(kLr)); + UnmarkTemp(TargetReg(kLr)); // Remove lr from the temp pool } } -void Codegen::GenShiftOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, +void Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_shift) { int func_offset = -1; // Make gcc happy @@ -1127,14 +1117,14 @@ void Codegen::GenShiftOpLong(CompilationUnit* cu, Instruction::Code opcode, RegL default: LOG(FATAL) << "Unexpected case"; } - FlushAllRegs(cu); /* Send everything to home location */ - CallRuntimeHelperRegLocationRegLocation(cu, func_offset, rl_src1, rl_shift, false); - RegLocation rl_result = GetReturnWide(cu, false); - StoreValueWide(cu, rl_dest, rl_result); + FlushAllRegs(); /* Send everything to home location */ + CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_shift, false); + RegLocation rl_result = GetReturnWide(false); + StoreValueWide(rl_dest, rl_result); } -void Codegen::GenArithOpInt(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, +void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { OpKind op = kOpBkpt; @@ -1209,58 +1199,58 @@ void Codegen::GenArithOpInt(CompilationUnit* cu, Instruction::Code opcode, RegLo } if (!is_div_rem) { if (unary) { - rl_src1 = LoadValue(cu, rl_src1, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegReg(cu, op, rl_result.low_reg, rl_src1.low_reg); + rl_src1 = LoadValue(rl_src1, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegReg(op, rl_result.low_reg, rl_src1.low_reg); } else { if (shift_op) { int t_reg = INVALID_REG; - if (cu->instruction_set == kX86) { + if (cu_->instruction_set == kX86) { // X86 doesn't require masking and must use ECX t_reg = TargetReg(kCount); // rCX - LoadValueDirectFixed(cu, rl_src2, t_reg); + LoadValueDirectFixed(rl_src2, t_reg); } else { - rl_src2 = LoadValue(cu, rl_src2, kCoreReg); - t_reg = AllocTemp(cu); - OpRegRegImm(cu, kOpAnd, t_reg, rl_src2.low_reg, 31); + rl_src2 = LoadValue(rl_src2, kCoreReg); + t_reg = AllocTemp(); + OpRegRegImm(kOpAnd, t_reg, rl_src2.low_reg, 31); } - rl_src1 = LoadValue(cu, rl_src1, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegRegReg(cu, op, rl_result.low_reg, rl_src1.low_reg, t_reg); - FreeTemp(cu, t_reg); + rl_src1 = LoadValue(rl_src1, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegRegReg(op, rl_result.low_reg, rl_src1.low_reg, t_reg); + FreeTemp(t_reg); } else { - rl_src1 = LoadValue(cu, rl_src1, kCoreReg); - rl_src2 = LoadValue(cu, rl_src2, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegRegReg(cu, op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); + rl_src1 = LoadValue(rl_src1, kCoreReg); + rl_src2 = LoadValue(rl_src2, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegRegReg(op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); } } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } else { - if (cu->instruction_set == kMips) { - rl_src1 = LoadValue(cu, rl_src1, kCoreReg); - rl_src2 = LoadValue(cu, rl_src2, kCoreReg); + if (cu_->instruction_set == kMips) { + rl_src1 = LoadValue(rl_src1, kCoreReg); + rl_src2 = LoadValue(rl_src2, kCoreReg); if (check_zero) { - GenImmedCheck(cu, kCondEq, rl_src2.low_reg, 0, kThrowDivZero); + GenImmedCheck(kCondEq, rl_src2.low_reg, 0, kThrowDivZero); } - rl_result = GenDivRem(cu, rl_dest, rl_src1.low_reg, rl_src2.low_reg, op == kOpDiv); + rl_result = GenDivRem(rl_dest, rl_src1.low_reg, rl_src2.low_reg, op == kOpDiv); } else { int func_offset = ENTRYPOINT_OFFSET(pIdivmod); - FlushAllRegs(cu); /* Send everything to home location */ - LoadValueDirectFixed(cu, rl_src2, TargetReg(kArg1)); - int r_tgt = CallHelperSetup(cu, func_offset); - LoadValueDirectFixed(cu, rl_src1, TargetReg(kArg0)); + FlushAllRegs(); /* Send everything to home location */ + LoadValueDirectFixed(rl_src2, TargetReg(kArg1)); + int r_tgt = CallHelperSetup(func_offset); + LoadValueDirectFixed(rl_src1, TargetReg(kArg0)); if (check_zero) { - GenImmedCheck(cu, kCondEq, TargetReg(kArg1), 0, kThrowDivZero); + GenImmedCheck(kCondEq, TargetReg(kArg1), 0, kThrowDivZero); } // NOTE: callout here is not a safepoint - CallHelper(cu, r_tgt, func_offset, false /* not a safepoint */ ); + CallHelper(r_tgt, func_offset, false /* not a safepoint */ ); if (op == kOpDiv) - rl_result = GetReturn(cu, false); + rl_result = GetReturn(false); else - rl_result = GetReturnAlt(cu); + rl_result = GetReturnAlt(); } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } } @@ -1298,16 +1288,15 @@ static int LowestSetBit(unsigned int x) { // Returns true if it added instructions to 'cu' to divide 'rl_src' by 'lit' // and store the result in 'rl_dest'. -static bool HandleEasyDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode, - RegLocation rl_src, RegLocation rl_dest, int lit) +bool Mir2Lir::HandleEasyDivide(Instruction::Code dalvik_opcode, + RegLocation rl_src, RegLocation rl_dest, int lit) { - if ((lit < 2) || ((cu->instruction_set != kThumb2) && !IsPowerOfTwo(lit))) { + if ((lit < 2) || ((cu_->instruction_set != kThumb2) && !IsPowerOfTwo(lit))) { return false; } - Codegen* cg = cu->cg.get(); // No divide instruction for Arm, so check for more special cases - if ((cu->instruction_set == kThumb2) && !IsPowerOfTwo(lit)) { - return cg->SmallLiteralDivide(cu, dalvik_opcode, rl_src, rl_dest, lit); + if ((cu_->instruction_set == kThumb2) && !IsPowerOfTwo(lit)) { + return SmallLiteralDivide(dalvik_opcode, rl_src, rl_dest, lit); } int k = LowestSetBit(lit); if (k >= 30) { @@ -1316,45 +1305,44 @@ static bool HandleEasyDivide(CompilationUnit* cu, Instruction::Code dalvik_opcod } bool div = (dalvik_opcode == Instruction::DIV_INT_LIT8 || dalvik_opcode == Instruction::DIV_INT_LIT16); - rl_src = cg->LoadValue(cu, rl_src, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src = LoadValue(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); if (div) { - int t_reg = AllocTemp(cu); + int t_reg = AllocTemp(); if (lit == 2) { // Division by 2 is by far the most common division by constant. - cg->OpRegRegImm(cu, kOpLsr, t_reg, rl_src.low_reg, 32 - k); - cg->OpRegRegReg(cu, kOpAdd, t_reg, t_reg, rl_src.low_reg); - cg->OpRegRegImm(cu, kOpAsr, rl_result.low_reg, t_reg, k); + OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, 32 - k); + OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.low_reg); + OpRegRegImm(kOpAsr, rl_result.low_reg, t_reg, k); } else { - cg->OpRegRegImm(cu, kOpAsr, t_reg, rl_src.low_reg, 31); - cg->OpRegRegImm(cu, kOpLsr, t_reg, t_reg, 32 - k); - cg->OpRegRegReg(cu, kOpAdd, t_reg, t_reg, rl_src.low_reg); - cg->OpRegRegImm(cu, kOpAsr, rl_result.low_reg, t_reg, k); + OpRegRegImm(kOpAsr, t_reg, rl_src.low_reg, 31); + OpRegRegImm(kOpLsr, t_reg, t_reg, 32 - k); + OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.low_reg); + OpRegRegImm(kOpAsr, rl_result.low_reg, t_reg, k); } } else { - int t_reg1 = AllocTemp(cu); - int t_reg2 = AllocTemp(cu); + int t_reg1 = AllocTemp(); + int t_reg2 = AllocTemp(); if (lit == 2) { - cg->OpRegRegImm(cu, kOpLsr, t_reg1, rl_src.low_reg, 32 - k); - cg->OpRegRegReg(cu, kOpAdd, t_reg2, t_reg1, rl_src.low_reg); - cg->OpRegRegImm(cu, kOpAnd, t_reg2, t_reg2, lit -1); - cg->OpRegRegReg(cu, kOpSub, rl_result.low_reg, t_reg2, t_reg1); + OpRegRegImm(kOpLsr, t_reg1, rl_src.low_reg, 32 - k); + OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.low_reg); + OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit -1); + OpRegRegReg(kOpSub, rl_result.low_reg, t_reg2, t_reg1); } else { - cg->OpRegRegImm(cu, kOpAsr, t_reg1, rl_src.low_reg, 31); - cg->OpRegRegImm(cu, kOpLsr, t_reg1, t_reg1, 32 - k); - cg->OpRegRegReg(cu, kOpAdd, t_reg2, t_reg1, rl_src.low_reg); - cg->OpRegRegImm(cu, kOpAnd, t_reg2, t_reg2, lit - 1); - cg->OpRegRegReg(cu, kOpSub, rl_result.low_reg, t_reg2, t_reg1); + OpRegRegImm(kOpAsr, t_reg1, rl_src.low_reg, 31); + OpRegRegImm(kOpLsr, t_reg1, t_reg1, 32 - k); + OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.low_reg); + OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit - 1); + OpRegRegReg(kOpSub, rl_result.low_reg, t_reg2, t_reg1); } } - cg->StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); return true; } // Returns true if it added instructions to 'cu' to multiply 'rl_src' by 'lit' // and store the result in 'rl_dest'. -static bool HandleEasyMultiply(CompilationUnit* cu, RegLocation rl_src, - RegLocation rl_dest, int lit) +bool Mir2Lir::HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) { // Can we simplify this multiplication? bool power_of_two = false; @@ -1372,31 +1360,30 @@ static bool HandleEasyMultiply(CompilationUnit* cu, RegLocation rl_src, } else { return false; } - Codegen* cg = cu->cg.get(); - rl_src = cg->LoadValue(cu, rl_src, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src = LoadValue(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); if (power_of_two) { // Shift. - cg->OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_src.low_reg, LowestSetBit(lit)); + OpRegRegImm(kOpLsl, rl_result.low_reg, rl_src.low_reg, LowestSetBit(lit)); } else if (pop_count_le2) { // Shift and add and shift. int first_bit = LowestSetBit(lit); int second_bit = LowestSetBit(lit ^ (1 << first_bit)); - cg->GenMultiplyByTwoBitMultiplier(cu, rl_src, rl_result, lit, first_bit, second_bit); + GenMultiplyByTwoBitMultiplier(rl_src, rl_result, lit, first_bit, second_bit); } else { // Reverse subtract: (src << (shift + 1)) - src. DCHECK(power_of_two_minus_one); // TUNING: rsb dst, src, src lsl#LowestSetBit(lit + 1) - int t_reg = AllocTemp(cu); - cg->OpRegRegImm(cu, kOpLsl, t_reg, rl_src.low_reg, LowestSetBit(lit + 1)); - cg->OpRegRegReg(cu, kOpSub, rl_result.low_reg, t_reg, rl_src.low_reg); + int t_reg = AllocTemp(); + OpRegRegImm(kOpLsl, t_reg, rl_src.low_reg, LowestSetBit(lit + 1)); + OpRegRegReg(kOpSub, rl_result.low_reg, t_reg, rl_src.low_reg); } - cg->StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); return true; } -void Codegen::GenArithOpIntLit(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src, int lit) +void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src, + int lit) { RegLocation rl_result; OpKind op = static_cast<OpKind>(0); /* Make gcc happy */ @@ -1406,15 +1393,15 @@ void Codegen::GenArithOpIntLit(CompilationUnit* cu, Instruction::Code opcode, switch (opcode) { case Instruction::RSUB_INT_LIT8: case Instruction::RSUB_INT: { - rl_src = LoadValue(cu, rl_src, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - if (cu->instruction_set == kThumb2) { - OpRegRegImm(cu, kOpRsub, rl_result.low_reg, rl_src.low_reg, lit); + rl_src = LoadValue(rl_src, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + if (cu_->instruction_set == kThumb2) { + OpRegRegImm(kOpRsub, rl_result.low_reg, rl_src.low_reg, lit); } else { - OpRegReg(cu, kOpNeg, rl_result.low_reg, rl_src.low_reg); - OpRegImm(cu, kOpAdd, rl_result.low_reg, lit); + OpRegReg(kOpNeg, rl_result.low_reg, rl_src.low_reg); + OpRegImm(kOpAdd, rl_result.low_reg, lit); } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); return; } @@ -1432,7 +1419,7 @@ void Codegen::GenArithOpIntLit(CompilationUnit* cu, Instruction::Code opcode, case Instruction::MUL_INT_2ADDR: case Instruction::MUL_INT_LIT8: case Instruction::MUL_INT_LIT16: { - if (HandleEasyMultiply(cu, rl_src, rl_dest, lit)) { + if (HandleEasyMultiply(rl_src, rl_dest, lit)) { return; } op = kOpMul; @@ -1487,10 +1474,10 @@ void Codegen::GenArithOpIntLit(CompilationUnit* cu, Instruction::Code opcode, case Instruction::REM_INT_LIT8: case Instruction::REM_INT_LIT16: { if (lit == 0) { - GenImmedCheck(cu, kCondAl, 0, 0, kThrowDivZero); + GenImmedCheck(kCondAl, 0, 0, kThrowDivZero); return; } - if (HandleEasyDivide(cu, opcode, rl_src, rl_dest, lit)) { + if (HandleEasyDivide(opcode, rl_src, rl_dest, lit)) { return; } if ((opcode == Instruction::DIV_INT_LIT8) || @@ -1501,38 +1488,38 @@ void Codegen::GenArithOpIntLit(CompilationUnit* cu, Instruction::Code opcode, } else { is_div = false; } - if (cu->instruction_set == kMips) { - rl_src = LoadValue(cu, rl_src, kCoreReg); - rl_result = GenDivRemLit(cu, rl_dest, rl_src.low_reg, lit, is_div); + if (cu_->instruction_set == kMips) { + rl_src = LoadValue(rl_src, kCoreReg); + rl_result = GenDivRemLit(rl_dest, rl_src.low_reg, lit, is_div); } else { - FlushAllRegs(cu); /* Everything to home location */ - LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0)); - Clobber(cu, TargetReg(kArg0)); + FlushAllRegs(); /* Everything to home location */ + LoadValueDirectFixed(rl_src, TargetReg(kArg0)); + Clobber(TargetReg(kArg0)); int func_offset = ENTRYPOINT_OFFSET(pIdivmod); - CallRuntimeHelperRegImm(cu, func_offset, TargetReg(kArg0), lit, false); + CallRuntimeHelperRegImm(func_offset, TargetReg(kArg0), lit, false); if (is_div) - rl_result = GetReturn(cu, false); + rl_result = GetReturn(false); else - rl_result = GetReturnAlt(cu); + rl_result = GetReturnAlt(); } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); return; } default: LOG(FATAL) << "Unexpected opcode " << opcode; } - rl_src = LoadValue(cu, rl_src, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src = LoadValue(rl_src, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); // Avoid shifts by literal 0 - no support in Thumb. Change to copy if (shift_op && (lit == 0)) { - OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg); + OpRegCopy(rl_result.low_reg, rl_src.low_reg); } else { - OpRegRegImm(cu, op, rl_result.low_reg, rl_src.low_reg, lit); + OpRegRegImm(op, rl_result.low_reg, rl_src.low_reg, lit); } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } -void Codegen::GenArithOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, +void Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { RegLocation rl_result; @@ -1545,25 +1532,25 @@ void Codegen::GenArithOpLong(CompilationUnit* cu, Instruction::Code opcode, RegL switch (opcode) { case Instruction::NOT_LONG: - rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); // Check for destructive overlap if (rl_result.low_reg == rl_src2.high_reg) { - int t_reg = AllocTemp(cu); - OpRegCopy(cu, t_reg, rl_src2.high_reg); - OpRegReg(cu, kOpMvn, rl_result.low_reg, rl_src2.low_reg); - OpRegReg(cu, kOpMvn, rl_result.high_reg, t_reg); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + OpRegCopy(t_reg, rl_src2.high_reg); + OpRegReg(kOpMvn, rl_result.low_reg, rl_src2.low_reg); + OpRegReg(kOpMvn, rl_result.high_reg, t_reg); + FreeTemp(t_reg); } else { - OpRegReg(cu, kOpMvn, rl_result.low_reg, rl_src2.low_reg); - OpRegReg(cu, kOpMvn, rl_result.high_reg, rl_src2.high_reg); + OpRegReg(kOpMvn, rl_result.low_reg, rl_src2.low_reg); + OpRegReg(kOpMvn, rl_result.high_reg, rl_src2.high_reg); } - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); return; case Instruction::ADD_LONG: case Instruction::ADD_LONG_2ADDR: - if (cu->instruction_set != kThumb2) { - GenAddLong(cu, rl_dest, rl_src1, rl_src2); + if (cu_->instruction_set != kThumb2) { + GenAddLong(rl_dest, rl_src1, rl_src2); return; } first_op = kOpAdd; @@ -1571,8 +1558,8 @@ void Codegen::GenArithOpLong(CompilationUnit* cu, Instruction::Code opcode, RegL break; case Instruction::SUB_LONG: case Instruction::SUB_LONG_2ADDR: - if (cu->instruction_set != kThumb2) { - GenSubLong(cu, rl_dest, rl_src1, rl_src2); + if (cu_->instruction_set != kThumb2) { + GenSubLong(rl_dest, rl_src1, rl_src2); return; } first_op = kOpSub; @@ -1580,8 +1567,8 @@ void Codegen::GenArithOpLong(CompilationUnit* cu, Instruction::Code opcode, RegL break; case Instruction::MUL_LONG: case Instruction::MUL_LONG_2ADDR: - if (cu->instruction_set == kThumb2) { - GenMulLong(cu, rl_dest, rl_src1, rl_src2); + if (cu_->instruction_set == kThumb2) { + GenMulLong(rl_dest, rl_src1, rl_src2); return; } else { call_out = true; @@ -1602,20 +1589,20 @@ void Codegen::GenArithOpLong(CompilationUnit* cu, Instruction::Code opcode, RegL check_zero = true; func_offset = ENTRYPOINT_OFFSET(pLdivmod); /* NOTE - for Arm, result is in kArg2/kArg3 instead of kRet0/kRet1 */ - ret_reg = (cu->instruction_set == kThumb2) ? TargetReg(kArg2) : TargetReg(kRet0); + ret_reg = (cu_->instruction_set == kThumb2) ? TargetReg(kArg2) : TargetReg(kRet0); break; case Instruction::AND_LONG_2ADDR: case Instruction::AND_LONG: - if (cu->instruction_set == kX86) { - return GenAndLong(cu, rl_dest, rl_src1, rl_src2); + if (cu_->instruction_set == kX86) { + return GenAndLong(rl_dest, rl_src1, rl_src2); } first_op = kOpAnd; second_op = kOpAnd; break; case Instruction::OR_LONG: case Instruction::OR_LONG_2ADDR: - if (cu->instruction_set == kX86) { - GenOrLong(cu, rl_dest, rl_src1, rl_src2); + if (cu_->instruction_set == kX86) { + GenOrLong(rl_dest, rl_src1, rl_src2); return; } first_op = kOpOr; @@ -1623,99 +1610,98 @@ void Codegen::GenArithOpLong(CompilationUnit* cu, Instruction::Code opcode, RegL break; case Instruction::XOR_LONG: case Instruction::XOR_LONG_2ADDR: - if (cu->instruction_set == kX86) { - GenXorLong(cu, rl_dest, rl_src1, rl_src2); + if (cu_->instruction_set == kX86) { + GenXorLong(rl_dest, rl_src1, rl_src2); return; } first_op = kOpXor; second_op = kOpXor; break; case Instruction::NEG_LONG: { - GenNegLong(cu, rl_dest, rl_src2); + GenNegLong(rl_dest, rl_src2); return; } default: LOG(FATAL) << "Invalid long arith op"; } if (!call_out) { - GenLong3Addr(cu, first_op, second_op, rl_dest, rl_src1, rl_src2); + GenLong3Addr(first_op, second_op, rl_dest, rl_src1, rl_src2); } else { - FlushAllRegs(cu); /* Send everything to home location */ + FlushAllRegs(); /* Send everything to home location */ if (check_zero) { - LoadValueDirectWideFixed(cu, rl_src2, TargetReg(kArg2), TargetReg(kArg3)); - int r_tgt = CallHelperSetup(cu, func_offset); - GenDivZeroCheck(cu, TargetReg(kArg2), TargetReg(kArg3)); - LoadValueDirectWideFixed(cu, rl_src1, TargetReg(kArg0), TargetReg(kArg1)); + LoadValueDirectWideFixed(rl_src2, TargetReg(kArg2), TargetReg(kArg3)); + int r_tgt = CallHelperSetup(func_offset); + GenDivZeroCheck(TargetReg(kArg2), TargetReg(kArg3)); + LoadValueDirectWideFixed(rl_src1, TargetReg(kArg0), TargetReg(kArg1)); // NOTE: callout here is not a safepoint - CallHelper(cu, r_tgt, func_offset, false /* not safepoint */); + CallHelper(r_tgt, func_offset, false /* not safepoint */); } else { - CallRuntimeHelperRegLocationRegLocation(cu, func_offset, - rl_src1, rl_src2, false); + CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_src2, false); } // Adjust return regs in to handle case of rem returning kArg2/kArg3 if (ret_reg == TargetReg(kRet0)) - rl_result = GetReturnWide(cu, false); + rl_result = GetReturnWide(false); else - rl_result = GetReturnWideAlt(cu); - StoreValueWide(cu, rl_dest, rl_result); + rl_result = GetReturnWideAlt(); + StoreValueWide(rl_dest, rl_result); } } -void Codegen::GenConversionCall(CompilationUnit* cu, int func_offset, +void Mir2Lir::GenConversionCall(int func_offset, RegLocation rl_dest, RegLocation rl_src) { /* * Don't optimize the register usage since it calls out to support * functions */ - FlushAllRegs(cu); /* Send everything to home location */ + FlushAllRegs(); /* Send everything to home location */ if (rl_src.wide) { - LoadValueDirectWideFixed(cu, rl_src, rl_src.fp ? TargetReg(kFArg0) : TargetReg(kArg0), + LoadValueDirectWideFixed(rl_src, rl_src.fp ? TargetReg(kFArg0) : TargetReg(kArg0), rl_src.fp ? TargetReg(kFArg1) : TargetReg(kArg1)); } else { - LoadValueDirectFixed(cu, rl_src, rl_src.fp ? TargetReg(kFArg0) : TargetReg(kArg0)); + LoadValueDirectFixed(rl_src, rl_src.fp ? TargetReg(kFArg0) : TargetReg(kArg0)); } - CallRuntimeHelperRegLocation(cu, func_offset, rl_src, false); + CallRuntimeHelperRegLocation(func_offset, rl_src, false); if (rl_dest.wide) { RegLocation rl_result; - rl_result = GetReturnWide(cu, rl_dest.fp); - StoreValueWide(cu, rl_dest, rl_result); + rl_result = GetReturnWide(rl_dest.fp); + StoreValueWide(rl_dest, rl_result); } else { RegLocation rl_result; - rl_result = GetReturn(cu, rl_dest.fp); - StoreValue(cu, rl_dest, rl_result); + rl_result = GetReturn(rl_dest.fp); + StoreValue(rl_dest, rl_result); } } /* Check if we need to check for pending suspend request */ -void Codegen::GenSuspendTest(CompilationUnit* cu, int opt_flags) +void Mir2Lir::GenSuspendTest(int opt_flags) { if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) { return; } - FlushAllRegs(cu); - LIR* branch = OpTestSuspend(cu, NULL); - LIR* ret_lab = NewLIR0(cu, kPseudoTargetLabel); - LIR* target = RawLIR(cu, cu->current_dalvik_offset, kPseudoSuspendTarget, - reinterpret_cast<uintptr_t>(ret_lab), cu->current_dalvik_offset); + FlushAllRegs(); + LIR* branch = OpTestSuspend(NULL); + LIR* ret_lab = NewLIR0(kPseudoTargetLabel); + LIR* target = RawLIR(current_dalvik_offset_, kPseudoSuspendTarget, + reinterpret_cast<uintptr_t>(ret_lab), current_dalvik_offset_); branch->target = target; - InsertGrowableList(cu, &cu->suspend_launchpads, reinterpret_cast<uintptr_t>(target)); + InsertGrowableList(cu_, &suspend_launchpads_, reinterpret_cast<uintptr_t>(target)); } /* Check if we need to check for pending suspend request */ -void Codegen::GenSuspendTestAndBranch(CompilationUnit* cu, int opt_flags, LIR* target) +void Mir2Lir::GenSuspendTestAndBranch(int opt_flags, LIR* target) { if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) { - OpUnconditionalBranch(cu, target); + OpUnconditionalBranch(target); return; } - OpTestSuspend(cu, target); + OpTestSuspend(target); LIR* launch_pad = - RawLIR(cu, cu->current_dalvik_offset, kPseudoSuspendTarget, - reinterpret_cast<uintptr_t>(target), cu->current_dalvik_offset); - FlushAllRegs(cu); - OpUnconditionalBranch(cu, launch_pad); - InsertGrowableList(cu, &cu->suspend_launchpads, reinterpret_cast<uintptr_t>(launch_pad)); + RawLIR(current_dalvik_offset_, kPseudoSuspendTarget, + reinterpret_cast<uintptr_t>(target), current_dalvik_offset_); + FlushAllRegs(); + OpUnconditionalBranch(launch_pad); + InsertGrowableList(cu_, &suspend_launchpads_, reinterpret_cast<uintptr_t>(launch_pad)); } } // namespace art diff --git a/src/compiler/dex/quick/gen_invoke.cc b/src/compiler/dex/quick/gen_invoke.cc index c654143aa0..3e946f89aa 100644 --- a/src/compiler/dex/quick/gen_invoke.cc +++ b/src/compiler/dex/quick/gen_invoke.cc @@ -14,11 +14,9 @@ * limitations under the License. */ -#include "codegen_util.h" #include "compiler/dex/compiler_ir.h" #include "invoke_type.h" #include "oat/runtime/oat_support_entrypoints.h" -#include "ralloc_util.h" #include "x86/codegen_x86.h" namespace art { @@ -35,198 +33,192 @@ namespace art { * has a memory call operation, part 1 is a NOP for x86. For other targets, * load arguments between the two parts. */ -int Codegen::CallHelperSetup(CompilationUnit* cu, int helper_offset) +int Mir2Lir::CallHelperSetup(int helper_offset) { - return (cu->instruction_set == kX86) ? 0 : LoadHelper(cu, helper_offset); + return (cu_->instruction_set == kX86) ? 0 : LoadHelper(helper_offset); } /* NOTE: if r_tgt is a temp, it will be freed following use */ -LIR* Codegen::CallHelper(CompilationUnit* cu, int r_tgt, int helper_offset, bool safepoint_pc) +LIR* Mir2Lir::CallHelper(int r_tgt, int helper_offset, bool safepoint_pc) { LIR* call_inst; - if (cu->instruction_set == kX86) { - call_inst = OpThreadMem(cu, kOpBlx, helper_offset); + if (cu_->instruction_set == kX86) { + call_inst = OpThreadMem(kOpBlx, helper_offset); } else { - call_inst = OpReg(cu, kOpBlx, r_tgt); - FreeTemp(cu, r_tgt); + call_inst = OpReg(kOpBlx, r_tgt); + FreeTemp(r_tgt); } if (safepoint_pc) { - MarkSafepointPC(cu, call_inst); + MarkSafepointPC(call_inst); } return call_inst; } -void Codegen::CallRuntimeHelperImm(CompilationUnit* cu, int helper_offset, int arg0, - bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - LoadConstant(cu, TargetReg(kArg0), arg0); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); +void Mir2Lir::CallRuntimeHelperImm(int helper_offset, int arg0, bool safepoint_pc) { + int r_tgt = CallHelperSetup(helper_offset); + LoadConstant(TargetReg(kArg0), arg0); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperReg(CompilationUnit* cu, int helper_offset, int arg0, - bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - OpRegCopy(cu, TargetReg(kArg0), arg0); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); +void Mir2Lir::CallRuntimeHelperReg(int helper_offset, int arg0, bool safepoint_pc) { + int r_tgt = CallHelperSetup(helper_offset); + OpRegCopy(TargetReg(kArg0), arg0); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperRegLocation(CompilationUnit* cu, int helper_offset, RegLocation arg0, - bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); +void Mir2Lir::CallRuntimeHelperRegLocation(int helper_offset, RegLocation arg0, bool safepoint_pc) { + int r_tgt = CallHelperSetup(helper_offset); if (arg0.wide == 0) { - LoadValueDirectFixed(cu, arg0, TargetReg(kArg0)); + LoadValueDirectFixed(arg0, TargetReg(kArg0)); } else { - LoadValueDirectWideFixed(cu, arg0, TargetReg(kArg0), TargetReg(kArg1)); + LoadValueDirectWideFixed(arg0, TargetReg(kArg0), TargetReg(kArg1)); } - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperImmImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1, +void Mir2Lir::CallRuntimeHelperImmImm(int helper_offset, int arg0, int arg1, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - LoadConstant(cu, TargetReg(kArg0), arg0); - LoadConstant(cu, TargetReg(kArg1), arg1); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + int r_tgt = CallHelperSetup(helper_offset); + LoadConstant(TargetReg(kArg0), arg0); + LoadConstant(TargetReg(kArg1), arg1); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperImmRegLocation(CompilationUnit* cu, int helper_offset, int arg0, +void Mir2Lir::CallRuntimeHelperImmRegLocation(int helper_offset, int arg0, RegLocation arg1, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); + int r_tgt = CallHelperSetup(helper_offset); if (arg1.wide == 0) { - LoadValueDirectFixed(cu, arg1, TargetReg(kArg1)); + LoadValueDirectFixed(arg1, TargetReg(kArg1)); } else { - LoadValueDirectWideFixed(cu, arg1, TargetReg(kArg1), TargetReg(kArg2)); + LoadValueDirectWideFixed(arg1, TargetReg(kArg1), TargetReg(kArg2)); } - LoadConstant(cu, TargetReg(kArg0), arg0); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + LoadConstant(TargetReg(kArg0), arg0); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperRegLocationImm(CompilationUnit* cu, int helper_offset, - RegLocation arg0, int arg1, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - LoadValueDirectFixed(cu, arg0, TargetReg(kArg0)); - LoadConstant(cu, TargetReg(kArg1), arg1); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); +void Mir2Lir::CallRuntimeHelperRegLocationImm(int helper_offset, RegLocation arg0, int arg1, + bool safepoint_pc) { + int r_tgt = CallHelperSetup(helper_offset); + LoadValueDirectFixed(arg0, TargetReg(kArg0)); + LoadConstant(TargetReg(kArg1), arg1); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperImmReg(CompilationUnit* cu, int helper_offset, int arg0, int arg1, +void Mir2Lir::CallRuntimeHelperImmReg(int helper_offset, int arg0, int arg1, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - OpRegCopy(cu, TargetReg(kArg1), arg1); - LoadConstant(cu, TargetReg(kArg0), arg0); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + int r_tgt = CallHelperSetup(helper_offset); + OpRegCopy(TargetReg(kArg1), arg1); + LoadConstant(TargetReg(kArg0), arg0); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperRegImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1, +void Mir2Lir::CallRuntimeHelperRegImm(int helper_offset, int arg0, int arg1, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - OpRegCopy(cu, TargetReg(kArg0), arg0); - LoadConstant(cu, TargetReg(kArg1), arg1); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + int r_tgt = CallHelperSetup(helper_offset); + OpRegCopy(TargetReg(kArg0), arg0); + LoadConstant(TargetReg(kArg1), arg1); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperImmMethod(CompilationUnit* cu, int helper_offset, int arg0, - bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - LoadCurrMethodDirect(cu, TargetReg(kArg1)); - LoadConstant(cu, TargetReg(kArg0), arg0); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); +void Mir2Lir::CallRuntimeHelperImmMethod(int helper_offset, int arg0, bool safepoint_pc) { + int r_tgt = CallHelperSetup(helper_offset); + LoadCurrMethodDirect(TargetReg(kArg1)); + LoadConstant(TargetReg(kArg0), arg0); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperRegLocationRegLocation(CompilationUnit* cu, int helper_offset, - RegLocation arg0, RegLocation arg1, - bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); +void Mir2Lir::CallRuntimeHelperRegLocationRegLocation(int helper_offset, RegLocation arg0, + RegLocation arg1, bool safepoint_pc) { + int r_tgt = CallHelperSetup(helper_offset); if (arg0.wide == 0) { - LoadValueDirectFixed(cu, arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0)); + LoadValueDirectFixed(arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0)); if (arg1.wide == 0) { - if (cu->instruction_set == kMips) { - LoadValueDirectFixed(cu, arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg1)); + if (cu_->instruction_set == kMips) { + LoadValueDirectFixed(arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg1)); } else { - LoadValueDirectFixed(cu, arg1, TargetReg(kArg1)); + LoadValueDirectFixed(arg1, TargetReg(kArg1)); } } else { - if (cu->instruction_set == kMips) { - LoadValueDirectWideFixed(cu, arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg1), arg1.fp ? TargetReg(kFArg3) : TargetReg(kArg2)); + if (cu_->instruction_set == kMips) { + LoadValueDirectWideFixed(arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg1), arg1.fp ? TargetReg(kFArg3) : TargetReg(kArg2)); } else { - LoadValueDirectWideFixed(cu, arg1, TargetReg(kArg1), TargetReg(kArg2)); + LoadValueDirectWideFixed(arg1, TargetReg(kArg1), TargetReg(kArg2)); } } } else { - LoadValueDirectWideFixed(cu, arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0), arg0.fp ? TargetReg(kFArg1) : TargetReg(kArg1)); + LoadValueDirectWideFixed(arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0), arg0.fp ? TargetReg(kFArg1) : TargetReg(kArg1)); if (arg1.wide == 0) { - LoadValueDirectFixed(cu, arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg2)); + LoadValueDirectFixed(arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg2)); } else { - LoadValueDirectWideFixed(cu, arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg2), arg1.fp ? TargetReg(kFArg3) : TargetReg(kArg3)); + LoadValueDirectWideFixed(arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg2), arg1.fp ? TargetReg(kFArg3) : TargetReg(kArg3)); } } - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperRegReg(CompilationUnit* cu, int helper_offset, int arg0, int arg1, - bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); +void Mir2Lir::CallRuntimeHelperRegReg(int helper_offset, int arg0, int arg1, bool safepoint_pc) { + int r_tgt = CallHelperSetup(helper_offset); DCHECK_NE(TargetReg(kArg0), arg1); // check copy into arg0 won't clobber arg1 - OpRegCopy(cu, TargetReg(kArg0), arg0); - OpRegCopy(cu, TargetReg(kArg1), arg1); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + OpRegCopy(TargetReg(kArg0), arg0); + OpRegCopy(TargetReg(kArg1), arg1); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperRegRegImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1, +void Mir2Lir::CallRuntimeHelperRegRegImm(int helper_offset, int arg0, int arg1, int arg2, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); + int r_tgt = CallHelperSetup(helper_offset); DCHECK_NE(TargetReg(kArg0), arg1); // check copy into arg0 won't clobber arg1 - OpRegCopy(cu, TargetReg(kArg0), arg0); - OpRegCopy(cu, TargetReg(kArg1), arg1); - LoadConstant(cu, TargetReg(kArg2), arg2); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + OpRegCopy(TargetReg(kArg0), arg0); + OpRegCopy(TargetReg(kArg1), arg1); + LoadConstant(TargetReg(kArg2), arg2); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperImmMethodRegLocation(CompilationUnit* cu, int helper_offset, +void Mir2Lir::CallRuntimeHelperImmMethodRegLocation(int helper_offset, int arg0, RegLocation arg2, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - LoadValueDirectFixed(cu, arg2, TargetReg(kArg2)); - LoadCurrMethodDirect(cu, TargetReg(kArg1)); - LoadConstant(cu, TargetReg(kArg0), arg0); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + int r_tgt = CallHelperSetup(helper_offset); + LoadValueDirectFixed(arg2, TargetReg(kArg2)); + LoadCurrMethodDirect(TargetReg(kArg1)); + LoadConstant(TargetReg(kArg0), arg0); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperImmMethodImm(CompilationUnit* cu, int helper_offset, int arg0, +void Mir2Lir::CallRuntimeHelperImmMethodImm(int helper_offset, int arg0, int arg2, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - LoadCurrMethodDirect(cu, TargetReg(kArg1)); - LoadConstant(cu, TargetReg(kArg2), arg2); - LoadConstant(cu, TargetReg(kArg0), arg0); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + int r_tgt = CallHelperSetup(helper_offset); + LoadCurrMethodDirect(TargetReg(kArg1)); + LoadConstant(TargetReg(kArg2), arg2); + LoadConstant(TargetReg(kArg0), arg0); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } -void Codegen::CallRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cu, int helper_offset, +void Mir2Lir::CallRuntimeHelperImmRegLocationRegLocation(int helper_offset, int arg0, RegLocation arg1, RegLocation arg2, bool safepoint_pc) { - int r_tgt = CallHelperSetup(cu, helper_offset); - LoadValueDirectFixed(cu, arg1, TargetReg(kArg1)); + int r_tgt = CallHelperSetup(helper_offset); + LoadValueDirectFixed(arg1, TargetReg(kArg1)); if (arg2.wide == 0) { - LoadValueDirectFixed(cu, arg2, TargetReg(kArg2)); + LoadValueDirectFixed(arg2, TargetReg(kArg2)); } else { - LoadValueDirectWideFixed(cu, arg2, TargetReg(kArg2), TargetReg(kArg3)); + LoadValueDirectWideFixed(arg2, TargetReg(kArg2), TargetReg(kArg3)); } - LoadConstant(cu, TargetReg(kArg0), arg0); - ClobberCalleeSave(cu); - CallHelper(cu, r_tgt, helper_offset, safepoint_pc); + LoadConstant(TargetReg(kArg0), arg0); + ClobberCalleeSave(); + CallHelper(r_tgt, helper_offset, safepoint_pc); } /* @@ -237,7 +229,7 @@ void Codegen::CallRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cu, in * ArgLocs is an array of location records describing the incoming arguments * with one location record per word of argument. */ -void Codegen::FlushIns(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl_method) +void Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { /* * Dummy up a RegLocation for the incoming Method* @@ -248,18 +240,18 @@ void Codegen::FlushIns(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl rl_src.location = kLocPhysReg; rl_src.low_reg = TargetReg(kArg0); rl_src.home = false; - MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low); - StoreValue(cu, rl_method, rl_src); + MarkLive(rl_src.low_reg, rl_src.s_reg_low); + StoreValue(rl_method, rl_src); // If Method* has been promoted, explicitly flush if (rl_method.location == kLocPhysReg) { - StoreWordDisp(cu, TargetReg(kSp), 0, TargetReg(kArg0)); + StoreWordDisp(TargetReg(kSp), 0, TargetReg(kArg0)); } - if (cu->num_ins == 0) + if (cu_->num_ins == 0) return; const int num_arg_regs = 3; static SpecialTargetRegister arg_regs[] = {kArg1, kArg2, kArg3}; - int start_vreg = cu->num_dalvik_registers - cu->num_ins; + int start_vreg = cu_->num_dalvik_registers - cu_->num_ins; /* * Copy incoming arguments to their proper home locations. * NOTE: an older version of dx had an issue in which @@ -272,17 +264,17 @@ void Codegen::FlushIns(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl * end up half-promoted. In those cases, we must flush the promoted * half to memory as well. */ - for (int i = 0; i < cu->num_ins; i++) { - PromotionMap* v_map = &cu->promotion_map[start_vreg + i]; + for (int i = 0; i < cu_->num_ins; i++) { + PromotionMap* v_map = &promotion_map_[start_vreg + i]; if (i < num_arg_regs) { // If arriving in register bool need_flush = true; RegLocation* t_loc = &ArgLocs[i]; if ((v_map->core_location == kLocPhysReg) && !t_loc->fp) { - OpRegCopy(cu, v_map->core_reg, TargetReg(arg_regs[i])); + OpRegCopy(v_map->core_reg, TargetReg(arg_regs[i])); need_flush = false; } else if ((v_map->fp_location == kLocPhysReg) && t_loc->fp) { - OpRegCopy(cu, v_map->FpReg, TargetReg(arg_regs[i])); + OpRegCopy(v_map->FpReg, TargetReg(arg_regs[i])); need_flush = false; } else { need_flush = true; @@ -295,17 +287,17 @@ void Codegen::FlushIns(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl (p_map->fp_location != v_map->fp_location); } if (need_flush) { - StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, start_vreg + i), + StoreBaseDisp(TargetReg(kSp), SRegOffset(start_vreg + i), TargetReg(arg_regs[i]), kWord); } } else { // If arriving in frame & promoted if (v_map->core_location == kLocPhysReg) { - LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, start_vreg + i), + LoadWordDisp(TargetReg(kSp), SRegOffset(start_vreg + i), v_map->core_reg); } if (v_map->fp_location == kLocPhysReg) { - LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, start_vreg + i), + LoadWordDisp(TargetReg(kSp), SRegOffset(start_vreg + i), v_map->FpReg); } } @@ -321,7 +313,7 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info, uintptr_t direct_code, uintptr_t direct_method, InvokeType type) { - Codegen* cg = cu->cg.get(); + Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get()); if (cu->instruction_set != kThumb2) { // Disable sharpening direct_code = 0; @@ -331,27 +323,27 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info, switch (state) { case 0: // Get the current Method* [sets kArg0] if (direct_code != static_cast<unsigned int>(-1)) { - cg->LoadConstant(cu, cg->TargetReg(kInvokeTgt), direct_code); + cg->LoadConstant(cg->TargetReg(kInvokeTgt), direct_code); } else { - LIR* data_target = ScanLiteralPool(cu->code_literal_list, dex_idx, 0); + LIR* data_target = cg->ScanLiteralPool(cg->code_literal_list_, dex_idx, 0); if (data_target == NULL) { - data_target = AddWordData(cu, &cu->code_literal_list, dex_idx); + data_target = cg->AddWordData(&cg->code_literal_list_, dex_idx); data_target->operands[1] = type; } - LIR* load_pc_rel = cg->OpPcRelLoad(cu, cg->TargetReg(kInvokeTgt), data_target); - AppendLIR(cu, load_pc_rel); + LIR* load_pc_rel = cg->OpPcRelLoad(cg->TargetReg(kInvokeTgt), data_target); + cg->AppendLIR(load_pc_rel); DCHECK_EQ(cu->instruction_set, kThumb2) << reinterpret_cast<void*>(data_target); } if (direct_method != static_cast<unsigned int>(-1)) { - cg->LoadConstant(cu, cg->TargetReg(kArg0), direct_method); + cg->LoadConstant(cg->TargetReg(kArg0), direct_method); } else { - LIR* data_target = ScanLiteralPool(cu->method_literal_list, dex_idx, 0); + LIR* data_target = cg->ScanLiteralPool(cg->method_literal_list_, dex_idx, 0); if (data_target == NULL) { - data_target = AddWordData(cu, &cu->method_literal_list, dex_idx); + data_target = cg->AddWordData(&cg->method_literal_list_, dex_idx); data_target->operands[1] = type; } - LIR* load_pc_rel = cg->OpPcRelLoad(cu, cg->TargetReg(kArg0), data_target); - AppendLIR(cu, load_pc_rel); + LIR* load_pc_rel = cg->OpPcRelLoad(cg->TargetReg(kArg0), data_target); + cg->AppendLIR(load_pc_rel); DCHECK_EQ(cu->instruction_set, kThumb2) << reinterpret_cast<void*>(data_target); } break; @@ -362,36 +354,36 @@ static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info, switch (state) { case 0: // Get the current Method* [sets kArg0] // TUNING: we can save a reg copy if Method* has been promoted. - cg->LoadCurrMethodDirect(cu, cg->TargetReg(kArg0)); + cg->LoadCurrMethodDirect(cg->TargetReg(kArg0)); break; case 1: // Get method->dex_cache_resolved_methods_ - cg->LoadWordDisp(cu, cg->TargetReg(kArg0), + cg->LoadWordDisp(cg->TargetReg(kArg0), mirror::AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0)); // Set up direct code if known. if (direct_code != 0) { if (direct_code != static_cast<unsigned int>(-1)) { - cg->LoadConstant(cu, cg->TargetReg(kInvokeTgt), direct_code); + cg->LoadConstant(cg->TargetReg(kInvokeTgt), direct_code); } else { - LIR* data_target = ScanLiteralPool(cu->code_literal_list, dex_idx, 0); + LIR* data_target = cg->ScanLiteralPool(cg->code_literal_list_, dex_idx, 0); if (data_target == NULL) { - data_target = AddWordData(cu, &cu->code_literal_list, dex_idx); + data_target = cg->AddWordData(&cg->code_literal_list_, dex_idx); data_target->operands[1] = type; } - LIR* load_pc_rel = cg->OpPcRelLoad(cu, cg->TargetReg(kInvokeTgt), data_target); - AppendLIR(cu, load_pc_rel); + LIR* load_pc_rel = cg->OpPcRelLoad(cg->TargetReg(kInvokeTgt), data_target); + cg->AppendLIR(load_pc_rel); DCHECK_EQ(cu->instruction_set, kThumb2) << reinterpret_cast<void*>(data_target); } } break; case 2: // Grab target method* - cg->LoadWordDisp(cu, cg->TargetReg(kArg0), + cg->LoadWordDisp(cg->TargetReg(kArg0), mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + dex_idx * 4, cg-> TargetReg(kArg0)); break; case 3: // Grab the code from the method* if (cu->instruction_set != kX86) { if (direct_code == 0) { - cg->LoadWordDisp(cu, cg->TargetReg(kArg0), + cg->LoadWordDisp(cg->TargetReg(kArg0), mirror::AbstractMethod::GetCodeOffset().Int32Value(), cg->TargetReg(kInvokeTgt)); } @@ -416,7 +408,7 @@ static int NextVCallInsn(CompilationUnit* cu, CallInfo* info, int state, uint32_t dex_idx, uint32_t method_idx, uintptr_t unused, uintptr_t unused2, InvokeType unused3) { - Codegen* cg = cu->cg.get(); + Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get()); /* * This is the fast path in which the target virtual method is * fully resolved at compile time. @@ -424,27 +416,27 @@ static int NextVCallInsn(CompilationUnit* cu, CallInfo* info, switch (state) { case 0: { // Get "this" [set kArg1] RegLocation rl_arg = info->args[0]; - cg->LoadValueDirectFixed(cu, rl_arg, cg->TargetReg(kArg1)); + cg->LoadValueDirectFixed(rl_arg, cg->TargetReg(kArg1)); break; } case 1: // Is "this" null? [use kArg1] - cg->GenNullCheck(cu, info->args[0].s_reg_low, cg->TargetReg(kArg1), info->opt_flags); + cg->GenNullCheck(info->args[0].s_reg_low, cg->TargetReg(kArg1), info->opt_flags); // get this->klass_ [use kArg1, set kInvokeTgt] - cg->LoadWordDisp(cu, cg->TargetReg(kArg1), mirror::Object::ClassOffset().Int32Value(), + cg->LoadWordDisp(cg->TargetReg(kArg1), mirror::Object::ClassOffset().Int32Value(), cg->TargetReg(kInvokeTgt)); break; case 2: // Get this->klass_->vtable [usr kInvokeTgt, set kInvokeTgt] - cg->LoadWordDisp(cu, cg->TargetReg(kInvokeTgt), mirror::Class::VTableOffset().Int32Value(), + cg->LoadWordDisp(cg->TargetReg(kInvokeTgt), mirror::Class::VTableOffset().Int32Value(), cg->TargetReg(kInvokeTgt)); break; case 3: // Get target method [use kInvokeTgt, set kArg0] - cg->LoadWordDisp(cu, cg->TargetReg(kInvokeTgt), (method_idx * 4) + + cg->LoadWordDisp(cg->TargetReg(kInvokeTgt), (method_idx * 4) + mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(), cg->TargetReg(kArg0)); break; case 4: // Get the compiled code address [uses kArg0, sets kInvokeTgt] if (cu->instruction_set != kX86) { - cg->LoadWordDisp(cu, cg->TargetReg(kArg0), + cg->LoadWordDisp(cg->TargetReg(kArg0), mirror::AbstractMethod::GetCodeOffset().Int32Value(), cg->TargetReg(kInvokeTgt)); break; @@ -464,7 +456,7 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state, uint32_t dex_idx, uint32_t unused, uintptr_t unused2, uintptr_t direct_method, InvokeType unused4) { - Codegen* cg = cu->cg.get(); + Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get()); if (cu->instruction_set != kThumb2) { // Disable sharpening direct_method = 0; @@ -476,19 +468,19 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state, switch (state) { case 0: // Load the trampoline target [sets kInvokeTgt]. if (cu->instruction_set != kX86) { - cg->LoadWordDisp(cu, cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt)); + cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt)); } // Get the interface Method* [sets kArg0] if (direct_method != static_cast<unsigned int>(-1)) { - cg->LoadConstant(cu, cg->TargetReg(kArg0), direct_method); + cg->LoadConstant(cg->TargetReg(kArg0), direct_method); } else { - LIR* data_target = ScanLiteralPool(cu->method_literal_list, dex_idx, 0); + LIR* data_target = cg->ScanLiteralPool(cg->method_literal_list_, dex_idx, 0); if (data_target == NULL) { - data_target = AddWordData(cu, &cu->method_literal_list, dex_idx); + data_target = cg->AddWordData(&cg->method_literal_list_, dex_idx); data_target->operands[1] = kInterface; } - LIR* load_pc_rel = cg->OpPcRelLoad(cu, cg->TargetReg(kArg0), data_target); - AppendLIR(cu, load_pc_rel); + LIR* load_pc_rel = cg->OpPcRelLoad(cg->TargetReg(kArg0), data_target); + cg->AppendLIR(load_pc_rel); DCHECK_EQ(cu->instruction_set, kThumb2) << reinterpret_cast<void*>(data_target); } break; @@ -499,19 +491,19 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state, switch (state) { case 0: // Get the current Method* [sets kArg0] - TUNING: remove copy of method if it is promoted. - cg->LoadCurrMethodDirect(cu, cg->TargetReg(kArg0)); + cg->LoadCurrMethodDirect(cg->TargetReg(kArg0)); // Load the trampoline target [sets kInvokeTgt]. if (cu->instruction_set != kX86) { - cg->LoadWordDisp(cu, cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt)); + cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt)); } break; case 1: // Get method->dex_cache_resolved_methods_ [set/use kArg0] - cg->LoadWordDisp(cu, cg->TargetReg(kArg0), + cg->LoadWordDisp(cg->TargetReg(kArg0), mirror::AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0)); break; case 2: // Grab target method* [set/use kArg0] - cg->LoadWordDisp(cu, cg->TargetReg(kArg0), + cg->LoadWordDisp(cg->TargetReg(kArg0), mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + dex_idx * 4, cg->TargetReg(kArg0)); break; @@ -525,7 +517,7 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state, static int NextInvokeInsnSP(CompilationUnit* cu, CallInfo* info, int trampoline, int state, uint32_t dex_idx, uint32_t method_idx) { - Codegen* cg = cu->cg.get(); + Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get()); /* * This handles the case in which the base method is not fully * resolved at compile time, we bail to a runtime helper. @@ -533,10 +525,10 @@ static int NextInvokeInsnSP(CompilationUnit* cu, CallInfo* info, int trampoline, if (state == 0) { if (cu->instruction_set != kX86) { // Load trampoline target - cg->LoadWordDisp(cu, cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt)); + cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt)); } // Load kArg0 with method index - cg->LoadConstant(cu, cg->TargetReg(kArg0), dex_idx); + cg->LoadConstant(cg->TargetReg(kArg0), dex_idx); return 1; } return -1; @@ -585,14 +577,13 @@ static int NextInterfaceCallInsnWithAccessCheck(CompilationUnit* cu, return NextInvokeInsnSP(cu, info, trampoline, state, dex_idx, 0); } -static int LoadArgRegs(CompilationUnit* cu, CallInfo* info, int call_state, - NextCallInsn next_call_insn, uint32_t dex_idx, - uint32_t method_idx, uintptr_t direct_code, - uintptr_t direct_method, InvokeType type, bool skip_this) +int Mir2Lir::LoadArgRegs(CallInfo* info, int call_state, + NextCallInsn next_call_insn, uint32_t dex_idx, + uint32_t method_idx, uintptr_t direct_code, + uintptr_t direct_method, InvokeType type, bool skip_this) { - Codegen* cg = cu->cg.get(); - int last_arg_reg = cg->TargetReg(kArg3); - int next_reg = cg->TargetReg(kArg1); + int last_arg_reg = TargetReg(kArg3); + int next_reg = TargetReg(kArg1); int next_arg = 0; if (skip_this) { next_reg++; @@ -600,9 +591,9 @@ static int LoadArgRegs(CompilationUnit* cu, CallInfo* info, int call_state, } for (; (next_reg <= last_arg_reg) && (next_arg < info->num_arg_words); next_reg++) { RegLocation rl_arg = info->args[next_arg++]; - rl_arg = UpdateRawLoc(cu, rl_arg); - if (rl_arg.wide && (next_reg <= cg->TargetReg(kArg2))) { - cg->LoadValueDirectWideFixed(cu, rl_arg, next_reg, next_reg + 1); + rl_arg = UpdateRawLoc(rl_arg); + if (rl_arg.wide && (next_reg <= TargetReg(kArg2))) { + LoadValueDirectWideFixed(rl_arg, next_reg, next_reg + 1); next_reg++; next_arg++; } else { @@ -610,9 +601,9 @@ static int LoadArgRegs(CompilationUnit* cu, CallInfo* info, int call_state, rl_arg.wide = false; rl_arg.is_const = false; } - cg->LoadValueDirectFixed(cu, rl_arg, next_reg); + LoadValueDirectFixed(rl_arg, next_reg); } - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); } return call_state; @@ -625,7 +616,7 @@ static int LoadArgRegs(CompilationUnit* cu, CallInfo* info, int call_state, * the target method pointer. Note, this may also be called * for "range" variants if the number of arguments is 5 or fewer. */ -int Codegen::GenDalvikArgsNoRange(CompilationUnit* cu, CallInfo* info, +int Mir2Lir::GenDalvikArgsNoRange(CallInfo* info, int call_state, LIR** pcrLabel, NextCallInsn next_call_insn, uint32_t dex_idx, uint32_t method_idx, uintptr_t direct_code, uintptr_t direct_method, InvokeType type, bool skip_this) @@ -636,7 +627,7 @@ int Codegen::GenDalvikArgsNoRange(CompilationUnit* cu, CallInfo* info, if (info->num_arg_words == 0) return call_state; - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); DCHECK_LE(info->num_arg_words, 5); @@ -650,19 +641,19 @@ int Codegen::GenDalvikArgsNoRange(CompilationUnit* cu, CallInfo* info, rl_use2.wide) { int reg = -1; // Wide spans, we need the 2nd half of uses[2]. - rl_arg = UpdateLocWide(cu, rl_use2); + rl_arg = UpdateLocWide(rl_use2); if (rl_arg.location == kLocPhysReg) { reg = rl_arg.high_reg; } else { // kArg2 & rArg3 can safely be used here reg = TargetReg(kArg3); - LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_arg.s_reg_low) + 4, reg); - call_state = next_call_insn(cu, info, call_state, dex_idx, + LoadWordDisp(TargetReg(kSp), SRegOffset(rl_arg.s_reg_low) + 4, reg); + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); } - StoreBaseDisp(cu, TargetReg(kSp), (next_use + 1) * 4, reg, kWord); - StoreBaseDisp(cu, TargetReg(kSp), 16 /* (3+1)*4 */, reg, kWord); - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + StoreBaseDisp(TargetReg(kSp), (next_use + 1) * 4, reg, kWord); + StoreBaseDisp(TargetReg(kSp), 16 /* (3+1)*4 */, reg, kWord); + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); next_use++; } @@ -671,7 +662,7 @@ int Codegen::GenDalvikArgsNoRange(CompilationUnit* cu, CallInfo* info, int low_reg; int high_reg = -1; rl_arg = info->args[next_use]; - rl_arg = UpdateRawLoc(cu, rl_arg); + rl_arg = UpdateRawLoc(rl_arg); if (rl_arg.location == kLocPhysReg) { low_reg = rl_arg.low_reg; high_reg = rl_arg.high_reg; @@ -679,32 +670,32 @@ int Codegen::GenDalvikArgsNoRange(CompilationUnit* cu, CallInfo* info, low_reg = TargetReg(kArg2); if (rl_arg.wide) { high_reg = TargetReg(kArg3); - LoadValueDirectWideFixed(cu, rl_arg, low_reg, high_reg); + LoadValueDirectWideFixed(rl_arg, low_reg, high_reg); } else { - LoadValueDirectFixed(cu, rl_arg, low_reg); + LoadValueDirectFixed(rl_arg, low_reg); } - call_state = next_call_insn(cu, info, call_state, dex_idx, + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); } int outs_offset = (next_use + 1) * 4; if (rl_arg.wide) { - StoreBaseDispWide(cu, TargetReg(kSp), outs_offset, low_reg, high_reg); + StoreBaseDispWide(TargetReg(kSp), outs_offset, low_reg, high_reg); next_use += 2; } else { - StoreWordDisp(cu, TargetReg(kSp), outs_offset, low_reg); + StoreWordDisp(TargetReg(kSp), outs_offset, low_reg); next_use++; } - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); } } - call_state = LoadArgRegs(cu, info, call_state, next_call_insn, + call_state = LoadArgRegs(info, call_state, next_call_insn, dex_idx, method_idx, direct_code, direct_method, type, skip_this); if (pcrLabel) { - *pcrLabel = GenNullCheck(cu, info->args[0].s_reg_low, TargetReg(kArg1), info->opt_flags); + *pcrLabel = GenNullCheck(info->args[0].s_reg_low, TargetReg(kArg1), info->opt_flags); } return call_state; } @@ -724,7 +715,7 @@ int Codegen::GenDalvikArgsNoRange(CompilationUnit* cu, CallInfo* info, * Pass arg0, arg1 & arg2 in kArg1-kArg3 * */ -int Codegen::GenDalvikArgsRange(CompilationUnit* cu, CallInfo* info, int call_state, +int Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state, LIR** pcrLabel, NextCallInsn next_call_insn, uint32_t dex_idx, uint32_t method_idx, uintptr_t direct_code, uintptr_t direct_method, InvokeType type, bool skip_this) @@ -732,7 +723,7 @@ int Codegen::GenDalvikArgsRange(CompilationUnit* cu, CallInfo* info, int call_st // If we can treat it as non-range (Jumbo ops will use range form) if (info->num_arg_words <= 5) - return GenDalvikArgsNoRange(cu, info, call_state, pcrLabel, + return GenDalvikArgsNoRange(info, call_state, pcrLabel, next_call_insn, dex_idx, method_idx, direct_code, direct_method, type, skip_this); /* @@ -745,98 +736,97 @@ int Codegen::GenDalvikArgsRange(CompilationUnit* cu, CallInfo* info, int call_st for (int next_arg = 0; next_arg < info->num_arg_words;) { RegLocation loc = info->args[next_arg]; if (loc.wide) { - loc = UpdateLocWide(cu, loc); + loc = UpdateLocWide(loc); if ((next_arg >= 2) && (loc.location == kLocPhysReg)) { - StoreBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, loc.s_reg_low), + StoreBaseDispWide(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.low_reg, loc.high_reg); } next_arg += 2; } else { - loc = UpdateLoc(cu, loc); + loc = UpdateLoc(loc); if ((next_arg >= 3) && (loc.location == kLocPhysReg)) { - StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, loc.s_reg_low), + StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.low_reg, kWord); } next_arg++; } } - int start_offset = SRegOffset(cu, info->args[3].s_reg_low); + int start_offset = SRegOffset(info->args[3].s_reg_low); int outs_offset = 4 /* Method* */ + (3 * 4); - if (cu->instruction_set != kThumb2) { + if (cu_->instruction_set != kThumb2) { // Generate memcpy - OpRegRegImm(cu, kOpAdd, TargetReg(kArg0), TargetReg(kSp), outs_offset); - OpRegRegImm(cu, kOpAdd, TargetReg(kArg1), TargetReg(kSp), start_offset); - CallRuntimeHelperRegRegImm(cu, ENTRYPOINT_OFFSET(pMemcpy), TargetReg(kArg0), + OpRegRegImm(kOpAdd, TargetReg(kArg0), TargetReg(kSp), outs_offset); + OpRegRegImm(kOpAdd, TargetReg(kArg1), TargetReg(kSp), start_offset); + CallRuntimeHelperRegRegImm(ENTRYPOINT_OFFSET(pMemcpy), TargetReg(kArg0), TargetReg(kArg1), (info->num_arg_words - 3) * 4, false); } else { if (info->num_arg_words >= 20) { // Generate memcpy - OpRegRegImm(cu, kOpAdd, TargetReg(kArg0), TargetReg(kSp), outs_offset); - OpRegRegImm(cu, kOpAdd, TargetReg(kArg1), TargetReg(kSp), start_offset); - CallRuntimeHelperRegRegImm(cu, ENTRYPOINT_OFFSET(pMemcpy), TargetReg(kArg0), + OpRegRegImm(kOpAdd, TargetReg(kArg0), TargetReg(kSp), outs_offset); + OpRegRegImm(kOpAdd, TargetReg(kArg1), TargetReg(kSp), start_offset); + CallRuntimeHelperRegRegImm(ENTRYPOINT_OFFSET(pMemcpy), TargetReg(kArg0), TargetReg(kArg1), (info->num_arg_words - 3) * 4, false); } else { // Use vldm/vstm pair using kArg3 as a temp int regs_left = std::min(info->num_arg_words - 3, 16); - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); - OpRegRegImm(cu, kOpAdd, TargetReg(kArg3), TargetReg(kSp), start_offset); - LIR* ld = OpVldm(cu, TargetReg(kArg3), regs_left); + OpRegRegImm(kOpAdd, TargetReg(kArg3), TargetReg(kSp), start_offset); + LIR* ld = OpVldm(TargetReg(kArg3), regs_left); //TUNING: loosen barrier ld->def_mask = ENCODE_ALL; - SetMemRefType(cu, ld, true /* is_load */, kDalvikReg); - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + SetMemRefType(ld, true /* is_load */, kDalvikReg); + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); - OpRegRegImm(cu, kOpAdd, TargetReg(kArg3), TargetReg(kSp), 4 /* Method* */ + (3 * 4)); - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + OpRegRegImm(kOpAdd, TargetReg(kArg3), TargetReg(kSp), 4 /* Method* */ + (3 * 4)); + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); - LIR* st = OpVstm(cu, TargetReg(kArg3), regs_left); - SetMemRefType(cu, st, false /* is_load */, kDalvikReg); + LIR* st = OpVstm(TargetReg(kArg3), regs_left); + SetMemRefType(st, false /* is_load */, kDalvikReg); st->def_mask = ENCODE_ALL; - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); } } - call_state = LoadArgRegs(cu, info, call_state, next_call_insn, + call_state = LoadArgRegs(info, call_state, next_call_insn, dex_idx, method_idx, direct_code, direct_method, type, skip_this); - call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx, + call_state = next_call_insn(cu_, info, call_state, dex_idx, method_idx, direct_code, direct_method, type); if (pcrLabel) { - *pcrLabel = GenNullCheck(cu, info->args[0].s_reg_low, TargetReg(kArg1), - info->opt_flags); + *pcrLabel = GenNullCheck(info->args[0].s_reg_low, TargetReg(kArg1), info->opt_flags); } return call_state; } -RegLocation Codegen::InlineTarget(CompilationUnit* cu, CallInfo* info) +RegLocation Mir2Lir::InlineTarget(CallInfo* info) { RegLocation res; if (info->result.location == kLocInvalid) { - res = GetReturn(cu, false); + res = GetReturn(false); } else { res = info->result; } return res; } -RegLocation Codegen::InlineTargetWide(CompilationUnit* cu, CallInfo* info) +RegLocation Mir2Lir::InlineTargetWide(CallInfo* info) { RegLocation res; if (info->result.location == kLocInvalid) { - res = GetReturnWide(cu, false); + res = GetReturnWide(false); } else { res = info->result; } return res; } -bool Codegen::GenInlinedCharAt(CompilationUnit* cu, CallInfo* info) +bool Mir2Lir::GenInlinedCharAt(CallInfo* info) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } @@ -851,59 +841,59 @@ bool Codegen::GenInlinedCharAt(CompilationUnit* cu, CallInfo* info) RegLocation rl_obj = info->args[0]; RegLocation rl_idx = info->args[1]; - rl_obj = LoadValue(cu, rl_obj, kCoreReg); - rl_idx = LoadValue(cu, rl_idx, kCoreReg); + rl_obj = LoadValue(rl_obj, kCoreReg); + rl_idx = LoadValue(rl_idx, kCoreReg); int reg_max; - GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, info->opt_flags); + GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, info->opt_flags); bool range_check = (!(info->opt_flags & MIR_IGNORE_RANGE_CHECK)); LIR* launch_pad = NULL; int reg_off = INVALID_REG; int reg_ptr = INVALID_REG; - if (cu->instruction_set != kX86) { - reg_off = AllocTemp(cu); - reg_ptr = AllocTemp(cu); + if (cu_->instruction_set != kX86) { + reg_off = AllocTemp(); + reg_ptr = AllocTemp(); if (range_check) { - reg_max = AllocTemp(cu); - LoadWordDisp(cu, rl_obj.low_reg, count_offset, reg_max); + reg_max = AllocTemp(); + LoadWordDisp(rl_obj.low_reg, count_offset, reg_max); } - LoadWordDisp(cu, rl_obj.low_reg, offset_offset, reg_off); - LoadWordDisp(cu, rl_obj.low_reg, value_offset, reg_ptr); + LoadWordDisp(rl_obj.low_reg, offset_offset, reg_off); + LoadWordDisp(rl_obj.low_reg, value_offset, reg_ptr); if (range_check) { // Set up a launch pad to allow retry in case of bounds violation */ - launch_pad = RawLIR(cu, 0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info)); - InsertGrowableList(cu, &cu->intrinsic_launchpads, + launch_pad = RawLIR(0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info)); + InsertGrowableList(cu_, &intrinsic_launchpads_, reinterpret_cast<uintptr_t>(launch_pad)); - OpRegReg(cu, kOpCmp, rl_idx.low_reg, reg_max); - FreeTemp(cu, reg_max); - OpCondBranch(cu, kCondCs, launch_pad); + OpRegReg(kOpCmp, rl_idx.low_reg, reg_max); + FreeTemp(reg_max); + OpCondBranch(kCondCs, launch_pad); } } else { if (range_check) { - reg_max = AllocTemp(cu); - LoadWordDisp(cu, rl_obj.low_reg, count_offset, reg_max); + reg_max = AllocTemp(); + LoadWordDisp(rl_obj.low_reg, count_offset, reg_max); // Set up a launch pad to allow retry in case of bounds violation */ - launch_pad = RawLIR(cu, 0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info)); - InsertGrowableList(cu, &cu->intrinsic_launchpads, + launch_pad = RawLIR(0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info)); + InsertGrowableList(cu_, &intrinsic_launchpads_, reinterpret_cast<uintptr_t>(launch_pad)); - OpRegReg(cu, kOpCmp, rl_idx.low_reg, reg_max); - FreeTemp(cu, reg_max); - OpCondBranch(cu, kCondCc, launch_pad); + OpRegReg(kOpCmp, rl_idx.low_reg, reg_max); + FreeTemp(reg_max); + OpCondBranch(kCondCc, launch_pad); } - reg_off = AllocTemp(cu); - reg_ptr = AllocTemp(cu); - LoadWordDisp(cu, rl_obj.low_reg, offset_offset, reg_off); - LoadWordDisp(cu, rl_obj.low_reg, value_offset, reg_ptr); + reg_off = AllocTemp(); + reg_ptr = AllocTemp(); + LoadWordDisp(rl_obj.low_reg, offset_offset, reg_off); + LoadWordDisp(rl_obj.low_reg, value_offset, reg_ptr); } - OpRegImm(cu, kOpAdd, reg_ptr, data_offset); - OpRegReg(cu, kOpAdd, reg_off, rl_idx.low_reg); - FreeTemp(cu, rl_obj.low_reg); - FreeTemp(cu, rl_idx.low_reg); - RegLocation rl_dest = InlineTarget(cu, info); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - LoadBaseIndexed(cu, reg_ptr, reg_off, rl_result.low_reg, 1, kUnsignedHalf); - FreeTemp(cu, reg_off); - FreeTemp(cu, reg_ptr); - StoreValue(cu, rl_dest, rl_result); + OpRegImm(kOpAdd, reg_ptr, data_offset); + OpRegReg(kOpAdd, reg_off, rl_idx.low_reg); + FreeTemp(rl_obj.low_reg); + FreeTemp(rl_idx.low_reg); + RegLocation rl_dest = InlineTarget(info); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + LoadBaseIndexed(reg_ptr, reg_off, rl_result.low_reg, 1, kUnsignedHalf); + FreeTemp(reg_off); + FreeTemp(reg_ptr); + StoreValue(rl_dest, rl_result); if (range_check) { launch_pad->operands[2] = 0; // no resumption } @@ -913,118 +903,117 @@ bool Codegen::GenInlinedCharAt(CompilationUnit* cu, CallInfo* info) } // Generates an inlined String.is_empty or String.length. -bool Codegen::GenInlinedStringIsEmptyOrLength(CompilationUnit* cu, CallInfo* info, bool is_empty) +bool Mir2Lir::GenInlinedStringIsEmptyOrLength(CallInfo* info, bool is_empty) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } // dst = src.length(); RegLocation rl_obj = info->args[0]; - rl_obj = LoadValue(cu, rl_obj, kCoreReg); - RegLocation rl_dest = InlineTarget(cu, info); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, info->opt_flags); - LoadWordDisp(cu, rl_obj.low_reg, mirror::String::CountOffset().Int32Value(), - rl_result.low_reg); + rl_obj = LoadValue(rl_obj, kCoreReg); + RegLocation rl_dest = InlineTarget(info); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, info->opt_flags); + LoadWordDisp(rl_obj.low_reg, mirror::String::CountOffset().Int32Value(), rl_result.low_reg); if (is_empty) { // dst = (dst == 0); - if (cu->instruction_set == kThumb2) { - int t_reg = AllocTemp(cu); - OpRegReg(cu, kOpNeg, t_reg, rl_result.low_reg); - OpRegRegReg(cu, kOpAdc, rl_result.low_reg, rl_result.low_reg, t_reg); + if (cu_->instruction_set == kThumb2) { + int t_reg = AllocTemp(); + OpRegReg(kOpNeg, t_reg, rl_result.low_reg); + OpRegRegReg(kOpAdc, rl_result.low_reg, rl_result.low_reg, t_reg); } else { - DCHECK_EQ(cu->instruction_set, kX86); - OpRegImm(cu, kOpSub, rl_result.low_reg, 1); - OpRegImm(cu, kOpLsr, rl_result.low_reg, 31); + DCHECK_EQ(cu_->instruction_set, kX86); + OpRegImm(kOpSub, rl_result.low_reg, 1); + OpRegImm(kOpLsr, rl_result.low_reg, 31); } } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); return true; } -bool Codegen::GenInlinedAbsInt(CompilationUnit *cu, CallInfo* info) +bool Mir2Lir::GenInlinedAbsInt(CallInfo* info) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } RegLocation rl_src = info->args[0]; - rl_src = LoadValue(cu, rl_src, kCoreReg); - RegLocation rl_dest = InlineTarget(cu, info); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int sign_reg = AllocTemp(cu); + rl_src = LoadValue(rl_src, kCoreReg); + RegLocation rl_dest = InlineTarget(info); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + int sign_reg = AllocTemp(); // abs(x) = y<=x>>31, (x+y)^y. - OpRegRegImm(cu, kOpAsr, sign_reg, rl_src.low_reg, 31); - OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, sign_reg); - OpRegReg(cu, kOpXor, rl_result.low_reg, sign_reg); - StoreValue(cu, rl_dest, rl_result); + OpRegRegImm(kOpAsr, sign_reg, rl_src.low_reg, 31); + OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src.low_reg, sign_reg); + OpRegReg(kOpXor, rl_result.low_reg, sign_reg); + StoreValue(rl_dest, rl_result); return true; } -bool Codegen::GenInlinedAbsLong(CompilationUnit *cu, CallInfo* info) +bool Mir2Lir::GenInlinedAbsLong(CallInfo* info) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } - if (cu->instruction_set == kThumb2) { + if (cu_->instruction_set == kThumb2) { RegLocation rl_src = info->args[0]; - rl_src = LoadValueWide(cu, rl_src, kCoreReg); - RegLocation rl_dest = InlineTargetWide(cu, info); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int sign_reg = AllocTemp(cu); + rl_src = LoadValueWide(rl_src, kCoreReg); + RegLocation rl_dest = InlineTargetWide(info); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + int sign_reg = AllocTemp(); // abs(x) = y<=x>>31, (x+y)^y. - OpRegRegImm(cu, kOpAsr, sign_reg, rl_src.high_reg, 31); - OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, sign_reg); - OpRegRegReg(cu, kOpAdc, rl_result.high_reg, rl_src.high_reg, sign_reg); - OpRegReg(cu, kOpXor, rl_result.low_reg, sign_reg); - OpRegReg(cu, kOpXor, rl_result.high_reg, sign_reg); - StoreValueWide(cu, rl_dest, rl_result); + OpRegRegImm(kOpAsr, sign_reg, rl_src.high_reg, 31); + OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src.low_reg, sign_reg); + OpRegRegReg(kOpAdc, rl_result.high_reg, rl_src.high_reg, sign_reg); + OpRegReg(kOpXor, rl_result.low_reg, sign_reg); + OpRegReg(kOpXor, rl_result.high_reg, sign_reg); + StoreValueWide(rl_dest, rl_result); return true; } else { - DCHECK_EQ(cu->instruction_set, kX86); + DCHECK_EQ(cu_->instruction_set, kX86); // Reuse source registers to avoid running out of temps RegLocation rl_src = info->args[0]; - rl_src = LoadValueWide(cu, rl_src, kCoreReg); - RegLocation rl_dest = InlineTargetWide(cu, info); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegCopyWide(cu, rl_result.low_reg, rl_result.high_reg, rl_src.low_reg, rl_src.high_reg); - FreeTemp(cu, rl_src.low_reg); - FreeTemp(cu, rl_src.high_reg); - int sign_reg = AllocTemp(cu); + rl_src = LoadValueWide(rl_src, kCoreReg); + RegLocation rl_dest = InlineTargetWide(info); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegCopyWide(rl_result.low_reg, rl_result.high_reg, rl_src.low_reg, rl_src.high_reg); + FreeTemp(rl_src.low_reg); + FreeTemp(rl_src.high_reg); + int sign_reg = AllocTemp(); // abs(x) = y<=x>>31, (x+y)^y. - OpRegRegImm(cu, kOpAsr, sign_reg, rl_result.high_reg, 31); - OpRegReg(cu, kOpAdd, rl_result.low_reg, sign_reg); - OpRegReg(cu, kOpAdc, rl_result.high_reg, sign_reg); - OpRegReg(cu, kOpXor, rl_result.low_reg, sign_reg); - OpRegReg(cu, kOpXor, rl_result.high_reg, sign_reg); - StoreValueWide(cu, rl_dest, rl_result); + OpRegRegImm(kOpAsr, sign_reg, rl_result.high_reg, 31); + OpRegReg(kOpAdd, rl_result.low_reg, sign_reg); + OpRegReg(kOpAdc, rl_result.high_reg, sign_reg); + OpRegReg(kOpXor, rl_result.low_reg, sign_reg); + OpRegReg(kOpXor, rl_result.high_reg, sign_reg); + StoreValueWide(rl_dest, rl_result); return true; } } -bool Codegen::GenInlinedFloatCvt(CompilationUnit *cu, CallInfo* info) +bool Mir2Lir::GenInlinedFloatCvt(CallInfo* info) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } RegLocation rl_src = info->args[0]; - RegLocation rl_dest = InlineTarget(cu, info); - StoreValue(cu, rl_dest, rl_src); + RegLocation rl_dest = InlineTarget(info); + StoreValue(rl_dest, rl_src); return true; } -bool Codegen::GenInlinedDoubleCvt(CompilationUnit *cu, CallInfo* info) +bool Mir2Lir::GenInlinedDoubleCvt(CallInfo* info) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } RegLocation rl_src = info->args[0]; - RegLocation rl_dest = InlineTargetWide(cu, info); - StoreValueWide(cu, rl_dest, rl_src); + RegLocation rl_dest = InlineTargetWide(info); + StoreValueWide(rl_dest, rl_src); return true; } @@ -1032,14 +1021,14 @@ bool Codegen::GenInlinedDoubleCvt(CompilationUnit *cu, CallInfo* info) * Fast string.index_of(I) & (II). Tests for simple case of char <= 0xffff, * otherwise bails to standard library code. */ -bool Codegen::GenInlinedIndexOf(CompilationUnit* cu, CallInfo* info, bool zero_based) +bool Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } - ClobberCalleeSave(cu); - LockCallTemps(cu); // Using fixed registers + ClobberCalleeSave(); + LockCallTemps(); // Using fixed registers int reg_ptr = TargetReg(kArg0); int reg_char = TargetReg(kArg1); int reg_start = TargetReg(kArg2); @@ -1047,89 +1036,89 @@ bool Codegen::GenInlinedIndexOf(CompilationUnit* cu, CallInfo* info, bool zero_b RegLocation rl_obj = info->args[0]; RegLocation rl_char = info->args[1]; RegLocation rl_start = info->args[2]; - LoadValueDirectFixed(cu, rl_obj, reg_ptr); - LoadValueDirectFixed(cu, rl_char, reg_char); + LoadValueDirectFixed(rl_obj, reg_ptr); + LoadValueDirectFixed(rl_char, reg_char); if (zero_based) { - LoadConstant(cu, reg_start, 0); + LoadConstant(reg_start, 0); } else { - LoadValueDirectFixed(cu, rl_start, reg_start); + LoadValueDirectFixed(rl_start, reg_start); } - int r_tgt = (cu->instruction_set != kX86) ? LoadHelper(cu, ENTRYPOINT_OFFSET(pIndexOf)) : 0; - GenNullCheck(cu, rl_obj.s_reg_low, reg_ptr, info->opt_flags); - LIR* launch_pad = RawLIR(cu, 0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info)); - InsertGrowableList(cu, &cu->intrinsic_launchpads, reinterpret_cast<uintptr_t>(launch_pad)); - OpCmpImmBranch(cu, kCondGt, reg_char, 0xFFFF, launch_pad); + int r_tgt = (cu_->instruction_set != kX86) ? LoadHelper(ENTRYPOINT_OFFSET(pIndexOf)) : 0; + GenNullCheck(rl_obj.s_reg_low, reg_ptr, info->opt_flags); + LIR* launch_pad = RawLIR(0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info)); + InsertGrowableList(cu_, &intrinsic_launchpads_, reinterpret_cast<uintptr_t>(launch_pad)); + OpCmpImmBranch(kCondGt, reg_char, 0xFFFF, launch_pad); // NOTE: not a safepoint - if (cu->instruction_set != kX86) { - OpReg(cu, kOpBlx, r_tgt); + if (cu_->instruction_set != kX86) { + OpReg(kOpBlx, r_tgt); } else { - OpThreadMem(cu, kOpBlx, ENTRYPOINT_OFFSET(pIndexOf)); + OpThreadMem(kOpBlx, ENTRYPOINT_OFFSET(pIndexOf)); } - LIR* resume_tgt = NewLIR0(cu, kPseudoTargetLabel); + LIR* resume_tgt = NewLIR0(kPseudoTargetLabel); launch_pad->operands[2] = reinterpret_cast<uintptr_t>(resume_tgt); // Record that we've already inlined & null checked info->opt_flags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK); - RegLocation rl_return = GetReturn(cu, false); - RegLocation rl_dest = InlineTarget(cu, info); - StoreValue(cu, rl_dest, rl_return); + RegLocation rl_return = GetReturn(false); + RegLocation rl_dest = InlineTarget(info); + StoreValue(rl_dest, rl_return); return true; } /* Fast string.compareTo(Ljava/lang/string;)I. */ -bool Codegen::GenInlinedStringCompareTo(CompilationUnit* cu, CallInfo* info) +bool Mir2Lir::GenInlinedStringCompareTo(CallInfo* info) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } - ClobberCalleeSave(cu); - LockCallTemps(cu); // Using fixed registers + ClobberCalleeSave(); + LockCallTemps(); // Using fixed registers int reg_this = TargetReg(kArg0); int reg_cmp = TargetReg(kArg1); RegLocation rl_this = info->args[0]; RegLocation rl_cmp = info->args[1]; - LoadValueDirectFixed(cu, rl_this, reg_this); - LoadValueDirectFixed(cu, rl_cmp, reg_cmp); - int r_tgt = (cu->instruction_set != kX86) ? - LoadHelper(cu, ENTRYPOINT_OFFSET(pStringCompareTo)) : 0; - GenNullCheck(cu, rl_this.s_reg_low, reg_this, info->opt_flags); + LoadValueDirectFixed(rl_this, reg_this); + LoadValueDirectFixed(rl_cmp, reg_cmp); + int r_tgt = (cu_->instruction_set != kX86) ? + LoadHelper(ENTRYPOINT_OFFSET(pStringCompareTo)) : 0; + GenNullCheck(rl_this.s_reg_low, reg_this, info->opt_flags); //TUNING: check if rl_cmp.s_reg_low is already null checked - LIR* launch_pad = RawLIR(cu, 0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info)); - InsertGrowableList(cu, &cu->intrinsic_launchpads, reinterpret_cast<uintptr_t>(launch_pad)); - OpCmpImmBranch(cu, kCondEq, reg_cmp, 0, launch_pad); + LIR* launch_pad = RawLIR(0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info)); + InsertGrowableList(cu_, &intrinsic_launchpads_, reinterpret_cast<uintptr_t>(launch_pad)); + OpCmpImmBranch(kCondEq, reg_cmp, 0, launch_pad); // NOTE: not a safepoint - if (cu->instruction_set != kX86) { - OpReg(cu, kOpBlx, r_tgt); + if (cu_->instruction_set != kX86) { + OpReg(kOpBlx, r_tgt); } else { - OpThreadMem(cu, kOpBlx, ENTRYPOINT_OFFSET(pStringCompareTo)); + OpThreadMem(kOpBlx, ENTRYPOINT_OFFSET(pStringCompareTo)); } launch_pad->operands[2] = 0; // No return possible // Record that we've already inlined & null checked info->opt_flags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK); - RegLocation rl_return = GetReturn(cu, false); - RegLocation rl_dest = InlineTarget(cu, info); - StoreValue(cu, rl_dest, rl_return); + RegLocation rl_return = GetReturn(false); + RegLocation rl_dest = InlineTarget(info); + StoreValue(rl_dest, rl_return); return true; } -bool Codegen::GenInlinedCurrentThread(CompilationUnit* cu, CallInfo* info) { - RegLocation rl_dest = InlineTarget(cu, info); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); +bool Mir2Lir::GenInlinedCurrentThread(CallInfo* info) { + RegLocation rl_dest = InlineTarget(info); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); int offset = Thread::PeerOffset().Int32Value(); - if (cu->instruction_set == kThumb2 || cu->instruction_set == kMips) { - LoadWordDisp(cu, TargetReg(kSelf), offset, rl_result.low_reg); + if (cu_->instruction_set == kThumb2 || cu_->instruction_set == kMips) { + LoadWordDisp(TargetReg(kSelf), offset, rl_result.low_reg); } else { - CHECK(cu->instruction_set == kX86); - ((X86Codegen*)this)->OpRegThreadMem(cu, kOpMov, rl_result.low_reg, offset); + CHECK(cu_->instruction_set == kX86); + ((X86Mir2Lir*)this)->OpRegThreadMem(kOpMov, rl_result.low_reg, offset); } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); return true; } -bool Codegen::GenInlinedUnsafeGet(CompilationUnit* cu, CallInfo* info, +bool Mir2Lir::GenInlinedUnsafeGet(CallInfo* info, bool is_long, bool is_volatile) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } @@ -1137,27 +1126,27 @@ bool Codegen::GenInlinedUnsafeGet(CompilationUnit* cu, CallInfo* info, RegLocation rl_src_obj = info->args[1]; // Object RegLocation rl_src_offset = info->args[2]; // long low rl_src_offset.wide = 0; // ignore high half in info->args[3] - RegLocation rl_dest = InlineTarget(cu, info); // result reg + RegLocation rl_dest = InlineTarget(info); // result reg if (is_volatile) { - GenMemBarrier(cu, kLoadLoad); + GenMemBarrier(kLoadLoad); } - RegLocation rl_object = LoadValue(cu, rl_src_obj, kCoreReg); - RegLocation rl_offset = LoadValue(cu, rl_src_offset, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg); + RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); if (is_long) { - OpRegReg(cu, kOpAdd, rl_object.low_reg, rl_offset.low_reg); - LoadBaseDispWide(cu, rl_object.low_reg, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); - StoreValueWide(cu, rl_dest, rl_result); + OpRegReg(kOpAdd, rl_object.low_reg, rl_offset.low_reg); + LoadBaseDispWide(rl_object.low_reg, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); + StoreValueWide(rl_dest, rl_result); } else { - LoadBaseIndexed(cu, rl_object.low_reg, rl_offset.low_reg, rl_result.low_reg, 0, kWord); - StoreValue(cu, rl_dest, rl_result); + LoadBaseIndexed(rl_object.low_reg, rl_offset.low_reg, rl_result.low_reg, 0, kWord); + StoreValue(rl_dest, rl_result); } return true; } -bool Codegen::GenInlinedUnsafePut(CompilationUnit* cu, CallInfo* info, bool is_long, +bool Mir2Lir::GenInlinedUnsafePut(CallInfo* info, bool is_long, bool is_object, bool is_volatile, bool is_ordered) { - if (cu->instruction_set == kMips) { + if (cu_->instruction_set == kMips) { // TODO - add Mips implementation return false; } @@ -1167,27 +1156,27 @@ bool Codegen::GenInlinedUnsafePut(CompilationUnit* cu, CallInfo* info, bool is_l rl_src_offset.wide = 0; // ignore high half in info->args[3] RegLocation rl_src_value = info->args[4]; // value to store if (is_volatile || is_ordered) { - GenMemBarrier(cu, kStoreStore); + GenMemBarrier(kStoreStore); } - RegLocation rl_object = LoadValue(cu, rl_src_obj, kCoreReg); - RegLocation rl_offset = LoadValue(cu, rl_src_offset, kCoreReg); - RegLocation rl_value = LoadValue(cu, rl_src_value, kCoreReg); + RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg); + RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg); + RegLocation rl_value = LoadValue(rl_src_value, kCoreReg); if (is_long) { - OpRegReg(cu, kOpAdd, rl_object.low_reg, rl_offset.low_reg); - StoreBaseDispWide(cu, rl_object.low_reg, 0, rl_value.low_reg, rl_value.high_reg); + OpRegReg(kOpAdd, rl_object.low_reg, rl_offset.low_reg); + StoreBaseDispWide(rl_object.low_reg, 0, rl_value.low_reg, rl_value.high_reg); } else { - StoreBaseIndexed(cu, rl_object.low_reg, rl_offset.low_reg, rl_value.low_reg, 0, kWord); + StoreBaseIndexed(rl_object.low_reg, rl_offset.low_reg, rl_value.low_reg, 0, kWord); } if (is_volatile) { - GenMemBarrier(cu, kStoreLoad); + GenMemBarrier(kStoreLoad); } if (is_object) { - MarkGCCard(cu, rl_value.low_reg, rl_object.low_reg); + MarkGCCard(rl_value.low_reg, rl_object.low_reg); } return true; } -bool Codegen::GenIntrinsic(CompilationUnit* cu, CallInfo* info) +bool Mir2Lir::GenIntrinsic(CallInfo* info) { if (info->opt_flags & MIR_INLINED) { return false; @@ -1202,129 +1191,129 @@ bool Codegen::GenIntrinsic(CompilationUnit* cu, CallInfo* info) * method. By doing this during basic block construction, we can also * take advantage of/generate new useful dataflow info. */ - std::string tgt_method(PrettyMethod(info->index, *cu->dex_file)); + std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file)); if (tgt_method.find(" java.lang") != std::string::npos) { if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") { - return GenInlinedDoubleCvt(cu, info); + return GenInlinedDoubleCvt(info); } if (tgt_method == "double java.lang.Double.longBitsToDouble(long)") { - return GenInlinedDoubleCvt(cu, info); + return GenInlinedDoubleCvt(info); } if (tgt_method == "int java.lang.Float.float_to_raw_int_bits(float)") { - return GenInlinedFloatCvt(cu, info); + return GenInlinedFloatCvt(info); } if (tgt_method == "float java.lang.Float.intBitsToFloat(int)") { - return GenInlinedFloatCvt(cu, info); + return GenInlinedFloatCvt(info); } if (tgt_method == "int java.lang.Math.abs(int)" || tgt_method == "int java.lang.StrictMath.abs(int)") { - return GenInlinedAbsInt(cu, info); + return GenInlinedAbsInt(info); } if (tgt_method == "long java.lang.Math.abs(long)" || tgt_method == "long java.lang.StrictMath.abs(long)") { - return GenInlinedAbsLong(cu, info); + return GenInlinedAbsLong(info); } if (tgt_method == "int java.lang.Math.max(int, int)" || tgt_method == "int java.lang.StrictMath.max(int, int)") { - return GenInlinedMinMaxInt(cu, info, false /* is_min */); + return GenInlinedMinMaxInt(info, false /* is_min */); } if (tgt_method == "int java.lang.Math.min(int, int)" || tgt_method == "int java.lang.StrictMath.min(int, int)") { - return GenInlinedMinMaxInt(cu, info, true /* is_min */); + return GenInlinedMinMaxInt(info, true /* is_min */); } if (tgt_method == "double java.lang.Math.sqrt(double)" || tgt_method == "double java.lang.StrictMath.sqrt(double)") { - return GenInlinedSqrt(cu, info); + return GenInlinedSqrt(info); } if (tgt_method == "char java.lang.String.charAt(int)") { - return GenInlinedCharAt(cu, info); + return GenInlinedCharAt(info); } if (tgt_method == "int java.lang.String.compareTo(java.lang.String)") { - return GenInlinedStringCompareTo(cu, info); + return GenInlinedStringCompareTo(info); } if (tgt_method == "boolean java.lang.String.is_empty()") { - return GenInlinedStringIsEmptyOrLength(cu, info, true /* is_empty */); + return GenInlinedStringIsEmptyOrLength(info, true /* is_empty */); } if (tgt_method == "int java.lang.String.index_of(int, int)") { - return GenInlinedIndexOf(cu, info, false /* base 0 */); + return GenInlinedIndexOf(info, false /* base 0 */); } if (tgt_method == "int java.lang.String.index_of(int)") { - return GenInlinedIndexOf(cu, info, true /* base 0 */); + return GenInlinedIndexOf(info, true /* base 0 */); } if (tgt_method == "int java.lang.String.length()") { - return GenInlinedStringIsEmptyOrLength(cu, info, false /* is_empty */); + return GenInlinedStringIsEmptyOrLength(info, false /* is_empty */); } if (tgt_method == "java.lang.Thread java.lang.Thread.currentThread()") { - return GenInlinedCurrentThread(cu, info); + return GenInlinedCurrentThread(info); } } else if (tgt_method.find(" sun.misc.Unsafe") != std::string::npos) { if (tgt_method == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") { - return GenInlinedCas32(cu, info, false); + return GenInlinedCas32(info, false); } if (tgt_method == "boolean sun.misc.Unsafe.compareAndSwapObject(java.lang.Object, long, java.lang.Object, java.lang.Object)") { - return GenInlinedCas32(cu, info, true); + return GenInlinedCas32(info, true); } if (tgt_method == "int sun.misc.Unsafe.getInt(java.lang.Object, long)") { - return GenInlinedUnsafeGet(cu, info, false /* is_long */, false /* is_volatile */); + return GenInlinedUnsafeGet(info, false /* is_long */, false /* is_volatile */); } if (tgt_method == "int sun.misc.Unsafe.getIntVolatile(java.lang.Object, long)") { - return GenInlinedUnsafeGet(cu, info, false /* is_long */, true /* is_volatile */); + return GenInlinedUnsafeGet(info, false /* is_long */, true /* is_volatile */); } if (tgt_method == "void sun.misc.Unsafe.putInt(java.lang.Object, long, int)") { - return GenInlinedUnsafePut(cu, info, false /* is_long */, false /* is_object */, + return GenInlinedUnsafePut(info, false /* is_long */, false /* is_object */, false /* is_volatile */, false /* is_ordered */); } if (tgt_method == "void sun.misc.Unsafe.putIntVolatile(java.lang.Object, long, int)") { - return GenInlinedUnsafePut(cu, info, false /* is_long */, false /* is_object */, + return GenInlinedUnsafePut(info, false /* is_long */, false /* is_object */, true /* is_volatile */, false /* is_ordered */); } if (tgt_method == "void sun.misc.Unsafe.putOrderedInt(java.lang.Object, long, int)") { - return GenInlinedUnsafePut(cu, info, false /* is_long */, false /* is_object */, + return GenInlinedUnsafePut(info, false /* is_long */, false /* is_object */, false /* is_volatile */, true /* is_ordered */); } if (tgt_method == "long sun.misc.Unsafe.getLong(java.lang.Object, long)") { - return GenInlinedUnsafeGet(cu, info, true /* is_long */, false /* is_volatile */); + return GenInlinedUnsafeGet(info, true /* is_long */, false /* is_volatile */); } if (tgt_method == "long sun.misc.Unsafe.getLongVolatile(java.lang.Object, long)") { - return GenInlinedUnsafeGet(cu, info, true /* is_long */, true /* is_volatile */); + return GenInlinedUnsafeGet(info, true /* is_long */, true /* is_volatile */); } if (tgt_method == "void sun.misc.Unsafe.putLong(java.lang.Object, long, long)") { - return GenInlinedUnsafePut(cu, info, true /* is_long */, false /* is_object */, + return GenInlinedUnsafePut(info, true /* is_long */, false /* is_object */, false /* is_volatile */, false /* is_ordered */); } if (tgt_method == "void sun.misc.Unsafe.putLongVolatile(java.lang.Object, long, long)") { - return GenInlinedUnsafePut(cu, info, true /* is_long */, false /* is_object */, + return GenInlinedUnsafePut(info, true /* is_long */, false /* is_object */, true /* is_volatile */, false /* is_ordered */); } if (tgt_method == "void sun.misc.Unsafe.putOrderedLong(java.lang.Object, long, long)") { - return GenInlinedUnsafePut(cu, info, true /* is_long */, false /* is_object */, + return GenInlinedUnsafePut(info, true /* is_long */, false /* is_object */, false /* is_volatile */, true /* is_ordered */); } if (tgt_method == "java.lang.Object sun.misc.Unsafe.getObject(java.lang.Object, long)") { - return GenInlinedUnsafeGet(cu, info, false /* is_long */, false /* is_volatile */); + return GenInlinedUnsafeGet(info, false /* is_long */, false /* is_volatile */); } if (tgt_method == "java.lang.Object sun.misc.Unsafe.getObjectVolatile(java.lang.Object, long)") { - return GenInlinedUnsafeGet(cu, info, false /* is_long */, true /* is_volatile */); + return GenInlinedUnsafeGet(info, false /* is_long */, true /* is_volatile */); } if (tgt_method == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") { - return GenInlinedUnsafePut(cu, info, false /* is_long */, true /* is_object */, + return GenInlinedUnsafePut(info, false /* is_long */, true /* is_object */, false /* is_volatile */, false /* is_ordered */); } if (tgt_method == "void sun.misc.Unsafe.putObjectVolatile(java.lang.Object, long, java.lang.Object)") { - return GenInlinedUnsafePut(cu, info, false /* is_long */, true /* is_object */, + return GenInlinedUnsafePut(info, false /* is_long */, true /* is_object */, true /* is_volatile */, false /* is_ordered */); } if (tgt_method == "void sun.misc.Unsafe.putOrderedObject(java.lang.Object, long, java.lang.Object)") { - return GenInlinedUnsafePut(cu, info, false /* is_long */, true /* is_object */, + return GenInlinedUnsafePut(info, false /* is_long */, true /* is_object */, false /* is_volatile */, true /* is_ordered */); } } return false; } -void Codegen::GenInvoke(CompilationUnit* cu, CallInfo* info) +void Mir2Lir::GenInvoke(CallInfo* info) { - if (GenIntrinsic(cu, info)) { + if (GenIntrinsic(info)) { return; } InvokeType original_type = info->type; // avoiding mutation by ComputeInvokeInfo @@ -1332,17 +1321,17 @@ void Codegen::GenInvoke(CompilationUnit* cu, CallInfo* info) LIR* null_ck; LIR** p_null_ck = NULL; NextCallInsn next_call_insn; - FlushAllRegs(cu); /* Everything to home location */ + FlushAllRegs(); /* Everything to home location */ // Explicit register usage - LockCallTemps(cu); + LockCallTemps(); uint32_t dex_method_idx = info->index; int vtable_idx; uintptr_t direct_code; uintptr_t direct_method; bool skip_this; - bool fast_path = cu->compiler_driver->ComputeInvokeInfo( - dex_method_idx, cu->mir_graph->GetCurrentDexCompilationUnit(), info->type, vtable_idx, + bool fast_path = cu_->compiler_driver->ComputeInvokeInfo( + dex_method_idx, mir_graph_->GetCurrentDexCompilationUnit(), info->type, vtable_idx, direct_code, direct_method) && !SLOW_INVOKE_PATH; if (info->type == kInterface) { if (fast_path) { @@ -1370,31 +1359,31 @@ void Codegen::GenInvoke(CompilationUnit* cu, CallInfo* info) skip_this = fast_path; } if (!info->is_range) { - call_state = GenDalvikArgsNoRange(cu, info, call_state, p_null_ck, + call_state = GenDalvikArgsNoRange(info, call_state, p_null_ck, next_call_insn, dex_method_idx, vtable_idx, direct_code, direct_method, original_type, skip_this); } else { - call_state = GenDalvikArgsRange(cu, info, call_state, p_null_ck, + call_state = GenDalvikArgsRange(info, call_state, p_null_ck, next_call_insn, dex_method_idx, vtable_idx, direct_code, direct_method, original_type, skip_this); } // Finish up any of the call sequence not interleaved in arg loading while (call_state >= 0) { - call_state = next_call_insn(cu, info, call_state, dex_method_idx, + call_state = next_call_insn(cu_, info, call_state, dex_method_idx, vtable_idx, direct_code, direct_method, original_type); } - if (cu->enable_debug & (1 << kDebugDisplayMissingTargets)) { - GenShowTarget(cu); + if (cu_->enable_debug & (1 << kDebugDisplayMissingTargets)) { + GenShowTarget(); } LIR* call_inst; - if (cu->instruction_set != kX86) { - call_inst = OpReg(cu, kOpBlx, TargetReg(kInvokeTgt)); + if (cu_->instruction_set != kX86) { + call_inst = OpReg(kOpBlx, TargetReg(kInvokeTgt)); } else { if (fast_path && info->type != kInterface) { - call_inst = OpMem(cu, kOpBlx, TargetReg(kArg0), + call_inst = OpMem(kOpBlx, TargetReg(kArg0), mirror::AbstractMethod::GetCodeOffset().Int32Value()); } else { int trampoline = 0; @@ -1418,54 +1407,22 @@ void Codegen::GenInvoke(CompilationUnit* cu, CallInfo* info) default: LOG(FATAL) << "Unexpected invoke type"; } - call_inst = OpThreadMem(cu, kOpBlx, trampoline); + call_inst = OpThreadMem(kOpBlx, trampoline); } } - MarkSafepointPC(cu, call_inst); + MarkSafepointPC(call_inst); - ClobberCalleeSave(cu); + ClobberCalleeSave(); if (info->result.location != kLocInvalid) { // We have a following MOVE_RESULT - do it now. if (info->result.wide) { - RegLocation ret_loc = GetReturnWide(cu, info->result.fp); - StoreValueWide(cu, info->result, ret_loc); + RegLocation ret_loc = GetReturnWide(info->result.fp); + StoreValueWide(info->result, ret_loc); } else { - RegLocation ret_loc = GetReturn(cu, info->result.fp); - StoreValue(cu, info->result, ret_loc); + RegLocation ret_loc = GetReturn(info->result.fp); + StoreValue(info->result, ret_loc); } } } -/* - * Build an array of location records for the incoming arguments. - * Note: one location record per word of arguments, with dummy - * high-word loc for wide arguments. Also pull up any following - * MOVE_RESULT and incorporate it into the invoke. - */ -CallInfo* Codegen::NewMemCallInfo(CompilationUnit* cu, BasicBlock* bb, MIR* mir, InvokeType type, - bool is_range) -{ - CallInfo* info = static_cast<CallInfo*>(NewMem(cu, sizeof(CallInfo), true, kAllocMisc)); - MIR* move_result_mir = cu->mir_graph->FindMoveResult(bb, mir); - if (move_result_mir == NULL) { - info->result.location = kLocInvalid; - } else { - info->result = GetRawDest(cu, move_result_mir); - move_result_mir->meta.original_opcode = move_result_mir->dalvikInsn.opcode; - move_result_mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); - } - info->num_arg_words = mir->ssa_rep->num_uses; - info->args = (info->num_arg_words == 0) ? NULL : static_cast<RegLocation*> - (NewMem(cu, sizeof(RegLocation) * info->num_arg_words, false, kAllocMisc)); - for (int i = 0; i < info->num_arg_words; i++) { - info->args[i] = GetRawSrc(cu, mir, i); - } - info->opt_flags = mir->optimization_flags; - info->type = type; - info->is_range = is_range; - info->index = mir->dalvikInsn.vB; - info->offset = mir->offset; - return info; -} - } // namespace art diff --git a/src/compiler/dex/quick/gen_loadstore.cc b/src/compiler/dex/quick/gen_loadstore.cc index 7e116fc100..1cebd31d19 100644 --- a/src/compiler/dex/quick/gen_loadstore.cc +++ b/src/compiler/dex/quick/gen_loadstore.cc @@ -14,11 +14,9 @@ * limitations under the License. */ -#include "compiler/dex/quick/codegen_util.h" #include "compiler/dex/compiler_ir.h" #include "compiler/dex/compiler_internals.h" #include "invoke_type.h" -#include "ralloc_util.h" namespace art { @@ -28,13 +26,13 @@ namespace art { * Load an immediate value into a fixed or temp register. Target * register is clobbered, and marked in_use. */ -LIR* Codegen::LoadConstant(CompilationUnit* cu, int r_dest, int value) +LIR* Mir2Lir::LoadConstant(int r_dest, int value) { - if (IsTemp(cu, r_dest)) { - Clobber(cu, r_dest); - MarkInUse(cu, r_dest); + if (IsTemp(r_dest)) { + Clobber(r_dest); + MarkInUse(r_dest); } - return LoadConstantNoClobber(cu, r_dest, value); + return LoadConstantNoClobber(r_dest, value); } /* @@ -42,54 +40,51 @@ LIR* Codegen::LoadConstant(CompilationUnit* cu, int r_dest, int value) * promoted floating point register, also copy a zero into the int/ref identity of * that sreg. */ -void Codegen::Workaround7250540(CompilationUnit* cu, RegLocation rl_dest, int zero_reg) +void Mir2Lir::Workaround7250540(RegLocation rl_dest, int zero_reg) { if (rl_dest.fp) { - int pmap_index = SRegToPMap(cu, rl_dest.s_reg_low); - if (cu->promotion_map[pmap_index].fp_location == kLocPhysReg) { + int pmap_index = SRegToPMap(rl_dest.s_reg_low); + if (promotion_map_[pmap_index].fp_location == kLocPhysReg) { // Now, determine if this vreg is ever used as a reference. If not, we're done. - if (!cu->gen_bitcode) { - // TUNING: We no longer have this info for QuickGBC - assume the worst - bool used_as_reference = false; - int base_vreg = cu->mir_graph->SRegToVReg(rl_dest.s_reg_low); - for (int i = 0; !used_as_reference && (i < cu->mir_graph->GetNumSSARegs()); i++) { - if (cu->mir_graph->SRegToVReg(cu->reg_location[i].s_reg_low) == base_vreg) { - used_as_reference |= cu->reg_location[i].ref; - } - } - if (!used_as_reference) { - return; + bool used_as_reference = false; + int base_vreg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); + for (int i = 0; !used_as_reference && (i < mir_graph_->GetNumSSARegs()); i++) { + if (mir_graph_->SRegToVReg(mir_graph_->reg_location_[i].s_reg_low) == base_vreg) { + used_as_reference |= mir_graph_->reg_location_[i].ref; } } + if (!used_as_reference) { + return; + } int temp_reg = zero_reg; if (temp_reg == INVALID_REG) { - temp_reg = AllocTemp(cu); - cu->cg->LoadConstant(cu, temp_reg, 0); + temp_reg = AllocTemp(); + LoadConstant(temp_reg, 0); } - if (cu->promotion_map[pmap_index].core_location == kLocPhysReg) { + if (promotion_map_[pmap_index].core_location == kLocPhysReg) { // Promoted - just copy in a zero - OpRegCopy(cu, cu->promotion_map[pmap_index].core_reg, temp_reg); + OpRegCopy(promotion_map_[pmap_index].core_reg, temp_reg); } else { // Lives in the frame, need to store. - StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low), temp_reg, kWord); + StoreBaseDisp(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low), temp_reg, kWord); } if (zero_reg == INVALID_REG) { - FreeTemp(cu, temp_reg); + FreeTemp(temp_reg); } } } } /* Load a word at base + displacement. Displacement must be word multiple */ -LIR* Codegen::LoadWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest) +LIR* Mir2Lir::LoadWordDisp(int rBase, int displacement, int r_dest) { - return LoadBaseDisp(cu, rBase, displacement, r_dest, kWord, + return LoadBaseDisp(rBase, displacement, r_dest, kWord, INVALID_SREG); } -LIR* Codegen::StoreWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_src) +LIR* Mir2Lir::StoreWordDisp(int rBase, int displacement, int r_src) { - return StoreBaseDisp(cu, rBase, displacement, r_src, kWord); + return StoreBaseDisp(rBase, displacement, r_src, kWord); } /* @@ -97,17 +92,17 @@ LIR* Codegen::StoreWordDisp(CompilationUnit* cu, int rBase, int displacement, in * using this routine, as it doesn't perform any bookkeeping regarding * register liveness. That is the responsibility of the caller. */ -void Codegen::LoadValueDirect(CompilationUnit* cu, RegLocation rl_src, int r_dest) +void Mir2Lir::LoadValueDirect(RegLocation rl_src, int r_dest) { - rl_src = UpdateLoc(cu, rl_src); + rl_src = UpdateLoc(rl_src); if (rl_src.location == kLocPhysReg) { - OpRegCopy(cu, r_dest, rl_src.low_reg); - } else if (IsInexpensiveConstant(cu, rl_src)) { - LoadConstantNoClobber(cu, r_dest, cu->mir_graph->ConstantValue(rl_src)); + OpRegCopy(r_dest, rl_src.low_reg); + } else if (IsInexpensiveConstant(rl_src)) { + LoadConstantNoClobber(r_dest, mir_graph_->ConstantValue(rl_src)); } else { DCHECK((rl_src.location == kLocDalvikFrame) || (rl_src.location == kLocCompilerTemp)); - LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low), r_dest); + LoadWordDisp(TargetReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest); } } @@ -116,11 +111,11 @@ void Codegen::LoadValueDirect(CompilationUnit* cu, RegLocation rl_src, int r_des * register. Should be used when loading to a fixed register (for example, * loading arguments to an out of line call. */ -void Codegen::LoadValueDirectFixed(CompilationUnit* cu, RegLocation rl_src, int r_dest) +void Mir2Lir::LoadValueDirectFixed(RegLocation rl_src, int r_dest) { - Clobber(cu, r_dest); - MarkInUse(cu, r_dest); - LoadValueDirect(cu, rl_src, r_dest); + Clobber(r_dest); + MarkInUse(r_dest); + LoadValueDirect(rl_src, r_dest); } /* @@ -128,18 +123,18 @@ void Codegen::LoadValueDirectFixed(CompilationUnit* cu, RegLocation rl_src, int * using this routine, as it doesn't perform any bookkeeping regarding * register liveness. That is the responsibility of the caller. */ -void Codegen::LoadValueDirectWide(CompilationUnit* cu, RegLocation rl_src, int reg_lo, +void Mir2Lir::LoadValueDirectWide(RegLocation rl_src, int reg_lo, int reg_hi) { - rl_src = UpdateLocWide(cu, rl_src); + rl_src = UpdateLocWide(rl_src); if (rl_src.location == kLocPhysReg) { - OpRegCopyWide(cu, reg_lo, reg_hi, rl_src.low_reg, rl_src.high_reg); - } else if (IsInexpensiveConstant(cu, rl_src)) { - LoadConstantWide(cu, reg_lo, reg_hi, cu->mir_graph->ConstantValueWide(rl_src)); + OpRegCopyWide(reg_lo, reg_hi, rl_src.low_reg, rl_src.high_reg); + } else if (IsInexpensiveConstant(rl_src)) { + LoadConstantWide(reg_lo, reg_hi, mir_graph_->ConstantValueWide(rl_src)); } else { DCHECK((rl_src.location == kLocDalvikFrame) || (rl_src.location == kLocCompilerTemp)); - LoadBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low), + LoadBaseDispWide(TargetReg(kSp), SRegOffset(rl_src.s_reg_low), reg_lo, reg_hi, INVALID_SREG); } } @@ -149,28 +144,28 @@ void Codegen::LoadValueDirectWide(CompilationUnit* cu, RegLocation rl_src, int r * registers. Should be used when loading to a fixed registers (for example, * loading arguments to an out of line call. */ -void Codegen::LoadValueDirectWideFixed(CompilationUnit* cu, RegLocation rl_src, int reg_lo, +void Mir2Lir::LoadValueDirectWideFixed(RegLocation rl_src, int reg_lo, int reg_hi) { - Clobber(cu, reg_lo); - Clobber(cu, reg_hi); - MarkInUse(cu, reg_lo); - MarkInUse(cu, reg_hi); - LoadValueDirectWide(cu, rl_src, reg_lo, reg_hi); + Clobber(reg_lo); + Clobber(reg_hi); + MarkInUse(reg_lo); + MarkInUse(reg_hi); + LoadValueDirectWide(rl_src, reg_lo, reg_hi); } -RegLocation Codegen::LoadValue(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind) +RegLocation Mir2Lir::LoadValue(RegLocation rl_src, RegisterClass op_kind) { - rl_src = EvalLoc(cu, rl_src, op_kind, false); - if (IsInexpensiveConstant(cu, rl_src) || rl_src.location != kLocPhysReg) { - LoadValueDirect(cu, rl_src, rl_src.low_reg); + rl_src = EvalLoc(rl_src, op_kind, false); + if (IsInexpensiveConstant(rl_src) || rl_src.location != kLocPhysReg) { + LoadValueDirect(rl_src, rl_src.low_reg); rl_src.location = kLocPhysReg; - MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low); + MarkLive(rl_src.low_reg, rl_src.s_reg_low); } return rl_src; } -void Codegen::StoreValue(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void Mir2Lir::StoreValue(RegLocation rl_dest, RegLocation rl_src) { /* * Sanity checking - should never try to store to the same @@ -178,68 +173,68 @@ void Codegen::StoreValue(CompilationUnit* cu, RegLocation rl_dest, RegLocation r * without an intervening ClobberSReg(). */ if (kIsDebugBuild) { - DCHECK((cu->live_sreg == INVALID_SREG) || - (rl_dest.s_reg_low != cu->live_sreg)); - cu->live_sreg = rl_dest.s_reg_low; + DCHECK((live_sreg_ == INVALID_SREG) || + (rl_dest.s_reg_low != live_sreg_)); + live_sreg_ = rl_dest.s_reg_low; } LIR* def_start; LIR* def_end; DCHECK(!rl_dest.wide); DCHECK(!rl_src.wide); - rl_src = UpdateLoc(cu, rl_src); - rl_dest = UpdateLoc(cu, rl_dest); + rl_src = UpdateLoc(rl_src); + rl_dest = UpdateLoc(rl_dest); if (rl_src.location == kLocPhysReg) { - if (IsLive(cu, rl_src.low_reg) || - IsPromoted(cu, rl_src.low_reg) || + if (IsLive(rl_src.low_reg) || + IsPromoted(rl_src.low_reg) || (rl_dest.location == kLocPhysReg)) { // Src is live/promoted or Dest has assigned reg. - rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false); - OpRegCopy(cu, rl_dest.low_reg, rl_src.low_reg); + rl_dest = EvalLoc(rl_dest, kAnyReg, false); + OpRegCopy(rl_dest.low_reg, rl_src.low_reg); } else { // Just re-assign the registers. Dest gets Src's regs rl_dest.low_reg = rl_src.low_reg; - Clobber(cu, rl_src.low_reg); + Clobber(rl_src.low_reg); } } else { // Load Src either into promoted Dest or temps allocated for Dest - rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false); - LoadValueDirect(cu, rl_src, rl_dest.low_reg); + rl_dest = EvalLoc(rl_dest, kAnyReg, false); + LoadValueDirect(rl_src, rl_dest.low_reg); } // Dest is now live and dirty (until/if we flush it to home location) - MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low); - MarkDirty(cu, rl_dest); + MarkLive(rl_dest.low_reg, rl_dest.s_reg_low); + MarkDirty(rl_dest); - ResetDefLoc(cu, rl_dest); - if (IsDirty(cu, rl_dest.low_reg) && - oat_live_out(cu, rl_dest.s_reg_low)) { - def_start = cu->last_lir_insn; - StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low), + ResetDefLoc(rl_dest); + if (IsDirty(rl_dest.low_reg) && + oat_live_out(rl_dest.s_reg_low)) { + def_start = last_lir_insn_; + StoreBaseDisp(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.low_reg, kWord); - MarkClean(cu, rl_dest); - def_end = cu->last_lir_insn; + MarkClean(rl_dest); + def_end = last_lir_insn_; if (!rl_dest.ref) { // Exclude references from store elimination - MarkDef(cu, rl_dest, def_start, def_end); + MarkDef(rl_dest, def_start, def_end); } } } -RegLocation Codegen::LoadValueWide(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind) +RegLocation Mir2Lir::LoadValueWide(RegLocation rl_src, RegisterClass op_kind) { DCHECK(rl_src.wide); - rl_src = EvalLoc(cu, rl_src, op_kind, false); - if (IsInexpensiveConstant(cu, rl_src) || rl_src.location != kLocPhysReg) { - LoadValueDirectWide(cu, rl_src, rl_src.low_reg, rl_src.high_reg); + rl_src = EvalLoc(rl_src, op_kind, false); + if (IsInexpensiveConstant(rl_src) || rl_src.location != kLocPhysReg) { + LoadValueDirectWide(rl_src, rl_src.low_reg, rl_src.high_reg); rl_src.location = kLocPhysReg; - MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low); - MarkLive(cu, rl_src.high_reg, GetSRegHi(rl_src.s_reg_low)); + MarkLive(rl_src.low_reg, rl_src.s_reg_low); + MarkLive(rl_src.high_reg, GetSRegHi(rl_src.s_reg_low)); } return rl_src; } -void Codegen::StoreValueWide(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void Mir2Lir::StoreValueWide(RegLocation rl_dest, RegLocation rl_src) { /* * Sanity checking - should never try to store to the same @@ -247,9 +242,9 @@ void Codegen::StoreValueWide(CompilationUnit* cu, RegLocation rl_dest, RegLocati * without an intervening ClobberSReg(). */ if (kIsDebugBuild) { - DCHECK((cu->live_sreg == INVALID_SREG) || - (rl_dest.s_reg_low != cu->live_sreg)); - cu->live_sreg = rl_dest.s_reg_low; + DCHECK((live_sreg_ == INVALID_SREG) || + (rl_dest.s_reg_low != live_sreg_)); + live_sreg_ = rl_dest.s_reg_low; } LIR* def_start; LIR* def_end; @@ -257,60 +252,60 @@ void Codegen::StoreValueWide(CompilationUnit* cu, RegLocation rl_dest, RegLocati DCHECK(rl_dest.wide); DCHECK(rl_src.wide); if (rl_src.location == kLocPhysReg) { - if (IsLive(cu, rl_src.low_reg) || - IsLive(cu, rl_src.high_reg) || - IsPromoted(cu, rl_src.low_reg) || - IsPromoted(cu, rl_src.high_reg) || + if (IsLive(rl_src.low_reg) || + IsLive(rl_src.high_reg) || + IsPromoted(rl_src.low_reg) || + IsPromoted(rl_src.high_reg) || (rl_dest.location == kLocPhysReg)) { // Src is live or promoted or Dest has assigned reg. - rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false); - OpRegCopyWide(cu, rl_dest.low_reg, rl_dest.high_reg, + rl_dest = EvalLoc(rl_dest, kAnyReg, false); + OpRegCopyWide(rl_dest.low_reg, rl_dest.high_reg, rl_src.low_reg, rl_src.high_reg); } else { // Just re-assign the registers. Dest gets Src's regs rl_dest.low_reg = rl_src.low_reg; rl_dest.high_reg = rl_src.high_reg; - Clobber(cu, rl_src.low_reg); - Clobber(cu, rl_src.high_reg); + Clobber(rl_src.low_reg); + Clobber(rl_src.high_reg); } } else { // Load Src either into promoted Dest or temps allocated for Dest - rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false); - LoadValueDirectWide(cu, rl_src, rl_dest.low_reg, rl_dest.high_reg); + rl_dest = EvalLoc(rl_dest, kAnyReg, false); + LoadValueDirectWide(rl_src, rl_dest.low_reg, rl_dest.high_reg); } // Dest is now live and dirty (until/if we flush it to home location) - MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low); - MarkLive(cu, rl_dest.high_reg, GetSRegHi(rl_dest.s_reg_low)); - MarkDirty(cu, rl_dest); - MarkPair(cu, rl_dest.low_reg, rl_dest.high_reg); + MarkLive(rl_dest.low_reg, rl_dest.s_reg_low); + MarkLive(rl_dest.high_reg, GetSRegHi(rl_dest.s_reg_low)); + MarkDirty(rl_dest); + MarkPair(rl_dest.low_reg, rl_dest.high_reg); - ResetDefLocWide(cu, rl_dest); - if ((IsDirty(cu, rl_dest.low_reg) || - IsDirty(cu, rl_dest.high_reg)) && - (oat_live_out(cu, rl_dest.s_reg_low) || - oat_live_out(cu, GetSRegHi(rl_dest.s_reg_low)))) { - def_start = cu->last_lir_insn; - DCHECK_EQ((cu->mir_graph->SRegToVReg(rl_dest.s_reg_low)+1), - cu->mir_graph->SRegToVReg(GetSRegHi(rl_dest.s_reg_low))); - StoreBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low), + ResetDefLocWide(rl_dest); + if ((IsDirty(rl_dest.low_reg) || + IsDirty(rl_dest.high_reg)) && + (oat_live_out(rl_dest.s_reg_low) || + oat_live_out(GetSRegHi(rl_dest.s_reg_low)))) { + def_start = last_lir_insn_; + DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1), + mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low))); + StoreBaseDispWide(TargetReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.low_reg, rl_dest.high_reg); - MarkClean(cu, rl_dest); - def_end = cu->last_lir_insn; - MarkDefWide(cu, rl_dest, def_start, def_end); + MarkClean(rl_dest); + def_end = last_lir_insn_; + MarkDefWide(rl_dest, def_start, def_end); } } /* Utilities to load the current Method* */ -void Codegen::LoadCurrMethodDirect(CompilationUnit *cu, int r_tgt) +void Mir2Lir::LoadCurrMethodDirect(int r_tgt) { - LoadValueDirectFixed(cu, cu->method_loc, r_tgt); + LoadValueDirectFixed(mir_graph_->GetMethodLoc(), r_tgt); } -RegLocation Codegen::LoadCurrMethod(CompilationUnit *cu) +RegLocation Mir2Lir::LoadCurrMethod() { - return LoadValue(cu, cu->method_loc, kCoreReg); + return LoadValue(mir_graph_->GetMethodLoc(), kCoreReg); } } // namespace art diff --git a/src/compiler/dex/quick/local_optimizations.cc b/src/compiler/dex/quick/local_optimizations.cc index 3c58937300..695b12c552 100644 --- a/src/compiler/dex/quick/local_optimizations.cc +++ b/src/compiler/dex/quick/local_optimizations.cc @@ -40,12 +40,11 @@ static bool IsDalvikRegisterClobbered(LIR* lir1, LIR* lir2) } /* Convert a more expensive instruction (ie load) into a move */ -static void ConvertMemOpIntoMove(CompilationUnit* cu, LIR* orig_lir, int dest, int src) +void Mir2Lir::ConvertMemOpIntoMove(LIR* orig_lir, int dest, int src) { - Codegen* cg = cu->cg.get(); /* Insert a move to replace the load */ LIR* move_lir; - move_lir = cg->OpRegCopyNoInsert( cu, dest, src); + move_lir = OpRegCopyNoInsert(dest, src); /* * Insert the converted instruction after the original since the * optimization is scannng in the top-down order and the new instruction @@ -73,9 +72,8 @@ static void ConvertMemOpIntoMove(CompilationUnit* cu, LIR* orig_lir, int dest, i * 1) They are must-aliases * 2) The memory location is not written to in between */ -static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) +void Mir2Lir::ApplyLoadStoreElimination(LIR* head_lir, LIR* tail_lir) { - Codegen* cg = cu->cg.get(); LIR* this_lir; if (head_lir == tail_lir) return; @@ -86,7 +84,7 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t int sink_distance = 0; - uint64_t target_flags = cg->GetTargetInstFlags(this_lir->opcode); + uint64_t target_flags = GetTargetInstFlags(this_lir->opcode); /* Skip non-interesting instructions */ if ((this_lir->flags.is_nop == true) || @@ -99,14 +97,14 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t } int native_reg_id; - if (cu->instruction_set == kX86) { + if (cu_->instruction_set == kX86) { // If x86, location differs depending on whether memory/reg operation. - native_reg_id = (cg->GetTargetInstFlags(this_lir->opcode) & IS_STORE) ? this_lir->operands[2] + native_reg_id = (GetTargetInstFlags(this_lir->opcode) & IS_STORE) ? this_lir->operands[2] : this_lir->operands[0]; } else { native_reg_id = this_lir->operands[0]; } - bool is_this_lir_load = cg->GetTargetInstFlags(this_lir->opcode) & IS_LOAD; + bool is_this_lir_load = GetTargetInstFlags(this_lir->opcode) & IS_LOAD; LIR* check_lir; /* Use the mem mask to determine the rough memory location */ uint64_t this_mem_mask = (this_lir->use_mask | this_lir->def_mask) & ENCODE_MEM; @@ -119,7 +117,7 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t uint64_t stop_def_reg_mask = this_lir->def_mask & ~ENCODE_MEM; uint64_t stop_use_reg_mask; - if (cu->instruction_set == kX86) { + if (cu_->instruction_set == kX86) { stop_use_reg_mask = (IS_BRANCH | this_lir->use_mask) & ~ENCODE_MEM; } else { /* @@ -128,7 +126,7 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t * region bits since stop_mask is used to check data/control * dependencies. */ - stop_use_reg_mask = (cg->GetPCUseDefEncoding() | this_lir->use_mask) & ~ENCODE_MEM; + stop_use_reg_mask = (GetPCUseDefEncoding() | this_lir->use_mask) & ~ENCODE_MEM; } for (check_lir = NEXT_LIR(this_lir); check_lir != tail_lir; check_lir = NEXT_LIR(check_lir)) { @@ -146,7 +144,7 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t /* * Potential aliases seen - check the alias relations */ - uint64_t check_flags = cg->GetTargetInstFlags(check_lir->opcode); + uint64_t check_flags = GetTargetInstFlags(check_lir->opcode); // TUNING: Support instructions with multiple register targets. if ((check_flags & (REG_DEF0 | REG_DEF1)) == (REG_DEF0 | REG_DEF1)) { stop_here = true; @@ -160,14 +158,13 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t DCHECK(!(check_flags & IS_STORE)); /* Same value && same register type */ if (check_lir->alias_info == this_lir->alias_info && - cg->SameRegType(check_lir->operands[0], native_reg_id)) { + SameRegType(check_lir->operands[0], native_reg_id)) { /* * Different destination register - insert * a move */ if (check_lir->operands[0] != native_reg_id) { - ConvertMemOpIntoMove(cu, check_lir, check_lir->operands[0], - native_reg_id); + ConvertMemOpIntoMove(check_lir, check_lir->operands[0], native_reg_id); } check_lir->flags.is_nop = true; } @@ -175,7 +172,7 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t /* Must alias */ if (check_lir->alias_info == this_lir->alias_info) { /* Only optimize compatible registers */ - bool reg_compatible = cg->SameRegType(check_lir->operands[0], native_reg_id); + bool reg_compatible = SameRegType(check_lir->operands[0], native_reg_id); if ((is_this_lir_load && is_check_lir_load) || (!is_this_lir_load && is_check_lir_load)) { /* RAR or RAW */ @@ -186,8 +183,7 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t */ if (check_lir->operands[0] != native_reg_id) { - ConvertMemOpIntoMove(cu, check_lir, check_lir->operands[0], - native_reg_id); + ConvertMemOpIntoMove(check_lir, check_lir->operands[0], native_reg_id); } check_lir->flags.is_nop = true; } else { @@ -237,10 +233,10 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t } if (stop_here == true) { - if (cu->instruction_set == kX86) { + if (cu_->instruction_set == kX86) { // Prevent stores from being sunk between ops that generate ccodes and // ops that use them. - uint64_t flags = cg->GetTargetInstFlags(check_lir->opcode); + uint64_t flags = GetTargetInstFlags(check_lir->opcode); if (sink_distance > 0 && (flags & IS_BRANCH) && (flags & USES_CCODES)) { check_lir = PREV_LIR(check_lir); sink_distance--; @@ -249,7 +245,7 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t DEBUG_OPT(dump_dependent_insn_pair(this_lir, check_lir, "REG CLOBBERED")); /* Only sink store instructions */ if (sink_distance && !is_this_lir_load) { - LIR* new_store_lir = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR)); + LIR* new_store_lir = static_cast<LIR*>(NewMem(cu_, sizeof(LIR), true, kAllocLIR)); *new_store_lir = *this_lir; /* * Stop point found - insert *before* the check_lir @@ -271,9 +267,8 @@ static void ApplyLoadStoreElimination(CompilationUnit* cu, LIR* head_lir, LIR* t * Perform a pass of bottom-up walk, from the second instruction in the * superblock, to try to hoist loads to earlier slots. */ -void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) +void Mir2Lir::ApplyLoadHoisting(LIR* head_lir, LIR* tail_lir) { - Codegen* cg = cu->cg.get(); LIR* this_lir, *check_lir; /* * Store the list of independent instructions that can be hoisted past. @@ -289,7 +284,7 @@ void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) if (is_pseudo_opcode(this_lir->opcode)) continue; - uint64_t target_flags = cg->GetTargetInstFlags(this_lir->opcode); + uint64_t target_flags = GetTargetInstFlags(this_lir->opcode); /* Skip non-interesting instructions */ if ((this_lir->flags.is_nop == true) || ((target_flags & (REG_DEF0 | REG_DEF1)) == (REG_DEF0 | REG_DEF1)) || @@ -299,7 +294,7 @@ void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) uint64_t stop_use_all_mask = this_lir->use_mask; - if (cu->instruction_set != kX86) { + if (cu_->instruction_set != kX86) { /* * Branches for null/range checks are marked with the true resource * bits, and loads to Dalvik registers, constant pools, and non-alias @@ -307,7 +302,7 @@ void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) * conservatively here. */ if (stop_use_all_mask & ENCODE_HEAP_REF) { - stop_use_all_mask |= cg->GetPCUseDefEncoding(); + stop_use_all_mask |= GetPCUseDefEncoding(); } } @@ -391,7 +386,7 @@ void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) LIR* dep_lir = prev_inst_list[next_slot-1]; /* If there is ld-ld dependency, wait LDLD_DISTANCE cycles */ if (!is_pseudo_opcode(dep_lir->opcode) && - (cg->GetTargetInstFlags(dep_lir->opcode) & IS_LOAD)) { + (GetTargetInstFlags(dep_lir->opcode) & IS_LOAD)) { first_slot -= LDLD_DISTANCE; } /* @@ -408,7 +403,7 @@ void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) * If the first instruction is a load, don't hoist anything * above it since it is unlikely to be beneficial. */ - if (cg->GetTargetInstFlags(cur_lir->opcode) & IS_LOAD) continue; + if (GetTargetInstFlags(cur_lir->opcode) & IS_LOAD) continue; /* * If the remaining number of slots is less than LD_LATENCY, * insert the hoisted load here. @@ -428,7 +423,7 @@ void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) * the remaining instructions are less than LD_LATENCY. */ bool prev_is_load = is_pseudo_opcode(prev_lir->opcode) ? false : - (cg->GetTargetInstFlags(prev_lir->opcode) & IS_LOAD); + (GetTargetInstFlags(prev_lir->opcode) & IS_LOAD); if (((cur_lir->use_mask & prev_lir->def_mask) && prev_is_load) || (slot < LD_LATENCY)) { break; } @@ -437,7 +432,7 @@ void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) /* Found a slot to hoist to */ if (slot >= 0) { LIR* cur_lir = prev_inst_list[slot]; - LIR* new_load_lir = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR)); + LIR* new_load_lir = static_cast<LIR*>(NewMem(cu_, sizeof(LIR), true, kAllocLIR)); *new_load_lir = *this_lir; /* * Insertion is guaranteed to succeed since check_lir @@ -450,14 +445,13 @@ void ApplyLoadHoisting(CompilationUnit* cu, LIR* head_lir, LIR* tail_lir) } } -void ApplyLocalOptimizations(CompilationUnit* cu, LIR* head_lir, - LIR* tail_lir) +void Mir2Lir::ApplyLocalOptimizations(LIR* head_lir, LIR* tail_lir) { - if (!(cu->disable_opt & (1 << kLoadStoreElimination))) { - ApplyLoadStoreElimination(cu, head_lir, tail_lir); + if (!(cu_->disable_opt & (1 << kLoadStoreElimination))) { + ApplyLoadStoreElimination(head_lir, tail_lir); } - if (!(cu->disable_opt & (1 << kLoadHoisting))) { - ApplyLoadHoisting(cu, head_lir, tail_lir); + if (!(cu_->disable_opt & (1 << kLoadHoisting))) { + ApplyLoadHoisting(head_lir, tail_lir); } } @@ -466,15 +460,14 @@ void ApplyLocalOptimizations(CompilationUnit* cu, LIR* head_lir, * Note: new redundant branches may be inserted later, and we'll * use a check in final instruction assembly to nop those out. */ -void RemoveRedundantBranches(CompilationUnit* cu) +void Mir2Lir::RemoveRedundantBranches() { LIR* this_lir; - Codegen* cg = cu->cg.get(); - for (this_lir = cu->first_lir_insn; this_lir != cu->last_lir_insn; this_lir = NEXT_LIR(this_lir)) { + for (this_lir = first_lir_insn_; this_lir != last_lir_insn_; this_lir = NEXT_LIR(this_lir)) { /* Branch to the next instruction */ - if (cg->IsUnconditionalBranch(this_lir)) { + if (IsUnconditionalBranch(this_lir)) { LIR* next_lir = this_lir; while (true) { @@ -490,11 +483,11 @@ void RemoveRedundantBranches(CompilationUnit* cu) /* * Found real useful stuff between the branch and the target. - * Need to explicitly check the last_lir_insn here because it + * Need to explicitly check the last_lir_insn_ here because it * might be the last real instruction. */ if (!is_pseudo_opcode(next_lir->opcode) || - (next_lir == cu->last_lir_insn)) + (next_lir == last_lir_insn_)) break; } } diff --git a/src/compiler/dex/quick/mips/assemble_mips.cc b/src/compiler/dex/quick/mips/assemble_mips.cc index c5cd401e48..5223a0ecfd 100644 --- a/src/compiler/dex/quick/mips/assemble_mips.cc +++ b/src/compiler/dex/quick/mips/assemble_mips.cc @@ -15,7 +15,6 @@ */ #include "codegen_mips.h" -#include "compiler/dex/quick/codegen_util.h" #include "mips_lir.h" namespace art { @@ -81,7 +80,7 @@ namespace art { * is expanded to include a nop. This scheme should be replaced with * an assembler pass to fill those slots when possible. */ -const MipsEncodingMap MipsCodegen::EncodingMap[kMipsLast] = { +const MipsEncodingMap MipsMir2Lir::EncodingMap[kMipsLast] = { ENCODING_MAP(kMips32BitData, 0x00000000, kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_UNARY_OP, @@ -457,7 +456,7 @@ const MipsEncodingMap MipsCodegen::EncodingMap[kMipsLast] = { * NOTE: An out-of-range bal isn't supported because it should * never happen with the current PIC model. */ -static void ConvertShortToLongBranch(CompilationUnit* cu, LIR* lir) +void MipsMir2Lir::ConvertShortToLongBranch(LIR* lir) { // For conditional branches we'll need to reverse the sense bool unconditional = false; @@ -482,24 +481,24 @@ static void ConvertShortToLongBranch(CompilationUnit* cu, LIR* lir) } LIR* hop_target = NULL; if (!unconditional) { - hop_target = RawLIR(cu, dalvik_offset, kPseudoTargetLabel); - LIR* hop_branch = RawLIR(cu, dalvik_offset, opcode, lir->operands[0], + hop_target = RawLIR(dalvik_offset, kPseudoTargetLabel); + LIR* hop_branch = RawLIR(dalvik_offset, opcode, lir->operands[0], lir->operands[1], 0, 0, 0, hop_target); InsertLIRBefore(lir, hop_branch); } - LIR* curr_pc = RawLIR(cu, dalvik_offset, kMipsCurrPC); + LIR* curr_pc = RawLIR(dalvik_offset, kMipsCurrPC); InsertLIRBefore(lir, curr_pc); - LIR* anchor = RawLIR(cu, dalvik_offset, kPseudoTargetLabel); - LIR* delta_hi = RawLIR(cu, dalvik_offset, kMipsDeltaHi, r_AT, 0, + LIR* anchor = RawLIR(dalvik_offset, kPseudoTargetLabel); + LIR* delta_hi = RawLIR(dalvik_offset, kMipsDeltaHi, r_AT, 0, reinterpret_cast<uintptr_t>(anchor), 0, 0, lir->target); InsertLIRBefore(lir, delta_hi); InsertLIRBefore(lir, anchor); - LIR* delta_lo = RawLIR(cu, dalvik_offset, kMipsDeltaLo, r_AT, 0, + LIR* delta_lo = RawLIR(dalvik_offset, kMipsDeltaLo, r_AT, 0, reinterpret_cast<uintptr_t>(anchor), 0, 0, lir->target); InsertLIRBefore(lir, delta_lo); - LIR* addu = RawLIR(cu, dalvik_offset, kMipsAddu, r_AT, r_AT, r_RA); + LIR* addu = RawLIR(dalvik_offset, kMipsAddu, r_AT, r_AT, r_RA); InsertLIRBefore(lir, addu); - LIR* jr = RawLIR(cu, dalvik_offset, kMipsJr, r_AT); + LIR* jr = RawLIR(dalvik_offset, kMipsJr, r_AT); InsertLIRBefore(lir, jr); if (!unconditional) { InsertLIRBefore(lir, hop_target); @@ -513,12 +512,12 @@ static void ConvertShortToLongBranch(CompilationUnit* cu, LIR* lir) * instruction. In those cases we will try to substitute a new code * sequence or request that the trace be shortened and retried. */ -AssemblerStatus MipsCodegen::AssembleInstructions(CompilationUnit *cu, uintptr_t start_addr) +AssemblerStatus MipsMir2Lir::AssembleInstructions(uintptr_t start_addr) { LIR *lir; AssemblerStatus res = kSuccess; // Assume success - for (lir = cu->first_lir_insn; lir != NULL; lir = NEXT_LIR(lir)) { + for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) { if (lir->opcode < 0) { continue; } @@ -550,17 +549,17 @@ AssemblerStatus MipsCodegen::AssembleInstructions(CompilationUnit *cu, uintptr_t } else { // Doesn't fit - must expand to kMipsDelta[Hi|Lo] pair LIR *new_delta_hi = - RawLIR(cu, lir->dalvik_offset, kMipsDeltaHi, + RawLIR(lir->dalvik_offset, kMipsDeltaHi, lir->operands[0], 0, lir->operands[2], lir->operands[3], 0, lir->target); InsertLIRBefore(lir, new_delta_hi); LIR *new_delta_lo = - RawLIR(cu, lir->dalvik_offset, kMipsDeltaLo, + RawLIR(lir->dalvik_offset, kMipsDeltaLo, lir->operands[0], 0, lir->operands[2], lir->operands[3], 0, lir->target); InsertLIRBefore(lir, new_delta_lo); LIR *new_addu = - RawLIR(cu, lir->dalvik_offset, kMipsAddu, + RawLIR(lir->dalvik_offset, kMipsAddu, lir->operands[0], lir->operands[0], r_RA); InsertLIRBefore(lir, new_addu); lir->flags.is_nop = true; @@ -588,7 +587,7 @@ AssemblerStatus MipsCodegen::AssembleInstructions(CompilationUnit *cu, uintptr_t } if (delta > 131068 || delta < -131069) { res = kRetryAll; - ConvertShortToLongBranch(cu, lir); + ConvertShortToLongBranch(lir); } else { lir->operands[0] = delta >> 2; } @@ -602,7 +601,7 @@ AssemblerStatus MipsCodegen::AssembleInstructions(CompilationUnit *cu, uintptr_t } if (delta > 131068 || delta < -131069) { res = kRetryAll; - ConvertShortToLongBranch(cu, lir); + ConvertShortToLongBranch(lir); } else { lir->operands[1] = delta >> 2; } @@ -616,7 +615,7 @@ AssemblerStatus MipsCodegen::AssembleInstructions(CompilationUnit *cu, uintptr_t } if (delta > 131068 || delta < -131069) { res = kRetryAll; - ConvertShortToLongBranch(cu, lir); + ConvertShortToLongBranch(lir); } else { lir->operands[2] = delta >> 2; } @@ -691,24 +690,24 @@ AssemblerStatus MipsCodegen::AssembleInstructions(CompilationUnit *cu, uintptr_t } } // We only support little-endian MIPS. - cu->code_buffer.push_back(bits & 0xff); - cu->code_buffer.push_back((bits >> 8) & 0xff); - cu->code_buffer.push_back((bits >> 16) & 0xff); - cu->code_buffer.push_back((bits >> 24) & 0xff); + code_buffer_.push_back(bits & 0xff); + code_buffer_.push_back((bits >> 8) & 0xff); + code_buffer_.push_back((bits >> 16) & 0xff); + code_buffer_.push_back((bits >> 24) & 0xff); // TUNING: replace with proper delay slot handling if (encoder->size == 8) { const MipsEncodingMap *encoder = &EncodingMap[kMipsNop]; uint32_t bits = encoder->skeleton; - cu->code_buffer.push_back(bits & 0xff); - cu->code_buffer.push_back((bits >> 8) & 0xff); - cu->code_buffer.push_back((bits >> 16) & 0xff); - cu->code_buffer.push_back((bits >> 24) & 0xff); + code_buffer_.push_back(bits & 0xff); + code_buffer_.push_back((bits >> 8) & 0xff); + code_buffer_.push_back((bits >> 16) & 0xff); + code_buffer_.push_back((bits >> 24) & 0xff); } } return res; } -int MipsCodegen::GetInsnSize(LIR* lir) +int MipsMir2Lir::GetInsnSize(LIR* lir) { return EncodingMap[lir->opcode].size; } diff --git a/src/compiler/dex/quick/mips/call_mips.cc b/src/compiler/dex/quick/mips/call_mips.cc index d7f9dce792..f73e602d47 100644 --- a/src/compiler/dex/quick/mips/call_mips.cc +++ b/src/compiler/dex/quick/mips/call_mips.cc @@ -17,14 +17,12 @@ /* This file contains codegen for the Mips ISA */ #include "codegen_mips.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "mips_lir.h" #include "oat/runtime/oat_support_entrypoints.h" namespace art { -void MipsCodegen::GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, +void MipsMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, SpecialCaseHandler special_case) { // TODO @@ -61,22 +59,22 @@ void MipsCodegen::GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, * done: * */ -void MipsCodegen::GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, +void MipsMir2Lir::GenSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; - if (cu->verbose) { + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + if (cu_->verbose) { DumpSparseSwitchTable(table); } // Add the table to the list - we'll process it later SwitchTable *tab_rec = - static_cast<SwitchTable*>(NewMem(cu, sizeof(SwitchTable), true, kAllocData)); + static_cast<SwitchTable*>(NewMem(cu_, sizeof(SwitchTable), true, kAllocData)); tab_rec->table = table; - tab_rec->vaddr = cu->current_dalvik_offset; + tab_rec->vaddr = current_dalvik_offset_; int elements = table[1]; tab_rec->targets = - static_cast<LIR**>(NewMem(cu, elements * sizeof(LIR*), true, kAllocLIR)); - InsertGrowableList(cu, &cu->switch_tables, reinterpret_cast<uintptr_t>(tab_rec)); + static_cast<LIR**>(NewMem(cu_, elements * sizeof(LIR*), true, kAllocLIR)); + InsertGrowableList(cu_, &switch_tables_, reinterpret_cast<uintptr_t>(tab_rec)); // The table is composed of 8-byte key/disp pairs int byte_size = elements * 8; @@ -84,47 +82,47 @@ void MipsCodegen::GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_ int size_hi = byte_size >> 16; int size_lo = byte_size & 0xffff; - int rEnd = AllocTemp(cu); + int rEnd = AllocTemp(); if (size_hi) { - NewLIR2(cu, kMipsLui, rEnd, size_hi); + NewLIR2(kMipsLui, rEnd, size_hi); } // Must prevent code motion for the curr pc pair - GenBarrier(cu); // Scheduling barrier - NewLIR0(cu, kMipsCurrPC); // Really a jal to .+8 + GenBarrier(); // Scheduling barrier + NewLIR0(kMipsCurrPC); // Really a jal to .+8 // Now, fill the branch delay slot if (size_hi) { - NewLIR3(cu, kMipsOri, rEnd, rEnd, size_lo); + NewLIR3(kMipsOri, rEnd, rEnd, size_lo); } else { - NewLIR3(cu, kMipsOri, rEnd, r_ZERO, size_lo); + NewLIR3(kMipsOri, rEnd, r_ZERO, size_lo); } - GenBarrier(cu); // Scheduling barrier + GenBarrier(); // Scheduling barrier // Construct BaseLabel and set up table base register - LIR* base_label = NewLIR0(cu, kPseudoTargetLabel); + LIR* base_label = NewLIR0(kPseudoTargetLabel); // Remember base label so offsets can be computed later tab_rec->anchor = base_label; - int rBase = AllocTemp(cu); - NewLIR4(cu, kMipsDelta, rBase, 0, reinterpret_cast<uintptr_t>(base_label), + int rBase = AllocTemp(); + NewLIR4(kMipsDelta, rBase, 0, reinterpret_cast<uintptr_t>(base_label), reinterpret_cast<uintptr_t>(tab_rec)); - OpRegRegReg(cu, kOpAdd, rEnd, rEnd, rBase); + OpRegRegReg(kOpAdd, rEnd, rEnd, rBase); // Grab switch test value - rl_src = LoadValue(cu, rl_src, kCoreReg); + rl_src = LoadValue(rl_src, kCoreReg); // Test loop - int r_key = AllocTemp(cu); - LIR* loop_label = NewLIR0(cu, kPseudoTargetLabel); - LIR* exit_branch = OpCmpBranch(cu , kCondEq, rBase, rEnd, NULL); - LoadWordDisp(cu, rBase, 0, r_key); - OpRegImm(cu, kOpAdd, rBase, 8); - OpCmpBranch(cu, kCondNe, rl_src.low_reg, r_key, loop_label); - int r_disp = AllocTemp(cu); - LoadWordDisp(cu, rBase, -4, r_disp); - OpRegRegReg(cu, kOpAdd, r_RA, r_RA, r_disp); - OpReg(cu, kOpBx, r_RA); + int r_key = AllocTemp(); + LIR* loop_label = NewLIR0(kPseudoTargetLabel); + LIR* exit_branch = OpCmpBranch(kCondEq, rBase, rEnd, NULL); + LoadWordDisp(rBase, 0, r_key); + OpRegImm(kOpAdd, rBase, 8); + OpCmpBranch(kCondNe, rl_src.low_reg, r_key, loop_label); + int r_disp = AllocTemp(); + LoadWordDisp(rBase, -4, r_disp); + OpRegRegReg(kOpAdd, r_RA, r_RA, r_disp); + OpReg(kOpBx, r_RA); // Loop exit - LIR* exit_label = NewLIR0(cu, kPseudoTargetLabel); + LIR* exit_label = NewLIR0(kPseudoTargetLabel); exit_branch->target = exit_label; } @@ -141,24 +139,24 @@ void MipsCodegen::GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_ * jr r_RA * done: */ -void MipsCodegen::GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, +void MipsMir2Lir::GenPackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; - if (cu->verbose) { + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + if (cu_->verbose) { DumpPackedSwitchTable(table); } // Add the table to the list - we'll process it later SwitchTable *tab_rec = - static_cast<SwitchTable*>(NewMem(cu, sizeof(SwitchTable), true, kAllocData)); + static_cast<SwitchTable*>(NewMem(cu_, sizeof(SwitchTable), true, kAllocData)); tab_rec->table = table; - tab_rec->vaddr = cu->current_dalvik_offset; + tab_rec->vaddr = current_dalvik_offset_; int size = table[1]; - tab_rec->targets = static_cast<LIR**>(NewMem(cu, size * sizeof(LIR*), true, kAllocLIR)); - InsertGrowableList(cu, &cu->switch_tables, reinterpret_cast<uintptr_t>(tab_rec)); + tab_rec->targets = static_cast<LIR**>(NewMem(cu_, size * sizeof(LIR*), true, kAllocLIR)); + InsertGrowableList(cu_, &switch_tables_, reinterpret_cast<uintptr_t>(tab_rec)); // Get the switch value - rl_src = LoadValue(cu, rl_src, kCoreReg); + rl_src = LoadValue(rl_src, kCoreReg); // Prepare the bias. If too big, handle 1st stage here int low_key = s4FromSwitchData(&table[2]); @@ -167,51 +165,51 @@ void MipsCodegen::GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_ if (low_key == 0) { r_key = rl_src.low_reg; } else if ((low_key & 0xffff) != low_key) { - r_key = AllocTemp(cu); - LoadConstant(cu, r_key, low_key); + r_key = AllocTemp(); + LoadConstant(r_key, low_key); large_bias = true; } else { - r_key = AllocTemp(cu); + r_key = AllocTemp(); } // Must prevent code motion for the curr pc pair - GenBarrier(cu); - NewLIR0(cu, kMipsCurrPC); // Really a jal to .+8 + GenBarrier(); + NewLIR0(kMipsCurrPC); // Really a jal to .+8 // Now, fill the branch delay slot with bias strip if (low_key == 0) { - NewLIR0(cu, kMipsNop); + NewLIR0(kMipsNop); } else { if (large_bias) { - OpRegRegReg(cu, kOpSub, r_key, rl_src.low_reg, r_key); + OpRegRegReg(kOpSub, r_key, rl_src.low_reg, r_key); } else { - OpRegRegImm(cu, kOpSub, r_key, rl_src.low_reg, low_key); + OpRegRegImm(kOpSub, r_key, rl_src.low_reg, low_key); } } - GenBarrier(cu); // Scheduling barrier + GenBarrier(); // Scheduling barrier // Construct BaseLabel and set up table base register - LIR* base_label = NewLIR0(cu, kPseudoTargetLabel); + LIR* base_label = NewLIR0(kPseudoTargetLabel); // Remember base label so offsets can be computed later tab_rec->anchor = base_label; // Bounds check - if < 0 or >= size continue following switch - LIR* branch_over = OpCmpImmBranch(cu, kCondHi, r_key, size-1, NULL); + LIR* branch_over = OpCmpImmBranch(kCondHi, r_key, size-1, NULL); // Materialize the table base pointer - int rBase = AllocTemp(cu); - NewLIR4(cu, kMipsDelta, rBase, 0, reinterpret_cast<uintptr_t>(base_label), + int rBase = AllocTemp(); + NewLIR4(kMipsDelta, rBase, 0, reinterpret_cast<uintptr_t>(base_label), reinterpret_cast<uintptr_t>(tab_rec)); // Load the displacement from the switch table - int r_disp = AllocTemp(cu); - LoadBaseIndexed(cu, rBase, r_key, r_disp, 2, kWord); + int r_disp = AllocTemp(); + LoadBaseIndexed(rBase, r_key, r_disp, 2, kWord); // Add to r_AP and go - OpRegRegReg(cu, kOpAdd, r_RA, r_RA, r_disp); - OpReg(cu, kOpBx, r_RA); + OpRegRegReg(kOpAdd, r_RA, r_RA, r_disp); + OpReg(kOpBx, r_RA); /* branch_over target here */ - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); branch_over->target = target; } @@ -225,165 +223,165 @@ void MipsCodegen::GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_ * * Total size is 4+(width * size + 1)/2 16-bit code units. */ -void MipsCodegen::GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, RegLocation rl_src) +void MipsMir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; // Add the table to the list - we'll process it later FillArrayData *tab_rec = - reinterpret_cast<FillArrayData*>(NewMem(cu, sizeof(FillArrayData), true, kAllocData)); + reinterpret_cast<FillArrayData*>(NewMem(cu_, sizeof(FillArrayData), true, kAllocData)); tab_rec->table = table; - tab_rec->vaddr = cu->current_dalvik_offset; + tab_rec->vaddr = current_dalvik_offset_; uint16_t width = tab_rec->table[1]; uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16); tab_rec->size = (size * width) + 8; - InsertGrowableList(cu, &cu->fill_array_data, reinterpret_cast<uintptr_t>(tab_rec)); + InsertGrowableList(cu_, &fill_array_data_, reinterpret_cast<uintptr_t>(tab_rec)); // Making a call - use explicit registers - FlushAllRegs(cu); /* Everything to home location */ - LockCallTemps(cu); - LoadValueDirectFixed(cu, rl_src, rMIPS_ARG0); + FlushAllRegs(); /* Everything to home location */ + LockCallTemps(); + LoadValueDirectFixed(rl_src, rMIPS_ARG0); // Must prevent code motion for the curr pc pair - GenBarrier(cu); - NewLIR0(cu, kMipsCurrPC); // Really a jal to .+8 + GenBarrier(); + NewLIR0(kMipsCurrPC); // Really a jal to .+8 // Now, fill the branch delay slot with the helper load - int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode)); - GenBarrier(cu); // Scheduling barrier + int r_tgt = LoadHelper(ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode)); + GenBarrier(); // Scheduling barrier // Construct BaseLabel and set up table base register - LIR* base_label = NewLIR0(cu, kPseudoTargetLabel); + LIR* base_label = NewLIR0(kPseudoTargetLabel); // Materialize a pointer to the fill data image - NewLIR4(cu, kMipsDelta, rMIPS_ARG1, 0, reinterpret_cast<uintptr_t>(base_label), + NewLIR4(kMipsDelta, rMIPS_ARG1, 0, reinterpret_cast<uintptr_t>(base_label), reinterpret_cast<uintptr_t>(tab_rec)); // And go... - ClobberCalleeSave(cu); - LIR* call_inst = OpReg(cu, kOpBlx, r_tgt); // ( array*, fill_data* ) - MarkSafepointPC(cu, call_inst); + ClobberCalleeSave(); + LIR* call_inst = OpReg(kOpBlx, r_tgt); // ( array*, fill_data* ) + MarkSafepointPC(call_inst); } /* * TODO: implement fast path to short-circuit thin-lock case */ -void MipsCodegen::GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation rl_src) +void MipsMir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) { - FlushAllRegs(cu); - LoadValueDirectFixed(cu, rl_src, rMIPS_ARG0); // Get obj - LockCallTemps(cu); // Prepare for explicit register usage - GenNullCheck(cu, rl_src.s_reg_low, rMIPS_ARG0, opt_flags); + FlushAllRegs(); + LoadValueDirectFixed(rl_src, rMIPS_ARG0); // Get obj + LockCallTemps(); // Prepare for explicit register usage + GenNullCheck(rl_src.s_reg_low, rMIPS_ARG0, opt_flags); // Go expensive route - artLockObjectFromCode(self, obj); - int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pLockObjectFromCode)); - ClobberCalleeSave(cu); - LIR* call_inst = OpReg(cu, kOpBlx, r_tgt); - MarkSafepointPC(cu, call_inst); + int r_tgt = LoadHelper(ENTRYPOINT_OFFSET(pLockObjectFromCode)); + ClobberCalleeSave(); + LIR* call_inst = OpReg(kOpBlx, r_tgt); + MarkSafepointPC(call_inst); } /* * TODO: implement fast path to short-circuit thin-lock case */ -void MipsCodegen::GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation rl_src) +void MipsMir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) { - FlushAllRegs(cu); - LoadValueDirectFixed(cu, rl_src, rMIPS_ARG0); // Get obj - LockCallTemps(cu); // Prepare for explicit register usage - GenNullCheck(cu, rl_src.s_reg_low, rMIPS_ARG0, opt_flags); + FlushAllRegs(); + LoadValueDirectFixed(rl_src, rMIPS_ARG0); // Get obj + LockCallTemps(); // Prepare for explicit register usage + GenNullCheck(rl_src.s_reg_low, rMIPS_ARG0, opt_flags); // Go expensive route - UnlockObjectFromCode(obj); - int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pUnlockObjectFromCode)); - ClobberCalleeSave(cu); - LIR* call_inst = OpReg(cu, kOpBlx, r_tgt); - MarkSafepointPC(cu, call_inst); + int r_tgt = LoadHelper(ENTRYPOINT_OFFSET(pUnlockObjectFromCode)); + ClobberCalleeSave(); + LIR* call_inst = OpReg(kOpBlx, r_tgt); + MarkSafepointPC(call_inst); } -void MipsCodegen::GenMoveException(CompilationUnit* cu, RegLocation rl_dest) +void MipsMir2Lir::GenMoveException(RegLocation rl_dest) { int ex_offset = Thread::ExceptionOffset().Int32Value(); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int reset_reg = AllocTemp(cu); - LoadWordDisp(cu, rMIPS_SELF, ex_offset, rl_result.low_reg); - LoadConstant(cu, reset_reg, 0); - StoreWordDisp(cu, rMIPS_SELF, ex_offset, reset_reg); - FreeTemp(cu, reset_reg); - StoreValue(cu, rl_dest, rl_result); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + int reset_reg = AllocTemp(); + LoadWordDisp(rMIPS_SELF, ex_offset, rl_result.low_reg); + LoadConstant(reset_reg, 0); + StoreWordDisp(rMIPS_SELF, ex_offset, reset_reg); + FreeTemp(reset_reg); + StoreValue(rl_dest, rl_result); } /* * Mark garbage collection card. Skip if the value we're storing is null. */ -void MipsCodegen::MarkGCCard(CompilationUnit* cu, int val_reg, int tgt_addr_reg) +void MipsMir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg) { - int reg_card_base = AllocTemp(cu); - int reg_card_no = AllocTemp(cu); - LIR* branch_over = OpCmpImmBranch(cu, kCondEq, val_reg, 0, NULL); - LoadWordDisp(cu, rMIPS_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base); - OpRegRegImm(cu, kOpLsr, reg_card_no, tgt_addr_reg, CardTable::kCardShift); - StoreBaseIndexed(cu, reg_card_base, reg_card_no, reg_card_base, 0, + int reg_card_base = AllocTemp(); + int reg_card_no = AllocTemp(); + LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL); + LoadWordDisp(rMIPS_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base); + OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, CardTable::kCardShift); + StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte); - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); branch_over->target = target; - FreeTemp(cu, reg_card_base); - FreeTemp(cu, reg_card_no); + FreeTemp(reg_card_base); + FreeTemp(reg_card_no); } -void MipsCodegen::GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl_method) +void MipsMir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) { - int spill_count = cu->num_core_spills + cu->num_fp_spills; + int spill_count = num_core_spills_ + num_fp_spills_; /* * On entry, rMIPS_ARG0, rMIPS_ARG1, rMIPS_ARG2 & rMIPS_ARG3 are live. Let the register * allocation mechanism know so it doesn't try to use any of them when * expanding the frame or flushing. This leaves the utility * code with a single temp: r12. This should be enough. */ - LockTemp(cu, rMIPS_ARG0); - LockTemp(cu, rMIPS_ARG1); - LockTemp(cu, rMIPS_ARG2); - LockTemp(cu, rMIPS_ARG3); + LockTemp(rMIPS_ARG0); + LockTemp(rMIPS_ARG1); + LockTemp(rMIPS_ARG2); + LockTemp(rMIPS_ARG3); /* * We can safely skip the stack overflow check if we're * a leaf *and* our frame size < fudge factor. */ - bool skip_overflow_check = ((cu->attributes & METHOD_IS_LEAF) && - (static_cast<size_t>(cu->frame_size) < Thread::kStackOverflowReservedBytes)); - NewLIR0(cu, kPseudoMethodEntry); - int check_reg = AllocTemp(cu); - int new_sp = AllocTemp(cu); + bool skip_overflow_check = (mir_graph_->MethodIsLeaf() && + (static_cast<size_t>(frame_size_) < Thread::kStackOverflowReservedBytes)); + NewLIR0(kPseudoMethodEntry); + int check_reg = AllocTemp(); + int new_sp = AllocTemp(); if (!skip_overflow_check) { /* Load stack limit */ - LoadWordDisp(cu, rMIPS_SELF, Thread::StackEndOffset().Int32Value(), check_reg); + LoadWordDisp(rMIPS_SELF, Thread::StackEndOffset().Int32Value(), check_reg); } /* Spill core callee saves */ - SpillCoreRegs(cu); + SpillCoreRegs(); /* NOTE: promotion of FP regs currently unsupported, thus no FP spill */ - DCHECK_EQ(cu->num_fp_spills, 0); + DCHECK_EQ(num_fp_spills_, 0); if (!skip_overflow_check) { - OpRegRegImm(cu, kOpSub, new_sp, rMIPS_SP, cu->frame_size - (spill_count * 4)); - GenRegRegCheck(cu, kCondCc, new_sp, check_reg, kThrowStackOverflow); - OpRegCopy(cu, rMIPS_SP, new_sp); // Establish stack + OpRegRegImm(kOpSub, new_sp, rMIPS_SP, frame_size_ - (spill_count * 4)); + GenRegRegCheck(kCondCc, new_sp, check_reg, kThrowStackOverflow); + OpRegCopy(rMIPS_SP, new_sp); // Establish stack } else { - OpRegImm(cu, kOpSub, rMIPS_SP, cu->frame_size - (spill_count * 4)); + OpRegImm(kOpSub, rMIPS_SP, frame_size_ - (spill_count * 4)); } - FlushIns(cu, ArgLocs, rl_method); + FlushIns(ArgLocs, rl_method); - FreeTemp(cu, rMIPS_ARG0); - FreeTemp(cu, rMIPS_ARG1); - FreeTemp(cu, rMIPS_ARG2); - FreeTemp(cu, rMIPS_ARG3); + FreeTemp(rMIPS_ARG0); + FreeTemp(rMIPS_ARG1); + FreeTemp(rMIPS_ARG2); + FreeTemp(rMIPS_ARG3); } -void MipsCodegen::GenExitSequence(CompilationUnit* cu) +void MipsMir2Lir::GenExitSequence() { /* * In the exit path, rMIPS_RET0/rMIPS_RET1 are live - make sure they aren't * allocated by the register utilities as temps. */ - LockTemp(cu, rMIPS_RET0); - LockTemp(cu, rMIPS_RET1); + LockTemp(rMIPS_RET0); + LockTemp(rMIPS_RET1); - NewLIR0(cu, kPseudoMethodExit); - UnSpillCoreRegs(cu); - OpReg(cu, kOpBx, r_RA); + NewLIR0(kPseudoMethodExit); + UnSpillCoreRegs(); + OpReg(kOpBx, r_RA); } } // namespace art diff --git a/src/compiler/dex/quick/mips/codegen_mips.h b/src/compiler/dex/quick/mips/codegen_mips.h index c9d0e219e9..f681eda8e7 100644 --- a/src/compiler/dex/quick/mips/codegen_mips.h +++ b/src/compiler/dex/quick/mips/codegen_mips.h @@ -22,64 +22,60 @@ namespace art { -class MipsCodegen : public Codegen { +class MipsMir2Lir : public Mir2Lir { public: + + MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph); + // Required for target - codegen utilities. - virtual bool SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode, - RegLocation rl_src, RegLocation rl_dest, int lit); - virtual int LoadHelper(CompilationUnit* cu, int offset); - virtual LIR* LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest, - OpSize size, int s_reg); - virtual LIR* LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo, - int r_dest_hi, int s_reg); - virtual LIR* LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest, int scale, - OpSize size); - virtual LIR* LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, - int displacement, int r_dest, int r_dest_hi, OpSize size, - int s_reg); - virtual LIR* LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value); - virtual LIR* LoadConstantWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi, int64_t value); - virtual LIR* StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src, - OpSize size); - virtual LIR* StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_src_lo, - int r_src_hi); - virtual LIR* StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src, int scale, - OpSize size); - virtual LIR* StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, - int displacement, int r_src, int r_src_hi, OpSize size, - int s_reg); - virtual void MarkGCCard(CompilationUnit* cu, int val_reg, int tgt_addr_reg); + virtual bool SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src, + RegLocation rl_dest, int lit); + virtual int LoadHelper(int offset); + virtual LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg); + virtual LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi, + int s_reg); + virtual LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size); + virtual LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_dest, int r_dest_hi, OpSize size, int s_reg); + virtual LIR* LoadConstantNoClobber(int r_dest, int value); + virtual LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value); + virtual LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size); + virtual LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi); + virtual LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size); + virtual LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_src, int r_src_hi, OpSize size, int s_reg); + virtual void MarkGCCard(int val_reg, int tgt_addr_reg); // Required for target - register utilities. virtual bool IsFpReg(int reg); virtual bool SameRegType(int reg1, int reg2); - virtual int AllocTypedTemp(CompilationUnit* cu, bool fp_hint, int reg_class); - virtual int AllocTypedTempPair(CompilationUnit* cu, bool fp_hint, int reg_class); + virtual int AllocTypedTemp(bool fp_hint, int reg_class); + virtual int AllocTypedTempPair(bool fp_hint, int reg_class); virtual int S2d(int low_reg, int high_reg); virtual int TargetReg(SpecialTargetRegister reg); - virtual RegisterInfo* GetRegInfo(CompilationUnit* cu, int reg); - virtual RegLocation GetReturnAlt(CompilationUnit* cu); - virtual RegLocation GetReturnWideAlt(CompilationUnit* cu); + virtual RegisterInfo* GetRegInfo(int reg); + virtual RegLocation GetReturnAlt(); + virtual RegLocation GetReturnWideAlt(); virtual RegLocation LocCReturn(); virtual RegLocation LocCReturnDouble(); virtual RegLocation LocCReturnFloat(); virtual RegLocation LocCReturnWide(); virtual uint32_t FpRegMask(); - virtual uint64_t GetRegMaskCommon(CompilationUnit* cu, int reg); - virtual void AdjustSpillMask(CompilationUnit* cu); - virtual void ClobberCalleeSave(CompilationUnit *cu); - virtual void FlushReg(CompilationUnit* cu, int reg); - virtual void FlushRegWide(CompilationUnit* cu, int reg1, int reg2); - virtual void FreeCallTemps(CompilationUnit* cu); - virtual void FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, RegLocation rl_free); - virtual void LockCallTemps(CompilationUnit* cu); - virtual void MarkPreservedSingle(CompilationUnit* cu, int v_reg, int reg); - virtual void CompilerInitializeRegAlloc(CompilationUnit* cu); + virtual uint64_t GetRegMaskCommon(int reg); + virtual void AdjustSpillMask(); + virtual void ClobberCalleeSave(); + virtual void FlushReg(int reg); + virtual void FlushRegWide(int reg1, int reg2); + virtual void FreeCallTemps(); + virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free); + virtual void LockCallTemps(); + virtual void MarkPreservedSingle(int v_reg, int reg); + virtual void CompilerInitializeRegAlloc(); // Required for target - miscellaneous. - virtual AssemblerStatus AssembleInstructions(CompilationUnit* cu, uintptr_t start_addr); + virtual AssemblerStatus AssembleInstructions(uintptr_t start_addr); virtual void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix); - virtual void SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir); + virtual void SetupTargetResourceMasks(LIR* lir); virtual const char* GetTargetInstFmt(int opcode); virtual const char* GetTargetInstName(int opcode); virtual std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr); @@ -89,118 +85,97 @@ class MipsCodegen : public Codegen { virtual bool IsUnconditionalBranch(LIR* lir); // Required for target - Dalvik-level generators. - virtual void GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, + virtual void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); - virtual void GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, - RegLocation rl_index, RegLocation rl_src, int scale); - virtual void GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, + virtual void GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index, + RegLocation rl_src, int scale); + virtual void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale); - virtual void GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, + virtual void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale); - virtual void GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_shift); - virtual void GenMulLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenAndLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenArithOpDouble(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest, + virtual void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_shift); + virtual void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenAndLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2); + virtual void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); - virtual void GenCmpFP(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); - virtual void GenConversion(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src); - virtual bool GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier); - virtual bool GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min); - virtual bool GenInlinedSqrt(CompilationUnit* cu, CallInfo* info); - virtual void GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenOrLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual LIR* GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code, int reg1, int base, - int offset, ThrowKind kind); - virtual RegLocation GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int reg_hi, - bool is_div); - virtual RegLocation GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int lit, - bool is_div); - virtual void GenCmpLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi); - virtual void GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, - RegLocation rl_method); - virtual void GenExitSequence(CompilationUnit* cu); - virtual void GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, - RegLocation rl_src); - virtual void GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, bool gt_bias, - bool is_double); - virtual void GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir); - virtual void GenSelect(CompilationUnit* cu, BasicBlock* bb, MIR* mir); - virtual void GenMemBarrier(CompilationUnit* cu, MemBarrierKind barrier_kind); - virtual void GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation rl_src); - virtual void GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation rl_src); - virtual void GenMoveException(CompilationUnit* cu, RegLocation rl_dest); - virtual void GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src, - RegLocation rl_result, int lit, int first_bit, - int second_bit); - virtual void GenNegDouble(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenNegFloat(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, - RegLocation rl_src); - virtual void GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, - RegLocation rl_src); - virtual void GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, - SpecialCaseHandler special_case); + virtual void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2); + virtual void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src); + virtual bool GenInlinedCas32(CallInfo* info, bool need_write_barrier); + virtual bool GenInlinedMinMaxInt(CallInfo* info, bool is_min); + virtual bool GenInlinedSqrt(CallInfo* info); + virtual void GenNegLong(RegLocation rl_dest, RegLocation rl_src); + virtual void GenOrLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenXorLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset, + ThrowKind kind); + virtual RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div); + virtual RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div); + virtual void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenDivZeroCheck(int reg_lo, int reg_hi); + virtual void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method); + virtual void GenExitSequence(); + virtual void GenFillArrayData(uint32_t table_offset, RegLocation rl_src); + virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double); + virtual void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir); + virtual void GenSelect(BasicBlock* bb, MIR* mir); + virtual void GenMemBarrier(MemBarrierKind barrier_kind); + virtual void GenMonitorEnter(int opt_flags, RegLocation rl_src); + virtual void GenMonitorExit(int opt_flags, RegLocation rl_src); + virtual void GenMoveException(RegLocation rl_dest); + virtual void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit, + int first_bit, int second_bit); + virtual void GenNegDouble(RegLocation rl_dest, RegLocation rl_src); + virtual void GenNegFloat(RegLocation rl_dest, RegLocation rl_src); + virtual void GenPackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src); + virtual void GenSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src); + virtual void GenSpecialCase(BasicBlock* bb, MIR* mir, SpecialCaseHandler special_case); // Required for target - single operation generators. - virtual LIR* OpUnconditionalBranch(CompilationUnit* cu, LIR* target); - virtual LIR* OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, int src2, - LIR* target); - virtual LIR* OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg, int check_value, - LIR* target); - virtual LIR* OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target); - virtual LIR* OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, - LIR* target); - virtual LIR* OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpIT(CompilationUnit* cu, ConditionCode cond, const char* guide); - virtual LIR* OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp); - virtual LIR* OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target); - virtual LIR* OpReg(CompilationUnit* cu, OpKind op, int r_dest_src); - virtual LIR* OpRegCopy(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpRegCopyNoInsert(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value); - virtual LIR* OpRegMem(CompilationUnit* cu, OpKind op, int r_dest, int rBase, int offset); - virtual LIR* OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2); - virtual LIR* OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value); - virtual LIR* OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, - int r_src2); - virtual LIR* OpTestSuspend(CompilationUnit* cu, LIR* target); - virtual LIR* OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset); - virtual LIR* OpVldm(CompilationUnit* cu, int rBase, int count); - virtual LIR* OpVstm(CompilationUnit* cu, int rBase, int count); - virtual void OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, - int offset); - virtual void OpRegCopyWide(CompilationUnit* cu, int dest_lo, int dest_hi, int src_lo, - int src_hi); - virtual void OpTlsCmp(CompilationUnit* cu, int offset, int val); + virtual LIR* OpUnconditionalBranch(LIR* target); + virtual LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target); + virtual LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target); + virtual LIR* OpCondBranch(ConditionCode cc, LIR* target); + virtual LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target); + virtual LIR* OpFpRegCopy(int r_dest, int r_src); + virtual LIR* OpIT(ConditionCode cond, const char* guide); + virtual LIR* OpMem(OpKind op, int rBase, int disp); + virtual LIR* OpPcRelLoad(int reg, LIR* target); + virtual LIR* OpReg(OpKind op, int r_dest_src); + virtual LIR* OpRegCopy(int r_dest, int r_src); + virtual LIR* OpRegCopyNoInsert(int r_dest, int r_src); + virtual LIR* OpRegImm(OpKind op, int r_dest_src1, int value); + virtual LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset); + virtual LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2); + virtual LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value); + virtual LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2); + virtual LIR* OpTestSuspend(LIR* target); + virtual LIR* OpThreadMem(OpKind op, int thread_offset); + virtual LIR* OpVldm(int rBase, int count); + virtual LIR* OpVstm(int rBase, int count); + virtual void OpLea(int rBase, int reg1, int reg2, int scale, int offset); + virtual void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi); + virtual void OpTlsCmp(int offset, int val); - LIR* LoadBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_dest, - int r_dest_hi, OpSize size, int s_reg); - LIR* StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_src, - int r_src_hi, OpSize size); - void SpillCoreRegs(CompilationUnit* cu); - void UnSpillCoreRegs(CompilationUnit* cu); + LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size, + int s_reg); + LIR* StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size); + void SpillCoreRegs(); + void UnSpillCoreRegs(); static const MipsEncodingMap EncodingMap[kMipsLast]; bool InexpensiveConstantInt(int32_t value); bool InexpensiveConstantFloat(int32_t value); bool InexpensiveConstantLong(int64_t value); bool InexpensiveConstantDouble(int64_t value); + + private: + void ConvertShortToLongBranch(LIR* lir); + }; } // namespace art diff --git a/src/compiler/dex/quick/mips/fp_mips.cc b/src/compiler/dex/quick/mips/fp_mips.cc index 96007d8c6e..5ddec00e80 100644 --- a/src/compiler/dex/quick/mips/fp_mips.cc +++ b/src/compiler/dex/quick/mips/fp_mips.cc @@ -15,14 +15,12 @@ */ #include "codegen_mips.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "mips_lir.h" #include "oat/runtime/oat_support_entrypoints.h" namespace art { -void MipsCodegen::GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode, +void MipsMir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { int op = kMipsNop; @@ -51,25 +49,25 @@ void MipsCodegen::GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode, break; case Instruction::REM_FLOAT_2ADDR: case Instruction::REM_FLOAT: - FlushAllRegs(cu); // Send everything to home location - CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false); - rl_result = GetReturn(cu, true); - StoreValue(cu, rl_dest, rl_result); + FlushAllRegs(); // Send everything to home location + CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false); + rl_result = GetReturn(true); + StoreValue(rl_dest, rl_result); return; case Instruction::NEG_FLOAT: - GenNegFloat(cu, rl_dest, rl_src1); + GenNegFloat(rl_dest, rl_src1); return; default: LOG(FATAL) << "Unexpected opcode: " << opcode; } - rl_src1 = LoadValue(cu, rl_src1, kFPReg); - rl_src2 = LoadValue(cu, rl_src2, kFPReg); - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR3(cu, op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); - StoreValue(cu, rl_dest, rl_result); + rl_src1 = LoadValue(rl_src1, kFPReg); + rl_src2 = LoadValue(rl_src2, kFPReg); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR3(op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); + StoreValue(rl_dest, rl_result); } -void MipsCodegen::GenArithOpDouble(CompilationUnit *cu, Instruction::Code opcode, +void MipsMir2Lir::GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { int op = kMipsNop; @@ -94,30 +92,30 @@ void MipsCodegen::GenArithOpDouble(CompilationUnit *cu, Instruction::Code opcode break; case Instruction::REM_DOUBLE_2ADDR: case Instruction::REM_DOUBLE: - FlushAllRegs(cu); // Send everything to home location - CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false); - rl_result = GetReturnWide(cu, true); - StoreValueWide(cu, rl_dest, rl_result); + FlushAllRegs(); // Send everything to home location + CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false); + rl_result = GetReturnWide(true); + StoreValueWide(rl_dest, rl_result); return; case Instruction::NEG_DOUBLE: - GenNegDouble(cu, rl_dest, rl_src1); + GenNegDouble(rl_dest, rl_src1); return; default: LOG(FATAL) << "Unpexpected opcode: " << opcode; } - rl_src1 = LoadValueWide(cu, rl_src1, kFPReg); + rl_src1 = LoadValueWide(rl_src1, kFPReg); DCHECK(rl_src1.wide); - rl_src2 = LoadValueWide(cu, rl_src2, kFPReg); + rl_src2 = LoadValueWide(rl_src2, kFPReg); DCHECK(rl_src2.wide); - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); + rl_result = EvalLoc(rl_dest, kFPReg, true); DCHECK(rl_dest.wide); DCHECK(rl_result.wide); - NewLIR3(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg), + NewLIR3(op, S2d(rl_result.low_reg, rl_result.high_reg), S2d(rl_src1.low_reg, rl_src1.high_reg), S2d(rl_src2.low_reg, rl_src2.high_reg)); - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void MipsCodegen::GenConversion(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest, +void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) { int op = kMipsNop; @@ -137,45 +135,45 @@ void MipsCodegen::GenConversion(CompilationUnit *cu, Instruction::Code opcode, R op = kMipsFcvtdw; break; case Instruction::FLOAT_TO_INT: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2iz), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pF2iz), rl_dest, rl_src); return; case Instruction::DOUBLE_TO_INT: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2iz), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pD2iz), rl_dest, rl_src); return; case Instruction::LONG_TO_DOUBLE: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src); return; case Instruction::FLOAT_TO_LONG: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src); return; case Instruction::LONG_TO_FLOAT: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src); return; case Instruction::DOUBLE_TO_LONG: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src); return; default: LOG(FATAL) << "Unexpected opcode: " << opcode; } if (rl_src.wide) { - rl_src = LoadValueWide(cu, rl_src, kFPReg); + rl_src = LoadValueWide(rl_src, kFPReg); src_reg = S2d(rl_src.low_reg, rl_src.high_reg); } else { - rl_src = LoadValue(cu, rl_src, kFPReg); + rl_src = LoadValue(rl_src, kFPReg); src_reg = rl_src.low_reg; } if (rl_dest.wide) { - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg); - StoreValueWide(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg); + StoreValueWide(rl_dest, rl_result); } else { - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, op, rl_result.low_reg, src_reg); - StoreValue(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(op, rl_result.low_reg, src_reg); + StoreValue(rl_dest, rl_result); } } -void MipsCodegen::GenCmpFP(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest, +void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { bool wide = true; @@ -199,48 +197,48 @@ void MipsCodegen::GenCmpFP(CompilationUnit *cu, Instruction::Code opcode, RegLoc default: LOG(FATAL) << "Unexpected opcode: " << opcode; } - FlushAllRegs(cu); - LockCallTemps(cu); + FlushAllRegs(); + LockCallTemps(); if (wide) { - LoadValueDirectWideFixed(cu, rl_src1, rMIPS_FARG0, rMIPS_FARG1); - LoadValueDirectWideFixed(cu, rl_src2, rMIPS_FARG2, rMIPS_FARG3); + LoadValueDirectWideFixed(rl_src1, rMIPS_FARG0, rMIPS_FARG1); + LoadValueDirectWideFixed(rl_src2, rMIPS_FARG2, rMIPS_FARG3); } else { - LoadValueDirectFixed(cu, rl_src1, rMIPS_FARG0); - LoadValueDirectFixed(cu, rl_src2, rMIPS_FARG2); + LoadValueDirectFixed(rl_src1, rMIPS_FARG0); + LoadValueDirectFixed(rl_src2, rMIPS_FARG2); } - int r_tgt = LoadHelper(cu, offset); + int r_tgt = LoadHelper(offset); // NOTE: not a safepoint - OpReg(cu, kOpBlx, r_tgt); - RegLocation rl_result = GetReturn(cu, false); - StoreValue(cu, rl_dest, rl_result); + OpReg(kOpBlx, r_tgt); + RegLocation rl_result = GetReturn(false); + StoreValue(rl_dest, rl_result); } -void MipsCodegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, +void MipsMir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) { UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch"; } -void MipsCodegen::GenNegFloat(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src) +void MipsMir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { RegLocation rl_result; - rl_src = LoadValue(cu, rl_src, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegRegImm(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000); - StoreValue(cu, rl_dest, rl_result); + rl_src = LoadValue(rl_src, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegRegImm(kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000); + StoreValue(rl_dest, rl_result); } -void MipsCodegen::GenNegDouble(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src) +void MipsMir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { RegLocation rl_result; - rl_src = LoadValueWide(cu, rl_src, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegRegImm(cu, kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000); - OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg); - StoreValueWide(cu, rl_dest, rl_result); + rl_src = LoadValueWide(rl_src, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegRegImm(kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000); + OpRegCopy(rl_result.low_reg, rl_src.low_reg); + StoreValueWide(rl_dest, rl_result); } -bool MipsCodegen::GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min) +bool MipsMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) { // TODO: need Mips implementation return false; diff --git a/src/compiler/dex/quick/mips/int_mips.cc b/src/compiler/dex/quick/mips/int_mips.cc index b1fa623d8c..d65d08a979 100644 --- a/src/compiler/dex/quick/mips/int_mips.cc +++ b/src/compiler/dex/quick/mips/int_mips.cc @@ -17,8 +17,6 @@ /* This file contains codegen for the Mips ISA */ #include "codegen_mips.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "mips_lir.h" #include "oat/runtime/oat_support_entrypoints.h" @@ -40,29 +38,29 @@ namespace art { * finish: * */ -void MipsCodegen::GenCmpLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void MipsMir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); - rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg); - int t0 = AllocTemp(cu); - int t1 = AllocTemp(cu); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - NewLIR3(cu, kMipsSlt, t0, rl_src1.high_reg, rl_src2.high_reg); - NewLIR3(cu, kMipsSlt, t1, rl_src2.high_reg, rl_src1.high_reg); - NewLIR3(cu, kMipsSubu, rl_result.low_reg, t1, t0); - LIR* branch = OpCmpImmBranch(cu, kCondNe, rl_result.low_reg, 0, NULL); - NewLIR3(cu, kMipsSltu, t0, rl_src1.low_reg, rl_src2.low_reg); - NewLIR3(cu, kMipsSltu, t1, rl_src2.low_reg, rl_src1.low_reg); - NewLIR3(cu, kMipsSubu, rl_result.low_reg, t1, t0); - FreeTemp(cu, t0); - FreeTemp(cu, t1); - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); + int t0 = AllocTemp(); + int t1 = AllocTemp(); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + NewLIR3(kMipsSlt, t0, rl_src1.high_reg, rl_src2.high_reg); + NewLIR3(kMipsSlt, t1, rl_src2.high_reg, rl_src1.high_reg); + NewLIR3(kMipsSubu, rl_result.low_reg, t1, t0); + LIR* branch = OpCmpImmBranch(kCondNe, rl_result.low_reg, 0, NULL); + NewLIR3(kMipsSltu, t0, rl_src1.low_reg, rl_src2.low_reg); + NewLIR3(kMipsSltu, t1, rl_src2.low_reg, rl_src1.low_reg); + NewLIR3(kMipsSubu, rl_result.low_reg, t1, t0); + FreeTemp(t0); + FreeTemp(t1); + LIR* target = NewLIR0(kPseudoTargetLabel); branch->target = target; - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } -LIR* MipsCodegen::OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, int src2, +LIR* MipsMir2Lir::OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target) { LIR* branch; @@ -115,31 +113,31 @@ LIR* MipsCodegen::OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, return NULL; } if (cmp_zero) { - branch = NewLIR2(cu, br_op, src1, src2); + branch = NewLIR2(br_op, src1, src2); } else { - int t_reg = AllocTemp(cu); + int t_reg = AllocTemp(); if (swapped) { - NewLIR3(cu, slt_op, t_reg, src2, src1); + NewLIR3(slt_op, t_reg, src2, src1); } else { - NewLIR3(cu, slt_op, t_reg, src1, src2); + NewLIR3(slt_op, t_reg, src1, src2); } - branch = NewLIR1(cu, br_op, t_reg); - FreeTemp(cu, t_reg); + branch = NewLIR1(br_op, t_reg); + FreeTemp(t_reg); } branch->target = target; return branch; } -LIR* MipsCodegen::OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg, +LIR* MipsMir2Lir::OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target) { LIR* branch; if (check_value != 0) { // TUNING: handle s16 & kCondLt/Mi case using slti - int t_reg = AllocTemp(cu); - LoadConstant(cu, t_reg, check_value); - branch = OpCmpBranch(cu, cond, reg, t_reg, target); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + LoadConstant(t_reg, check_value); + branch = OpCmpBranch(cond, reg, t_reg, target); + FreeTemp(t_reg); return branch; } MipsOpCode opc; @@ -153,37 +151,37 @@ LIR* MipsCodegen::OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int re case kCondNe: opc = kMipsBnez; break; default: // Tuning: use slti when applicable - int t_reg = AllocTemp(cu); - LoadConstant(cu, t_reg, check_value); - branch = OpCmpBranch(cu, cond, reg, t_reg, target); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + LoadConstant(t_reg, check_value); + branch = OpCmpBranch(cond, reg, t_reg, target); + FreeTemp(t_reg); return branch; } - branch = NewLIR1(cu, opc, reg); + branch = NewLIR1(opc, reg); branch->target = target; return branch; } -LIR* MipsCodegen::OpRegCopyNoInsert(CompilationUnit *cu, int r_dest, int r_src) +LIR* MipsMir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) { if (MIPS_FPREG(r_dest) || MIPS_FPREG(r_src)) - return OpFpRegCopy(cu, r_dest, r_src); - LIR* res = RawLIR(cu, cu->current_dalvik_offset, kMipsMove, + return OpFpRegCopy(r_dest, r_src); + LIR* res = RawLIR(current_dalvik_offset_, kMipsMove, r_dest, r_src); - if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) { + if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) { res->flags.is_nop = true; } return res; } -LIR* MipsCodegen::OpRegCopy(CompilationUnit *cu, int r_dest, int r_src) +LIR* MipsMir2Lir::OpRegCopy(int r_dest, int r_src) { - LIR *res = OpRegCopyNoInsert(cu, r_dest, r_src); - AppendLIR(cu, res); + LIR *res = OpRegCopyNoInsert(r_dest, r_src); + AppendLIR(res); return res; } -void MipsCodegen::OpRegCopyWide(CompilationUnit *cu, int dest_lo, int dest_hi, int src_lo, +void MipsMir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi) { bool dest_fp = MIPS_FPREG(dest_lo) && MIPS_FPREG(dest_hi); @@ -192,172 +190,172 @@ void MipsCodegen::OpRegCopyWide(CompilationUnit *cu, int dest_lo, int dest_hi, i assert(MIPS_FPREG(dest_lo) == MIPS_FPREG(dest_hi)); if (dest_fp) { if (src_fp) { - OpRegCopy(cu, S2d(dest_lo, dest_hi), S2d(src_lo, src_hi)); + OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi)); } else { /* note the operands are swapped for the mtc1 instr */ - NewLIR2(cu, kMipsMtc1, src_lo, dest_lo); - NewLIR2(cu, kMipsMtc1, src_hi, dest_hi); + NewLIR2(kMipsMtc1, src_lo, dest_lo); + NewLIR2(kMipsMtc1, src_hi, dest_hi); } } else { if (src_fp) { - NewLIR2(cu, kMipsMfc1, dest_lo, src_lo); - NewLIR2(cu, kMipsMfc1, dest_hi, src_hi); + NewLIR2(kMipsMfc1, dest_lo, src_lo); + NewLIR2(kMipsMfc1, dest_hi, src_hi); } else { // Handle overlap if (src_hi == dest_lo) { - OpRegCopy(cu, dest_hi, src_hi); - OpRegCopy(cu, dest_lo, src_lo); + OpRegCopy(dest_hi, src_hi); + OpRegCopy(dest_lo, src_lo); } else { - OpRegCopy(cu, dest_lo, src_lo); - OpRegCopy(cu, dest_hi, src_hi); + OpRegCopy(dest_lo, src_lo); + OpRegCopy(dest_hi, src_hi); } } } } -void MipsCodegen::GenSelect(CompilationUnit* cu, BasicBlock* bb, MIR* mir) +void MipsMir2Lir::GenSelect(BasicBlock* bb, MIR* mir) { UNIMPLEMENTED(FATAL) << "Need codegen for select"; } -void MipsCodegen::GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir) +void MipsMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) { UNIMPLEMENTED(FATAL) << "Need codegen for fused long cmp branch"; } -LIR* MipsCodegen::GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code, +LIR* MipsMir2Lir::GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset, ThrowKind kind) { LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm"; return NULL; } -RegLocation MipsCodegen::GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg1, int reg2, +RegLocation MipsMir2Lir::GenDivRem(RegLocation rl_dest, int reg1, int reg2, bool is_div) { - NewLIR4(cu, kMipsDiv, r_HI, r_LO, reg1, reg2); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + NewLIR4(kMipsDiv, r_HI, r_LO, reg1, reg2); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); if (is_div) { - NewLIR2(cu, kMipsMflo, rl_result.low_reg, r_LO); + NewLIR2(kMipsMflo, rl_result.low_reg, r_LO); } else { - NewLIR2(cu, kMipsMfhi, rl_result.low_reg, r_HI); + NewLIR2(kMipsMfhi, rl_result.low_reg, r_HI); } return rl_result; } -RegLocation MipsCodegen::GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg1, int lit, +RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit, bool is_div) { - int t_reg = AllocTemp(cu); - NewLIR3(cu, kMipsAddiu, t_reg, r_ZERO, lit); - NewLIR4(cu, kMipsDiv, r_HI, r_LO, reg1, t_reg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + int t_reg = AllocTemp(); + NewLIR3(kMipsAddiu, t_reg, r_ZERO, lit); + NewLIR4(kMipsDiv, r_HI, r_LO, reg1, t_reg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); if (is_div) { - NewLIR2(cu, kMipsMflo, rl_result.low_reg, r_LO); + NewLIR2(kMipsMflo, rl_result.low_reg, r_LO); } else { - NewLIR2(cu, kMipsMfhi, rl_result.low_reg, r_HI); + NewLIR2(kMipsMfhi, rl_result.low_reg, r_HI); } - FreeTemp(cu, t_reg); + FreeTemp(t_reg); return rl_result; } -void MipsCodegen::OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, int offset) +void MipsMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) { LOG(FATAL) << "Unexpected use of OpLea for Arm"; } -void MipsCodegen::OpTlsCmp(CompilationUnit* cu, int offset, int val) +void MipsMir2Lir::OpTlsCmp(int offset, int val) { LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm"; } -bool MipsCodegen::GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier) { - DCHECK_NE(cu->instruction_set, kThumb2); +bool MipsMir2Lir::GenInlinedCas32(CallInfo* info, bool need_write_barrier) { + DCHECK_NE(cu_->instruction_set, kThumb2); return false; } -bool MipsCodegen::GenInlinedSqrt(CompilationUnit* cu, CallInfo* info) { - DCHECK_NE(cu->instruction_set, kThumb2); +bool MipsMir2Lir::GenInlinedSqrt(CallInfo* info) { + DCHECK_NE(cu_->instruction_set, kThumb2); return false; } -LIR* MipsCodegen::OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target) { +LIR* MipsMir2Lir::OpPcRelLoad(int reg, LIR* target) { LOG(FATAL) << "Unexpected use of OpPcRelLoad for Mips"; return NULL; } -LIR* MipsCodegen::OpVldm(CompilationUnit* cu, int rBase, int count) +LIR* MipsMir2Lir::OpVldm(int rBase, int count) { LOG(FATAL) << "Unexpected use of OpVldm for Mips"; return NULL; } -LIR* MipsCodegen::OpVstm(CompilationUnit* cu, int rBase, int count) +LIR* MipsMir2Lir::OpVstm(int rBase, int count) { LOG(FATAL) << "Unexpected use of OpVstm for Mips"; return NULL; } -void MipsCodegen::GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src, +void MipsMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit, int first_bit, int second_bit) { - int t_reg = AllocTemp(cu); - OpRegRegImm(cu, kOpLsl, t_reg, rl_src.low_reg, second_bit - first_bit); - OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, t_reg); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + OpRegRegImm(kOpLsl, t_reg, rl_src.low_reg, second_bit - first_bit); + OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src.low_reg, t_reg); + FreeTemp(t_reg); if (first_bit != 0) { - OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit); + OpRegRegImm(kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit); } } -void MipsCodegen::GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi) +void MipsMir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) { - int t_reg = AllocTemp(cu); - OpRegRegReg(cu, kOpOr, t_reg, reg_lo, reg_hi); - GenImmedCheck(cu, kCondEq, t_reg, 0, kThrowDivZero); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + OpRegRegReg(kOpOr, t_reg, reg_lo, reg_hi); + GenImmedCheck(kCondEq, t_reg, 0, kThrowDivZero); + FreeTemp(t_reg); } // Test suspend flag, return target of taken suspend branch -LIR* MipsCodegen::OpTestSuspend(CompilationUnit* cu, LIR* target) +LIR* MipsMir2Lir::OpTestSuspend(LIR* target) { - OpRegImm(cu, kOpSub, rMIPS_SUSPEND, 1); - return OpCmpImmBranch(cu, (target == NULL) ? kCondEq : kCondNe, rMIPS_SUSPEND, 0, target); + OpRegImm(kOpSub, rMIPS_SUSPEND, 1); + return OpCmpImmBranch((target == NULL) ? kCondEq : kCondNe, rMIPS_SUSPEND, 0, target); } // Decrement register and branch on condition -LIR* MipsCodegen::OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, LIR* target) +LIR* MipsMir2Lir::OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) { - OpRegImm(cu, kOpSub, reg, 1); - return OpCmpImmBranch(cu, c_code, reg, 0, target); + OpRegImm(kOpSub, reg, 1); + return OpCmpImmBranch(c_code, reg, 0, target); } -bool MipsCodegen::SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode, +bool MipsMir2Lir::SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src, RegLocation rl_dest, int lit) { LOG(FATAL) << "Unexpected use of smallLiteralDive in Mips"; return false; } -LIR* MipsCodegen::OpIT(CompilationUnit* cu, ConditionCode cond, const char* guide) +LIR* MipsMir2Lir::OpIT(ConditionCode cond, const char* guide) { LOG(FATAL) << "Unexpected use of OpIT in Mips"; return NULL; } -void MipsCodegen::GenMulLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void MipsMir2Lir::GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenMulLong for Mips"; } -void MipsCodegen::GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void MipsMir2Lir::GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); - rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); /* * [v1 v0] = [a1 a0] + [a3 a2]; * addu v0,a2,a0 @@ -366,21 +364,21 @@ void MipsCodegen::GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocati * addu v1,v1,t1 */ - OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src2.low_reg, rl_src1.low_reg); - int t_reg = AllocTemp(cu); - OpRegRegReg(cu, kOpAdd, t_reg, rl_src2.high_reg, rl_src1.high_reg); - NewLIR3(cu, kMipsSltu, rl_result.high_reg, rl_result.low_reg, rl_src2.low_reg); - OpRegRegReg(cu, kOpAdd, rl_result.high_reg, rl_result.high_reg, t_reg); - FreeTemp(cu, t_reg); - StoreValueWide(cu, rl_dest, rl_result); + OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src2.low_reg, rl_src1.low_reg); + int t_reg = AllocTemp(); + OpRegRegReg(kOpAdd, t_reg, rl_src2.high_reg, rl_src1.high_reg); + NewLIR3(kMipsSltu, rl_result.high_reg, rl_result.low_reg, rl_src2.low_reg); + OpRegRegReg(kOpAdd, rl_result.high_reg, rl_result.high_reg, t_reg); + FreeTemp(t_reg); + StoreValueWide(rl_dest, rl_result); } -void MipsCodegen::GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void MipsMir2Lir::GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { - rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg); - rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); /* * [v1 v0] = [a1 a0] - [a3 a2]; * sltu t1,a0,a2 @@ -389,19 +387,19 @@ void MipsCodegen::GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocati * subu v1,v1,t1 */ - int t_reg = AllocTemp(cu); - NewLIR3(cu, kMipsSltu, t_reg, rl_src1.low_reg, rl_src2.low_reg); - OpRegRegReg(cu, kOpSub, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); - OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg); - OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_result.high_reg, t_reg); - FreeTemp(cu, t_reg); - StoreValueWide(cu, rl_dest, rl_result); + int t_reg = AllocTemp(); + NewLIR3(kMipsSltu, t_reg, rl_src1.low_reg, rl_src2.low_reg); + OpRegRegReg(kOpSub, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg); + OpRegRegReg(kOpSub, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg); + OpRegRegReg(kOpSub, rl_result.high_reg, rl_result.high_reg, t_reg); + FreeTemp(t_reg); + StoreValueWide(rl_dest, rl_result); } -void MipsCodegen::GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void MipsMir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) { - rl_src = LoadValueWide(cu, rl_src, kCoreReg); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); + rl_src = LoadValueWide(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); /* * [v1 v0] = -[a1 a0] * negu v0,a0 @@ -410,28 +408,28 @@ void MipsCodegen::GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocati * subu v1,v1,t1 */ - OpRegReg(cu, kOpNeg, rl_result.low_reg, rl_src.low_reg); - OpRegReg(cu, kOpNeg, rl_result.high_reg, rl_src.high_reg); - int t_reg = AllocTemp(cu); - NewLIR3(cu, kMipsSltu, t_reg, r_ZERO, rl_result.low_reg); - OpRegRegReg(cu, kOpSub, rl_result.high_reg, rl_result.high_reg, t_reg); - FreeTemp(cu, t_reg); - StoreValueWide(cu, rl_dest, rl_result); + OpRegReg(kOpNeg, rl_result.low_reg, rl_src.low_reg); + OpRegReg(kOpNeg, rl_result.high_reg, rl_src.high_reg); + int t_reg = AllocTemp(); + NewLIR3(kMipsSltu, t_reg, r_ZERO, rl_result.low_reg); + OpRegRegReg(kOpSub, rl_result.high_reg, rl_result.high_reg, t_reg); + FreeTemp(t_reg); + StoreValueWide(rl_dest, rl_result); } -void MipsCodegen::GenAndLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void MipsMir2Lir::GenAndLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenAndLong for Mips"; } -void MipsCodegen::GenOrLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void MipsMir2Lir::GenOrLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenOrLong for Mips"; } -void MipsCodegen::GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void MipsMir2Lir::GenXorLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenXorLong for Mips"; @@ -440,15 +438,15 @@ void MipsCodegen::GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocati /* * Generate array load */ -void MipsCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, +void MipsMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset; RegLocation rl_result; - rl_array = LoadValue(cu, rl_array, kCoreReg); - rl_index = LoadValue(cu, rl_index, kCoreReg); + rl_array = LoadValue(rl_array, kCoreReg); + rl_index = LoadValue(rl_index, kCoreReg); if (size == kLong || size == kDouble) { data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value(); @@ -457,54 +455,54 @@ void MipsCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, R } /* null object? */ - GenNullCheck(cu, rl_array.s_reg_low, rl_array.low_reg, opt_flags); + GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags); - int reg_ptr = AllocTemp(cu); + int reg_ptr = AllocTemp(); bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK)); int reg_len = INVALID_REG; if (needs_range_check) { - reg_len = AllocTemp(cu); + reg_len = AllocTemp(); /* Get len */ - LoadWordDisp(cu, rl_array.low_reg, len_offset, reg_len); + LoadWordDisp(rl_array.low_reg, len_offset, reg_len); } /* reg_ptr -> array data */ - OpRegRegImm(cu, kOpAdd, reg_ptr, rl_array.low_reg, data_offset); - FreeTemp(cu, rl_array.low_reg); + OpRegRegImm(kOpAdd, reg_ptr, rl_array.low_reg, data_offset); + FreeTemp(rl_array.low_reg); if ((size == kLong) || (size == kDouble)) { if (scale) { - int r_new_index = AllocTemp(cu); - OpRegRegImm(cu, kOpLsl, r_new_index, rl_index.low_reg, scale); - OpRegReg(cu, kOpAdd, reg_ptr, r_new_index); - FreeTemp(cu, r_new_index); + int r_new_index = AllocTemp(); + OpRegRegImm(kOpLsl, r_new_index, rl_index.low_reg, scale); + OpRegReg(kOpAdd, reg_ptr, r_new_index); + FreeTemp(r_new_index); } else { - OpRegReg(cu, kOpAdd, reg_ptr, rl_index.low_reg); + OpRegReg(kOpAdd, reg_ptr, rl_index.low_reg); } - FreeTemp(cu, rl_index.low_reg); - rl_result = EvalLoc(cu, rl_dest, reg_class, true); + FreeTemp(rl_index.low_reg); + rl_result = EvalLoc(rl_dest, reg_class, true); if (needs_range_check) { // TODO: change kCondCS to a more meaningful name, is the sense of // carry-set/clear flipped? - GenRegRegCheck(cu, kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); - FreeTemp(cu, reg_len); + GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); + FreeTemp(reg_len); } - LoadBaseDispWide(cu, reg_ptr, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); + LoadBaseDispWide(reg_ptr, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); - FreeTemp(cu, reg_ptr); - StoreValueWide(cu, rl_dest, rl_result); + FreeTemp(reg_ptr); + StoreValueWide(rl_dest, rl_result); } else { - rl_result = EvalLoc(cu, rl_dest, reg_class, true); + rl_result = EvalLoc(rl_dest, reg_class, true); if (needs_range_check) { // TODO: change kCondCS to a more meaningful name, is the sense of // carry-set/clear flipped? - GenRegRegCheck(cu, kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); - FreeTemp(cu, reg_len); + GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); + FreeTemp(reg_len); } - LoadBaseIndexed(cu, reg_ptr, rl_index.low_reg, rl_result.low_reg, scale, size); + LoadBaseIndexed(reg_ptr, rl_index.low_reg, rl_result.low_reg, scale, size); - FreeTemp(cu, reg_ptr); - StoreValue(cu, rl_dest, rl_result); + FreeTemp(reg_ptr); + StoreValue(rl_dest, rl_result); } } @@ -512,7 +510,7 @@ void MipsCodegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, R * Generate array store * */ -void MipsCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, +void MipsMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); @@ -525,58 +523,58 @@ void MipsCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, R data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value(); } - rl_array = LoadValue(cu, rl_array, kCoreReg); - rl_index = LoadValue(cu, rl_index, kCoreReg); + rl_array = LoadValue(rl_array, kCoreReg); + rl_index = LoadValue(rl_index, kCoreReg); int reg_ptr = INVALID_REG; - if (IsTemp(cu, rl_array.low_reg)) { - Clobber(cu, rl_array.low_reg); + if (IsTemp(rl_array.low_reg)) { + Clobber(rl_array.low_reg); reg_ptr = rl_array.low_reg; } else { - reg_ptr = AllocTemp(cu); - OpRegCopy(cu, reg_ptr, rl_array.low_reg); + reg_ptr = AllocTemp(); + OpRegCopy(reg_ptr, rl_array.low_reg); } /* null object? */ - GenNullCheck(cu, rl_array.s_reg_low, rl_array.low_reg, opt_flags); + GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags); bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK)); int reg_len = INVALID_REG; if (needs_range_check) { - reg_len = AllocTemp(cu); + reg_len = AllocTemp(); //NOTE: max live temps(4) here. /* Get len */ - LoadWordDisp(cu, rl_array.low_reg, len_offset, reg_len); + LoadWordDisp(rl_array.low_reg, len_offset, reg_len); } /* reg_ptr -> array data */ - OpRegImm(cu, kOpAdd, reg_ptr, data_offset); + OpRegImm(kOpAdd, reg_ptr, data_offset); /* at this point, reg_ptr points to array, 2 live temps */ if ((size == kLong) || (size == kDouble)) { //TUNING: specific wide routine that can handle fp regs if (scale) { - int r_new_index = AllocTemp(cu); - OpRegRegImm(cu, kOpLsl, r_new_index, rl_index.low_reg, scale); - OpRegReg(cu, kOpAdd, reg_ptr, r_new_index); - FreeTemp(cu, r_new_index); + int r_new_index = AllocTemp(); + OpRegRegImm(kOpLsl, r_new_index, rl_index.low_reg, scale); + OpRegReg(kOpAdd, reg_ptr, r_new_index); + FreeTemp(r_new_index); } else { - OpRegReg(cu, kOpAdd, reg_ptr, rl_index.low_reg); + OpRegReg(kOpAdd, reg_ptr, rl_index.low_reg); } - rl_src = LoadValueWide(cu, rl_src, reg_class); + rl_src = LoadValueWide(rl_src, reg_class); if (needs_range_check) { - GenRegRegCheck(cu, kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); - FreeTemp(cu, reg_len); + GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); + FreeTemp(reg_len); } - StoreBaseDispWide(cu, reg_ptr, 0, rl_src.low_reg, rl_src.high_reg); + StoreBaseDispWide(reg_ptr, 0, rl_src.low_reg, rl_src.high_reg); - FreeTemp(cu, reg_ptr); + FreeTemp(reg_ptr); } else { - rl_src = LoadValue(cu, rl_src, reg_class); + rl_src = LoadValue(rl_src, reg_class); if (needs_range_check) { - GenRegRegCheck(cu, kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); - FreeTemp(cu, reg_len); + GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds); + FreeTemp(reg_len); } - StoreBaseIndexed(cu, reg_ptr, rl_index.low_reg, rl_src.low_reg, + StoreBaseIndexed(reg_ptr, rl_index.low_reg, rl_src.low_reg, scale, size); } } @@ -585,75 +583,75 @@ void MipsCodegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, R * Generate array store * */ -void MipsCodegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, +void MipsMir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(); - FlushAllRegs(cu); // Use explicit registers - LockCallTemps(cu); + FlushAllRegs(); // Use explicit registers + LockCallTemps(); int r_value = TargetReg(kArg0); // Register holding value int r_array_class = TargetReg(kArg1); // Register holding array's Class int r_array = TargetReg(kArg2); // Register holding array int r_index = TargetReg(kArg3); // Register holding index into array - LoadValueDirectFixed(cu, rl_array, r_array); // Grab array - LoadValueDirectFixed(cu, rl_src, r_value); // Grab value - LoadValueDirectFixed(cu, rl_index, r_index); // Grab index + LoadValueDirectFixed(rl_array, r_array); // Grab array + LoadValueDirectFixed(rl_src, r_value); // Grab value + LoadValueDirectFixed(rl_index, r_index); // Grab index - GenNullCheck(cu, rl_array.s_reg_low, r_array, opt_flags); // NPE? + GenNullCheck(rl_array.s_reg_low, r_array, opt_flags); // NPE? // Store of null? - LIR* null_value_check = OpCmpImmBranch(cu, kCondEq, r_value, 0, NULL); + LIR* null_value_check = OpCmpImmBranch(kCondEq, r_value, 0, NULL); // Get the array's class. - LoadWordDisp(cu, r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); - CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, + LoadWordDisp(r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); + CallRuntimeHelperRegReg(ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, r_array_class, true); // Redo LoadValues in case they didn't survive the call. - LoadValueDirectFixed(cu, rl_array, r_array); // Reload array - LoadValueDirectFixed(cu, rl_index, r_index); // Reload index - LoadValueDirectFixed(cu, rl_src, r_value); // Reload value + LoadValueDirectFixed(rl_array, r_array); // Reload array + LoadValueDirectFixed(rl_index, r_index); // Reload index + LoadValueDirectFixed(rl_src, r_value); // Reload value r_array_class = INVALID_REG; // Branch here if value to be stored == null - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); null_value_check->target = target; bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK)); int reg_len = INVALID_REG; if (needs_range_check) { reg_len = TargetReg(kArg1); - LoadWordDisp(cu, r_array, len_offset, reg_len); // Get len + LoadWordDisp(r_array, len_offset, reg_len); // Get len } /* r_ptr -> array data */ - int r_ptr = AllocTemp(cu); - OpRegRegImm(cu, kOpAdd, r_ptr, r_array, data_offset); + int r_ptr = AllocTemp(); + OpRegRegImm(kOpAdd, r_ptr, r_array, data_offset); if (needs_range_check) { - GenRegRegCheck(cu, kCondCs, r_index, reg_len, kThrowArrayBounds); + GenRegRegCheck(kCondCs, r_index, reg_len, kThrowArrayBounds); } - StoreBaseIndexed(cu, r_ptr, r_index, r_value, scale, kWord); - FreeTemp(cu, r_ptr); - FreeTemp(cu, r_index); - if (!cu->mir_graph->IsConstantNullRef(rl_src)) { - MarkGCCard(cu, r_value, r_array); + StoreBaseIndexed(r_ptr, r_index, r_value, scale, kWord); + FreeTemp(r_ptr); + FreeTemp(r_index); + if (!mir_graph_->IsConstantNullRef(rl_src)) { + MarkGCCard(r_value, r_array); } } -void MipsCodegen::GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, +void MipsMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_shift) { // Default implementation is just to ignore the constant case. - GenShiftOpLong(cu, opcode, rl_dest, rl_src1, rl_shift); + GenShiftOpLong(opcode, rl_dest, rl_src1, rl_shift); } -void MipsCodegen::GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode, +void MipsMir2Lir::GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { // Default - bail to non-const handler. - GenArithOpLong(cu, opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); } } // namespace art diff --git a/src/compiler/dex/quick/mips/target_mips.cc b/src/compiler/dex/quick/mips/target_mips.cc index 85e8a9ba24..8d342af748 100644 --- a/src/compiler/dex/quick/mips/target_mips.cc +++ b/src/compiler/dex/quick/mips/target_mips.cc @@ -15,9 +15,7 @@ */ #include "codegen_mips.h" -#include "compiler/dex/quick/codegen_util.h" #include "compiler/dex/compiler_internals.h" -#include "compiler/dex/quick/ralloc_util.h" #include "mips_lir.h" #include <string> @@ -37,32 +35,32 @@ static int FpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7, static int fp_temps[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7, r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15}; -RegLocation MipsCodegen::LocCReturn() +RegLocation MipsMir2Lir::LocCReturn() { RegLocation res = MIPS_LOC_C_RETURN; return res; } -RegLocation MipsCodegen::LocCReturnWide() +RegLocation MipsMir2Lir::LocCReturnWide() { RegLocation res = MIPS_LOC_C_RETURN_WIDE; return res; } -RegLocation MipsCodegen::LocCReturnFloat() +RegLocation MipsMir2Lir::LocCReturnFloat() { RegLocation res = MIPS_LOC_C_RETURN_FLOAT; return res; } -RegLocation MipsCodegen::LocCReturnDouble() +RegLocation MipsMir2Lir::LocCReturnDouble() { RegLocation res = MIPS_LOC_C_RETURN_DOUBLE; return res; } // Return a target-dependent special register. -int MipsCodegen::TargetReg(SpecialTargetRegister reg) { +int MipsMir2Lir::TargetReg(SpecialTargetRegister reg) { int res = INVALID_REG; switch (reg) { case kSelf: res = rMIPS_SELF; break; @@ -87,19 +85,19 @@ int MipsCodegen::TargetReg(SpecialTargetRegister reg) { } // Create a double from a pair of singles. -int MipsCodegen::S2d(int low_reg, int high_reg) +int MipsMir2Lir::S2d(int low_reg, int high_reg) { return MIPS_S2D(low_reg, high_reg); } // Return mask to strip off fp reg flags and bias. -uint32_t MipsCodegen::FpRegMask() +uint32_t MipsMir2Lir::FpRegMask() { return MIPS_FP_REG_MASK; } // True if both regs single, both core or both double. -bool MipsCodegen::SameRegType(int reg1, int reg2) +bool MipsMir2Lir::SameRegType(int reg1, int reg2) { return (MIPS_REGTYPE(reg1) == MIPS_REGTYPE(reg2)); } @@ -107,7 +105,7 @@ bool MipsCodegen::SameRegType(int reg1, int reg2) /* * Decode the register id. */ -uint64_t MipsCodegen::GetRegMaskCommon(CompilationUnit* cu, int reg) +uint64_t MipsMir2Lir::GetRegMaskCommon(int reg) { uint64_t seed; int shift; @@ -124,18 +122,18 @@ uint64_t MipsCodegen::GetRegMaskCommon(CompilationUnit* cu, int reg) return (seed << shift); } -uint64_t MipsCodegen::GetPCUseDefEncoding() +uint64_t MipsMir2Lir::GetPCUseDefEncoding() { return ENCODE_MIPS_REG_PC; } -void MipsCodegen::SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir) +void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir) { - DCHECK_EQ(cu->instruction_set, kMips); + DCHECK_EQ(cu_->instruction_set, kMips); // Mips-specific resource map setup here. - uint64_t flags = MipsCodegen::EncodingMap[lir->opcode].flags; + uint64_t flags = MipsMir2Lir::EncodingMap[lir->opcode].flags; if (flags & REG_DEF_SP) { lir->def_mask |= ENCODE_MIPS_REG_SP; @@ -163,7 +161,7 @@ static const char *mips_reg_name[MIPS_REG_COUNT] = { * Interpret a format string and build a string no longer than size * See format key in Assemble.c. */ -std::string MipsCodegen::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) +std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { std::string buf; int i; @@ -256,7 +254,7 @@ std::string MipsCodegen::BuildInsnString(const char *fmt, LIR *lir, unsigned cha } // FIXME: need to redo resource maps for MIPS - fix this at that time -void MipsCodegen::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) +void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) { char buf[256]; buf[0] = 0; @@ -307,10 +305,10 @@ void MipsCodegen::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *pre * machinery is in place, always spill lr. */ -void MipsCodegen::AdjustSpillMask(CompilationUnit* cu) +void MipsMir2Lir::AdjustSpillMask() { - cu->core_spill_mask |= (1 << r_RA); - cu->num_core_spills++; + core_spill_mask_ |= (1 << r_RA); + num_core_spills_++; } /* @@ -319,15 +317,15 @@ void MipsCodegen::AdjustSpillMask(CompilationUnit* cu) * include any holes in the mask. Associate holes with * Dalvik register INVALID_VREG (0xFFFFU). */ -void MipsCodegen::MarkPreservedSingle(CompilationUnit* cu, int s_reg, int reg) +void MipsMir2Lir::MarkPreservedSingle(int s_reg, int reg) { LOG(FATAL) << "No support yet for promoted FP regs"; } -void MipsCodegen::FlushRegWide(CompilationUnit* cu, int reg1, int reg2) +void MipsMir2Lir::FlushRegWide(int reg1, int reg2) { - RegisterInfo* info1 = GetRegInfo(cu, reg1); - RegisterInfo* info2 = GetRegInfo(cu, reg2); + RegisterInfo* info1 = GetRegInfo(reg1); + RegisterInfo* info2 = GetRegInfo(reg2); DCHECK(info1 && info2 && info1->pair && info2->pair && (info1->partner == info2->reg) && (info2->partner == info1->reg)); @@ -339,114 +337,114 @@ void MipsCodegen::FlushRegWide(CompilationUnit* cu, int reg1, int reg2) info1->dirty = false; info2->dirty = false; - if (cu->mir_graph->SRegToVReg(info2->s_reg) < cu->mir_graph->SRegToVReg(info1->s_reg)) + if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg)) info1 = info2; - int v_reg = cu->mir_graph->SRegToVReg(info1->s_reg); - StoreBaseDispWide(cu, rMIPS_SP, VRegOffset(cu, v_reg), info1->reg, info1->partner); + int v_reg = mir_graph_->SRegToVReg(info1->s_reg); + StoreBaseDispWide(rMIPS_SP, VRegOffset(v_reg), info1->reg, info1->partner); } } -void MipsCodegen::FlushReg(CompilationUnit* cu, int reg) +void MipsMir2Lir::FlushReg(int reg) { - RegisterInfo* info = GetRegInfo(cu, reg); + RegisterInfo* info = GetRegInfo(reg); if (info->live && info->dirty) { info->dirty = false; - int v_reg = cu->mir_graph->SRegToVReg(info->s_reg); - StoreBaseDisp(cu, rMIPS_SP, VRegOffset(cu, v_reg), reg, kWord); + int v_reg = mir_graph_->SRegToVReg(info->s_reg); + StoreBaseDisp(rMIPS_SP, VRegOffset(v_reg), reg, kWord); } } /* Give access to the target-dependent FP register encoding to common code */ -bool MipsCodegen::IsFpReg(int reg) { +bool MipsMir2Lir::IsFpReg(int reg) { return MIPS_FPREG(reg); } /* Clobber all regs that might be used by an external C call */ -void MipsCodegen::ClobberCalleeSave(CompilationUnit *cu) -{ - Clobber(cu, r_ZERO); - Clobber(cu, r_AT); - Clobber(cu, r_V0); - Clobber(cu, r_V1); - Clobber(cu, r_A0); - Clobber(cu, r_A1); - Clobber(cu, r_A2); - Clobber(cu, r_A3); - Clobber(cu, r_T0); - Clobber(cu, r_T1); - Clobber(cu, r_T2); - Clobber(cu, r_T3); - Clobber(cu, r_T4); - Clobber(cu, r_T5); - Clobber(cu, r_T6); - Clobber(cu, r_T7); - Clobber(cu, r_T8); - Clobber(cu, r_T9); - Clobber(cu, r_K0); - Clobber(cu, r_K1); - Clobber(cu, r_GP); - Clobber(cu, r_FP); - Clobber(cu, r_RA); - Clobber(cu, r_F0); - Clobber(cu, r_F1); - Clobber(cu, r_F2); - Clobber(cu, r_F3); - Clobber(cu, r_F4); - Clobber(cu, r_F5); - Clobber(cu, r_F6); - Clobber(cu, r_F7); - Clobber(cu, r_F8); - Clobber(cu, r_F9); - Clobber(cu, r_F10); - Clobber(cu, r_F11); - Clobber(cu, r_F12); - Clobber(cu, r_F13); - Clobber(cu, r_F14); - Clobber(cu, r_F15); -} - -RegLocation MipsCodegen::GetReturnWideAlt(CompilationUnit* cu) +void MipsMir2Lir::ClobberCalleeSave() +{ + Clobber(r_ZERO); + Clobber(r_AT); + Clobber(r_V0); + Clobber(r_V1); + Clobber(r_A0); + Clobber(r_A1); + Clobber(r_A2); + Clobber(r_A3); + Clobber(r_T0); + Clobber(r_T1); + Clobber(r_T2); + Clobber(r_T3); + Clobber(r_T4); + Clobber(r_T5); + Clobber(r_T6); + Clobber(r_T7); + Clobber(r_T8); + Clobber(r_T9); + Clobber(r_K0); + Clobber(r_K1); + Clobber(r_GP); + Clobber(r_FP); + Clobber(r_RA); + Clobber(r_F0); + Clobber(r_F1); + Clobber(r_F2); + Clobber(r_F3); + Clobber(r_F4); + Clobber(r_F5); + Clobber(r_F6); + Clobber(r_F7); + Clobber(r_F8); + Clobber(r_F9); + Clobber(r_F10); + Clobber(r_F11); + Clobber(r_F12); + Clobber(r_F13); + Clobber(r_F14); + Clobber(r_F15); +} + +RegLocation MipsMir2Lir::GetReturnWideAlt() { UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS"; RegLocation res = LocCReturnWide(); return res; } -RegLocation MipsCodegen::GetReturnAlt(CompilationUnit* cu) +RegLocation MipsMir2Lir::GetReturnAlt() { UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS"; RegLocation res = LocCReturn(); return res; } -RegisterInfo* MipsCodegen::GetRegInfo(CompilationUnit* cu, int reg) +MipsMir2Lir::RegisterInfo* MipsMir2Lir::GetRegInfo(int reg) { - return MIPS_FPREG(reg) ? &cu->reg_pool->FPRegs[reg & MIPS_FP_REG_MASK] - : &cu->reg_pool->core_regs[reg]; + return MIPS_FPREG(reg) ? ®_pool_->FPRegs[reg & MIPS_FP_REG_MASK] + : ®_pool_->core_regs[reg]; } /* To be used when explicitly managing register use */ -void MipsCodegen::LockCallTemps(CompilationUnit* cu) +void MipsMir2Lir::LockCallTemps() { - LockTemp(cu, rMIPS_ARG0); - LockTemp(cu, rMIPS_ARG1); - LockTemp(cu, rMIPS_ARG2); - LockTemp(cu, rMIPS_ARG3); + LockTemp(rMIPS_ARG0); + LockTemp(rMIPS_ARG1); + LockTemp(rMIPS_ARG2); + LockTemp(rMIPS_ARG3); } /* To be used when explicitly managing register use */ -void MipsCodegen::FreeCallTemps(CompilationUnit* cu) +void MipsMir2Lir::FreeCallTemps() { - FreeTemp(cu, rMIPS_ARG0); - FreeTemp(cu, rMIPS_ARG1); - FreeTemp(cu, rMIPS_ARG2); - FreeTemp(cu, rMIPS_ARG3); + FreeTemp(rMIPS_ARG0); + FreeTemp(rMIPS_ARG1); + FreeTemp(rMIPS_ARG2); + FreeTemp(rMIPS_ARG3); } -void MipsCodegen::GenMemBarrier(CompilationUnit *cu, MemBarrierKind barrier_kind) +void MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { #if ANDROID_SMP != 0 - NewLIR1(cu, kMipsSync, 0 /* Only stype currently supported */); + NewLIR1(kMipsSync, 0 /* Only stype currently supported */); #endif } @@ -454,7 +452,7 @@ void MipsCodegen::GenMemBarrier(CompilationUnit *cu, MemBarrierKind barrier_kind * Alloc a pair of core registers, or a double. Low reg in low byte, * high reg in next byte. */ -int MipsCodegen::AllocTypedTempPair(CompilationUnit *cu, bool fp_hint, +int MipsMir2Lir::AllocTypedTempPair(bool fp_hint, int reg_class) { int high_reg; @@ -462,69 +460,67 @@ int MipsCodegen::AllocTypedTempPair(CompilationUnit *cu, bool fp_hint, int res = 0; if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { - low_reg = AllocTempDouble(cu); + low_reg = AllocTempDouble(); high_reg = low_reg + 1; res = (low_reg & 0xff) | ((high_reg & 0xff) << 8); return res; } - low_reg = AllocTemp(cu); - high_reg = AllocTemp(cu); + low_reg = AllocTemp(); + high_reg = AllocTemp(); res = (low_reg & 0xff) | ((high_reg & 0xff) << 8); return res; } -int MipsCodegen::AllocTypedTemp(CompilationUnit *cu, bool fp_hint, int reg_class) +int MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) { if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { - return AllocTempFloat(cu); + return AllocTempFloat(); } - return AllocTemp(cu); + return AllocTemp(); } -void MipsCodegen::CompilerInitializeRegAlloc(CompilationUnit* cu) +void MipsMir2Lir::CompilerInitializeRegAlloc() { int num_regs = sizeof(core_regs)/sizeof(*core_regs); int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs); int num_temps = sizeof(core_temps)/sizeof(*core_temps); int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs); int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps); - RegisterPool *pool = - static_cast<RegisterPool*>(NewMem(cu, sizeof(*pool), true, kAllocRegAlloc)); - cu->reg_pool = pool; - pool->num_core_regs = num_regs; - pool->core_regs = static_cast<RegisterInfo*> - (NewMem(cu, num_regs * sizeof(*cu->reg_pool->core_regs), true, kAllocRegAlloc)); - pool->num_fp_regs = num_fp_regs; - pool->FPRegs = static_cast<RegisterInfo*> - (NewMem(cu, num_fp_regs * sizeof(*cu->reg_pool->FPRegs), true, kAllocRegAlloc)); - CompilerInitPool(pool->core_regs, core_regs, pool->num_core_regs); - CompilerInitPool(pool->FPRegs, FpRegs, pool->num_fp_regs); + reg_pool_ = static_cast<RegisterPool*>(NewMem(cu_, sizeof(*reg_pool_), true, kAllocRegAlloc)); + reg_pool_->num_core_regs = num_regs; + reg_pool_->core_regs = static_cast<RegisterInfo*> + (NewMem(cu_, num_regs * sizeof(*reg_pool_->core_regs), true, kAllocRegAlloc)); + reg_pool_->num_fp_regs = num_fp_regs; + reg_pool_->FPRegs = static_cast<RegisterInfo*> + (NewMem(cu_, num_fp_regs * sizeof(*reg_pool_->FPRegs), true, kAllocRegAlloc)); + CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs); + CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs); // Keep special registers from being allocated for (int i = 0; i < num_reserved; i++) { if (NO_SUSPEND && (ReservedRegs[i] == rMIPS_SUSPEND)) { //To measure cost of suspend check continue; } - MarkInUse(cu, ReservedRegs[i]); + MarkInUse(ReservedRegs[i]); } // Mark temp regs - all others not in use can be used for promotion for (int i = 0; i < num_temps; i++) { - MarkTemp(cu, core_temps[i]); + MarkTemp(core_temps[i]); } for (int i = 0; i < num_fp_temps; i++) { - MarkTemp(cu, fp_temps[i]); + MarkTemp(fp_temps[i]); } } -void MipsCodegen::FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, RegLocation rl_free) +void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) { if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) && (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) { // No overlap, free both - FreeTemp(cu, rl_free.low_reg); - FreeTemp(cu, rl_free.high_reg); + FreeTemp(rl_free.low_reg); + FreeTemp(rl_free.high_reg); } } /* @@ -533,76 +529,76 @@ void MipsCodegen::FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, RegL * ensure that all branch instructions can be restarted if * there is a trap in the shadow. Allocate a temp register. */ -int MipsCodegen::LoadHelper(CompilationUnit* cu, int offset) +int MipsMir2Lir::LoadHelper(int offset) { - LoadWordDisp(cu, rMIPS_SELF, offset, r_T9); + LoadWordDisp(rMIPS_SELF, offset, r_T9); return r_T9; } -void MipsCodegen::SpillCoreRegs(CompilationUnit* cu) +void MipsMir2Lir::SpillCoreRegs() { - if (cu->num_core_spills == 0) { + if (num_core_spills_ == 0) { return; } - uint32_t mask = cu->core_spill_mask; - int offset = cu->num_core_spills * 4; - OpRegImm(cu, kOpSub, rMIPS_SP, offset); + uint32_t mask = core_spill_mask_; + int offset = num_core_spills_ * 4; + OpRegImm(kOpSub, rMIPS_SP, offset); for (int reg = 0; mask; mask >>= 1, reg++) { if (mask & 0x1) { offset -= 4; - StoreWordDisp(cu, rMIPS_SP, offset, reg); + StoreWordDisp(rMIPS_SP, offset, reg); } } } -void MipsCodegen::UnSpillCoreRegs(CompilationUnit* cu) +void MipsMir2Lir::UnSpillCoreRegs() { - if (cu->num_core_spills == 0) { + if (num_core_spills_ == 0) { return; } - uint32_t mask = cu->core_spill_mask; - int offset = cu->frame_size; + uint32_t mask = core_spill_mask_; + int offset = frame_size_; for (int reg = 0; mask; mask >>= 1, reg++) { if (mask & 0x1) { offset -= 4; - LoadWordDisp(cu, rMIPS_SP, offset, reg); + LoadWordDisp(rMIPS_SP, offset, reg); } } - OpRegImm(cu, kOpAdd, rMIPS_SP, cu->frame_size); + OpRegImm(kOpAdd, rMIPS_SP, frame_size_); } -bool MipsCodegen::IsUnconditionalBranch(LIR* lir) +bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) { return (lir->opcode == kMipsB); } -/* Common initialization routine for an architecture family */ -bool InitMipsCodegen(CompilationUnit* cu) -{ - cu->cg.reset(new MipsCodegen()); +MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph) : Mir2Lir(cu, mir_graph) { for (int i = 0; i < kMipsLast; i++) { - if (MipsCodegen::EncodingMap[i].opcode != i) { - LOG(FATAL) << "Encoding order for " << MipsCodegen::EncodingMap[i].name + if (MipsMir2Lir::EncodingMap[i].opcode != i) { + LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name << " is wrong: expecting " << i << ", seeing " - << static_cast<int>(MipsCodegen::EncodingMap[i].opcode); + << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode); } } - return true; } -uint64_t MipsCodegen::GetTargetInstFlags(int opcode) +Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph) { + return new MipsMir2Lir(cu, mir_graph); +} + +uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) { - return MipsCodegen::EncodingMap[opcode].flags; + return MipsMir2Lir::EncodingMap[opcode].flags; } -const char* MipsCodegen::GetTargetInstName(int opcode) +const char* MipsMir2Lir::GetTargetInstName(int opcode) { - return MipsCodegen::EncodingMap[opcode].name; + return MipsMir2Lir::EncodingMap[opcode].name; } -const char* MipsCodegen::GetTargetInstFmt(int opcode) +const char* MipsMir2Lir::GetTargetInstFmt(int opcode) { - return MipsCodegen::EncodingMap[opcode].fmt; + return MipsMir2Lir::EncodingMap[opcode].fmt; } } // namespace art diff --git a/src/compiler/dex/quick/mips/utility_mips.cc b/src/compiler/dex/quick/mips/utility_mips.cc index 168eb6883a..5f9f8c58a7 100644 --- a/src/compiler/dex/quick/mips/utility_mips.cc +++ b/src/compiler/dex/quick/mips/utility_mips.cc @@ -15,14 +15,12 @@ */ #include "codegen_mips.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "mips_lir.h" namespace art { /* This file contains codegen for the MIPS32 ISA. */ -LIR* MipsCodegen::OpFpRegCopy(CompilationUnit *cu, int r_dest, int r_src) +LIR* MipsMir2Lir::OpFpRegCopy(int r_dest, int r_src) { int opcode; /* must be both DOUBLE or both not DOUBLE */ @@ -45,29 +43,29 @@ LIR* MipsCodegen::OpFpRegCopy(CompilationUnit *cu, int r_dest, int r_src) opcode = kMipsMfc1; } } - LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_src, r_dest); - if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) { + LIR* res = RawLIR(current_dalvik_offset_, opcode, r_src, r_dest); + if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) { res->flags.is_nop = true; } return res; } -bool MipsCodegen::InexpensiveConstantInt(int32_t value) +bool MipsMir2Lir::InexpensiveConstantInt(int32_t value) { return ((value == 0) || IsUint(16, value) || ((value < 0) && (value >= -32768))); } -bool MipsCodegen::InexpensiveConstantFloat(int32_t value) +bool MipsMir2Lir::InexpensiveConstantFloat(int32_t value) { return false; // TUNING } -bool MipsCodegen::InexpensiveConstantLong(int64_t value) +bool MipsMir2Lir::InexpensiveConstantLong(int64_t value) { return false; // TUNING } -bool MipsCodegen::InexpensiveConstantDouble(int64_t value) +bool MipsMir2Lir::InexpensiveConstantDouble(int64_t value) { return false; // TUNING } @@ -81,7 +79,7 @@ bool MipsCodegen::InexpensiveConstantDouble(int64_t value) * 1) r_dest is freshly returned from AllocTemp or * 2) The codegen is under fixed register usage */ -LIR* MipsCodegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value) +LIR* MipsMir2Lir::LoadConstantNoClobber(int r_dest, int value) { LIR *res; @@ -89,38 +87,38 @@ LIR* MipsCodegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int val int is_fp_reg = MIPS_FPREG(r_dest); if (is_fp_reg) { DCHECK(MIPS_SINGLEREG(r_dest)); - r_dest = AllocTemp(cu); + r_dest = AllocTemp(); } /* See if the value can be constructed cheaply */ if (value == 0) { - res = NewLIR2(cu, kMipsMove, r_dest, r_ZERO); + res = NewLIR2(kMipsMove, r_dest, r_ZERO); } else if ((value > 0) && (value <= 65535)) { - res = NewLIR3(cu, kMipsOri, r_dest, r_ZERO, value); + res = NewLIR3(kMipsOri, r_dest, r_ZERO, value); } else if ((value < 0) && (value >= -32768)) { - res = NewLIR3(cu, kMipsAddiu, r_dest, r_ZERO, value); + res = NewLIR3(kMipsAddiu, r_dest, r_ZERO, value); } else { - res = NewLIR2(cu, kMipsLui, r_dest, value>>16); + res = NewLIR2(kMipsLui, r_dest, value>>16); if (value & 0xffff) - NewLIR3(cu, kMipsOri, r_dest, r_dest, value); + NewLIR3(kMipsOri, r_dest, r_dest, value); } if (is_fp_reg) { - NewLIR2(cu, kMipsMtc1, r_dest, r_dest_save); - FreeTemp(cu, r_dest); + NewLIR2(kMipsMtc1, r_dest, r_dest_save); + FreeTemp(r_dest); } return res; } -LIR* MipsCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target) +LIR* MipsMir2Lir::OpUnconditionalBranch(LIR* target) { - LIR* res = NewLIR1(cu, kMipsB, 0 /* offset to be patched during assembly*/ ); + LIR* res = NewLIR1(kMipsB, 0 /* offset to be patched during assembly*/ ); res->target = target; return res; } -LIR* MipsCodegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src) +LIR* MipsMir2Lir::OpReg(OpKind op, int r_dest_src) { MipsOpCode opcode = kMipsNop; switch (op) { @@ -128,15 +126,15 @@ LIR* MipsCodegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src) opcode = kMipsJalr; break; case kOpBx: - return NewLIR1(cu, kMipsJr, r_dest_src); + return NewLIR1(kMipsJr, r_dest_src); break; default: LOG(FATAL) << "Bad case in OpReg"; } - return NewLIR2(cu, opcode, r_RA, r_dest_src); + return NewLIR2(opcode, r_RA, r_dest_src); } -LIR* MipsCodegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1, +LIR* MipsMir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value) { LIR *res; @@ -146,29 +144,29 @@ LIR* MipsCodegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1, MipsOpCode opcode = kMipsNop; switch (op) { case kOpAdd: - return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value); + return OpRegRegImm(op, r_dest_src1, r_dest_src1, value); break; case kOpSub: - return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value); + return OpRegRegImm(op, r_dest_src1, r_dest_src1, value); break; default: LOG(FATAL) << "Bad case in OpRegImm"; break; } if (short_form) - res = NewLIR2(cu, opcode, r_dest_src1, abs_value); + res = NewLIR2(opcode, r_dest_src1, abs_value); else { - int r_scratch = AllocTemp(cu); - res = LoadConstant(cu, r_scratch, value); + int r_scratch = AllocTemp(); + res = LoadConstant(r_scratch, value); if (op == kOpCmp) - NewLIR2(cu, opcode, r_dest_src1, r_scratch); + NewLIR2(opcode, r_dest_src1, r_scratch); else - NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_scratch); + NewLIR3(opcode, r_dest_src1, r_dest_src1, r_scratch); } return res; } -LIR* MipsCodegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, int r_src2) +LIR* MipsMir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2) { MipsOpCode opcode = kMipsNop; switch (op) { @@ -207,10 +205,10 @@ LIR* MipsCodegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_ LOG(FATAL) << "bad case in OpRegRegReg"; break; } - return NewLIR3(cu, opcode, r_dest, r_src1, r_src2); + return NewLIR3(opcode, r_dest, r_src1, r_src2); } -LIR* MipsCodegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, int value) +LIR* MipsMir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src1, int value) { LIR *res; MipsOpCode opcode = kMipsNop; @@ -285,21 +283,21 @@ LIR* MipsCodegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_ } if (short_form) - res = NewLIR3(cu, opcode, r_dest, r_src1, value); + res = NewLIR3(opcode, r_dest, r_src1, value); else { if (r_dest != r_src1) { - res = LoadConstant(cu, r_dest, value); - NewLIR3(cu, opcode, r_dest, r_src1, r_dest); + res = LoadConstant(r_dest, value); + NewLIR3(opcode, r_dest, r_src1, r_dest); } else { - int r_scratch = AllocTemp(cu); - res = LoadConstant(cu, r_scratch, value); - NewLIR3(cu, opcode, r_dest, r_src1, r_scratch); + int r_scratch = AllocTemp(); + res = LoadConstant(r_scratch, value); + NewLIR3(opcode, r_dest, r_src1, r_scratch); } } return res; } -LIR* MipsCodegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2) +LIR* MipsMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) { MipsOpCode opcode = kMipsNop; LIR *res; @@ -308,57 +306,57 @@ LIR* MipsCodegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int opcode = kMipsMove; break; case kOpMvn: - return NewLIR3(cu, kMipsNor, r_dest_src1, r_src2, r_ZERO); + return NewLIR3(kMipsNor, r_dest_src1, r_src2, r_ZERO); case kOpNeg: - return NewLIR3(cu, kMipsSubu, r_dest_src1, r_ZERO, r_src2); + return NewLIR3(kMipsSubu, r_dest_src1, r_ZERO, r_src2); case kOpAdd: case kOpAnd: case kOpMul: case kOpOr: case kOpSub: case kOpXor: - return OpRegRegReg(cu, op, r_dest_src1, r_dest_src1, r_src2); + return OpRegRegReg(op, r_dest_src1, r_dest_src1, r_src2); case kOp2Byte: #if __mips_isa_rev>=2 - res = NewLIR2(cu, kMipsSeb, r_dest_src1, r_src2); + res = NewLIR2(kMipsSeb, r_dest_src1, r_src2); #else - res = OpRegRegImm(cu, kOpLsl, r_dest_src1, r_src2, 24); - OpRegRegImm(cu, kOpAsr, r_dest_src1, r_dest_src1, 24); + res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 24); + OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 24); #endif return res; case kOp2Short: #if __mips_isa_rev>=2 - res = NewLIR2(cu, kMipsSeh, r_dest_src1, r_src2); + res = NewLIR2(kMipsSeh, r_dest_src1, r_src2); #else - res = OpRegRegImm(cu, kOpLsl, r_dest_src1, r_src2, 16); - OpRegRegImm(cu, kOpAsr, r_dest_src1, r_dest_src1, 16); + res = OpRegRegImm(kOpLsl, r_dest_src1, r_src2, 16); + OpRegRegImm(kOpAsr, r_dest_src1, r_dest_src1, 16); #endif return res; case kOp2Char: - return NewLIR3(cu, kMipsAndi, r_dest_src1, r_src2, 0xFFFF); + return NewLIR3(kMipsAndi, r_dest_src1, r_src2, 0xFFFF); default: LOG(FATAL) << "Bad case in OpRegReg"; break; } - return NewLIR2(cu, opcode, r_dest_src1, r_src2); + return NewLIR2(opcode, r_dest_src1, r_src2); } -LIR* MipsCodegen::LoadConstantWide(CompilationUnit *cu, int r_dest_lo, int r_dest_hi, int64_t value) +LIR* MipsMir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) { LIR *res; - res = LoadConstantNoClobber(cu, r_dest_lo, Low32Bits(value)); - LoadConstantNoClobber(cu, r_dest_hi, High32Bits(value)); + res = LoadConstantNoClobber(r_dest_lo, Low32Bits(value)); + LoadConstantNoClobber(r_dest_hi, High32Bits(value)); return res; } /* Load value from base + scaled index. */ -LIR* MipsCodegen::LoadBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_dest, +LIR* MipsMir2Lir::LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size) { LIR *first = NULL; LIR *res; MipsOpCode opcode = kMipsNop; - int t_reg = AllocTemp(cu); + int t_reg = AllocTemp(); if (MIPS_FPREG(r_dest)) { DCHECK(MIPS_SINGLEREG(r_dest)); @@ -370,10 +368,10 @@ LIR* MipsCodegen::LoadBaseIndexed(CompilationUnit *cu, int rBase, int r_index, i } if (!scale) { - first = NewLIR3(cu, kMipsAddu, t_reg , rBase, r_index); + first = NewLIR3(kMipsAddu, t_reg , rBase, r_index); } else { - first = OpRegRegImm(cu, kOpLsl, t_reg, r_index, scale); - NewLIR3(cu, kMipsAddu, t_reg , rBase, t_reg); + first = OpRegRegImm(kOpLsl, t_reg, r_index, scale); + NewLIR3(kMipsAddu, t_reg , rBase, t_reg); } switch (size) { @@ -399,19 +397,19 @@ LIR* MipsCodegen::LoadBaseIndexed(CompilationUnit *cu, int rBase, int r_index, i LOG(FATAL) << "Bad case in LoadBaseIndexed"; } - res = NewLIR3(cu, opcode, r_dest, 0, t_reg); - FreeTemp(cu, t_reg); + res = NewLIR3(opcode, r_dest, 0, t_reg); + FreeTemp(t_reg); return (first) ? first : res; } /* store value base base + scaled index. */ -LIR* MipsCodegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src, +LIR* MipsMir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size) { LIR *first = NULL; MipsOpCode opcode = kMipsNop; int r_new_index = r_index; - int t_reg = AllocTemp(cu); + int t_reg = AllocTemp(); if (MIPS_FPREG(r_src)) { DCHECK(MIPS_SINGLEREG(r_src)); @@ -423,10 +421,10 @@ LIR* MipsCodegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, } if (!scale) { - first = NewLIR3(cu, kMipsAddu, t_reg , rBase, r_index); + first = NewLIR3(kMipsAddu, t_reg , rBase, r_index); } else { - first = OpRegRegImm(cu, kOpLsl, t_reg, r_index, scale); - NewLIR3(cu, kMipsAddu, t_reg , rBase, t_reg); + first = OpRegRegImm(kOpLsl, t_reg, r_index, scale); + NewLIR3(kMipsAddu, t_reg , rBase, t_reg); } switch (size) { @@ -447,12 +445,12 @@ LIR* MipsCodegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, default: LOG(FATAL) << "Bad case in StoreBaseIndexed"; } - NewLIR3(cu, opcode, r_src, 0, t_reg); - FreeTemp(cu, r_new_index); + NewLIR3(opcode, r_src, 0, t_reg); + FreeTemp(r_new_index); return first; } -LIR* MipsCodegen::LoadBaseDispBody(CompilationUnit *cu, int rBase, int displacement, int r_dest, +LIR* MipsMir2Lir::LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size, int s_reg) /* * Load value from base + displacement. Optionally perform null check @@ -517,54 +515,54 @@ LIR* MipsCodegen::LoadBaseDispBody(CompilationUnit *cu, int rBase, int displacem if (short_form) { if (!pair) { - load = res = NewLIR3(cu, opcode, r_dest, displacement, rBase); + load = res = NewLIR3(opcode, r_dest, displacement, rBase); } else { - load = res = NewLIR3(cu, opcode, r_dest, + load = res = NewLIR3(opcode, r_dest, displacement + LOWORD_OFFSET, rBase); - load2 = NewLIR3(cu, opcode, r_dest_hi, + load2 = NewLIR3(opcode, r_dest_hi, displacement + HIWORD_OFFSET, rBase); } } else { if (pair) { - int r_tmp = AllocFreeTemp(cu); - res = OpRegRegImm(cu, kOpAdd, r_tmp, rBase, displacement); - load = NewLIR3(cu, opcode, r_dest, LOWORD_OFFSET, r_tmp); - load2 = NewLIR3(cu, opcode, r_dest_hi, HIWORD_OFFSET, r_tmp); - FreeTemp(cu, r_tmp); + int r_tmp = AllocFreeTemp(); + res = OpRegRegImm(kOpAdd, r_tmp, rBase, displacement); + load = NewLIR3(opcode, r_dest, LOWORD_OFFSET, r_tmp); + load2 = NewLIR3(opcode, r_dest_hi, HIWORD_OFFSET, r_tmp); + FreeTemp(r_tmp); } else { - int r_tmp = (rBase == r_dest) ? AllocFreeTemp(cu) : r_dest; - res = OpRegRegImm(cu, kOpAdd, r_tmp, rBase, displacement); - load = NewLIR3(cu, opcode, r_dest, 0, r_tmp); + int r_tmp = (rBase == r_dest) ? AllocFreeTemp() : r_dest; + res = OpRegRegImm(kOpAdd, r_tmp, rBase, displacement); + load = NewLIR3(opcode, r_dest, 0, r_tmp); if (r_tmp != r_dest) - FreeTemp(cu, r_tmp); + FreeTemp(r_tmp); } } if (rBase == rMIPS_SP) { - AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, + AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, true /* is_load */, pair /* is64bit */); if (pair) { - AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2, + AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2, true /* is_load */, pair /* is64bit */); } } return load; } -LIR* MipsCodegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement, int r_dest, +LIR* MipsMir2Lir::LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg) { - return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1, + return LoadBaseDispBody(rBase, displacement, r_dest, -1, size, s_reg); } -LIR* MipsCodegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement, +LIR* MipsMir2Lir::LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi, int s_reg) { - return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg); + return LoadBaseDispBody(rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg); } -LIR* MipsCodegen::StoreBaseDispBody(CompilationUnit *cu, int rBase, int displacement, +LIR* MipsMir2Lir::StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size) { LIR *res; @@ -616,30 +614,30 @@ LIR* MipsCodegen::StoreBaseDispBody(CompilationUnit *cu, int rBase, int displace if (short_form) { if (!pair) { - store = res = NewLIR3(cu, opcode, r_src, displacement, rBase); + store = res = NewLIR3(opcode, r_src, displacement, rBase); } else { - store = res = NewLIR3(cu, opcode, r_src, displacement + LOWORD_OFFSET, + store = res = NewLIR3(opcode, r_src, displacement + LOWORD_OFFSET, rBase); - store2 = NewLIR3(cu, opcode, r_src_hi, displacement + HIWORD_OFFSET, + store2 = NewLIR3(opcode, r_src_hi, displacement + HIWORD_OFFSET, rBase); } } else { - int r_scratch = AllocTemp(cu); - res = OpRegRegImm(cu, kOpAdd, r_scratch, rBase, displacement); + int r_scratch = AllocTemp(); + res = OpRegRegImm(kOpAdd, r_scratch, rBase, displacement); if (!pair) { - store = NewLIR3(cu, opcode, r_src, 0, r_scratch); + store = NewLIR3(opcode, r_src, 0, r_scratch); } else { - store = NewLIR3(cu, opcode, r_src, LOWORD_OFFSET, r_scratch); - store2 = NewLIR3(cu, opcode, r_src_hi, HIWORD_OFFSET, r_scratch); + store = NewLIR3(opcode, r_src, LOWORD_OFFSET, r_scratch); + store2 = NewLIR3(opcode, r_src_hi, HIWORD_OFFSET, r_scratch); } - FreeTemp(cu, r_scratch); + FreeTemp(r_scratch); } if (rBase == rMIPS_SP) { - AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, + AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, false /* is_load */, pair /* is64bit */); if (pair) { - AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2, + AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2, false /* is_load */, pair /* is64bit */); } } @@ -647,56 +645,52 @@ LIR* MipsCodegen::StoreBaseDispBody(CompilationUnit *cu, int rBase, int displace return res; } -LIR* MipsCodegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement, int r_src, +LIR* MipsMir2Lir::StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size) { - return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size); + return StoreBaseDispBody(rBase, displacement, r_src, -1, size); } -LIR* MipsCodegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement, +LIR* MipsMir2Lir::StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi) { - return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong); + return StoreBaseDispBody(rBase, displacement, r_src_lo, r_src_hi, kLong); } -LIR* MipsCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset) +LIR* MipsMir2Lir::OpThreadMem(OpKind op, int thread_offset) { LOG(FATAL) << "Unexpected use of OpThreadMem for MIPS"; return NULL; } -LIR* MipsCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp) +LIR* MipsMir2Lir::OpMem(OpKind op, int rBase, int disp) { LOG(FATAL) << "Unexpected use of OpMem for MIPS"; return NULL; } -LIR* MipsCodegen::StoreBaseIndexedDisp(CompilationUnit *cu, - int rBase, int r_index, int scale, int displacement, - int r_src, int r_src_hi, - OpSize size, int s_reg) +LIR* MipsMir2Lir::StoreBaseIndexedDisp( int rBase, int r_index, int scale, int displacement, + int r_src, int r_src_hi, OpSize size, int s_reg) { LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for MIPS"; return NULL; } -LIR* MipsCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, +LIR* MipsMir2Lir::OpRegMem(OpKind op, int r_dest, int rBase, int offset) { LOG(FATAL) << "Unexpected use of OpRegMem for MIPS"; return NULL; } -LIR* MipsCodegen::LoadBaseIndexedDisp(CompilationUnit *cu, - int rBase, int r_index, int scale, int displacement, - int r_dest, int r_dest_hi, - OpSize size, int s_reg) +LIR* MipsMir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_dest, int r_dest_hi, OpSize size, int s_reg) { LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for MIPS"; return NULL; } -LIR* MipsCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target) +LIR* MipsMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) { LOG(FATAL) << "Unexpected use of OpCondBranch for MIPS"; return NULL; diff --git a/src/compiler/dex/quick/mir_to_lir.cc b/src/compiler/dex/quick/mir_to_lir.cc index 7aec54e1e0..1f50914a3c 100644 --- a/src/compiler/dex/quick/mir_to_lir.cc +++ b/src/compiler/dex/quick/mir_to_lir.cc @@ -18,9 +18,6 @@ #include "compiler/dex/compiler_internals.h" #include "compiler/dex/dataflow_iterator.h" -#include "local_optimizations.h" -#include "codegen_util.h" -#include "ralloc_util.h" namespace art { @@ -29,13 +26,11 @@ namespace art { * load/store utilities here, or target-dependent genXX() handlers * when necessary. */ -static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* bb, - LIR* label_list) +void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list) { - Codegen* cg = cu->cg.get(); RegLocation rl_src[3]; - RegLocation rl_dest = GetBadLoc(); - RegLocation rl_result = GetBadLoc(); + RegLocation rl_dest = mir_graph_->GetBadLoc(); + RegLocation rl_result = mir_graph_->GetBadLoc(); Instruction::Code opcode = mir->dalvikInsn.opcode; int opt_flags = mir->optimization_flags; uint32_t vB = mir->dalvikInsn.vB; @@ -44,38 +39,38 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* // Prep Src and Dest locations. int next_sreg = 0; int next_loc = 0; - int attrs = oat_data_flow_attributes[opcode]; - rl_src[0] = rl_src[1] = rl_src[2] = GetBadLoc(); + int attrs = mir_graph_->oat_data_flow_attributes_[opcode]; + rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc(); if (attrs & DF_UA) { if (attrs & DF_A_WIDE) { - rl_src[next_loc++] = GetSrcWide(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); next_sreg+= 2; } else { - rl_src[next_loc++] = GetSrc(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); next_sreg++; } } if (attrs & DF_UB) { if (attrs & DF_B_WIDE) { - rl_src[next_loc++] = GetSrcWide(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); next_sreg+= 2; } else { - rl_src[next_loc++] = GetSrc(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); next_sreg++; } } if (attrs & DF_UC) { if (attrs & DF_C_WIDE) { - rl_src[next_loc++] = GetSrcWide(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg); } else { - rl_src[next_loc++] = GetSrc(cu, mir, next_sreg); + rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg); } } if (attrs & DF_DA) { if (attrs & DF_A_WIDE) { - rl_dest = GetDestWide(cu, mir); + rl_dest = mir_graph_->GetDestWide(mir); } else { - rl_dest = GetDest(cu, mir); + rl_dest = mir_graph_->GetDest(mir); } } switch (opcode) { @@ -83,47 +78,46 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* break; case Instruction::MOVE_EXCEPTION: - cg->GenMoveException(cu, rl_dest); + GenMoveException(rl_dest); break; case Instruction::RETURN_VOID: - if (((cu->access_flags & kAccConstructor) != 0) && - cu->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu->dex_file, - cu->class_def_idx)) { - cg->GenMemBarrier(cu, kStoreStore); + if (((cu_->access_flags & kAccConstructor) != 0) && + cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu_->dex_file, + cu_->class_def_idx)) { + GenMemBarrier(kStoreStore); } - if (!(cu->attributes & METHOD_IS_LEAF)) { - cg->GenSuspendTest(cu, opt_flags); + if (!mir_graph_->MethodIsLeaf()) { + GenSuspendTest(opt_flags); } break; case Instruction::RETURN: case Instruction::RETURN_OBJECT: - if (!(cu->attributes & METHOD_IS_LEAF)) { - cg->GenSuspendTest(cu, opt_flags); + if (!mir_graph_->MethodIsLeaf()) { + GenSuspendTest(opt_flags); } - cg->StoreValue(cu, GetReturn(cu, cu->shorty[0] == 'F'), rl_src[0]); + StoreValue(GetReturn(cu_->shorty[0] == 'F'), rl_src[0]); break; case Instruction::RETURN_WIDE: - if (!(cu->attributes & METHOD_IS_LEAF)) { - cg->GenSuspendTest(cu, opt_flags); + if (!mir_graph_->MethodIsLeaf()) { + GenSuspendTest(opt_flags); } - cg->StoreValueWide(cu, GetReturnWide(cu, - cu->shorty[0] == 'D'), rl_src[0]); + StoreValueWide(GetReturnWide(cu_->shorty[0] == 'D'), rl_src[0]); break; case Instruction::MOVE_RESULT_WIDE: if (opt_flags & MIR_INLINED) break; // Nop - combined w/ previous invoke. - cg->StoreValueWide(cu, rl_dest, GetReturnWide(cu, rl_dest.fp)); + StoreValueWide(rl_dest, GetReturnWide(rl_dest.fp)); break; case Instruction::MOVE_RESULT: case Instruction::MOVE_RESULT_OBJECT: if (opt_flags & MIR_INLINED) break; // Nop - combined w/ previous invoke. - cg->StoreValue(cu, rl_dest, GetReturn(cu, rl_dest.fp)); + StoreValue(rl_dest, GetReturn(rl_dest.fp)); break; case Instruction::MOVE: @@ -132,144 +126,144 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::MOVE_OBJECT_16: case Instruction::MOVE_FROM16: case Instruction::MOVE_OBJECT_FROM16: - cg->StoreValue(cu, rl_dest, rl_src[0]); + StoreValue(rl_dest, rl_src[0]); break; case Instruction::MOVE_WIDE: case Instruction::MOVE_WIDE_16: case Instruction::MOVE_WIDE_FROM16: - cg->StoreValueWide(cu, rl_dest, rl_src[0]); + StoreValueWide(rl_dest, rl_src[0]); break; case Instruction::CONST: case Instruction::CONST_4: case Instruction::CONST_16: - rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); - cg->LoadConstantNoClobber(cu, rl_result.low_reg, vB); - cg->StoreValue(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kAnyReg, true); + LoadConstantNoClobber(rl_result.low_reg, vB); + StoreValue(rl_dest, rl_result); if (vB == 0) { - cg->Workaround7250540(cu, rl_dest, rl_result.low_reg); + Workaround7250540(rl_dest, rl_result.low_reg); } break; case Instruction::CONST_HIGH16: - rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); - cg->LoadConstantNoClobber(cu, rl_result.low_reg, vB << 16); - cg->StoreValue(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kAnyReg, true); + LoadConstantNoClobber(rl_result.low_reg, vB << 16); + StoreValue(rl_dest, rl_result); if (vB == 0) { - cg->Workaround7250540(cu, rl_dest, rl_result.low_reg); + Workaround7250540(rl_dest, rl_result.low_reg); } break; case Instruction::CONST_WIDE_16: case Instruction::CONST_WIDE_32: - rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); - cg->LoadConstantWide(cu, rl_result.low_reg, rl_result.high_reg, + rl_result = EvalLoc(rl_dest, kAnyReg, true); + LoadConstantWide(rl_result.low_reg, rl_result.high_reg, static_cast<int64_t>(static_cast<int32_t>(vB))); - cg->StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); break; case Instruction::CONST_WIDE: - rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); - cg->LoadConstantWide(cu, rl_result.low_reg, rl_result.high_reg, mir->dalvikInsn.vB_wide); - cg->StoreValueWide(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kAnyReg, true); + LoadConstantWide(rl_result.low_reg, rl_result.high_reg, mir->dalvikInsn.vB_wide); + StoreValueWide(rl_dest, rl_result); break; case Instruction::CONST_WIDE_HIGH16: - rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); - cg->LoadConstantWide(cu, rl_result.low_reg, rl_result.high_reg, + rl_result = EvalLoc(rl_dest, kAnyReg, true); + LoadConstantWide(rl_result.low_reg, rl_result.high_reg, static_cast<int64_t>(vB) << 48); - cg->StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); break; case Instruction::MONITOR_ENTER: - cg->GenMonitorEnter(cu, opt_flags, rl_src[0]); + GenMonitorEnter(opt_flags, rl_src[0]); break; case Instruction::MONITOR_EXIT: - cg->GenMonitorExit(cu, opt_flags, rl_src[0]); + GenMonitorExit(opt_flags, rl_src[0]); break; case Instruction::CHECK_CAST: - cg->GenCheckCast(cu, vB, rl_src[0]); + GenCheckCast(vB, rl_src[0]); break; case Instruction::INSTANCE_OF: - cg->GenInstanceof(cu, vC, rl_dest, rl_src[0]); + GenInstanceof(vC, rl_dest, rl_src[0]); break; case Instruction::NEW_INSTANCE: - cg->GenNewInstance(cu, vB, rl_dest); + GenNewInstance(vB, rl_dest); break; case Instruction::THROW: - cg->GenThrow(cu, rl_src[0]); + GenThrow(rl_src[0]); break; case Instruction::ARRAY_LENGTH: int len_offset; len_offset = mirror::Array::LengthOffset().Int32Value(); - rl_src[0] = cg->LoadValue(cu, rl_src[0], kCoreReg); - cg->GenNullCheck(cu, rl_src[0].s_reg_low, rl_src[0].low_reg, opt_flags); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - cg->LoadWordDisp(cu, rl_src[0].low_reg, len_offset, rl_result.low_reg); - cg->StoreValue(cu, rl_dest, rl_result); + rl_src[0] = LoadValue(rl_src[0], kCoreReg); + GenNullCheck(rl_src[0].s_reg_low, rl_src[0].low_reg, opt_flags); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + LoadWordDisp(rl_src[0].low_reg, len_offset, rl_result.low_reg); + StoreValue(rl_dest, rl_result); break; case Instruction::CONST_STRING: case Instruction::CONST_STRING_JUMBO: - cg->GenConstString(cu, vB, rl_dest); + GenConstString(vB, rl_dest); break; case Instruction::CONST_CLASS: - cg->GenConstClass(cu, vB, rl_dest); + GenConstClass(vB, rl_dest); break; case Instruction::FILL_ARRAY_DATA: - cg->GenFillArrayData(cu, vB, rl_src[0]); + GenFillArrayData(vB, rl_src[0]); break; case Instruction::FILLED_NEW_ARRAY: - cg->GenFilledNewArray(cu, cg->NewMemCallInfo(cu, bb, mir, kStatic, + GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic, false /* not range */)); break; case Instruction::FILLED_NEW_ARRAY_RANGE: - cg->GenFilledNewArray(cu, cg->NewMemCallInfo(cu, bb, mir, kStatic, + GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic, true /* range */)); break; case Instruction::NEW_ARRAY: - cg->GenNewArray(cu, vC, rl_dest, rl_src[0]); + GenNewArray(vC, rl_dest, rl_src[0]); break; case Instruction::GOTO: case Instruction::GOTO_16: case Instruction::GOTO_32: if (bb->taken->start_offset <= mir->offset) { - cg->GenSuspendTestAndBranch(cu, opt_flags, &label_list[bb->taken->id]); + GenSuspendTestAndBranch(opt_flags, &label_list[bb->taken->id]); } else { - cg->OpUnconditionalBranch(cu, &label_list[bb->taken->id]); + OpUnconditionalBranch(&label_list[bb->taken->id]); } break; case Instruction::PACKED_SWITCH: - cg->GenPackedSwitch(cu, mir, vB, rl_src[0]); + GenPackedSwitch(mir, vB, rl_src[0]); break; case Instruction::SPARSE_SWITCH: - cg->GenSparseSwitch(cu, mir, vB, rl_src[0]); + GenSparseSwitch(mir, vB, rl_src[0]); break; case Instruction::CMPL_FLOAT: case Instruction::CMPG_FLOAT: case Instruction::CMPL_DOUBLE: case Instruction::CMPG_DOUBLE: - cg->GenCmpFP(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenCmpFP(opcode, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::CMP_LONG: - cg->GenCmpLong(cu, rl_dest, rl_src[0], rl_src[1]); + GenCmpLong(rl_dest, rl_src[0], rl_src[1]); break; case Instruction::IF_EQ: @@ -284,18 +278,18 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* backward_branch = (bb->taken->start_offset <= mir->offset); // Result known at compile time? if (rl_src[0].is_const && rl_src[1].is_const) { - bool is_taken = EvaluateBranch(opcode, cu->mir_graph->ConstantValue(rl_src[0].orig_sreg), - cu->mir_graph->ConstantValue(rl_src[1].orig_sreg)); + bool is_taken = EvaluateBranch(opcode, mir_graph_->ConstantValue(rl_src[0].orig_sreg), + mir_graph_->ConstantValue(rl_src[1].orig_sreg)); if (is_taken && backward_branch) { - cg->GenSuspendTest(cu, opt_flags); + GenSuspendTest(opt_flags); } int id = is_taken ? bb->taken->id : bb->fall_through->id; - cg->OpUnconditionalBranch(cu, &label_list[id]); + OpUnconditionalBranch(&label_list[id]); } else { if (backward_branch) { - cg->GenSuspendTest(cu, opt_flags); + GenSuspendTest(opt_flags); } - cg->GenCompareAndBranch(cu, opcode, rl_src[0], rl_src[1], taken, + GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken, fall_through); } break; @@ -313,126 +307,126 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* backward_branch = (bb->taken->start_offset <= mir->offset); // Result known at compile time? if (rl_src[0].is_const) { - bool is_taken = EvaluateBranch(opcode, cu->mir_graph->ConstantValue(rl_src[0].orig_sreg), 0); + bool is_taken = EvaluateBranch(opcode, mir_graph_->ConstantValue(rl_src[0].orig_sreg), 0); if (is_taken && backward_branch) { - cg->GenSuspendTest(cu, opt_flags); + GenSuspendTest(opt_flags); } int id = is_taken ? bb->taken->id : bb->fall_through->id; - cg->OpUnconditionalBranch(cu, &label_list[id]); + OpUnconditionalBranch(&label_list[id]); } else { if (backward_branch) { - cg->GenSuspendTest(cu, opt_flags); + GenSuspendTest(opt_flags); } - cg->GenCompareZeroAndBranch(cu, opcode, rl_src[0], taken, fall_through); + GenCompareZeroAndBranch(opcode, rl_src[0], taken, fall_through); } break; } case Instruction::AGET_WIDE: - cg->GenArrayGet(cu, opt_flags, kLong, rl_src[0], rl_src[1], rl_dest, 3); + GenArrayGet(opt_flags, kLong, rl_src[0], rl_src[1], rl_dest, 3); break; case Instruction::AGET: case Instruction::AGET_OBJECT: - cg->GenArrayGet(cu, opt_flags, kWord, rl_src[0], rl_src[1], rl_dest, 2); + GenArrayGet(opt_flags, kWord, rl_src[0], rl_src[1], rl_dest, 2); break; case Instruction::AGET_BOOLEAN: - cg->GenArrayGet(cu, opt_flags, kUnsignedByte, rl_src[0], rl_src[1], rl_dest, 0); + GenArrayGet(opt_flags, kUnsignedByte, rl_src[0], rl_src[1], rl_dest, 0); break; case Instruction::AGET_BYTE: - cg->GenArrayGet(cu, opt_flags, kSignedByte, rl_src[0], rl_src[1], rl_dest, 0); + GenArrayGet(opt_flags, kSignedByte, rl_src[0], rl_src[1], rl_dest, 0); break; case Instruction::AGET_CHAR: - cg->GenArrayGet(cu, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], rl_dest, 1); + GenArrayGet(opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], rl_dest, 1); break; case Instruction::AGET_SHORT: - cg->GenArrayGet(cu, opt_flags, kSignedHalf, rl_src[0], rl_src[1], rl_dest, 1); + GenArrayGet(opt_flags, kSignedHalf, rl_src[0], rl_src[1], rl_dest, 1); break; case Instruction::APUT_WIDE: - cg->GenArrayPut(cu, opt_flags, kLong, rl_src[1], rl_src[2], rl_src[0], 3); + GenArrayPut(opt_flags, kLong, rl_src[1], rl_src[2], rl_src[0], 3); break; case Instruction::APUT: - cg->GenArrayPut(cu, opt_flags, kWord, rl_src[1], rl_src[2], rl_src[0], 2); + GenArrayPut(opt_flags, kWord, rl_src[1], rl_src[2], rl_src[0], 2); break; case Instruction::APUT_OBJECT: - cg->GenArrayObjPut(cu, opt_flags, rl_src[1], rl_src[2], rl_src[0], 2); + GenArrayObjPut(opt_flags, rl_src[1], rl_src[2], rl_src[0], 2); break; case Instruction::APUT_SHORT: case Instruction::APUT_CHAR: - cg->GenArrayPut(cu, opt_flags, kUnsignedHalf, rl_src[1], rl_src[2], rl_src[0], 1); + GenArrayPut(opt_flags, kUnsignedHalf, rl_src[1], rl_src[2], rl_src[0], 1); break; case Instruction::APUT_BYTE: case Instruction::APUT_BOOLEAN: - cg->GenArrayPut(cu, opt_flags, kUnsignedByte, rl_src[1], rl_src[2], + GenArrayPut(opt_flags, kUnsignedByte, rl_src[1], rl_src[2], rl_src[0], 0); break; case Instruction::IGET_OBJECT: - cg->GenIGet(cu, vC, opt_flags, kWord, rl_dest, rl_src[0], false, true); + GenIGet(vC, opt_flags, kWord, rl_dest, rl_src[0], false, true); break; case Instruction::IGET_WIDE: - cg->GenIGet(cu, vC, opt_flags, kLong, rl_dest, rl_src[0], true, false); + GenIGet(vC, opt_flags, kLong, rl_dest, rl_src[0], true, false); break; case Instruction::IGET: - cg->GenIGet(cu, vC, opt_flags, kWord, rl_dest, rl_src[0], false, false); + GenIGet(vC, opt_flags, kWord, rl_dest, rl_src[0], false, false); break; case Instruction::IGET_CHAR: - cg->GenIGet(cu, vC, opt_flags, kUnsignedHalf, rl_dest, rl_src[0], false, false); + GenIGet(vC, opt_flags, kUnsignedHalf, rl_dest, rl_src[0], false, false); break; case Instruction::IGET_SHORT: - cg->GenIGet(cu, vC, opt_flags, kSignedHalf, rl_dest, rl_src[0], false, false); + GenIGet(vC, opt_flags, kSignedHalf, rl_dest, rl_src[0], false, false); break; case Instruction::IGET_BOOLEAN: case Instruction::IGET_BYTE: - cg->GenIGet(cu, vC, opt_flags, kUnsignedByte, rl_dest, rl_src[0], false, false); + GenIGet(vC, opt_flags, kUnsignedByte, rl_dest, rl_src[0], false, false); break; case Instruction::IPUT_WIDE: - cg->GenIPut(cu, vC, opt_flags, kLong, rl_src[0], rl_src[1], true, false); + GenIPut(vC, opt_flags, kLong, rl_src[0], rl_src[1], true, false); break; case Instruction::IPUT_OBJECT: - cg->GenIPut(cu, vC, opt_flags, kWord, rl_src[0], rl_src[1], false, true); + GenIPut(vC, opt_flags, kWord, rl_src[0], rl_src[1], false, true); break; case Instruction::IPUT: - cg->GenIPut(cu, vC, opt_flags, kWord, rl_src[0], rl_src[1], false, false); + GenIPut(vC, opt_flags, kWord, rl_src[0], rl_src[1], false, false); break; case Instruction::IPUT_BOOLEAN: case Instruction::IPUT_BYTE: - cg->GenIPut(cu, vC, opt_flags, kUnsignedByte, rl_src[0], rl_src[1], false, false); + GenIPut(vC, opt_flags, kUnsignedByte, rl_src[0], rl_src[1], false, false); break; case Instruction::IPUT_CHAR: - cg->GenIPut(cu, vC, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], false, false); + GenIPut(vC, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], false, false); break; case Instruction::IPUT_SHORT: - cg->GenIPut(cu, vC, opt_flags, kSignedHalf, rl_src[0], rl_src[1], false, false); + GenIPut(vC, opt_flags, kSignedHalf, rl_src[0], rl_src[1], false, false); break; case Instruction::SGET_OBJECT: - cg->GenSget(cu, vB, rl_dest, false, true); + GenSget(vB, rl_dest, false, true); break; case Instruction::SGET: case Instruction::SGET_BOOLEAN: case Instruction::SGET_BYTE: case Instruction::SGET_CHAR: case Instruction::SGET_SHORT: - cg->GenSget(cu, vB, rl_dest, false, false); + GenSget(vB, rl_dest, false, false); break; case Instruction::SGET_WIDE: - cg->GenSget(cu, vB, rl_dest, true, false); + GenSget(vB, rl_dest, true, false); break; case Instruction::SPUT_OBJECT: - cg->GenSput(cu, vB, rl_src[0], false, true); + GenSput(vB, rl_src[0], false, true); break; case Instruction::SPUT: @@ -440,80 +434,80 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::SPUT_BYTE: case Instruction::SPUT_CHAR: case Instruction::SPUT_SHORT: - cg->GenSput(cu, vB, rl_src[0], false, false); + GenSput(vB, rl_src[0], false, false); break; case Instruction::SPUT_WIDE: - cg->GenSput(cu, vB, rl_src[0], true, false); + GenSput(vB, rl_src[0], true, false); break; case Instruction::INVOKE_STATIC_RANGE: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kStatic, true)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, true)); break; case Instruction::INVOKE_STATIC: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kStatic, false)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, false)); break; case Instruction::INVOKE_DIRECT: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kDirect, false)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, false)); break; case Instruction::INVOKE_DIRECT_RANGE: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kDirect, true)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, true)); break; case Instruction::INVOKE_VIRTUAL: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kVirtual, false)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, false)); break; case Instruction::INVOKE_VIRTUAL_RANGE: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kVirtual, true)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, true)); break; case Instruction::INVOKE_SUPER: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kSuper, false)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, false)); break; case Instruction::INVOKE_SUPER_RANGE: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kSuper, true)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, true)); break; case Instruction::INVOKE_INTERFACE: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kInterface, false)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, false)); break; case Instruction::INVOKE_INTERFACE_RANGE: - cg->GenInvoke(cu, cg->NewMemCallInfo(cu, bb, mir, kInterface, true)); + GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, true)); break; case Instruction::NEG_INT: case Instruction::NOT_INT: - cg->GenArithOpInt(cu, opcode, rl_dest, rl_src[0], rl_src[0]); + GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[0]); break; case Instruction::NEG_LONG: case Instruction::NOT_LONG: - cg->GenArithOpLong(cu, opcode, rl_dest, rl_src[0], rl_src[0]); + GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[0]); break; case Instruction::NEG_FLOAT: - cg->GenArithOpFloat(cu, opcode, rl_dest, rl_src[0], rl_src[0]); + GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[0]); break; case Instruction::NEG_DOUBLE: - cg->GenArithOpDouble(cu, opcode, rl_dest, rl_src[0], rl_src[0]); + GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[0]); break; case Instruction::INT_TO_LONG: - cg->GenIntToLong(cu, rl_dest, rl_src[0]); + GenIntToLong(rl_dest, rl_src[0]); break; case Instruction::LONG_TO_INT: - rl_src[0] = UpdateLocWide(cu, rl_src[0]); - rl_src[0] = WideToNarrow(cu, rl_src[0]); - cg->StoreValue(cu, rl_dest, rl_src[0]); + rl_src[0] = UpdateLocWide(rl_src[0]); + rl_src[0] = WideToNarrow(rl_src[0]); + StoreValue(rl_dest, rl_src[0]); break; case Instruction::INT_TO_BYTE: case Instruction::INT_TO_SHORT: case Instruction::INT_TO_CHAR: - cg->GenIntNarrowing(cu, opcode, rl_dest, rl_src[0]); + GenIntNarrowing(opcode, rl_dest, rl_src[0]); break; case Instruction::INT_TO_FLOAT: @@ -526,7 +520,7 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::DOUBLE_TO_INT: case Instruction::DOUBLE_TO_LONG: case Instruction::DOUBLE_TO_FLOAT: - cg->GenConversion(cu, opcode, rl_dest, rl_src[0]); + GenConversion(opcode, rl_dest, rl_src[0]); break; @@ -541,15 +535,15 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::XOR_INT: case Instruction::XOR_INT_2ADDR: if (rl_src[0].is_const && - cu->cg->InexpensiveConstantInt(cu->mir_graph->ConstantValue(rl_src[0]))) { - cg->GenArithOpIntLit(cu, opcode, rl_dest, rl_src[1], - cu->mir_graph->ConstantValue(rl_src[0].orig_sreg)); + InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[0]))) { + GenArithOpIntLit(opcode, rl_dest, rl_src[1], + mir_graph_->ConstantValue(rl_src[0].orig_sreg)); } else if (rl_src[1].is_const && - cu->cg->InexpensiveConstantInt(cu->mir_graph->ConstantValue(rl_src[1]))) { - cg->GenArithOpIntLit(cu, opcode, rl_dest, rl_src[0], - cu->mir_graph->ConstantValue(rl_src[1].orig_sreg)); + InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]))) { + GenArithOpIntLit(opcode, rl_dest, rl_src[0], + mir_graph_->ConstantValue(rl_src[1].orig_sreg)); } else { - cg->GenArithOpInt(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1]); } break; @@ -566,10 +560,10 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::USHR_INT: case Instruction::USHR_INT_2ADDR: if (rl_src[1].is_const && - cu->cg->InexpensiveConstantInt(cu->mir_graph->ConstantValue(rl_src[1]))) { - cg->GenArithOpIntLit(cu, opcode, rl_dest, rl_src[0], cu->mir_graph->ConstantValue(rl_src[1])); + InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]))) { + GenArithOpIntLit(opcode, rl_dest, rl_src[0], mir_graph_->ConstantValue(rl_src[1])); } else { - cg->GenArithOpInt(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1]); } break; @@ -584,7 +578,7 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::OR_LONG_2ADDR: case Instruction::XOR_LONG_2ADDR: if (rl_src[0].is_const || rl_src[1].is_const) { - cg->GenArithImmOpLong(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); break; } // Note: intentional fallthrough. @@ -595,7 +589,7 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::MUL_LONG_2ADDR: case Instruction::DIV_LONG_2ADDR: case Instruction::REM_LONG_2ADDR: - cg->GenArithOpLong(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::SHL_LONG: @@ -605,9 +599,9 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::SHR_LONG_2ADDR: case Instruction::USHR_LONG_2ADDR: if (rl_src[1].is_const) { - cg->GenShiftImmOpLong(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenShiftImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); } else { - cg->GenShiftOpLong(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenShiftOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); } break; @@ -621,7 +615,7 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::MUL_FLOAT_2ADDR: case Instruction::DIV_FLOAT_2ADDR: case Instruction::REM_FLOAT_2ADDR: - cg->GenArithOpFloat(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::ADD_DOUBLE: @@ -634,7 +628,7 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::MUL_DOUBLE_2ADDR: case Instruction::DIV_DOUBLE_2ADDR: case Instruction::REM_DOUBLE_2ADDR: - cg->GenArithOpDouble(cu, opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[1]); break; case Instruction::RSUB_INT: @@ -656,7 +650,7 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* case Instruction::SHL_INT_LIT8: case Instruction::SHR_INT_LIT8: case Instruction::USHR_INT_LIT8: - cg->GenArithOpIntLit(cu, opcode, rl_dest, rl_src[0], vC); + GenArithOpIntLit(opcode, rl_dest, rl_src[0], vC); break; default: @@ -665,33 +659,32 @@ static void CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* } // Process extended MIR instructions -static void HandleExtendedMethodMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir) +void Mir2Lir::HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir) { - Codegen* cg = cu->cg.get(); switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { case kMirOpCopy: { - RegLocation rl_src = GetSrc(cu, mir, 0); - RegLocation rl_dest = GetDest(cu, mir); - cg->StoreValue(cu, rl_dest, rl_src); + RegLocation rl_src = mir_graph_->GetSrc(mir, 0); + RegLocation rl_dest = mir_graph_->GetDest(mir); + StoreValue(rl_dest, rl_src); break; } case kMirOpFusedCmplFloat: - cg->GenFusedFPCmpBranch(cu, bb, mir, false /*gt bias*/, false /*double*/); + GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, false /*double*/); break; case kMirOpFusedCmpgFloat: - cg->GenFusedFPCmpBranch(cu, bb, mir, true /*gt bias*/, false /*double*/); + GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, false /*double*/); break; case kMirOpFusedCmplDouble: - cg->GenFusedFPCmpBranch(cu, bb, mir, false /*gt bias*/, true /*double*/); + GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, true /*double*/); break; case kMirOpFusedCmpgDouble: - cg->GenFusedFPCmpBranch(cu, bb, mir, true /*gt bias*/, true /*double*/); + GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, true /*double*/); break; case kMirOpFusedCmpLong: - cg->GenFusedLongCmpBranch(cu, bb, mir); + GenFusedLongCmpBranch(bb, mir); break; case kMirOpSelect: - cg->GenSelect(cu, bb, mir); + GenSelect(bb, mir); break; default: break; @@ -699,65 +692,63 @@ static void HandleExtendedMethodMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mi } // Handle the content in each basic block. -static bool MethodBlockCodeGen(CompilationUnit* cu, BasicBlock* bb) +bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) { if (bb->block_type == kDead) return false; - Codegen* cg = cu->cg.get(); - cu->current_dalvik_offset = bb->start_offset; + current_dalvik_offset_ = bb->start_offset; MIR* mir; - LIR* label_list = cu->block_label_list; int block_id = bb->id; - label_list[block_id].operands[0] = bb->start_offset; + block_label_list_[block_id].operands[0] = bb->start_offset; // Insert the block label. - label_list[block_id].opcode = kPseudoNormalBlockLabel; - AppendLIR(cu, &label_list[block_id]); + block_label_list_[block_id].opcode = kPseudoNormalBlockLabel; + AppendLIR(&block_label_list_[block_id]); LIR* head_lir = NULL; // If this is a catch block, export the start address. if (bb->catch_entry) { - head_lir = NewLIR0(cu, kPseudoExportedPC); + head_lir = NewLIR0(kPseudoExportedPC); } // Free temp registers and reset redundant store tracking. - ResetRegPool(cu); - ResetDefTracking(cu); + ResetRegPool(); + ResetDefTracking(); - ClobberAllRegs(cu); + ClobberAllRegs(); if (bb->block_type == kEntryBlock) { - int start_vreg = cu->num_dalvik_registers - cu->num_ins; - cg->GenEntrySequence(cu, &cu->reg_location[start_vreg], - cu->reg_location[cu->method_sreg]); + int start_vreg = cu_->num_dalvik_registers - cu_->num_ins; + GenEntrySequence(&mir_graph_->reg_location_[start_vreg], + mir_graph_->reg_location_[mir_graph_->GetMethodSReg()]); } else if (bb->block_type == kExitBlock) { - cg->GenExitSequence(cu); + GenExitSequence(); } for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { - ResetRegPool(cu); - if (cu->disable_opt & (1 << kTrackLiveTemps)) { - ClobberAllRegs(cu); + ResetRegPool(); + if (cu_->disable_opt & (1 << kTrackLiveTemps)) { + ClobberAllRegs(); } - if (cu->disable_opt & (1 << kSuppressLoads)) { - ResetDefTracking(cu); + if (cu_->disable_opt & (1 << kSuppressLoads)) { + ResetDefTracking(); } // Reset temp tracking sanity check. if (kIsDebugBuild) { - cu->live_sreg = INVALID_SREG; + live_sreg_ = INVALID_SREG; } - cu->current_dalvik_offset = mir->offset; + current_dalvik_offset_ = mir->offset; int opcode = mir->dalvikInsn.opcode; LIR* boundary_lir; // Mark the beginning of a Dalvik instruction for line tracking. - char* inst_str = cu->verbose ? - GetDalvikDisassembly(cu, mir) : NULL; - boundary_lir = MarkBoundary(cu, mir->offset, inst_str); + char* inst_str = cu_->verbose ? + mir_graph_->GetDalvikDisassembly(mir) : NULL; + boundary_lir = MarkBoundary(mir->offset, inst_str); // Remember the first LIR for this block. if (head_lir == NULL) { head_lir = boundary_lir; @@ -777,35 +768,34 @@ static bool MethodBlockCodeGen(CompilationUnit* cu, BasicBlock* bb) } if (opcode >= kMirOpFirst) { - HandleExtendedMethodMIR(cu, bb, mir); + HandleExtendedMethodMIR(bb, mir); continue; } - CompileDalvikInstruction(cu, mir, bb, label_list); + CompileDalvikInstruction(mir, bb, block_label_list_); } if (head_lir) { // Eliminate redundant loads/stores and delay stores into later slots. - ApplyLocalOptimizations(cu, head_lir, cu->last_lir_insn); + ApplyLocalOptimizations(head_lir, last_lir_insn_); // Generate an unconditional branch to the fallthrough block. if (bb->fall_through) { - cg->OpUnconditionalBranch(cu, &label_list[bb->fall_through->id]); + OpUnconditionalBranch(&block_label_list_[bb->fall_through->id]); } } return false; } -void SpecialMIR2LIR(CompilationUnit* cu, SpecialCaseHandler special_case) +void Mir2Lir::SpecialMIR2LIR(SpecialCaseHandler special_case) { - Codegen* cg = cu->cg.get(); // Find the first DalvikByteCode block. - int num_reachable_blocks = cu->mir_graph->GetNumReachableBlocks(); + int num_reachable_blocks = mir_graph_->GetNumReachableBlocks(); BasicBlock*bb = NULL; for (int idx = 0; idx < num_reachable_blocks; idx++) { // TODO: no direct access of growable lists. - int dfs_index = cu->mir_graph->GetDfsOrder()->elem_list[idx]; - bb = cu->mir_graph->GetBasicBlock(dfs_index); + int dfs_index = mir_graph_->GetDfsOrder()->elem_list[idx]; + bb = mir_graph_->GetBasicBlock(dfs_index); if (bb->block_type == kDalvikByteCode) { break; } @@ -820,33 +810,32 @@ void SpecialMIR2LIR(CompilationUnit* cu, SpecialCaseHandler special_case) MIR* mir = bb->first_mir_insn; // Free temp registers and reset redundant store tracking. - ResetRegPool(cu); - ResetDefTracking(cu); - ClobberAllRegs(cu); + ResetRegPool(); + ResetDefTracking(); + ClobberAllRegs(); - cg->GenSpecialCase(cu, bb, mir, special_case); + GenSpecialCase(bb, mir, special_case); } -void MethodMIR2LIR(CompilationUnit* cu) +void Mir2Lir::MethodMIR2LIR() { - Codegen* cg = cu->cg.get(); // Hold the labels of each block. - cu->block_label_list = - static_cast<LIR*>(NewMem(cu, sizeof(LIR) * cu->mir_graph->GetNumBlocks(), true, kAllocLIR)); + block_label_list_ = + static_cast<LIR*>(NewMem(cu_, sizeof(LIR) * mir_graph_->GetNumBlocks(), true, kAllocLIR)); - PreOrderDfsIterator iter(cu->mir_graph.get(), false /* not iterative */); + PreOrderDfsIterator iter(mir_graph_, false /* not iterative */); for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { - MethodBlockCodeGen(cu, bb); + MethodBlockCodeGen(bb); } - cg->HandleSuspendLaunchPads(cu); + HandleSuspendLaunchPads(); - cg->HandleThrowLaunchPads(cu); + HandleThrowLaunchPads(); - cg->HandleIntrinsicLaunchPads(cu); + HandleIntrinsicLaunchPads(); - if (!(cu->disable_opt & (1 << kSafeOptimizations))) { - RemoveRedundantBranches(cu); + if (!(cu_->disable_opt & (1 << kSafeOptimizations))) { + RemoveRedundantBranches(); } } diff --git a/src/compiler/dex/quick/mir_to_lir.h b/src/compiler/dex/quick/mir_to_lir.h index b2767ba622..d2d56f7e88 100644 --- a/src/compiler/dex/quick/mir_to_lir.h +++ b/src/compiler/dex/quick/mir_to_lir.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,738 @@ * limitations under the License. */ -#ifndef ART_SRC_COMPILER_DEX_QUICK_MIRTOLIR_H_ -#define ART_SRC_COMPILER_DEX_QUICK_MIRTOLIR_H_ +#ifndef ART_SRC_COMPILER_DEX_QUICK_CODEGEN_H_ +#define ART_SRC_COMPILER_DEX_QUICK_CODEGEN_H_ + +#include "invoke_type.h" +#include "compiled_method.h" +#include "compiler/dex/compiler_enums.h" +#include "compiler/dex/compiler_ir.h" +#include "compiler/dex/compiler_utility.h" +#include "compiler/dex/backend.h" +#include "safe_map.h" namespace art { -void SpecialMIR2LIR(CompilationUnit* cu, SpecialCaseHandler special_case); -void MethodMIR2LIR(CompilationUnit* cu); +// Set to 1 to measure cost of suspend check. +#define NO_SUSPEND 0 + +#define IS_BINARY_OP (1ULL << kIsBinaryOp) +#define IS_BRANCH (1ULL << kIsBranch) +#define IS_IT (1ULL << kIsIT) +#define IS_LOAD (1ULL << kMemLoad) +#define IS_QUAD_OP (1ULL << kIsQuadOp) +#define IS_QUIN_OP (1ULL << kIsQuinOp) +#define IS_SEXTUPLE_OP (1ULL << kIsSextupleOp) +#define IS_STORE (1ULL << kMemStore) +#define IS_TERTIARY_OP (1ULL << kIsTertiaryOp) +#define IS_UNARY_OP (1ULL << kIsUnaryOp) +#define NEEDS_FIXUP (1ULL << kPCRelFixup) +#define NO_OPERAND (1ULL << kNoOperand) +#define REG_DEF0 (1ULL << kRegDef0) +#define REG_DEF1 (1ULL << kRegDef1) +#define REG_DEFA (1ULL << kRegDefA) +#define REG_DEFD (1ULL << kRegDefD) +#define REG_DEF_FPCS_LIST0 (1ULL << kRegDefFPCSList0) +#define REG_DEF_FPCS_LIST2 (1ULL << kRegDefFPCSList2) +#define REG_DEF_LIST0 (1ULL << kRegDefList0) +#define REG_DEF_LIST1 (1ULL << kRegDefList1) +#define REG_DEF_LR (1ULL << kRegDefLR) +#define REG_DEF_SP (1ULL << kRegDefSP) +#define REG_USE0 (1ULL << kRegUse0) +#define REG_USE1 (1ULL << kRegUse1) +#define REG_USE2 (1ULL << kRegUse2) +#define REG_USE3 (1ULL << kRegUse3) +#define REG_USE4 (1ULL << kRegUse4) +#define REG_USEA (1ULL << kRegUseA) +#define REG_USEC (1ULL << kRegUseC) +#define REG_USED (1ULL << kRegUseD) +#define REG_USE_FPCS_LIST0 (1ULL << kRegUseFPCSList0) +#define REG_USE_FPCS_LIST2 (1ULL << kRegUseFPCSList2) +#define REG_USE_LIST0 (1ULL << kRegUseList0) +#define REG_USE_LIST1 (1ULL << kRegUseList1) +#define REG_USE_LR (1ULL << kRegUseLR) +#define REG_USE_PC (1ULL << kRegUsePC) +#define REG_USE_SP (1ULL << kRegUseSP) +#define SETS_CCODES (1ULL << kSetsCCodes) +#define USES_CCODES (1ULL << kUsesCCodes) + +// Common combo register usage patterns. +#define REG_DEF01 (REG_DEF0 | REG_DEF1) +#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2) +#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01) +#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0) +#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12) +#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1) +#define REG_DEF0_USE2 (REG_DEF0 | REG_USE2) +#define REG_DEFAD_USEAD (REG_DEFAD_USEA | REG_USED) +#define REG_DEFAD_USEA (REG_DEFA_USEA | REG_DEFD) +#define REG_DEFA_USEA (REG_DEFA | REG_USEA) +#define REG_USE012 (REG_USE01 | REG_USE2) +#define REG_USE014 (REG_USE01 | REG_USE4) +#define REG_USE01 (REG_USE0 | REG_USE1) +#define REG_USE02 (REG_USE0 | REG_USE2) +#define REG_USE12 (REG_USE1 | REG_USE2) +#define REG_USE23 (REG_USE2 | REG_USE3) + +struct BasicBlock; +struct CallInfo; +struct CompilationUnit; +struct MIR; +struct RegLocation; +struct RegisterInfo; +class MIRGraph; +class Mir2Lir; + +typedef int (*NextCallInsn)(CompilationUnit*, CallInfo*, int, uint32_t dex_idx, + uint32_t method_idx, uintptr_t direct_code, + uintptr_t direct_method, InvokeType type); + +typedef std::vector<uint8_t> CodeBuffer; + + +struct LIR { + int offset; // Offset of this instruction. + int dalvik_offset; // Offset of Dalvik opcode. + LIR* next; + LIR* prev; + LIR* target; + int opcode; + int operands[5]; // [0..4] = [dest, src1, src2, extra, extra2]. + struct { + bool is_nop:1; // LIR is optimized away. + bool pcRelFixup:1; // May need pc-relative fixup. + unsigned int size:5; // Note: size is in bytes. + unsigned int unused:25; + } flags; + int alias_info; // For Dalvik register & litpool disambiguation. + uint64_t use_mask; // Resource mask for use. + uint64_t def_mask; // Resource mask for def. +}; + +// Target-specific initialization. +Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph); +Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph); +Mir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph); + +// Utility macros to traverse the LIR list. +#define NEXT_LIR(lir) (lir->next) +#define PREV_LIR(lir) (lir->prev) + +// Defines for alias_info (tracks Dalvik register references). +#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff) +#define DECODE_ALIAS_INFO_WIDE_FLAG (0x80000000) +#define DECODE_ALIAS_INFO_WIDE(X) ((X & DECODE_ALIAS_INFO_WIDE_FLAG) ? 1 : 0) +#define ENCODE_ALIAS_INFO(REG, ISWIDE) (REG | (ISWIDE ? DECODE_ALIAS_INFO_WIDE_FLAG : 0)) + +// Common resource macros. +#define ENCODE_CCODE (1ULL << kCCode) +#define ENCODE_FP_STATUS (1ULL << kFPStatus) + +// Abstract memory locations. +#define ENCODE_DALVIK_REG (1ULL << kDalvikReg) +#define ENCODE_LITERAL (1ULL << kLiteral) +#define ENCODE_HEAP_REF (1ULL << kHeapRef) +#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias) + +#define ENCODE_ALL (~0ULL) +#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \ + ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS) +//TODO: replace these macros +#define SLOW_FIELD_PATH (cu_->enable_debug & (1 << kDebugSlowFieldPath)) +#define SLOW_INVOKE_PATH (cu_->enable_debug & (1 << kDebugSlowInvokePath)) +#define SLOW_STRING_PATH (cu_->enable_debug & (1 << kDebugSlowStringPath)) +#define SLOW_TYPE_PATH (cu_->enable_debug & (1 << kDebugSlowTypePath)) +#define EXERCISE_SLOWEST_STRING_PATH (cu_->enable_debug & (1 << kDebugSlowestStringPath)) +#define is_pseudo_opcode(opcode) (static_cast<int>(opcode) < 0) + +class Mir2Lir : public Backend { + + public: + struct SwitchTable { + int offset; + const uint16_t* table; // Original dex table. + int vaddr; // Dalvik offset of switch opcode. + LIR* anchor; // Reference instruction for relative offsets. + LIR** targets; // Array of case targets. + }; + + struct FillArrayData { + int offset; + const uint16_t* table; // Original dex table. + int size; + int vaddr; // Dalvik offset of FILL_ARRAY_DATA opcode. + }; + + /* Static register use counts */ + struct RefCounts { + int count; + int s_reg; + bool double_start; // Starting v_reg for a double + }; + + /* + * Data structure tracking the mapping between a Dalvik register (pair) and a + * native register (pair). The idea is to reuse the previously loaded value + * if possible, otherwise to keep the value in a native register as long as + * possible. + */ + struct RegisterInfo { + int reg; // Reg number + bool in_use; // Has it been allocated? + bool is_temp; // Can allocate as temp? + bool pair; // Part of a register pair? + int partner; // If pair, other reg of pair. + bool live; // Is there an associated SSA name? + bool dirty; // If live, is it dirty? + int s_reg; // Name of live value. + LIR *def_start; // Starting inst in last def sequence. + LIR *def_end; // Ending inst in last def sequence. + }; + + struct RegisterPool { + int num_core_regs; + RegisterInfo *core_regs; + int next_core_reg; + int num_fp_regs; + RegisterInfo *FPRegs; + int next_fp_reg; + }; + + struct PromotionMap { + RegLocationType core_location:3; + uint8_t core_reg; + RegLocationType fp_location:3; + uint8_t FpReg; + bool first_in_pair; + }; + + virtual ~Mir2Lir(){}; + + int32_t s4FromSwitchData(const void* switch_data) { + return *reinterpret_cast<const int32_t*>(switch_data); + } + + RegisterClass oat_reg_class_by_size(OpSize size) { + return (size == kUnsignedHalf || size == kSignedHalf || size == kUnsignedByte || + size == kSignedByte ) ? kCoreReg : kAnyReg; + } + + size_t CodeBufferSizeInBytes() { + return code_buffer_.size() / sizeof(code_buffer_[0]); + } + + // Shared by all targets - implemented in codegen_util.cc + void AppendLIR(LIR* lir); + void InsertLIRBefore(LIR* current_lir, LIR* new_lir); + void InsertLIRAfter(LIR* current_lir, LIR* new_lir); + + int ComputeFrameSize(); + virtual void Materialize(); + virtual CompiledMethod* GetCompiledMethod(); + void MarkSafepointPC(LIR* inst); + bool FastInstance(uint32_t field_idx, int& field_offset, bool& is_volatile, bool is_put); + void SetupResourceMasks(LIR* lir); + void AssembleLIR(); + void SetMemRefType(LIR* lir, bool is_load, int mem_type); + void AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load, bool is64bit); + void SetupRegMask(uint64_t* mask, int reg); + void DumpLIRInsn(LIR* arg, unsigned char* base_addr); + void DumpPromotionMap(); + void CodegenDump(); + LIR* RawLIR(int dalvik_offset, int opcode, int op0 = 0, int op1 = 0, + int op2 = 0, int op3 = 0, int op4 = 0, LIR* target = NULL); + LIR* NewLIR0(int opcode); + LIR* NewLIR1(int opcode, int dest); + LIR* NewLIR2(int opcode, int dest, int src1); + LIR* NewLIR3(int opcode, int dest, int src1, int src2); + LIR* NewLIR4(int opcode, int dest, int src1, int src2, int info); + LIR* NewLIR5(int opcode, int dest, int src1, int src2, int info1, int info2); + LIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta); + LIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi); + LIR* AddWordData(LIR* *constant_list_p, int value); + LIR* AddWideData(LIR* *constant_list_p, int val_lo, int val_hi); + void ProcessSwitchTables(); + void DumpSparseSwitchTable(const uint16_t* table); + void DumpPackedSwitchTable(const uint16_t* table); + LIR* MarkBoundary(int offset, const char* inst_str); + void NopLIR(LIR* lir); + bool EvaluateBranch(Instruction::Code opcode, int src1, int src2); + bool IsInexpensiveConstant(RegLocation rl_src); + ConditionCode FlipComparisonOrder(ConditionCode before); + void DumpMappingTable(const char* table_name, const std::string& descriptor, + const std::string& name, const std::string& signature, + const std::vector<uint32_t>& v); + void InstallLiteralPools(); + void InstallSwitchTables(); + void InstallFillArrayData(); + bool VerifyCatchEntries(); + void CreateMappingTables(); + void CreateNativeGcMap(); + int AssignLiteralOffset(int offset); + int AssignSwitchTablesOffset(int offset); + int AssignFillArrayDataOffset(int offset); + int AssignInsnOffsets(); + void AssignOffsets(); + LIR* InsertCaseLabel(int vaddr, int keyVal); + void MarkPackedCaseLabels(Mir2Lir::SwitchTable *tab_rec); + void MarkSparseCaseLabels(Mir2Lir::SwitchTable *tab_rec); + + // Shared by all targets - implemented in local_optimizations.cc + void ConvertMemOpIntoMove(LIR* orig_lir, int dest, int src); + void ApplyLoadStoreElimination(LIR* head_lir, LIR* tail_lir); + void ApplyLoadHoisting(LIR* head_lir, LIR* tail_lir); + void ApplyLocalOptimizations(LIR* head_lir, LIR* tail_lir); + void RemoveRedundantBranches(); + + // Shared by all targets - implemented in ralloc_util.cc + int GetSRegHi(int lowSreg); + bool oat_live_out(int s_reg); + int oatSSASrc(MIR* mir, int num); + void SimpleRegAlloc(); + void ResetRegPool(); + void CompilerInitPool(RegisterInfo* regs, int* reg_nums, int num); + void DumpRegPool(RegisterInfo* p, int num_regs); + void DumpCoreRegPool(); + void DumpFpRegPool(); + void ClobberBody(RegisterInfo* p); + void Clobber(int reg); + void ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg); + void ClobberSReg(int s_reg); + int SRegToPMap(int s_reg); + void RecordCorePromotion(int reg, int s_reg); + int AllocPreservedCoreReg(int s_reg); + void RecordFpPromotion(int reg, int s_reg); + int AllocPreservedSingle(int s_reg, bool even); + int AllocPreservedDouble(int s_reg); + int AllocPreservedFPReg(int s_reg, bool double_start); + int AllocTempBody(RegisterInfo* p, int num_regs, int* next_temp, + bool required); + int AllocTempDouble(); + int AllocFreeTemp(); + int AllocTemp(); + int AllocTempFloat(); + RegisterInfo* AllocLiveBody(RegisterInfo* p, int num_regs, int s_reg); + RegisterInfo* AllocLive(int s_reg, int reg_class); + void FreeTemp(int reg); + RegisterInfo* IsLive(int reg); + RegisterInfo* IsTemp(int reg); + RegisterInfo* IsPromoted(int reg); + bool IsDirty(int reg); + void LockTemp(int reg); + void ResetDefBody(RegisterInfo* p); + void ResetDef(int reg); + void NullifyRange(LIR *start, LIR *finish, int s_reg1, int s_reg2); + void MarkDef(RegLocation rl, LIR *start, LIR *finish); + void MarkDefWide(RegLocation rl, LIR *start, LIR *finish); + RegLocation WideToNarrow(RegLocation rl); + void ResetDefLoc(RegLocation rl); + void ResetDefLocWide(RegLocation rl); + void ResetDefTracking(); + void ClobberAllRegs(); + void FlushAllRegsBody(RegisterInfo* info, int num_regs); + void FlushAllRegs(); + bool RegClassMatches(int reg_class, int reg); + void MarkLive(int reg, int s_reg); + void MarkTemp(int reg); + void UnmarkTemp(int reg); + void MarkPair(int low_reg, int high_reg); + void MarkClean(RegLocation loc); + void MarkDirty(RegLocation loc); + void MarkInUse(int reg); + void CopyRegInfo(int new_reg, int old_reg); + bool CheckCorePoolSanity(); + RegLocation UpdateLoc(RegLocation loc); + RegLocation UpdateLocWide(RegLocation loc); + RegLocation UpdateRawLoc(RegLocation loc); + RegLocation EvalLocWide(RegLocation loc, int reg_class, bool update); + RegLocation EvalLoc(RegLocation loc, int reg_class, bool update); + void CountRefs(BasicBlock* bb, RefCounts* core_counts, + RefCounts* fp_counts); + void DumpCounts(const RefCounts* arr, int size, const char* msg); + void DoPromotion(); + int VRegOffset(int v_reg); + int SRegOffset(int s_reg); + RegLocation GetReturnWide(bool is_double); + RegLocation GetReturn(bool is_float); + + // Shared by all targets - implemented in gen_common.cc. + bool HandleEasyDivide(Instruction::Code dalvik_opcode, + RegLocation rl_src, RegLocation rl_dest, int lit); + bool HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit); + void HandleSuspendLaunchPads(); + void HandleIntrinsicLaunchPads(); + void HandleThrowLaunchPads(); + void GenBarrier(); + LIR* GenCheck(ConditionCode c_code, ThrowKind kind); + LIR* GenImmedCheck(ConditionCode c_code, int reg, int imm_val, + ThrowKind kind); + LIR* GenNullCheck(int s_reg, int m_reg, int opt_flags); + LIR* GenRegRegCheck(ConditionCode c_code, int reg1, int reg2, + ThrowKind kind); + void GenCompareAndBranch(Instruction::Code opcode, RegLocation rl_src1, + RegLocation rl_src2, LIR* taken, LIR* fall_through); + void GenCompareZeroAndBranch(Instruction::Code opcode, RegLocation rl_src, + LIR* taken, LIR* fall_through); + void GenIntToLong(RegLocation rl_dest, RegLocation rl_src); + void GenIntNarrowing(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src); + void GenNewArray(uint32_t type_idx, RegLocation rl_dest, + RegLocation rl_src); + void GenFilledNewArray(CallInfo* info); + void GenSput(uint32_t field_idx, RegLocation rl_src, + bool is_long_or_double, bool is_object); + void GenSget(uint32_t field_idx, RegLocation rl_dest, + bool is_long_or_double, bool is_object); + void GenShowTarget(); + void GenIGet(uint32_t field_idx, int opt_flags, OpSize size, + RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double, bool is_object); + void GenIPut(uint32_t field_idx, int opt_flags, OpSize size, + RegLocation rl_src, RegLocation rl_obj, bool is_long_or_double, bool is_object); + void GenConstClass(uint32_t type_idx, RegLocation rl_dest); + void GenConstString(uint32_t string_idx, RegLocation rl_dest); + void GenNewInstance(uint32_t type_idx, RegLocation rl_dest); + void GenThrow(RegLocation rl_src); + void GenInstanceof(uint32_t type_idx, RegLocation rl_dest, + RegLocation rl_src); + void GenCheckCast(uint32_t type_idx, RegLocation rl_src); + void GenLong3Addr(OpKind first_op, OpKind second_op, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2); + void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_shift); + void GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2); + void GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src, int lit); + void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2); + void GenConversionCall(int func_offset, RegLocation rl_dest, + RegLocation rl_src); + void GenSuspendTest(int opt_flags); + void GenSuspendTestAndBranch(int opt_flags, LIR* target); + + // Shared by all targets - implemented in gen_invoke.cc. + int CallHelperSetup(int helper_offset); + LIR* CallHelper(int r_tgt, int helper_offset, bool safepoint_pc); + void CallRuntimeHelperImm(int helper_offset, int arg0, bool safepoint_pc); + void CallRuntimeHelperReg(int helper_offset, int arg0, bool safepoint_pc); + void CallRuntimeHelperRegLocation(int helper_offset, RegLocation arg0, + bool safepoint_pc); + void CallRuntimeHelperImmImm(int helper_offset, int arg0, int arg1, + bool safepoint_pc); + void CallRuntimeHelperImmRegLocation(int helper_offset, int arg0, + RegLocation arg1, bool safepoint_pc); + void CallRuntimeHelperRegLocationImm(int helper_offset, RegLocation arg0, + int arg1, bool safepoint_pc); + void CallRuntimeHelperImmReg(int helper_offset, int arg0, int arg1, + bool safepoint_pc); + void CallRuntimeHelperRegImm(int helper_offset, int arg0, int arg1, + bool safepoint_pc); + void CallRuntimeHelperImmMethod(int helper_offset, int arg0, + bool safepoint_pc); + void CallRuntimeHelperRegLocationRegLocation(int helper_offset, + RegLocation arg0, RegLocation arg1, + bool safepoint_pc); + void CallRuntimeHelperRegReg(int helper_offset, int arg0, int arg1, + bool safepoint_pc); + void CallRuntimeHelperRegRegImm(int helper_offset, int arg0, int arg1, + int arg2, bool safepoint_pc); + void CallRuntimeHelperImmMethodRegLocation(int helper_offset, int arg0, + RegLocation arg2, bool safepoint_pc); + void CallRuntimeHelperImmMethodImm(int helper_offset, int arg0, int arg2, + bool safepoint_pc); + void CallRuntimeHelperImmRegLocationRegLocation(int helper_offset, + int arg0, RegLocation arg1, RegLocation arg2, + bool safepoint_pc); + void GenInvoke(CallInfo* info); + void FlushIns(RegLocation* ArgLocs, RegLocation rl_method); + int GenDalvikArgsNoRange(CallInfo* info, int call_state, LIR** pcrLabel, + NextCallInsn next_call_insn, uint32_t dex_idx, uint32_t method_idx, + uintptr_t direct_code, uintptr_t direct_method, InvokeType type, + bool skip_this); + int GenDalvikArgsRange(CallInfo* info, int call_state, LIR** pcrLabel, + NextCallInsn next_call_insn, uint32_t dex_idx, uint32_t method_idx, + uintptr_t direct_code, uintptr_t direct_method, InvokeType type, + bool skip_this); + RegLocation InlineTarget(CallInfo* info); + RegLocation InlineTargetWide(CallInfo* info); + + bool GenInlinedCharAt(CallInfo* info); + bool GenInlinedStringIsEmptyOrLength(CallInfo* info, bool is_empty); + bool GenInlinedAbsInt(CallInfo* info); + bool GenInlinedAbsLong(CallInfo* info); + bool GenInlinedFloatCvt(CallInfo* info); + bool GenInlinedDoubleCvt(CallInfo* info); + bool GenInlinedIndexOf(CallInfo* info, bool zero_based); + bool GenInlinedStringCompareTo(CallInfo* info); + bool GenInlinedCurrentThread(CallInfo* info); + bool GenInlinedUnsafeGet(CallInfo* info, bool is_long, bool is_volatile); + bool GenInlinedUnsafePut(CallInfo* info, bool is_long, bool is_object, + bool is_volatile, bool is_ordered); + bool GenIntrinsic(CallInfo* info); + int LoadArgRegs(CallInfo* info, int call_state, + NextCallInsn next_call_insn, uint32_t dex_idx, uint32_t method_idx, + uintptr_t direct_code, uintptr_t direct_method, InvokeType type, + bool skip_this); + + // Shared by all targets - implemented in gen_loadstore.cc. + RegLocation LoadCurrMethod(); + void LoadCurrMethodDirect(int r_tgt); + LIR* LoadConstant(int r_dest, int value); + LIR* LoadWordDisp(int rBase, int displacement, int r_dest); + RegLocation LoadValue(RegLocation rl_src, RegisterClass op_kind); + RegLocation LoadValueWide(RegLocation rl_src, RegisterClass op_kind); + void LoadValueDirect(RegLocation rl_src, int r_dest); + void LoadValueDirectFixed(RegLocation rl_src, int r_dest); + void LoadValueDirectWide(RegLocation rl_src, int reg_lo, int reg_hi); + void LoadValueDirectWideFixed(RegLocation rl_src, int reg_lo, int reg_hi); + LIR* StoreWordDisp(int rBase, int displacement, int r_src); + void StoreValue(RegLocation rl_dest, RegLocation rl_src); + void StoreValueWide(RegLocation rl_dest, RegLocation rl_src); + + // Shared by all targets - implemented in mir_to_lir.cc. + void CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list); + void HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir); + bool MethodBlockCodeGen(BasicBlock* bb); + void SpecialMIR2LIR(SpecialCaseHandler special_case); + void MethodMIR2LIR(); + + + + // Required for target - codegen helpers. + virtual bool SmallLiteralDivide(Instruction::Code dalvik_opcode, + RegLocation rl_src, RegLocation rl_dest, int lit) = 0; + virtual int LoadHelper(int offset) = 0; + virtual LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg) = 0; + virtual LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi, + int s_reg) = 0; + virtual LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size) = 0; + virtual LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_dest, int r_dest_hi, OpSize size, int s_reg) = 0; + virtual LIR* LoadConstantNoClobber(int r_dest, int value) = 0; + virtual LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) = 0; + virtual LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size) = 0; + virtual LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi) = 0; + virtual LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size) = 0; + virtual LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_src, int r_src_hi, OpSize size, int s_reg) = 0; + virtual void MarkGCCard(int val_reg, int tgt_addr_reg) = 0; + + // Required for target - register utilities. + virtual bool IsFpReg(int reg) = 0; + virtual bool SameRegType(int reg1, int reg2) = 0; + virtual int AllocTypedTemp(bool fp_hint, int reg_class) = 0; + virtual int AllocTypedTempPair(bool fp_hint, int reg_class) = 0; + virtual int S2d(int low_reg, int high_reg) = 0; + virtual int TargetReg(SpecialTargetRegister reg) = 0; + virtual RegisterInfo* GetRegInfo(int reg) = 0; + virtual RegLocation GetReturnAlt() = 0; + virtual RegLocation GetReturnWideAlt() = 0; + virtual RegLocation LocCReturn() = 0; + virtual RegLocation LocCReturnDouble() = 0; + virtual RegLocation LocCReturnFloat() = 0; + virtual RegLocation LocCReturnWide() = 0; + virtual uint32_t FpRegMask() = 0; + virtual uint64_t GetRegMaskCommon(int reg) = 0; + virtual void AdjustSpillMask() = 0; + virtual void ClobberCalleeSave() = 0; + virtual void FlushReg(int reg) = 0; + virtual void FlushRegWide(int reg1, int reg2) = 0; + virtual void FreeCallTemps() = 0; + virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) = 0; + virtual void LockCallTemps() = 0; + virtual void MarkPreservedSingle(int v_reg, int reg) = 0; + virtual void CompilerInitializeRegAlloc() = 0; + + // Required for target - miscellaneous. + virtual AssemblerStatus AssembleInstructions(uintptr_t start_addr) = 0; + virtual void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix) = 0; + virtual void SetupTargetResourceMasks(LIR* lir) = 0; + virtual const char* GetTargetInstFmt(int opcode) = 0; + virtual const char* GetTargetInstName(int opcode) = 0; + virtual std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) = 0; + virtual uint64_t GetPCUseDefEncoding() = 0; + virtual uint64_t GetTargetInstFlags(int opcode) = 0; + virtual int GetInsnSize(LIR* lir) = 0; + virtual bool IsUnconditionalBranch(LIR* lir) = 0; + + // Required for target - Dalvik-level generators. + virtual void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2) = 0; + virtual void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) = 0; + virtual void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) = 0; + virtual void GenAndLong(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) = 0; + virtual void GenArithOpDouble(Instruction::Code opcode, + RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) = 0; + virtual void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2) = 0; + virtual void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2) = 0; + virtual void GenConversion(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src) = 0; + virtual bool GenInlinedCas32(CallInfo* info, bool need_write_barrier) = 0; + virtual bool GenInlinedMinMaxInt(CallInfo* info, bool is_min) = 0; + virtual bool GenInlinedSqrt(CallInfo* info) = 0; + virtual void GenNegLong(RegLocation rl_dest, RegLocation rl_src) = 0; + virtual void GenOrLong(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) = 0; + virtual void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) = 0; + virtual void GenXorLong(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) = 0; + virtual LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, + int offset, ThrowKind kind) = 0; + virtual RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, + bool is_div) = 0; + virtual RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, + bool is_div) = 0; + virtual void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) = 0; + virtual void GenDivZeroCheck(int reg_lo, int reg_hi) = 0; + virtual void GenEntrySequence(RegLocation* ArgLocs, + RegLocation rl_method) = 0; + virtual void GenExitSequence() = 0; + virtual void GenFillArrayData(uint32_t table_offset, + RegLocation rl_src) = 0; + virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, + bool is_double) = 0; + virtual void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) = 0; + virtual void GenSelect(BasicBlock* bb, MIR* mir) = 0; + virtual void GenMemBarrier(MemBarrierKind barrier_kind) = 0; + virtual void GenMonitorEnter(int opt_flags, RegLocation rl_src) = 0; + virtual void GenMonitorExit(int opt_flags, RegLocation rl_src) = 0; + virtual void GenMoveException(RegLocation rl_dest) = 0; + virtual void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, + RegLocation rl_result, int lit, int first_bit, + int second_bit) = 0; + virtual void GenNegDouble(RegLocation rl_dest, RegLocation rl_src) = 0; + virtual void GenNegFloat(RegLocation rl_dest, RegLocation rl_src) = 0; + virtual void GenPackedSwitch(MIR* mir, uint32_t table_offset, + RegLocation rl_src) = 0; + virtual void GenSparseSwitch(MIR* mir, uint32_t table_offset, + RegLocation rl_src) = 0; + virtual void GenSpecialCase(BasicBlock* bb, MIR* mir, + SpecialCaseHandler special_case) = 0; + virtual void GenArrayObjPut(int opt_flags, RegLocation rl_array, + RegLocation rl_index, RegLocation rl_src, int scale) = 0; + virtual void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, + RegLocation rl_index, RegLocation rl_dest, int scale) = 0; + virtual void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, + RegLocation rl_index, RegLocation rl_src, int scale) = 0; + virtual void GenShiftImmOpLong(Instruction::Code opcode, + RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_shift) = 0; + + // Required for target - single operation generators. + virtual LIR* OpUnconditionalBranch(LIR* target) = 0; + virtual LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, + LIR* target) = 0; + virtual LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, + LIR* target) = 0; + virtual LIR* OpCondBranch(ConditionCode cc, LIR* target) = 0; + virtual LIR* OpDecAndBranch(ConditionCode c_code, int reg, + LIR* target) = 0; + virtual LIR* OpFpRegCopy(int r_dest, int r_src) = 0; + virtual LIR* OpIT(ConditionCode cond, const char* guide) = 0; + virtual LIR* OpMem(OpKind op, int rBase, int disp) = 0; + virtual LIR* OpPcRelLoad(int reg, LIR* target) = 0; + virtual LIR* OpReg(OpKind op, int r_dest_src) = 0; + virtual LIR* OpRegCopy(int r_dest, int r_src) = 0; + virtual LIR* OpRegCopyNoInsert(int r_dest, int r_src) = 0; + virtual LIR* OpRegImm(OpKind op, int r_dest_src1, int value) = 0; + virtual LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset) = 0; + virtual LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2) = 0; + virtual LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value) = 0; + virtual LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, + int r_src2) = 0; + virtual LIR* OpTestSuspend(LIR* target) = 0; + virtual LIR* OpThreadMem(OpKind op, int thread_offset) = 0; + virtual LIR* OpVldm(int rBase, int count) = 0; + virtual LIR* OpVstm(int rBase, int count) = 0; + virtual void OpLea(int rBase, int reg1, int reg2, int scale, + int offset) = 0; + virtual void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, + int src_hi) = 0; + virtual void OpTlsCmp(int offset, int val) = 0; + virtual bool InexpensiveConstantInt(int32_t value) = 0; + virtual bool InexpensiveConstantFloat(int32_t value) = 0; + virtual bool InexpensiveConstantLong(int64_t value) = 0; + virtual bool InexpensiveConstantDouble(int64_t value) = 0; + + // Temp workaround + void Workaround7250540(RegLocation rl_dest, int value); + + // TODO: add accessors for these. + LIR* literal_list_; // Constants. + LIR* method_literal_list_; // Method literals requiring patching. + LIR* code_literal_list_; // Code literals requiring patching. + + protected: + Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph); + + CompilationUnit* GetCompilationUnit() { + return cu_; + } + + CompilationUnit* const cu_; + MIRGraph* const mir_graph_; + GrowableList switch_tables_; + GrowableList fill_array_data_; + GrowableList throw_launchpads_; + GrowableList suspend_launchpads_; + GrowableList intrinsic_launchpads_; + SafeMap<unsigned int, LIR*> boundary_map_; // boundary lookup cache. + /* + * Holds mapping from native PC to dex PC for safepoints where we may deoptimize. + * Native PC is on the return address of the safepointed operation. Dex PC is for + * the instruction being executed at the safepoint. + */ + std::vector<uint32_t> pc2dex_mapping_table_; + /* + * Holds mapping from Dex PC to native PC for catch entry points. Native PC and Dex PC + * immediately preceed the instruction. + */ + std::vector<uint32_t> dex2pc_mapping_table_; + int data_offset_; // starting offset of literal pool. + int total_size_; // header + code size. + LIR* block_label_list_; + PromotionMap* promotion_map_; + /* + * TODO: The code generation utilities don't have a built-in + * mechanism to propagate the original Dalvik opcode address to the + * associated generated instructions. For the trace compiler, this wasn't + * necessary because the interpreter handled all throws and debugging + * requests. For now we'll handle this by placing the Dalvik offset + * in the CompilationUnit struct before codegen for each instruction. + * The low-level LIR creation utilites will pull it from here. Rework this. + */ + int current_dalvik_offset_; + RegisterPool* reg_pool_; + /* + * Sanity checking for the register temp tracking. The same ssa + * name should never be associated with one temp register per + * instruction compilation. + */ + int live_sreg_; + CodeBuffer code_buffer_; + std::vector<uint32_t> combined_mapping_table_; + std::vector<uint32_t> core_vmap_table_; + std::vector<uint32_t> fp_vmap_table_; + std::vector<uint8_t> native_gc_map_; + int num_core_spills_; + int num_fp_spills_; + int frame_size_; + unsigned int core_spill_mask_; + unsigned int fp_spill_mask_; + LIR* first_lir_insn_; + LIR* last_lir_insn_; + +}; // Class Mir2Lir } // namespace art -#endif // ART_SRC_COMPILER_DEX_QUICK_MIRTOLIR_H_ +#endif // ART_SRC_COMPILER_DEX_QUICK_CODEGEN_H_ diff --git a/src/compiler/dex/quick/ralloc_util.cc b/src/compiler/dex/quick/ralloc_util.cc index 18c77141e1..a89cfa837b 100644 --- a/src/compiler/dex/quick/ralloc_util.cc +++ b/src/compiler/dex/quick/ralloc_util.cc @@ -19,31 +19,24 @@ #include "compiler/dex/compiler_ir.h" #include "compiler/dex/compiler_internals.h" #include "compiler/dex/compiler_utility.h" -//#include "compiler/dex/dataflow.h" -#include "compiler/dex/quick/codegen_util.h" -#include "ralloc_util.h" namespace art { -static const RegLocation bad_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0, - INVALID_REG, INVALID_REG, INVALID_SREG, - INVALID_SREG}; - /* * Free all allocated temps in the temp pools. Note that this does * not affect the "liveness" of a temp register, which will stay * live until it is either explicitly killed or reallocated. */ -void ResetRegPool(CompilationUnit* cu) +void Mir2Lir::ResetRegPool() { int i; - for (i=0; i < cu->reg_pool->num_core_regs; i++) { - if (cu->reg_pool->core_regs[i].is_temp) - cu->reg_pool->core_regs[i].in_use = false; + for (i=0; i < reg_pool_->num_core_regs; i++) { + if (reg_pool_->core_regs[i].is_temp) + reg_pool_->core_regs[i].in_use = false; } - for (i=0; i < cu->reg_pool->num_fp_regs; i++) { - if (cu->reg_pool->FPRegs[i].is_temp) - cu->reg_pool->FPRegs[i].in_use = false; + for (i=0; i < reg_pool_->num_fp_regs; i++) { + if (reg_pool_->FPRegs[i].is_temp) + reg_pool_->FPRegs[i].in_use = false; } } @@ -51,7 +44,7 @@ void ResetRegPool(CompilationUnit* cu) * Set up temp & preserved register pools specialized by target. * Note: num_regs may be zero. */ -void CompilerInitPool(RegisterInfo* regs, int* reg_nums, int num) +void Mir2Lir::CompilerInitPool(RegisterInfo* regs, int* reg_nums, int num) { int i; for (i=0; i < num; i++) { @@ -65,7 +58,7 @@ void CompilerInitPool(RegisterInfo* regs, int* reg_nums, int num) } } -void DumpRegPool(RegisterInfo* p, int num_regs) +void Mir2Lir::DumpRegPool(RegisterInfo* p, int num_regs) { LOG(INFO) << "================================================"; for (int i = 0; i < num_regs; i++) { @@ -78,18 +71,18 @@ void DumpRegPool(RegisterInfo* p, int num_regs) LOG(INFO) << "================================================"; } -void DumpCoreRegPool(CompilationUnit* cu) +void Mir2Lir::DumpCoreRegPool() { - DumpRegPool(cu->reg_pool->core_regs, cu->reg_pool->num_core_regs); + DumpRegPool(reg_pool_->core_regs, reg_pool_->num_core_regs); } -void DumpFpRegPool(CompilationUnit* cu) +void Mir2Lir::DumpFpRegPool() { - DumpRegPool(cu->reg_pool->FPRegs, cu->reg_pool->num_fp_regs); + DumpRegPool(reg_pool_->FPRegs, reg_pool_->num_fp_regs); } /* Mark a temp register as dead. Does not affect allocation state. */ -static void ClobberBody(CompilationUnit *cu, RegisterInfo* p) +void Mir2Lir::ClobberBody(RegisterInfo* p) { if (p->is_temp) { DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber"; @@ -99,19 +92,18 @@ static void ClobberBody(CompilationUnit *cu, RegisterInfo* p) p->def_end = NULL; if (p->pair) { p->pair = false; - Clobber(cu, p->partner); + Clobber(p->partner); } } } /* Mark a temp register as dead. Does not affect allocation state. */ -void Clobber(CompilationUnit* cu, int reg) +void Mir2Lir::Clobber(int reg) { - Codegen* cg = cu->cg.get(); - ClobberBody(cu, cg->GetRegInfo(cu, reg)); + ClobberBody(GetRegInfo(reg)); } -static void ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg) +void Mir2Lir::ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg) { int i; for (i=0; i< num_regs; i++) { @@ -136,16 +128,16 @@ static void ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg) * changes (for example: INT_TO_FLOAT v1, v1). Revisit when improved register allocation is * addressed. */ -void ClobberSReg(CompilationUnit* cu, int s_reg) +void Mir2Lir::ClobberSReg(int s_reg) { /* Reset live temp tracking sanity checker */ if (kIsDebugBuild) { - if (s_reg == cu->live_sreg) { - cu->live_sreg = INVALID_SREG; + if (s_reg == live_sreg_) { + live_sreg_ = INVALID_SREG; } } - ClobberSRegBody(cu->reg_pool->core_regs, cu->reg_pool->num_core_regs, s_reg); - ClobberSRegBody(cu->reg_pool->FPRegs, cu->reg_pool->num_fp_regs, s_reg); + ClobberSRegBody(reg_pool_->core_regs, reg_pool_->num_core_regs, s_reg); + ClobberSRegBody(reg_pool_->FPRegs, reg_pool_->num_fp_regs, s_reg); } /* @@ -157,60 +149,57 @@ void ClobberSReg(CompilationUnit* cu, int s_reg) * ssa name (above the last original Dalvik register). This function * maps SSA names to positions in the promotion_map array. */ -int SRegToPMap(CompilationUnit* cu, int s_reg) +int Mir2Lir::SRegToPMap(int s_reg) { - DCHECK_LT(s_reg, cu->mir_graph->GetNumSSARegs()); + DCHECK_LT(s_reg, mir_graph_->GetNumSSARegs()); DCHECK_GE(s_reg, 0); - int v_reg = cu->mir_graph->SRegToVReg(s_reg); + int v_reg = mir_graph_->SRegToVReg(s_reg); if (v_reg >= 0) { - DCHECK_LT(v_reg, cu->num_dalvik_registers); + DCHECK_LT(v_reg, cu_->num_dalvik_registers); return v_reg; } else { int pos = std::abs(v_reg) - std::abs(SSA_METHOD_BASEREG); - DCHECK_LE(pos, cu->num_compiler_temps); - return cu->num_dalvik_registers + pos; + DCHECK_LE(pos, cu_->num_compiler_temps); + return cu_->num_dalvik_registers + pos; } } -void RecordCorePromotion(CompilationUnit* cu, int reg, int s_reg) +void Mir2Lir::RecordCorePromotion(int reg, int s_reg) { - Codegen* cg = cu->cg.get(); - int p_map_idx = SRegToPMap(cu, s_reg); - int v_reg = cu->mir_graph->SRegToVReg(s_reg); - cg->GetRegInfo(cu, reg)->in_use = true; - cu->core_spill_mask |= (1 << reg); + int p_map_idx = SRegToPMap(s_reg); + int v_reg = mir_graph_->SRegToVReg(s_reg); + GetRegInfo(reg)->in_use = true; + core_spill_mask_ |= (1 << reg); // Include reg for later sort - cu->core_vmap_table.push_back(reg << VREG_NUM_WIDTH | - (v_reg & ((1 << VREG_NUM_WIDTH) - 1))); - cu->num_core_spills++; - cu->promotion_map[p_map_idx].core_location = kLocPhysReg; - cu->promotion_map[p_map_idx].core_reg = reg; + core_vmap_table_.push_back(reg << VREG_NUM_WIDTH | (v_reg & ((1 << VREG_NUM_WIDTH) - 1))); + num_core_spills_++; + promotion_map_[p_map_idx].core_location = kLocPhysReg; + promotion_map_[p_map_idx].core_reg = reg; } /* Reserve a callee-save register. Return -1 if none available */ -static int AllocPreservedCoreReg(CompilationUnit* cu, int s_reg) +int Mir2Lir::AllocPreservedCoreReg(int s_reg) { int res = -1; - RegisterInfo* core_regs = cu->reg_pool->core_regs; - for (int i = 0; i < cu->reg_pool->num_core_regs; i++) { + RegisterInfo* core_regs = reg_pool_->core_regs; + for (int i = 0; i < reg_pool_->num_core_regs; i++) { if (!core_regs[i].is_temp && !core_regs[i].in_use) { res = core_regs[i].reg; - RecordCorePromotion(cu, res, s_reg); + RecordCorePromotion(res, s_reg); break; } } return res; } -void RecordFpPromotion(CompilationUnit* cu, int reg, int s_reg) +void Mir2Lir::RecordFpPromotion(int reg, int s_reg) { - Codegen* cg = cu->cg.get(); - int p_map_idx = SRegToPMap(cu, s_reg); - int v_reg = cu->mir_graph->SRegToVReg(s_reg); - cg->GetRegInfo(cu, reg)->in_use = true; - cg->MarkPreservedSingle(cu, v_reg, reg); - cu->promotion_map[p_map_idx].fp_location = kLocPhysReg; - cu->promotion_map[p_map_idx].FpReg = reg; + int p_map_idx = SRegToPMap(s_reg); + int v_reg = mir_graph_->SRegToVReg(s_reg); + GetRegInfo(reg)->in_use = true; + MarkPreservedSingle(v_reg, reg); + promotion_map_[p_map_idx].fp_location = kLocPhysReg; + promotion_map_[p_map_idx].FpReg = reg; } /* @@ -218,15 +207,15 @@ void RecordFpPromotion(CompilationUnit* cu, int reg, int s_reg) * even/odd allocation, but go ahead and allocate anything if not * available. If nothing's available, return -1. */ -static int AllocPreservedSingle(CompilationUnit* cu, int s_reg, bool even) +int Mir2Lir::AllocPreservedSingle(int s_reg, bool even) { int res = -1; - RegisterInfo* FPRegs = cu->reg_pool->FPRegs; - for (int i = 0; i < cu->reg_pool->num_fp_regs; i++) { + RegisterInfo* FPRegs = reg_pool_->FPRegs; + for (int i = 0; i < reg_pool_->num_fp_regs; i++) { if (!FPRegs[i].is_temp && !FPRegs[i].in_use && ((FPRegs[i].reg & 0x1) == 0) == even) { res = FPRegs[i].reg; - RecordFpPromotion(cu, res, s_reg); + RecordFpPromotion(res, s_reg); break; } } @@ -241,21 +230,20 @@ static int AllocPreservedSingle(CompilationUnit* cu, int s_reg, bool even) * allocate if we can't meet the requirements for the pair of * s_reg<=sX[even] & (s_reg+1)<= sX+1. */ -static int AllocPreservedDouble(CompilationUnit* cu, int s_reg) +int Mir2Lir::AllocPreservedDouble(int s_reg) { - Codegen* cg = cu->cg.get(); int res = -1; // Assume failure - int v_reg = cu->mir_graph->SRegToVReg(s_reg); - int p_map_idx = SRegToPMap(cu, s_reg); - if (cu->promotion_map[p_map_idx+1].fp_location == kLocPhysReg) { + int v_reg = mir_graph_->SRegToVReg(s_reg); + int p_map_idx = SRegToPMap(s_reg); + if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) { // Upper reg is already allocated. Can we fit? - int high_reg = cu->promotion_map[p_map_idx+1].FpReg; + int high_reg = promotion_map_[p_map_idx+1].FpReg; if ((high_reg & 1) == 0) { // High reg is even - fail. return res; } // Is the low reg of the pair free? - RegisterInfo* p = cg->GetRegInfo(cu, high_reg-1); + RegisterInfo* p = GetRegInfo(high_reg-1); if (p->in_use || p->is_temp) { // Already allocated or not preserved - fail. return res; @@ -264,10 +252,10 @@ static int AllocPreservedDouble(CompilationUnit* cu, int s_reg) res = p->reg; p->in_use = true; DCHECK_EQ((res & 1), 0); - cg->MarkPreservedSingle(cu, v_reg, res); + MarkPreservedSingle(v_reg, res); } else { - RegisterInfo* FPRegs = cu->reg_pool->FPRegs; - for (int i = 0; i < cu->reg_pool->num_fp_regs; i++) { + RegisterInfo* FPRegs = reg_pool_->FPRegs; + for (int i = 0; i < reg_pool_->num_fp_regs; i++) { if (!FPRegs[i].is_temp && !FPRegs[i].in_use && ((FPRegs[i].reg & 0x1) == 0x0) && !FPRegs[i+1].is_temp && !FPRegs[i+1].in_use && @@ -275,19 +263,19 @@ static int AllocPreservedDouble(CompilationUnit* cu, int s_reg) (FPRegs[i].reg + 1) == FPRegs[i+1].reg) { res = FPRegs[i].reg; FPRegs[i].in_use = true; - cg->MarkPreservedSingle(cu, v_reg, res); + MarkPreservedSingle(v_reg, res); FPRegs[i+1].in_use = true; DCHECK_EQ(res + 1, FPRegs[i+1].reg); - cg->MarkPreservedSingle(cu, v_reg+1, res+1); + MarkPreservedSingle(v_reg+1, res+1); break; } } } if (res != -1) { - cu->promotion_map[p_map_idx].fp_location = kLocPhysReg; - cu->promotion_map[p_map_idx].FpReg = res; - cu->promotion_map[p_map_idx+1].fp_location = kLocPhysReg; - cu->promotion_map[p_map_idx+1].FpReg = res + 1; + promotion_map_[p_map_idx].fp_location = kLocPhysReg; + promotion_map_[p_map_idx].FpReg = res; + promotion_map_[p_map_idx+1].fp_location = kLocPhysReg; + promotion_map_[p_map_idx+1].FpReg = res + 1; } return res; } @@ -299,22 +287,22 @@ static int AllocPreservedDouble(CompilationUnit* cu, int s_reg) * single regs (but if can't still attempt to allocate a single, preferring * first to allocate an odd register. */ -static int AllocPreservedFPReg(CompilationUnit* cu, int s_reg, bool double_start) +int Mir2Lir::AllocPreservedFPReg(int s_reg, bool double_start) { int res = -1; if (double_start) { - res = AllocPreservedDouble(cu, s_reg); + res = AllocPreservedDouble(s_reg); } if (res == -1) { - res = AllocPreservedSingle(cu, s_reg, false /* try odd # */); + res = AllocPreservedSingle(s_reg, false /* try odd # */); } if (res == -1) - res = AllocPreservedSingle(cu, s_reg, true /* try even # */); + res = AllocPreservedSingle(s_reg, true /* try even # */); return res; } -static int AllocTempBody(CompilationUnit* cu, RegisterInfo* p, int num_regs, int* next_temp, - bool required) +int Mir2Lir::AllocTempBody(RegisterInfo* p, int num_regs, int* next_temp, + bool required) { int i; int next = *next_temp; @@ -322,7 +310,7 @@ static int AllocTempBody(CompilationUnit* cu, RegisterInfo* p, int num_regs, int if (next >= num_regs) next = 0; if (p[next].is_temp && !p[next].in_use && !p[next].live) { - Clobber(cu, p[next].reg); + Clobber(p[next].reg); p[next].in_use = true; p[next].pair = false; *next_temp = next + 1; @@ -335,7 +323,7 @@ static int AllocTempBody(CompilationUnit* cu, RegisterInfo* p, int num_regs, int if (next >= num_regs) next = 0; if (p[next].is_temp && !p[next].in_use) { - Clobber(cu, p[next].reg); + Clobber(p[next].reg); p[next].in_use = true; p[next].pair = false; *next_temp = next + 1; @@ -344,21 +332,21 @@ static int AllocTempBody(CompilationUnit* cu, RegisterInfo* p, int num_regs, int next++; } if (required) { - CodegenDump(cu); - DumpRegPool(cu->reg_pool->core_regs, - cu->reg_pool->num_core_regs); + CodegenDump(); + DumpRegPool(reg_pool_->core_regs, + reg_pool_->num_core_regs); LOG(FATAL) << "No free temp registers"; } return -1; // No register available } //REDO: too many assumptions. -int AllocTempDouble(CompilationUnit* cu) +int Mir2Lir::AllocTempDouble() { - RegisterInfo* p = cu->reg_pool->FPRegs; - int num_regs = cu->reg_pool->num_fp_regs; + RegisterInfo* p = reg_pool_->FPRegs; + int num_regs = reg_pool_->num_fp_regs; /* Start looking at an even reg */ - int next = cu->reg_pool->next_fp_reg & ~0x1; + int next = reg_pool_->next_fp_reg & ~0x1; // First try to avoid allocating live registers for (int i=0; i < num_regs; i+=2) { @@ -366,21 +354,21 @@ int AllocTempDouble(CompilationUnit* cu) next = 0; if ((p[next].is_temp && !p[next].in_use && !p[next].live) && (p[next+1].is_temp && !p[next+1].in_use && !p[next+1].live)) { - Clobber(cu, p[next].reg); - Clobber(cu, p[next+1].reg); + Clobber(p[next].reg); + Clobber(p[next+1].reg); p[next].in_use = true; p[next+1].in_use = true; DCHECK_EQ((p[next].reg+1), p[next+1].reg); DCHECK_EQ((p[next].reg & 0x1), 0); - cu->reg_pool->next_fp_reg = next + 2; - if (cu->reg_pool->next_fp_reg >= num_regs) { - cu->reg_pool->next_fp_reg = 0; + reg_pool_->next_fp_reg = next + 2; + if (reg_pool_->next_fp_reg >= num_regs) { + reg_pool_->next_fp_reg = 0; } return p[next].reg; } next += 2; } - next = cu->reg_pool->next_fp_reg & ~0x1; + next = reg_pool_->next_fp_reg & ~0x1; // No choice - find a pair and kill it. for (int i=0; i < num_regs; i+=2) { @@ -388,15 +376,15 @@ int AllocTempDouble(CompilationUnit* cu) next = 0; if (p[next].is_temp && !p[next].in_use && p[next+1].is_temp && !p[next+1].in_use) { - Clobber(cu, p[next].reg); - Clobber(cu, p[next+1].reg); + Clobber(p[next].reg); + Clobber(p[next+1].reg); p[next].in_use = true; p[next+1].in_use = true; DCHECK_EQ((p[next].reg+1), p[next+1].reg); DCHECK_EQ((p[next].reg & 0x1), 0); - cu->reg_pool->next_fp_reg = next + 2; - if (cu->reg_pool->next_fp_reg >= num_regs) { - cu->reg_pool->next_fp_reg = 0; + reg_pool_->next_fp_reg = next + 2; + if (reg_pool_->next_fp_reg >= num_regs) { + reg_pool_->next_fp_reg = 0; } return p[next].reg; } @@ -407,28 +395,28 @@ int AllocTempDouble(CompilationUnit* cu) } /* Return a temp if one is available, -1 otherwise */ -int AllocFreeTemp(CompilationUnit* cu) +int Mir2Lir::AllocFreeTemp() { - return AllocTempBody(cu, cu->reg_pool->core_regs, - cu->reg_pool->num_core_regs, - &cu->reg_pool->next_core_reg, true); + return AllocTempBody(reg_pool_->core_regs, + reg_pool_->num_core_regs, + ®_pool_->next_core_reg, true); } -int AllocTemp(CompilationUnit* cu) +int Mir2Lir::AllocTemp() { - return AllocTempBody(cu, cu->reg_pool->core_regs, - cu->reg_pool->num_core_regs, - &cu->reg_pool->next_core_reg, true); + return AllocTempBody(reg_pool_->core_regs, + reg_pool_->num_core_regs, + ®_pool_->next_core_reg, true); } -int AllocTempFloat(CompilationUnit* cu) +int Mir2Lir::AllocTempFloat() { - return AllocTempBody(cu, cu->reg_pool->FPRegs, - cu->reg_pool->num_fp_regs, - &cu->reg_pool->next_fp_reg, true); + return AllocTempBody(reg_pool_->FPRegs, + reg_pool_->num_fp_regs, + ®_pool_->next_fp_reg, true); } -static RegisterInfo* AllocLiveBody(RegisterInfo* p, int num_regs, int s_reg) +Mir2Lir::RegisterInfo* Mir2Lir::AllocLiveBody(RegisterInfo* p, int num_regs, int s_reg) { int i; if (s_reg == -1) @@ -443,23 +431,23 @@ static RegisterInfo* AllocLiveBody(RegisterInfo* p, int num_regs, int s_reg) return NULL; } -RegisterInfo* AllocLive(CompilationUnit* cu, int s_reg, int reg_class) +Mir2Lir::RegisterInfo* Mir2Lir::AllocLive(int s_reg, int reg_class) { RegisterInfo* res = NULL; switch (reg_class) { case kAnyReg: - res = AllocLiveBody(cu->reg_pool->FPRegs, - cu->reg_pool->num_fp_regs, s_reg); + res = AllocLiveBody(reg_pool_->FPRegs, + reg_pool_->num_fp_regs, s_reg); if (res) break; /* Intentional fallthrough */ case kCoreReg: - res = AllocLiveBody(cu->reg_pool->core_regs, - cu->reg_pool->num_core_regs, s_reg); + res = AllocLiveBody(reg_pool_->core_regs, + reg_pool_->num_core_regs, s_reg); break; case kFPReg: - res = AllocLiveBody(cu->reg_pool->FPRegs, - cu->reg_pool->num_fp_regs, s_reg); + res = AllocLiveBody(reg_pool_->FPRegs, + reg_pool_->num_fp_regs, s_reg); break; default: LOG(FATAL) << "Invalid register type"; @@ -467,10 +455,10 @@ RegisterInfo* AllocLive(CompilationUnit* cu, int s_reg, int reg_class) return res; } -void FreeTemp(CompilationUnit* cu, int reg) +void Mir2Lir::FreeTemp(int reg) { - RegisterInfo* p = cu->reg_pool->core_regs; - int num_regs = cu->reg_pool->num_core_regs; + RegisterInfo* p = reg_pool_->core_regs; + int num_regs = reg_pool_->num_core_regs; int i; for (i=0; i< num_regs; i++) { if (p[i].reg == reg) { @@ -481,8 +469,8 @@ void FreeTemp(CompilationUnit* cu, int reg) return; } } - p = cu->reg_pool->FPRegs; - num_regs = cu->reg_pool->num_fp_regs; + p = reg_pool_->FPRegs; + num_regs = reg_pool_->num_fp_regs; for (i=0; i< num_regs; i++) { if (p[i].reg == reg) { if (p[i].is_temp) { @@ -495,18 +483,18 @@ void FreeTemp(CompilationUnit* cu, int reg) LOG(FATAL) << "Tried to free a non-existant temp: r" << reg; } -RegisterInfo* IsLive(CompilationUnit* cu, int reg) +Mir2Lir::RegisterInfo* Mir2Lir::IsLive(int reg) { - RegisterInfo* p = cu->reg_pool->core_regs; - int num_regs = cu->reg_pool->num_core_regs; + RegisterInfo* p = reg_pool_->core_regs; + int num_regs = reg_pool_->num_core_regs; int i; for (i=0; i< num_regs; i++) { if (p[i].reg == reg) { return p[i].live ? &p[i] : NULL; } } - p = cu->reg_pool->FPRegs; - num_regs = cu->reg_pool->num_fp_regs; + p = reg_pool_->FPRegs; + num_regs = reg_pool_->num_fp_regs; for (i=0; i< num_regs; i++) { if (p[i].reg == reg) { return p[i].live ? &p[i] : NULL; @@ -515,24 +503,21 @@ RegisterInfo* IsLive(CompilationUnit* cu, int reg) return NULL; } -RegisterInfo* IsTemp(CompilationUnit* cu, int reg) +Mir2Lir::RegisterInfo* Mir2Lir::IsTemp(int reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* p = cg->GetRegInfo(cu, reg); + RegisterInfo* p = GetRegInfo(reg); return (p->is_temp) ? p : NULL; } -RegisterInfo* IsPromoted(CompilationUnit* cu, int reg) +Mir2Lir::RegisterInfo* Mir2Lir::IsPromoted(int reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* p = cg->GetRegInfo(cu, reg); + RegisterInfo* p = GetRegInfo(reg); return (p->is_temp) ? NULL : p; } -bool IsDirty(CompilationUnit* cu, int reg) +bool Mir2Lir::IsDirty(int reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* p = cg->GetRegInfo(cu, reg); + RegisterInfo* p = GetRegInfo(reg); return p->dirty; } @@ -541,10 +526,10 @@ bool IsDirty(CompilationUnit* cu, int reg) * register. No check is made to see if the register was previously * allocated. Use with caution. */ -void LockTemp(CompilationUnit* cu, int reg) +void Mir2Lir::LockTemp(int reg) { - RegisterInfo* p = cu->reg_pool->core_regs; - int num_regs = cu->reg_pool->num_core_regs; + RegisterInfo* p = reg_pool_->core_regs; + int num_regs = reg_pool_->num_core_regs; int i; for (i=0; i< num_regs; i++) { if (p[i].reg == reg) { @@ -554,8 +539,8 @@ void LockTemp(CompilationUnit* cu, int reg) return; } } - p = cu->reg_pool->FPRegs; - num_regs = cu->reg_pool->num_fp_regs; + p = reg_pool_->FPRegs; + num_regs = reg_pool_->num_fp_regs; for (i=0; i< num_regs; i++) { if (p[i].reg == reg) { DCHECK(p[i].is_temp); @@ -567,19 +552,18 @@ void LockTemp(CompilationUnit* cu, int reg) LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg; } -static void ResetDefBody(RegisterInfo* p) +void Mir2Lir::ResetDefBody(RegisterInfo* p) { p->def_start = NULL; p->def_end = NULL; } -void ResetDef(CompilationUnit* cu, int reg) +void Mir2Lir::ResetDef(int reg) { - Codegen* cg = cu->cg.get(); - ResetDefBody(cg->GetRegInfo(cu, reg)); + ResetDefBody(GetRegInfo(reg)); } -static void NullifyRange(CompilationUnit* cu, LIR *start, LIR *finish, int s_reg1, int s_reg2) +void Mir2Lir::NullifyRange(LIR *start, LIR *finish, int s_reg1, int s_reg2) { if (start && finish) { LIR *p; @@ -597,14 +581,12 @@ static void NullifyRange(CompilationUnit* cu, LIR *start, LIR *finish, int s_reg * on entry start points to the LIR prior to the beginning of the * sequence. */ -void MarkDef(CompilationUnit* cu, RegLocation rl, - LIR *start, LIR *finish) +void Mir2Lir::MarkDef(RegLocation rl, LIR *start, LIR *finish) { DCHECK(!rl.wide); DCHECK(start && start->next); DCHECK(finish); - Codegen* cg = cu->cg.get(); - RegisterInfo* p = cg->GetRegInfo(cu, rl.low_reg); + RegisterInfo* p = GetRegInfo(rl.low_reg); p->def_start = start->next; p->def_end = finish; } @@ -614,26 +596,23 @@ void MarkDef(CompilationUnit* cu, RegLocation rl, * on entry start points to the LIR prior to the beginning of the * sequence. */ -void MarkDefWide(CompilationUnit* cu, RegLocation rl, - LIR *start, LIR *finish) +void Mir2Lir::MarkDefWide(RegLocation rl, LIR *start, LIR *finish) { DCHECK(rl.wide); DCHECK(start && start->next); DCHECK(finish); - Codegen* cg = cu->cg.get(); - RegisterInfo* p = cg->GetRegInfo(cu, rl.low_reg); - ResetDef(cu, rl.high_reg); // Only track low of pair + RegisterInfo* p = GetRegInfo(rl.low_reg); + ResetDef(rl.high_reg); // Only track low of pair p->def_start = start->next; p->def_end = finish; } -RegLocation WideToNarrow(CompilationUnit* cu, RegLocation rl) +RegLocation Mir2Lir::WideToNarrow(RegLocation rl) { DCHECK(rl.wide); - Codegen* cg = cu->cg.get(); if (rl.location == kLocPhysReg) { - RegisterInfo* info_lo = cg->GetRegInfo(cu, rl.low_reg); - RegisterInfo* info_hi = cg->GetRegInfo(cu, rl.high_reg); + RegisterInfo* info_lo = GetRegInfo(rl.low_reg); + RegisterInfo* info_hi = GetRegInfo(rl.high_reg); if (info_lo->is_temp) { info_lo->pair = false; info_lo->def_start = NULL; @@ -649,102 +628,99 @@ RegLocation WideToNarrow(CompilationUnit* cu, RegLocation rl) return rl; } -void ResetDefLoc(CompilationUnit* cu, RegLocation rl) +void Mir2Lir::ResetDefLoc(RegLocation rl) { DCHECK(!rl.wide); - RegisterInfo* p = IsTemp(cu, rl.low_reg); - if (p && !(cu->disable_opt & (1 << kSuppressLoads))) { + RegisterInfo* p = IsTemp(rl.low_reg); + if (p && !(cu_->disable_opt & (1 << kSuppressLoads))) { DCHECK(!p->pair); - NullifyRange(cu, p->def_start, p->def_end, p->s_reg, rl.s_reg_low); + NullifyRange(p->def_start, p->def_end, p->s_reg, rl.s_reg_low); } - ResetDef(cu, rl.low_reg); + ResetDef(rl.low_reg); } -void ResetDefLocWide(CompilationUnit* cu, RegLocation rl) +void Mir2Lir::ResetDefLocWide(RegLocation rl) { DCHECK(rl.wide); - RegisterInfo* p_low = IsTemp(cu, rl.low_reg); - RegisterInfo* p_high = IsTemp(cu, rl.high_reg); - if (p_low && !(cu->disable_opt & (1 << kSuppressLoads))) { + RegisterInfo* p_low = IsTemp(rl.low_reg); + RegisterInfo* p_high = IsTemp(rl.high_reg); + if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) { DCHECK(p_low->pair); - NullifyRange(cu, p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low); + NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low); } - if (p_high && !(cu->disable_opt & (1 << kSuppressLoads))) { + if (p_high && !(cu_->disable_opt & (1 << kSuppressLoads))) { DCHECK(p_high->pair); } - ResetDef(cu, rl.low_reg); - ResetDef(cu, rl.high_reg); + ResetDef(rl.low_reg); + ResetDef(rl.high_reg); } -void ResetDefTracking(CompilationUnit* cu) +void Mir2Lir::ResetDefTracking() { int i; - for (i=0; i< cu->reg_pool->num_core_regs; i++) { - ResetDefBody(&cu->reg_pool->core_regs[i]); + for (i=0; i< reg_pool_->num_core_regs; i++) { + ResetDefBody(®_pool_->core_regs[i]); } - for (i=0; i< cu->reg_pool->num_fp_regs; i++) { - ResetDefBody(&cu->reg_pool->FPRegs[i]); + for (i=0; i< reg_pool_->num_fp_regs; i++) { + ResetDefBody(®_pool_->FPRegs[i]); } } -void ClobberAllRegs(CompilationUnit* cu) +void Mir2Lir::ClobberAllRegs() { int i; - for (i=0; i< cu->reg_pool->num_core_regs; i++) { - ClobberBody(cu, &cu->reg_pool->core_regs[i]); + for (i=0; i< reg_pool_->num_core_regs; i++) { + ClobberBody(®_pool_->core_regs[i]); } - for (i=0; i< cu->reg_pool->num_fp_regs; i++) { - ClobberBody(cu, &cu->reg_pool->FPRegs[i]); + for (i=0; i< reg_pool_->num_fp_regs; i++) { + ClobberBody(®_pool_->FPRegs[i]); } } // Make sure nothing is live and dirty -static void FlushAllRegsBody(CompilationUnit* cu, RegisterInfo* info, int num_regs) +void Mir2Lir::FlushAllRegsBody(RegisterInfo* info, int num_regs) { - Codegen* cg = cu->cg.get(); int i; for (i=0; i < num_regs; i++) { if (info[i].live && info[i].dirty) { if (info[i].pair) { - cg->FlushRegWide(cu, info[i].reg, info[i].partner); + FlushRegWide(info[i].reg, info[i].partner); } else { - cg->FlushReg(cu, info[i].reg); + FlushReg(info[i].reg); } } } } -void FlushAllRegs(CompilationUnit* cu) +void Mir2Lir::FlushAllRegs() { - FlushAllRegsBody(cu, cu->reg_pool->core_regs, - cu->reg_pool->num_core_regs); - FlushAllRegsBody(cu, cu->reg_pool->FPRegs, - cu->reg_pool->num_fp_regs); - ClobberAllRegs(cu); + FlushAllRegsBody(reg_pool_->core_regs, + reg_pool_->num_core_regs); + FlushAllRegsBody(reg_pool_->FPRegs, + reg_pool_->num_fp_regs); + ClobberAllRegs(); } //TUNING: rewrite all of this reg stuff. Probably use an attribute table -static bool RegClassMatches(CompilationUnit* cu, int reg_class, int reg) +bool Mir2Lir::RegClassMatches(int reg_class, int reg) { - Codegen* cg = cu->cg.get(); if (reg_class == kAnyReg) { return true; } else if (reg_class == kCoreReg) { - return !cg->IsFpReg(reg); + return !IsFpReg(reg); } else { - return cg->IsFpReg(reg); + return IsFpReg(reg); } } -void MarkLive(CompilationUnit* cu, int reg, int s_reg) +void Mir2Lir::MarkLive(int reg, int s_reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* info = cg->GetRegInfo(cu, reg); + RegisterInfo* info = GetRegInfo(reg); if ((info->reg == reg) && (info->s_reg == s_reg) && info->live) { return; /* already live */ } else if (s_reg != INVALID_SREG) { - ClobberSReg(cu, s_reg); + ClobberSReg(s_reg); if (info->is_temp) { info->live = true; } @@ -756,68 +732,61 @@ void MarkLive(CompilationUnit* cu, int reg, int s_reg) info->s_reg = s_reg; } -void MarkTemp(CompilationUnit* cu, int reg) +void Mir2Lir::MarkTemp(int reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* info = cg->GetRegInfo(cu, reg); + RegisterInfo* info = GetRegInfo(reg); info->is_temp = true; } -void UnmarkTemp(CompilationUnit* cu, int reg) +void Mir2Lir::UnmarkTemp(int reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* info = cg->GetRegInfo(cu, reg); + RegisterInfo* info = GetRegInfo(reg); info->is_temp = false; } -void MarkPair(CompilationUnit* cu, int low_reg, int high_reg) +void Mir2Lir::MarkPair(int low_reg, int high_reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* info_lo = cg->GetRegInfo(cu, low_reg); - RegisterInfo* info_hi = cg->GetRegInfo(cu, high_reg); + RegisterInfo* info_lo = GetRegInfo(low_reg); + RegisterInfo* info_hi = GetRegInfo(high_reg); info_lo->pair = info_hi->pair = true; info_lo->partner = high_reg; info_hi->partner = low_reg; } -void MarkClean(CompilationUnit* cu, RegLocation loc) +void Mir2Lir::MarkClean(RegLocation loc) { - Codegen* cg = cu->cg.get(); - RegisterInfo* info = cg->GetRegInfo(cu, loc.low_reg); + RegisterInfo* info = GetRegInfo(loc.low_reg); info->dirty = false; if (loc.wide) { - info = cg->GetRegInfo(cu, loc.high_reg); + info = GetRegInfo(loc.high_reg); info->dirty = false; } } -void MarkDirty(CompilationUnit* cu, RegLocation loc) +void Mir2Lir::MarkDirty(RegLocation loc) { if (loc.home) { // If already home, can't be dirty return; } - Codegen* cg = cu->cg.get(); - RegisterInfo* info = cg->GetRegInfo(cu, loc.low_reg); + RegisterInfo* info = GetRegInfo(loc.low_reg); info->dirty = true; if (loc.wide) { - info = cg->GetRegInfo(cu, loc.high_reg); + info = GetRegInfo(loc.high_reg); info->dirty = true; } } -void MarkInUse(CompilationUnit* cu, int reg) +void Mir2Lir::MarkInUse(int reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* info = cg->GetRegInfo(cu, reg); + RegisterInfo* info = GetRegInfo(reg); info->in_use = true; } -static void CopyRegInfo(CompilationUnit* cu, int new_reg, int old_reg) +void Mir2Lir::CopyRegInfo(int new_reg, int old_reg) { - Codegen* cg = cu->cg.get(); - RegisterInfo* new_info = cg->GetRegInfo(cu, new_reg); - RegisterInfo* old_info = cg->GetRegInfo(cu, old_reg); + RegisterInfo* new_info = GetRegInfo(new_reg); + RegisterInfo* old_info = GetRegInfo(old_reg); // Target temp status must not change bool is_temp = new_info->is_temp; *new_info = *old_info; @@ -826,15 +795,14 @@ static void CopyRegInfo(CompilationUnit* cu, int new_reg, int old_reg) new_info->reg = new_reg; } -static bool CheckCorePoolSanity(CompilationUnit* cu) +bool Mir2Lir::CheckCorePoolSanity() { - Codegen* cg = cu->cg.get(); - for (static int i = 0; i < cu->reg_pool->num_core_regs; i++) { - if (cu->reg_pool->core_regs[i].pair) { - static int my_reg = cu->reg_pool->core_regs[i].reg; - static int my_sreg = cu->reg_pool->core_regs[i].s_reg; - static int partner_reg = cu->reg_pool->core_regs[i].partner; - static RegisterInfo* partner = cg->GetRegInfo(cu, partner_reg); + for (static int i = 0; i < reg_pool_->num_core_regs; i++) { + if (reg_pool_->core_regs[i].pair) { + static int my_reg = reg_pool_->core_regs[i].reg; + static int my_sreg = reg_pool_->core_regs[i].s_reg; + static int partner_reg = reg_pool_->core_regs[i].partner; + static RegisterInfo* partner = GetRegInfo(partner_reg); DCHECK(partner != NULL); DCHECK(partner->pair); DCHECK_EQ(my_reg, partner->partner); @@ -846,9 +814,9 @@ static bool CheckCorePoolSanity(CompilationUnit* cu) DCHECK((diff == -1) || (diff == 1)); } } - if (!cu->reg_pool->core_regs[i].live) { - DCHECK(cu->reg_pool->core_regs[i].def_start == NULL); - DCHECK(cu->reg_pool->core_regs[i].def_end == NULL); + if (!reg_pool_->core_regs[i].live) { + DCHECK(reg_pool_->core_regs[i].def_start == NULL); + DCHECK(reg_pool_->core_regs[i].def_end == NULL); } } return true; @@ -864,19 +832,19 @@ static bool CheckCorePoolSanity(CompilationUnit* cu) * if it's worthwhile trying to be more clever here. */ -RegLocation UpdateLoc(CompilationUnit* cu, RegLocation loc) +RegLocation Mir2Lir::UpdateLoc(RegLocation loc) { DCHECK(!loc.wide); - DCHECK(CheckCorePoolSanity(cu)); + DCHECK(CheckCorePoolSanity()); if (loc.location != kLocPhysReg) { DCHECK((loc.location == kLocDalvikFrame) || (loc.location == kLocCompilerTemp)); - RegisterInfo* info_lo = AllocLive(cu, loc.s_reg_low, kAnyReg); + RegisterInfo* info_lo = AllocLive(loc.s_reg_low, kAnyReg); if (info_lo) { if (info_lo->pair) { - Clobber(cu, info_lo->reg); - Clobber(cu, info_lo->partner); - FreeTemp(cu, info_lo->reg); + Clobber(info_lo->reg); + Clobber(info_lo->partner); + FreeTemp(info_lo->reg); } else { loc.low_reg = info_lo->reg; loc.location = kLocPhysReg; @@ -888,25 +856,23 @@ RegLocation UpdateLoc(CompilationUnit* cu, RegLocation loc) } /* see comments for update_loc */ -RegLocation UpdateLocWide(CompilationUnit* cu, RegLocation loc) +RegLocation Mir2Lir::UpdateLocWide(RegLocation loc) { DCHECK(loc.wide); - DCHECK(CheckCorePoolSanity(cu)); - Codegen* cg = cu->cg.get(); + DCHECK(CheckCorePoolSanity()); if (loc.location != kLocPhysReg) { DCHECK((loc.location == kLocDalvikFrame) || (loc.location == kLocCompilerTemp)); // Are the dalvik regs already live in physical registers? - RegisterInfo* info_lo = AllocLive(cu, loc.s_reg_low, kAnyReg); - RegisterInfo* info_hi = AllocLive(cu, - GetSRegHi(loc.s_reg_low), kAnyReg); + RegisterInfo* info_lo = AllocLive(loc.s_reg_low, kAnyReg); + RegisterInfo* info_hi = AllocLive(GetSRegHi(loc.s_reg_low), kAnyReg); bool match = true; match = match && (info_lo != NULL); match = match && (info_hi != NULL); // Are they both core or both FP? - match = match && (cg->IsFpReg(info_lo->reg) == cg->IsFpReg(info_hi->reg)); + match = match && (IsFpReg(info_lo->reg) == IsFpReg(info_hi->reg)); // If a pair of floating point singles, are they properly aligned? - if (match && cg->IsFpReg(info_lo->reg)) { + if (match && IsFpReg(info_lo->reg)) { match &= ((info_lo->reg & 0x1) == 0); match &= ((info_hi->reg - info_lo->reg) == 1); } @@ -921,22 +887,22 @@ RegLocation UpdateLocWide(CompilationUnit* cu, RegLocation loc) loc.low_reg = info_lo->reg; loc.high_reg = info_hi->reg; loc.location = kLocPhysReg; - MarkPair(cu, loc.low_reg, loc.high_reg); - DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); + MarkPair(loc.low_reg, loc.high_reg); + DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); return loc; } // Can't easily reuse - clobber and free any overlaps if (info_lo) { - Clobber(cu, info_lo->reg); - FreeTemp(cu, info_lo->reg); + Clobber(info_lo->reg); + FreeTemp(info_lo->reg); if (info_lo->pair) - Clobber(cu, info_lo->partner); + Clobber(info_lo->partner); } if (info_hi) { - Clobber(cu, info_hi->reg); - FreeTemp(cu, info_hi->reg); + Clobber(info_hi->reg); + FreeTemp(info_hi->reg); if (info_hi->pair) - Clobber(cu, info_hi->partner); + Clobber(info_hi->partner); } } return loc; @@ -944,42 +910,41 @@ RegLocation UpdateLocWide(CompilationUnit* cu, RegLocation loc) /* For use in cases we don't know (or care) width */ -RegLocation UpdateRawLoc(CompilationUnit* cu, RegLocation loc) +RegLocation Mir2Lir::UpdateRawLoc(RegLocation loc) { if (loc.wide) - return UpdateLocWide(cu, loc); + return UpdateLocWide(loc); else - return UpdateLoc(cu, loc); + return UpdateLoc(loc); } -RegLocation EvalLocWide(CompilationUnit* cu, RegLocation loc, int reg_class, bool update) +RegLocation Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) { DCHECK(loc.wide); int new_regs; int low_reg; int high_reg; - Codegen* cg = cu->cg.get(); - loc = UpdateLocWide(cu, loc); + loc = UpdateLocWide(loc); /* If already in registers, we can assume proper form. Right reg class? */ if (loc.location == kLocPhysReg) { - DCHECK_EQ(cg->IsFpReg(loc.low_reg), cg->IsFpReg(loc.high_reg)); - DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); - if (!RegClassMatches(cu, reg_class, loc.low_reg)) { + DCHECK_EQ(IsFpReg(loc.low_reg), IsFpReg(loc.high_reg)); + DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); + if (!RegClassMatches(reg_class, loc.low_reg)) { /* Wrong register class. Reallocate and copy */ - new_regs = cg->AllocTypedTempPair(cu, loc.fp, reg_class); + new_regs = AllocTypedTempPair(loc.fp, reg_class); low_reg = new_regs & 0xff; high_reg = (new_regs >> 8) & 0xff; - cg->OpRegCopyWide(cu, low_reg, high_reg, loc.low_reg, loc.high_reg); - CopyRegInfo(cu, low_reg, loc.low_reg); - CopyRegInfo(cu, high_reg, loc.high_reg); - Clobber(cu, loc.low_reg); - Clobber(cu, loc.high_reg); + OpRegCopyWide(low_reg, high_reg, loc.low_reg, loc.high_reg); + CopyRegInfo(low_reg, loc.low_reg); + CopyRegInfo(high_reg, loc.high_reg); + Clobber(loc.low_reg); + Clobber(loc.high_reg); loc.low_reg = low_reg; loc.high_reg = high_reg; - MarkPair(cu, loc.low_reg, loc.high_reg); - DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); + MarkPair(loc.low_reg, loc.high_reg); + DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); } return loc; } @@ -987,38 +952,36 @@ RegLocation EvalLocWide(CompilationUnit* cu, RegLocation loc, int reg_class, boo DCHECK_NE(loc.s_reg_low, INVALID_SREG); DCHECK_NE(GetSRegHi(loc.s_reg_low), INVALID_SREG); - new_regs = cg->AllocTypedTempPair(cu, loc.fp, reg_class); + new_regs = AllocTypedTempPair(loc.fp, reg_class); loc.low_reg = new_regs & 0xff; loc.high_reg = (new_regs >> 8) & 0xff; - MarkPair(cu, loc.low_reg, loc.high_reg); + MarkPair(loc.low_reg, loc.high_reg); if (update) { loc.location = kLocPhysReg; - MarkLive(cu, loc.low_reg, loc.s_reg_low); - MarkLive(cu, loc.high_reg, GetSRegHi(loc.s_reg_low)); + MarkLive(loc.low_reg, loc.s_reg_low); + MarkLive(loc.high_reg, GetSRegHi(loc.s_reg_low)); } - DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); + DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); return loc; } -RegLocation EvalLoc(CompilationUnit* cu, RegLocation loc, - int reg_class, bool update) +RegLocation Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) { int new_reg; if (loc.wide) - return EvalLocWide(cu, loc, reg_class, update); + return EvalLocWide(loc, reg_class, update); - Codegen* cg = cu->cg.get(); - loc = UpdateLoc(cu, loc); + loc = UpdateLoc(loc); if (loc.location == kLocPhysReg) { - if (!RegClassMatches(cu, reg_class, loc.low_reg)) { + if (!RegClassMatches(reg_class, loc.low_reg)) { /* Wrong register class. Realloc, copy and transfer ownership */ - new_reg = cg->AllocTypedTemp(cu, loc.fp, reg_class); - cg->OpRegCopy(cu, new_reg, loc.low_reg); - CopyRegInfo(cu, new_reg, loc.low_reg); - Clobber(cu, loc.low_reg); + new_reg = AllocTypedTemp(loc.fp, reg_class); + OpRegCopy(new_reg, loc.low_reg); + CopyRegInfo(new_reg, loc.low_reg); + Clobber(loc.low_reg); loc.low_reg = new_reg; } return loc; @@ -1026,76 +989,33 @@ RegLocation EvalLoc(CompilationUnit* cu, RegLocation loc, DCHECK_NE(loc.s_reg_low, INVALID_SREG); - new_reg = cg->AllocTypedTemp(cu, loc.fp, reg_class); + new_reg = AllocTypedTemp(loc.fp, reg_class); loc.low_reg = new_reg; if (update) { loc.location = kLocPhysReg; - MarkLive(cu, loc.low_reg, loc.s_reg_low); + MarkLive(loc.low_reg, loc.s_reg_low); } return loc; } -RegLocation GetRawSrc(CompilationUnit* cu, MIR* mir, int num) -{ - DCHECK(num < mir->ssa_rep->num_uses); - RegLocation res = cu->reg_location[mir->ssa_rep->uses[num]]; - return res; -} - -RegLocation GetRawDest(CompilationUnit* cu, MIR* mir) -{ - DCHECK_GT(mir->ssa_rep->num_defs, 0); - RegLocation res = cu->reg_location[mir->ssa_rep->defs[0]]; - return res; -} - -RegLocation GetDest(CompilationUnit* cu, MIR* mir) -{ - RegLocation res = GetRawDest(cu, mir); - DCHECK(!res.wide); - return res; -} - -RegLocation GetSrc(CompilationUnit* cu, MIR* mir, int num) -{ - RegLocation res = GetRawSrc(cu, mir, num); - DCHECK(!res.wide); - return res; -} - -RegLocation GetDestWide(CompilationUnit* cu, MIR* mir) -{ - RegLocation res = GetRawDest(cu, mir); - DCHECK(res.wide); - return res; -} - -RegLocation GetSrcWide(CompilationUnit* cu, MIR* mir, - int low) -{ - RegLocation res = GetRawSrc(cu, mir, low); - DCHECK(res.wide); - return res; -} - /* USE SSA names to count references of base Dalvik v_regs. */ -static void CountRefs(CompilationUnit *cu, BasicBlock* bb, RefCounts* core_counts, - RefCounts* fp_counts) +void Mir2Lir::CountRefs(BasicBlock* bb, RefCounts* core_counts, + RefCounts* fp_counts) { // TUNING: this routine could use some tweaking. - if ((cu->disable_opt & (1 << kPromoteRegs)) || + if ((cu_->disable_opt & (1 << kPromoteRegs)) || !((bb->block_type == kEntryBlock) || (bb->block_type == kExitBlock) || (bb->block_type == kDalvikByteCode))) { return; } - for (int i = 0; i < cu->mir_graph->GetNumSSARegs(); i++) { - RegLocation loc = cu->reg_location[i]; + for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) { + RegLocation loc = mir_graph_->reg_location_[i]; RefCounts* counts = loc.fp ? fp_counts : core_counts; - int p_map_idx = SRegToPMap(cu, loc.s_reg_low); + int p_map_idx = SRegToPMap(loc.s_reg_low); //Don't count easily regenerated immediates - if (loc.fp || !IsInexpensiveConstant(cu, loc)) { - counts[p_map_idx].count += cu->mir_graph->GetUseCount(i); + if (loc.fp || !IsInexpensiveConstant(loc)) { + counts[p_map_idx].count += mir_graph_->GetUseCount(i); } if (loc.wide && loc.fp && !loc.high_word) { counts[p_map_idx].double_start = true; @@ -1106,12 +1026,12 @@ static void CountRefs(CompilationUnit *cu, BasicBlock* bb, RefCounts* core_count /* qsort callback function, sort descending */ static int SortCounts(const void *val1, const void *val2) { - const RefCounts* op1 = reinterpret_cast<const RefCounts*>(val1); - const RefCounts* op2 = reinterpret_cast<const RefCounts*>(val2); + const Mir2Lir::RefCounts* op1 = reinterpret_cast<const Mir2Lir::RefCounts*>(val1); + const Mir2Lir::RefCounts* op2 = reinterpret_cast<const Mir2Lir::RefCounts*>(val2); return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1); } -static void DumpCounts(const RefCounts* arr, int size, const char* msg) +void Mir2Lir::DumpCounts(const RefCounts* arr, int size, const char* msg) { LOG(INFO) << msg; for (int i = 0; i < size; i++) { @@ -1123,16 +1043,15 @@ static void DumpCounts(const RefCounts* arr, int size, const char* msg) * Note: some portions of this code required even if the kPromoteRegs * optimization is disabled. */ -void DoPromotion(CompilationUnit* cu) +void Mir2Lir::DoPromotion() { - Codegen* cg = cu->cg.get(); - int reg_bias = cu->num_compiler_temps + 1; - int dalvik_regs = cu->num_dalvik_registers; + int reg_bias = cu_->num_compiler_temps + 1; + int dalvik_regs = cu_->num_dalvik_registers; int num_regs = dalvik_regs + reg_bias; const int promotion_threshold = 2; // Allow target code to add any special registers - cg->AdjustSpillMask(cu); + AdjustSpillMask(); /* * Simple register promotion. Just do a static count of the uses @@ -1145,30 +1064,30 @@ void DoPromotion(CompilationUnit* cu) * TUNING: replace with linear scan once we have the ability * to describe register live ranges for GC. */ - RefCounts *core_regs = static_cast<RefCounts*>(NewMem(cu, sizeof(RefCounts) * num_regs, + RefCounts *core_regs = static_cast<RefCounts*>(NewMem(cu_, sizeof(RefCounts) * num_regs, true, kAllocRegAlloc)); - RefCounts *FpRegs = static_cast<RefCounts *>(NewMem(cu, sizeof(RefCounts) * num_regs, + RefCounts *FpRegs = static_cast<RefCounts *>(NewMem(cu_, sizeof(RefCounts) * num_regs, true, kAllocRegAlloc)); // Set ssa names for original Dalvik registers for (int i = 0; i < dalvik_regs; i++) { core_regs[i].s_reg = FpRegs[i].s_reg = i; } // Set ssa name for Method* - core_regs[dalvik_regs].s_reg = cu->method_sreg; - FpRegs[dalvik_regs].s_reg = cu->method_sreg; // For consistecy + core_regs[dalvik_regs].s_reg = mir_graph_->GetMethodSReg(); + FpRegs[dalvik_regs].s_reg = mir_graph_->GetMethodSReg(); // For consistecy // Set ssa names for compiler_temps - for (int i = 1; i <= cu->num_compiler_temps; i++) { - CompilerTemp* ct = reinterpret_cast<CompilerTemp*>(cu->compiler_temps.elem_list[i]); + for (int i = 1; i <= cu_->num_compiler_temps; i++) { + CompilerTemp* ct = reinterpret_cast<CompilerTemp*>(mir_graph_->compiler_temps_.elem_list[i]); core_regs[dalvik_regs + i].s_reg = ct->s_reg; FpRegs[dalvik_regs + i].s_reg = ct->s_reg; } - GrowableListIterator iterator = cu->mir_graph->GetBasicBlockIterator(); + GrowableListIterator iterator = mir_graph_->GetBasicBlockIterator(); while (true) { BasicBlock* bb; bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iterator)); if (bb == NULL) break; - CountRefs(cu, bb, core_regs, FpRegs); + CountRefs(bb, core_regs, FpRegs); } /* @@ -1186,18 +1105,18 @@ void DoPromotion(CompilationUnit* cu) qsort(core_regs, num_regs, sizeof(RefCounts), SortCounts); qsort(FpRegs, num_regs, sizeof(RefCounts), SortCounts); - if (cu->verbose) { + if (cu_->verbose) { DumpCounts(core_regs, num_regs, "Core regs after sort"); DumpCounts(FpRegs, num_regs, "Fp regs after sort"); } - if (!(cu->disable_opt & (1 << kPromoteRegs))) { + if (!(cu_->disable_opt & (1 << kPromoteRegs))) { // Promote FpRegs for (int i = 0; (i < num_regs) && (FpRegs[i].count >= promotion_threshold ); i++) { - int p_map_idx = SRegToPMap(cu, FpRegs[i].s_reg); - if (cu->promotion_map[p_map_idx].fp_location != kLocPhysReg) { - int reg = AllocPreservedFPReg(cu, FpRegs[i].s_reg, + int p_map_idx = SRegToPMap(FpRegs[i].s_reg); + if (promotion_map_[p_map_idx].fp_location != kLocPhysReg) { + int reg = AllocPreservedFPReg(FpRegs[i].s_reg, FpRegs[i].double_start); if (reg < 0) { break; // No more left @@ -1208,10 +1127,10 @@ void DoPromotion(CompilationUnit* cu) // Promote core regs for (int i = 0; (i < num_regs) && (core_regs[i].count > promotion_threshold); i++) { - int p_map_idx = SRegToPMap(cu, core_regs[i].s_reg); - if (cu->promotion_map[p_map_idx].core_location != + int p_map_idx = SRegToPMap(core_regs[i].s_reg); + if (promotion_map_[p_map_idx].core_location != kLocPhysReg) { - int reg = AllocPreservedCoreReg(cu, core_regs[i].s_reg); + int reg = AllocPreservedCoreReg(core_regs[i].s_reg); if (reg < 0) { break; // No more left } @@ -1220,20 +1139,20 @@ void DoPromotion(CompilationUnit* cu) } // Now, update SSA names to new home locations - for (int i = 0; i < cu->mir_graph->GetNumSSARegs(); i++) { - RegLocation *curr = &cu->reg_location[i]; - int p_map_idx = SRegToPMap(cu, curr->s_reg_low); + for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) { + RegLocation *curr = &mir_graph_->reg_location_[i]; + int p_map_idx = SRegToPMap(curr->s_reg_low); if (!curr->wide) { if (curr->fp) { - if (cu->promotion_map[p_map_idx].fp_location == kLocPhysReg) { + if (promotion_map_[p_map_idx].fp_location == kLocPhysReg) { curr->location = kLocPhysReg; - curr->low_reg = cu->promotion_map[p_map_idx].FpReg; + curr->low_reg = promotion_map_[p_map_idx].FpReg; curr->home = true; } } else { - if (cu->promotion_map[p_map_idx].core_location == kLocPhysReg) { + if (promotion_map_[p_map_idx].core_location == kLocPhysReg) { curr->location = kLocPhysReg; - curr->low_reg = cu->promotion_map[p_map_idx].core_reg; + curr->low_reg = promotion_map_[p_map_idx].core_reg; curr->home = true; } } @@ -1243,11 +1162,11 @@ void DoPromotion(CompilationUnit* cu) continue; } if (curr->fp) { - if ((cu->promotion_map[p_map_idx].fp_location == kLocPhysReg) && - (cu->promotion_map[p_map_idx+1].fp_location == + if ((promotion_map_[p_map_idx].fp_location == kLocPhysReg) && + (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg)) { - int low_reg = cu->promotion_map[p_map_idx].FpReg; - int high_reg = cu->promotion_map[p_map_idx+1].FpReg; + int low_reg = promotion_map_[p_map_idx].FpReg; + int high_reg = promotion_map_[p_map_idx+1].FpReg; // Doubles require pair of singles starting at even reg if (((low_reg & 0x1) == 0) && ((low_reg + 1) == high_reg)) { curr->location = kLocPhysReg; @@ -1257,85 +1176,97 @@ void DoPromotion(CompilationUnit* cu) } } } else { - if ((cu->promotion_map[p_map_idx].core_location == kLocPhysReg) - && (cu->promotion_map[p_map_idx+1].core_location == + if ((promotion_map_[p_map_idx].core_location == kLocPhysReg) + && (promotion_map_[p_map_idx+1].core_location == kLocPhysReg)) { curr->location = kLocPhysReg; - curr->low_reg = cu->promotion_map[p_map_idx].core_reg; - curr->high_reg = cu->promotion_map[p_map_idx+1].core_reg; + curr->low_reg = promotion_map_[p_map_idx].core_reg; + curr->high_reg = promotion_map_[p_map_idx+1].core_reg; curr->home = true; } } } } - if (cu->verbose) { - DumpPromotionMap(cu); + if (cu_->verbose) { + DumpPromotionMap(); } } /* Returns sp-relative offset in bytes for a VReg */ -int VRegOffset(CompilationUnit* cu, int v_reg) +int Mir2Lir::VRegOffset(int v_reg) { - return StackVisitor::GetVRegOffset(cu->code_item, cu->core_spill_mask, - cu->fp_spill_mask, cu->frame_size, v_reg); + return StackVisitor::GetVRegOffset(cu_->code_item, core_spill_mask_, + fp_spill_mask_, frame_size_, v_reg); } /* Returns sp-relative offset in bytes for a SReg */ -int SRegOffset(CompilationUnit* cu, int s_reg) +int Mir2Lir::SRegOffset(int s_reg) { - return VRegOffset(cu, cu->mir_graph->SRegToVReg(s_reg)); -} - -RegLocation GetBadLoc() -{ - RegLocation res = bad_loc; - return res; + return VRegOffset(mir_graph_->SRegToVReg(s_reg)); } /* Mark register usage state and return long retloc */ -RegLocation GetReturnWide(CompilationUnit* cu, bool is_double) +RegLocation Mir2Lir::GetReturnWide(bool is_double) { - Codegen* cg = cu->cg.get(); - RegLocation gpr_res = cg->LocCReturnWide(); - RegLocation fpr_res = cg->LocCReturnDouble(); + RegLocation gpr_res = LocCReturnWide(); + RegLocation fpr_res = LocCReturnDouble(); RegLocation res = is_double ? fpr_res : gpr_res; - Clobber(cu, res.low_reg); - Clobber(cu, res.high_reg); - LockTemp(cu, res.low_reg); - LockTemp(cu, res.high_reg); - MarkPair(cu, res.low_reg, res.high_reg); + Clobber(res.low_reg); + Clobber(res.high_reg); + LockTemp(res.low_reg); + LockTemp(res.high_reg); + MarkPair(res.low_reg, res.high_reg); return res; } -RegLocation GetReturn(CompilationUnit* cu, bool is_float) +RegLocation Mir2Lir::GetReturn(bool is_float) { - Codegen* cg = cu->cg.get(); - RegLocation gpr_res = cg->LocCReturn(); - RegLocation fpr_res = cg->LocCReturnFloat(); + RegLocation gpr_res = LocCReturn(); + RegLocation fpr_res = LocCReturnFloat(); RegLocation res = is_float ? fpr_res : gpr_res; - Clobber(cu, res.low_reg); - if (cu->instruction_set == kMips) { - MarkInUse(cu, res.low_reg); + Clobber(res.low_reg); + if (cu_->instruction_set == kMips) { + MarkInUse(res.low_reg); } else { - LockTemp(cu, res.low_reg); + LockTemp(res.low_reg); } return res; } -void Codegen::SimpleRegAlloc(CompilationUnit* cu) +void Mir2Lir::SimpleRegAlloc() { - DoPromotion(cu); + DoPromotion(); - /* Get easily-accessable post-promotion copy of RegLocation for Method* */ - cu->method_loc = cu->reg_location[cu->method_sreg]; - - if (cu->verbose && !(cu->disable_opt & (1 << kPromoteRegs))) { + if (cu_->verbose && !(cu_->disable_opt & (1 << kPromoteRegs))) { LOG(INFO) << "After Promotion"; - cu->mir_graph->DumpRegLocTable(cu->reg_location, cu->mir_graph->GetNumSSARegs()); + mir_graph_->DumpRegLocTable(mir_graph_->reg_location_, mir_graph_->GetNumSSARegs()); } /* Set the frame size */ - cu->frame_size = cu->mir_graph->ComputeFrameSize(); + frame_size_ = ComputeFrameSize(); +} + +/* + * Get the "real" sreg number associated with an s_reg slot. In general, + * s_reg values passed through codegen are the SSA names created by + * dataflow analysis and refer to slot numbers in the mir_graph_->reg_location + * array. However, renaming is accomplished by simply replacing RegLocation + * entries in the reglocation[] array. Therefore, when location + * records for operands are first created, we need to ask the locRecord + * identified by the dataflow pass what it's new name is. + */ +int Mir2Lir::GetSRegHi(int lowSreg) { + return (lowSreg == INVALID_SREG) ? INVALID_SREG : lowSreg + 1; +} + +bool Mir2Lir::oat_live_out(int s_reg) { + //For now. + return true; +} + +int Mir2Lir::oatSSASrc(MIR* mir, int num) { + DCHECK_GT(mir->ssa_rep->num_uses, num); + return mir->ssa_rep->uses[num]; } } // namespace art diff --git a/src/compiler/dex/quick/ralloc_util.h b/src/compiler/dex/quick/ralloc_util.h deleted file mode 100644 index 1f99600efb..0000000000 --- a/src/compiler/dex/quick/ralloc_util.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_SRC_COMPILER_DEX_QUICK_RALLOCUTIL_H_ -#define ART_SRC_COMPILER_DEX_QUICK_RALLOCUTIL_H_ - -/* - * This file contains target independent register alloction support. - */ - -#include "compiler/dex/compiler_ir.h" -#include "compiler/dex/compiler_utility.h" - -namespace art { - -/* Static register use counts */ -struct RefCounts { - int count; - int s_reg; - bool double_start; // Starting v_reg for a double -}; - -/* - * Get the "real" sreg number associated with an s_reg slot. In general, - * s_reg values passed through codegen are the SSA names created by - * dataflow analysis and refer to slot numbers in the cu->reg_location - * array. However, renaming is accomplished by simply replacing RegLocation - * entries in the cu->reglocation[] array. Therefore, when location - * records for operands are first created, we need to ask the locRecord - * identified by the dataflow pass what it's new name is. - */ -inline int GetSRegHi(int lowSreg) { - return (lowSreg == INVALID_SREG) ? INVALID_SREG : lowSreg + 1; -} - -inline bool oat_live_out(CompilationUnit* cu, int s_reg) { - //For now. - return true; -} - -inline int oatSSASrc(MIR* mir, int num) { - DCHECK_GT(mir->ssa_rep->num_uses, num); - return mir->ssa_rep->uses[num]; -} - -void ClobberSReg(CompilationUnit* cu, int s_reg); -RegLocation EvalLoc(CompilationUnit* cu, RegLocation loc, - int reg_class, bool update); -// Mark a temp register as dead. Does not affect allocation state. -void Clobber(CompilationUnit* cu, int reg); - -RegLocation UpdateLoc(CompilationUnit* cu, RegLocation loc); -RegLocation UpdateLocWide(CompilationUnit* cu, RegLocation loc); -RegLocation UpdateRawLoc(CompilationUnit* cu, RegLocation loc); - -void MarkLive(CompilationUnit* cu, int reg, int s_reg); -void MarkTemp(CompilationUnit* cu, int reg); -void UnmarkTemp(CompilationUnit* cu, int reg); -void MarkDirty(CompilationUnit* cu, RegLocation loc); -void MarkPair(CompilationUnit* cu, int low_reg, int high_reg); -void MarkClean(CompilationUnit* cu, RegLocation loc); -void ResetDef(CompilationUnit* cu, int reg); -void ResetDefLoc(CompilationUnit* cu, RegLocation rl); - -// Set up temp & preserved register pools specialized by target. -void CompilerInitPool(RegisterInfo* regs, int* reg_nums, int num); - -/* - * Mark the beginning and end LIR of a def sequence. Note that - * on entry start points to the LIR prior to the beginning of the - * sequence. - */ -void MarkDef(CompilationUnit* cu, RegLocation rl, LIR* start, LIR* finish); -void MarkDefWide(CompilationUnit* cu, RegLocation rl, LIR* start, LIR* finish); -void ResetDefLocWide(CompilationUnit* cu, RegLocation rl); -void ResetDefTracking(CompilationUnit* cu); - - -// Get the LocRecord associated with an SSA name use. -RegLocation GetSrc(CompilationUnit* cu, MIR* mir, int num); -RegLocation GetSrcWide(CompilationUnit* cu, MIR* mir, int low); -// Non-width checking version. -RegLocation GetRawSrc(CompilationUnit* cu, MIR* mir, int num); - -// Get the LocRecord associated with an SSA name def. -RegLocation GetDest(CompilationUnit* cu, MIR* mir); -RegLocation GetDestWide(CompilationUnit* cu, MIR* mir); -// Non-width checking version. -RegLocation GetRawDest(CompilationUnit* cu, MIR* mir); - -// Clobber all regs that might be used by an external C call. -void ClobberCalleeSave(CompilationUnit* cu); - -RegisterInfo *IsTemp(CompilationUnit* cu, int reg); -RegisterInfo *IsPromoted(CompilationUnit* cu, int reg); -RegisterInfo *IsLive(CompilationUnit* cu, int reg); -bool IsDirty(CompilationUnit* cu, int reg); - -void MarkInUse(CompilationUnit* cu, int reg); - -int AllocTemp(CompilationUnit* cu); -int AllocTempFloat(CompilationUnit* cu); -int AllocTempDouble(CompilationUnit* cu); -void FreeTemp(CompilationUnit* cu, int reg); -// Return a temp if one is available, -1 otherwise. -int AllocFreeTemp(CompilationUnit* cu); -/* - * Attempt to allocate a callee-save register. - * Similar to AllocTemp(), but forces the allocation of a specific - * register. No check is made to see if the register was previously - * allocated. Use with caution. - */ -void LockTemp(CompilationUnit* cu, int reg); - -/* To be used when explicitly managing register use */ -void LockCallTemps(CompilationUnit* cu); -void FreeCallTemps(CompilationUnit* cu); - -void FlushAllRegs(CompilationUnit* cu); - -RegLocation GetReturn(CompilationUnit* cu, bool is_float); -RegLocation GetReturnWide(CompilationUnit* cu, bool is_double); -RegLocation GetBadLoc(); -RegLocation WideToNarrow(CompilationUnit* cu, RegLocation rl); - -/* - * Free all allocated temps in the temp pools. Note that this does - * not affect the "liveness" of a temp register, which will stay - * live until it is either explicitly killed or reallocated. - */ -void ResetRegPool(CompilationUnit* cu); - -void ClobberAllRegs(CompilationUnit* cu); - -void FlushRegWide(CompilationUnit* cu, int reg1, int reg2); - -void FlushReg(CompilationUnit* cu, int reg); - -void DoPromotion(CompilationUnit* cu); -int VRegOffset(CompilationUnit* cu, int reg); -int SRegOffset(CompilationUnit* cu, int reg); -void RecordCorePromotion(CompilationUnit* cu, int reg, int s_reg); -void RecordFpPromotion(CompilationUnit* cu, int reg, int s_reg); -int SRegToPMap(CompilationUnit* cu, int s_reg); -void DumpRegPool(RegisterInfo* p, int num_regs); - -} // namespace art - -#endif // ART_SRC_COMPILER_DEX_QUICK_RALLOCUTIL_H_ diff --git a/src/compiler/dex/quick/x86/assemble_x86.cc b/src/compiler/dex/quick/x86/assemble_x86.cc index 2369e49416..f7c1594908 100644 --- a/src/compiler/dex/quick/x86/assemble_x86.cc +++ b/src/compiler/dex/quick/x86/assemble_x86.cc @@ -15,14 +15,13 @@ */ #include "codegen_x86.h" -#include "compiler/dex/quick/codegen_util.h" #include "x86_lir.h" namespace art { #define MAX_ASSEMBLER_RETRIES 50 -const X86EncodingMap X86Codegen::EncodingMap[kX86Last] = { +const X86EncodingMap X86Mir2Lir::EncodingMap[kX86Last] = { { kX8632BitData, kData, IS_UNARY_OP, { 0, 0, 0x00, 0, 0, 0, 0, 4 }, "data", "0x!0d" }, { kX86Bkpt, kNullary, NO_OPERAND | IS_BRANCH, { 0, 0, 0xCC, 0, 0, 0, 0, 0 }, "int 3", "" }, { kX86Nop, kNop, IS_UNARY_OP, { 0, 0, 0x90, 0, 0, 0, 0, 0 }, "nop", "" }, @@ -361,8 +360,8 @@ static size_t ComputeSize(const X86EncodingMap* entry, int base, int displacemen return size; } -int X86Codegen::GetInsnSize(LIR* lir) { - const X86EncodingMap* entry = &X86Codegen::EncodingMap[lir->opcode]; +int X86Mir2Lir::GetInsnSize(LIR* lir) { + const X86EncodingMap* entry = &X86Mir2Lir::EncodingMap[lir->opcode]; switch (entry->kind) { case kData: return 4; // 4 bytes of data @@ -479,7 +478,7 @@ int X86Codegen::GetInsnSize(LIR* lir) { case kMacro: DCHECK_EQ(lir->opcode, static_cast<int>(kX86StartOfMethod)); return 5 /* call opcode + 4 byte displacement */ + 1 /* pop reg */ + - ComputeSize(&X86Codegen::EncodingMap[kX86Sub32RI], 0, 0, false) - + ComputeSize(&X86Mir2Lir::EncodingMap[kX86Sub32RI], 0, 0, false) - (lir->operands[0] == rAX ? 1 : 0); // shorter ax encoding default: break; @@ -499,34 +498,34 @@ static uint8_t ModrmForDisp(int base, int disp) { } } -static void EmitDisp(CompilationUnit* cu, int base, int disp) { +void X86Mir2Lir::EmitDisp(int base, int disp) { // BP requires an explicit disp, so do not omit it in the 0 case if (disp == 0 && base != rBP) { return; } else if (IS_SIMM8(disp)) { - cu->code_buffer.push_back(disp & 0xFF); + code_buffer_.push_back(disp & 0xFF); } else { - cu->code_buffer.push_back(disp & 0xFF); - cu->code_buffer.push_back((disp >> 8) & 0xFF); - cu->code_buffer.push_back((disp >> 16) & 0xFF); - cu->code_buffer.push_back((disp >> 24) & 0xFF); + code_buffer_.push_back(disp & 0xFF); + code_buffer_.push_back((disp >> 8) & 0xFF); + code_buffer_.push_back((disp >> 16) & 0xFF); + code_buffer_.push_back((disp >> 24) & 0xFF); } } -static void EmitOpReg(CompilationUnit* cu, const X86EncodingMap* entry, uint8_t reg) { +void X86Mir2Lir::EmitOpReg(const X86EncodingMap* entry, uint8_t reg) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -539,51 +538,51 @@ static void EmitOpReg(CompilationUnit* cu, const X86EncodingMap* entry, uint8_t } if (reg >= 4) { DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) - << " in " << PrettyMethod(cu->method_idx, *cu->dex_file); + << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); } DCHECK_LT(reg, 8); uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitOpMem(CompilationUnit* cu, const X86EncodingMap* entry, uint8_t base, int disp) { +void X86Mir2Lir::EmitOpMem(const X86EncodingMap* entry, uint8_t base, int disp) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); DCHECK_EQ(0, entry->skeleton.extra_opcode1); DCHECK_EQ(0, entry->skeleton.extra_opcode2); DCHECK_LT(entry->skeleton.modrm_opcode, 8); DCHECK_LT(base, 8); uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (entry->skeleton.modrm_opcode << 3) | base; - cu->code_buffer.push_back(modrm); - EmitDisp(cu, base, disp); + code_buffer_.push_back(modrm); + EmitDisp(base, disp); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitMemReg(CompilationUnit* cu, const X86EncodingMap* entry, +void X86Mir2Lir::EmitMemReg(const X86EncodingMap* entry, uint8_t base, int disp, uint8_t reg) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -596,43 +595,43 @@ static void EmitMemReg(CompilationUnit* cu, const X86EncodingMap* entry, } if (reg >= 4) { DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) - << " in " << PrettyMethod(cu->method_idx, *cu->dex_file); + << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); } DCHECK_LT(reg, 8); DCHECK_LT(base, 8); uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (reg << 3) | base; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); if (base == rX86_SP) { // Special SIB for SP base - cu->code_buffer.push_back(0 << 6 | (rX86_SP << 3) | rX86_SP); + code_buffer_.push_back(0 << 6 | (rX86_SP << 3) | rX86_SP); } - EmitDisp(cu, base, disp); + EmitDisp(base, disp); DCHECK_EQ(0, entry->skeleton.modrm_opcode); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitRegMem(CompilationUnit* cu, const X86EncodingMap* entry, +void X86Mir2Lir::EmitRegMem(const X86EncodingMap* entry, uint8_t reg, uint8_t base, int disp) { // Opcode will flip operands. - EmitMemReg(cu, entry, base, disp, reg); + EmitMemReg(entry, base, disp, reg); } -static void EmitRegArray(CompilationUnit* cu, const X86EncodingMap* entry, uint8_t reg, - uint8_t base, uint8_t index, int scale, int disp) { +void X86Mir2Lir::EmitRegArray(const X86EncodingMap* entry, uint8_t reg, uint8_t base, uint8_t index, + int scale, int disp) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -645,36 +644,35 @@ static void EmitRegArray(CompilationUnit* cu, const X86EncodingMap* entry, uint8 } DCHECK_LT(reg, 8); uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (reg << 3) | rX86_SP; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); DCHECK_LT(scale, 4); DCHECK_LT(index, 8); DCHECK_LT(base, 8); uint8_t sib = (scale << 6) | (index << 3) | base; - cu->code_buffer.push_back(sib); - EmitDisp(cu, base, disp); + code_buffer_.push_back(sib); + EmitDisp(base, disp); DCHECK_EQ(0, entry->skeleton.modrm_opcode); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitArrayReg(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t base, uint8_t index, int scale, int disp, uint8_t reg) { +void X86Mir2Lir::EmitArrayReg(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp, + uint8_t reg) { // Opcode will flip operands. - EmitRegArray(cu, entry, reg, base, index, scale, disp); + EmitRegArray(entry, reg, base, index, scale, disp); } -static void EmitRegThread(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t reg, int disp) { +void X86Mir2Lir::EmitRegThread(const X86EncodingMap* entry, uint8_t reg, int disp) { DCHECK_NE(entry->skeleton.prefix1, 0); - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -687,35 +685,34 @@ static void EmitRegThread(CompilationUnit* cu, const X86EncodingMap* entry, } if (reg >= 4) { DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) - << " in " << PrettyMethod(cu->method_idx, *cu->dex_file); + << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); } DCHECK_LT(reg, 8); uint8_t modrm = (0 << 6) | (reg << 3) | rBP; - cu->code_buffer.push_back(modrm); - cu->code_buffer.push_back(disp & 0xFF); - cu->code_buffer.push_back((disp >> 8) & 0xFF); - cu->code_buffer.push_back((disp >> 16) & 0xFF); - cu->code_buffer.push_back((disp >> 24) & 0xFF); + code_buffer_.push_back(modrm); + code_buffer_.push_back(disp & 0xFF); + code_buffer_.push_back((disp >> 8) & 0xFF); + code_buffer_.push_back((disp >> 16) & 0xFF); + code_buffer_.push_back((disp >> 24) & 0xFF); DCHECK_EQ(0, entry->skeleton.modrm_opcode); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitRegReg(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t reg1, uint8_t reg2) { +void X86Mir2Lir::EmitRegReg(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -732,27 +729,27 @@ static void EmitRegReg(CompilationUnit* cu, const X86EncodingMap* entry, DCHECK_LT(reg1, 8); DCHECK_LT(reg2, 8); uint8_t modrm = (3 << 6) | (reg1 << 3) | reg2; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); DCHECK_EQ(0, entry->skeleton.modrm_opcode); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitRegRegImm(CompilationUnit* cu, const X86EncodingMap* entry, +void X86Mir2Lir::EmitRegRegImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -769,24 +766,24 @@ static void EmitRegRegImm(CompilationUnit* cu, const X86EncodingMap* entry, DCHECK_LT(reg1, 8); DCHECK_LT(reg2, 8); uint8_t modrm = (3 << 6) | (reg1 << 3) | reg2; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); DCHECK_EQ(0, entry->skeleton.modrm_opcode); DCHECK_EQ(0, entry->skeleton.ax_opcode); switch (entry->skeleton.immediate_bytes) { case 1: DCHECK(IS_SIMM8(imm)); - cu->code_buffer.push_back(imm & 0xFF); + code_buffer_.push_back(imm & 0xFF); break; case 2: DCHECK(IS_SIMM16(imm)); - cu->code_buffer.push_back(imm & 0xFF); - cu->code_buffer.push_back((imm >> 8) & 0xFF); + code_buffer_.push_back(imm & 0xFF); + code_buffer_.push_back((imm >> 8) & 0xFF); break; case 4: - cu->code_buffer.push_back(imm & 0xFF); - cu->code_buffer.push_back((imm >> 8) & 0xFF); - cu->code_buffer.push_back((imm >> 16) & 0xFF); - cu->code_buffer.push_back((imm >> 24) & 0xFF); + code_buffer_.push_back(imm & 0xFF); + code_buffer_.push_back((imm >> 8) & 0xFF); + code_buffer_.push_back((imm >> 16) & 0xFF); + code_buffer_.push_back((imm >> 24) & 0xFF); break; default: LOG(FATAL) << "Unexpected immediate bytes (" << entry->skeleton.immediate_bytes @@ -795,24 +792,23 @@ static void EmitRegRegImm(CompilationUnit* cu, const X86EncodingMap* entry, } } -static void EmitRegImm(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t reg, int imm) { +void X86Mir2Lir::EmitRegImm(const X86EncodingMap* entry, uint8_t reg, int imm) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } if (reg == rAX && entry->skeleton.ax_opcode != 0) { - cu->code_buffer.push_back(entry->skeleton.ax_opcode); + code_buffer_.push_back(entry->skeleton.ax_opcode); } else { - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -824,23 +820,23 @@ static void EmitRegImm(CompilationUnit* cu, const X86EncodingMap* entry, reg = reg & X86_FP_REG_MASK; } uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); } switch (entry->skeleton.immediate_bytes) { case 1: DCHECK(IS_SIMM8(imm)); - cu->code_buffer.push_back(imm & 0xFF); + code_buffer_.push_back(imm & 0xFF); break; case 2: DCHECK(IS_SIMM16(imm)); - cu->code_buffer.push_back(imm & 0xFF); - cu->code_buffer.push_back((imm >> 8) & 0xFF); + code_buffer_.push_back(imm & 0xFF); + code_buffer_.push_back((imm >> 8) & 0xFF); break; case 4: - cu->code_buffer.push_back(imm & 0xFF); - cu->code_buffer.push_back((imm >> 8) & 0xFF); - cu->code_buffer.push_back((imm >> 16) & 0xFF); - cu->code_buffer.push_back((imm >> 24) & 0xFF); + code_buffer_.push_back(imm & 0xFF); + code_buffer_.push_back((imm >> 8) & 0xFF); + code_buffer_.push_back((imm >> 16) & 0xFF); + code_buffer_.push_back((imm >> 24) & 0xFF); break; default: LOG(FATAL) << "Unexpected immediate bytes (" << entry->skeleton.immediate_bytes @@ -849,21 +845,20 @@ static void EmitRegImm(CompilationUnit* cu, const X86EncodingMap* entry, } } -static void EmitThreadImm(CompilationUnit* cu, const X86EncodingMap* entry, - int disp, int imm) { +void X86Mir2Lir::EmitThreadImm(const X86EncodingMap* entry, int disp, int imm) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -872,26 +867,26 @@ static void EmitThreadImm(CompilationUnit* cu, const X86EncodingMap* entry, DCHECK_EQ(0, entry->skeleton.extra_opcode2); } uint8_t modrm = (0 << 6) | (entry->skeleton.modrm_opcode << 3) | rBP; - cu->code_buffer.push_back(modrm); - cu->code_buffer.push_back(disp & 0xFF); - cu->code_buffer.push_back((disp >> 8) & 0xFF); - cu->code_buffer.push_back((disp >> 16) & 0xFF); - cu->code_buffer.push_back((disp >> 24) & 0xFF); + code_buffer_.push_back(modrm); + code_buffer_.push_back(disp & 0xFF); + code_buffer_.push_back((disp >> 8) & 0xFF); + code_buffer_.push_back((disp >> 16) & 0xFF); + code_buffer_.push_back((disp >> 24) & 0xFF); switch (entry->skeleton.immediate_bytes) { case 1: DCHECK(IS_SIMM8(imm)); - cu->code_buffer.push_back(imm & 0xFF); + code_buffer_.push_back(imm & 0xFF); break; case 2: DCHECK(IS_SIMM16(imm)); - cu->code_buffer.push_back(imm & 0xFF); - cu->code_buffer.push_back((imm >> 8) & 0xFF); + code_buffer_.push_back(imm & 0xFF); + code_buffer_.push_back((imm >> 8) & 0xFF); break; case 4: - cu->code_buffer.push_back(imm & 0xFF); - cu->code_buffer.push_back((imm >> 8) & 0xFF); - cu->code_buffer.push_back((imm >> 16) & 0xFF); - cu->code_buffer.push_back((imm >> 24) & 0xFF); + code_buffer_.push_back(imm & 0xFF); + code_buffer_.push_back((imm >> 8) & 0xFF); + code_buffer_.push_back((imm >> 16) & 0xFF); + code_buffer_.push_back((imm >> 24) & 0xFF); break; default: LOG(FATAL) << "Unexpected immediate bytes (" << entry->skeleton.immediate_bytes @@ -901,36 +896,34 @@ static void EmitThreadImm(CompilationUnit* cu, const X86EncodingMap* entry, DCHECK_EQ(entry->skeleton.ax_opcode, 0); } -static void EmitMovRegImm(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t reg, int imm) { +void X86Mir2Lir::EmitMovRegImm(const X86EncodingMap* entry, uint8_t reg, int imm) { DCHECK_LT(reg, 8); - cu->code_buffer.push_back(0xB8 + reg); - cu->code_buffer.push_back(imm & 0xFF); - cu->code_buffer.push_back((imm >> 8) & 0xFF); - cu->code_buffer.push_back((imm >> 16) & 0xFF); - cu->code_buffer.push_back((imm >> 24) & 0xFF); + code_buffer_.push_back(0xB8 + reg); + code_buffer_.push_back(imm & 0xFF); + code_buffer_.push_back((imm >> 8) & 0xFF); + code_buffer_.push_back((imm >> 16) & 0xFF); + code_buffer_.push_back((imm >> 24) & 0xFF); } -static void EmitShiftRegImm(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t reg, int imm) { +void X86Mir2Lir::EmitShiftRegImm(const X86EncodingMap* entry, uint8_t reg, int imm) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } if (imm != 1) { - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); } else { // Shorter encoding for 1 bit shift - cu->code_buffer.push_back(entry->skeleton.ax_opcode); + code_buffer_.push_back(entry->skeleton.ax_opcode); } if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -940,115 +933,111 @@ static void EmitShiftRegImm(CompilationUnit* cu, const X86EncodingMap* entry, } if (reg >= 4) { DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " " << static_cast<int>(reg) - << " in " << PrettyMethod(cu->method_idx, *cu->dex_file); + << " in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); } DCHECK_LT(reg, 8); uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); if (imm != 1) { DCHECK_EQ(entry->skeleton.immediate_bytes, 1); DCHECK(IS_SIMM8(imm)); - cu->code_buffer.push_back(imm & 0xFF); + code_buffer_.push_back(imm & 0xFF); } } -static void EmitShiftRegCl(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t reg, uint8_t cl) { +void X86Mir2Lir::EmitShiftRegCl(const X86EncodingMap* entry, uint8_t reg, uint8_t cl) { DCHECK_EQ(cl, static_cast<uint8_t>(rCX)); if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); DCHECK_EQ(0, entry->skeleton.extra_opcode1); DCHECK_EQ(0, entry->skeleton.extra_opcode2); DCHECK_LT(reg, 8); uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitRegCond(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t reg, uint8_t condition) { +void X86Mir2Lir::EmitRegCond(const X86EncodingMap* entry, uint8_t reg, uint8_t condition) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0x0F, entry->skeleton.opcode); - cu->code_buffer.push_back(0x0F); + code_buffer_.push_back(0x0F); DCHECK_EQ(0x90, entry->skeleton.extra_opcode1); - cu->code_buffer.push_back(0x90 | condition); + code_buffer_.push_back(0x90 | condition); DCHECK_EQ(0, entry->skeleton.extra_opcode2); DCHECK_LT(reg, 8); uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); DCHECK_EQ(entry->skeleton.immediate_bytes, 0); } -static void EmitJmp(CompilationUnit* cu, const X86EncodingMap* entry, int rel) { +void X86Mir2Lir::EmitJmp(const X86EncodingMap* entry, int rel) { if (entry->opcode == kX86Jmp8) { DCHECK(IS_SIMM8(rel)); - cu->code_buffer.push_back(0xEB); - cu->code_buffer.push_back(rel & 0xFF); + code_buffer_.push_back(0xEB); + code_buffer_.push_back(rel & 0xFF); } else if (entry->opcode == kX86Jmp32) { - cu->code_buffer.push_back(0xE9); - cu->code_buffer.push_back(rel & 0xFF); - cu->code_buffer.push_back((rel >> 8) & 0xFF); - cu->code_buffer.push_back((rel >> 16) & 0xFF); - cu->code_buffer.push_back((rel >> 24) & 0xFF); + code_buffer_.push_back(0xE9); + code_buffer_.push_back(rel & 0xFF); + code_buffer_.push_back((rel >> 8) & 0xFF); + code_buffer_.push_back((rel >> 16) & 0xFF); + code_buffer_.push_back((rel >> 24) & 0xFF); } else { DCHECK(entry->opcode == kX86JmpR); - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); uint8_t reg = static_cast<uint8_t>(rel); DCHECK_LT(reg, 8); uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); } } -static void EmitJcc(CompilationUnit* cu, const X86EncodingMap* entry, - int rel, uint8_t cc) { +void X86Mir2Lir::EmitJcc(const X86EncodingMap* entry, int rel, uint8_t cc) { DCHECK_LT(cc, 16); if (entry->opcode == kX86Jcc8) { DCHECK(IS_SIMM8(rel)); - cu->code_buffer.push_back(0x70 | cc); - cu->code_buffer.push_back(rel & 0xFF); + code_buffer_.push_back(0x70 | cc); + code_buffer_.push_back(rel & 0xFF); } else { DCHECK(entry->opcode == kX86Jcc32); - cu->code_buffer.push_back(0x0F); - cu->code_buffer.push_back(0x80 | cc); - cu->code_buffer.push_back(rel & 0xFF); - cu->code_buffer.push_back((rel >> 8) & 0xFF); - cu->code_buffer.push_back((rel >> 16) & 0xFF); - cu->code_buffer.push_back((rel >> 24) & 0xFF); + code_buffer_.push_back(0x0F); + code_buffer_.push_back(0x80 | cc); + code_buffer_.push_back(rel & 0xFF); + code_buffer_.push_back((rel >> 8) & 0xFF); + code_buffer_.push_back((rel >> 16) & 0xFF); + code_buffer_.push_back((rel >> 24) & 0xFF); } } -static void EmitCallMem(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t base, int disp) { +void X86Mir2Lir::EmitCallMem(const X86EncodingMap* entry, uint8_t base, int disp) { if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -1057,27 +1046,27 @@ static void EmitCallMem(CompilationUnit* cu, const X86EncodingMap* entry, DCHECK_EQ(0, entry->skeleton.extra_opcode2); } uint8_t modrm = (ModrmForDisp(base, disp) << 6) | (entry->skeleton.modrm_opcode << 3) | base; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); if (base == rX86_SP) { // Special SIB for SP base - cu->code_buffer.push_back(0 << 6 | (rX86_SP << 3) | rX86_SP); + code_buffer_.push_back(0 << 6 | (rX86_SP << 3) | rX86_SP); } - EmitDisp(cu, base, disp); + EmitDisp(base, disp); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitCallThread(CompilationUnit* cu, const X86EncodingMap* entry, int disp) { +void X86Mir2Lir::EmitCallThread(const X86EncodingMap* entry, int disp) { DCHECK_NE(entry->skeleton.prefix1, 0); - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.opcode == 0x0F) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode1 == 0x38 || entry->skeleton.extra_opcode2 == 0x3A) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); } @@ -1086,30 +1075,30 @@ static void EmitCallThread(CompilationUnit* cu, const X86EncodingMap* entry, int DCHECK_EQ(0, entry->skeleton.extra_opcode2); } uint8_t modrm = (0 << 6) | (entry->skeleton.modrm_opcode << 3) | rBP; - cu->code_buffer.push_back(modrm); - cu->code_buffer.push_back(disp & 0xFF); - cu->code_buffer.push_back((disp >> 8) & 0xFF); - cu->code_buffer.push_back((disp >> 16) & 0xFF); - cu->code_buffer.push_back((disp >> 24) & 0xFF); + code_buffer_.push_back(modrm); + code_buffer_.push_back(disp & 0xFF); + code_buffer_.push_back((disp >> 8) & 0xFF); + code_buffer_.push_back((disp >> 16) & 0xFF); + code_buffer_.push_back((disp >> 24) & 0xFF); DCHECK_EQ(0, entry->skeleton.ax_opcode); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } -static void EmitPcRel(CompilationUnit* cu, const X86EncodingMap* entry, uint8_t reg, +void X86Mir2Lir::EmitPcRel(const X86EncodingMap* entry, uint8_t reg, int base_or_table, uint8_t index, int scale, int table_or_disp) { int disp; if (entry->opcode == kX86PcRelLoadRA) { - Codegen::SwitchTable *tab_rec = reinterpret_cast<Codegen::SwitchTable*>(table_or_disp); + Mir2Lir::SwitchTable *tab_rec = reinterpret_cast<Mir2Lir::SwitchTable*>(table_or_disp); disp = tab_rec->offset; } else { DCHECK(entry->opcode == kX86PcRelAdr); - Codegen::FillArrayData *tab_rec = reinterpret_cast<Codegen::FillArrayData*>(base_or_table); + Mir2Lir::FillArrayData *tab_rec = reinterpret_cast<Mir2Lir::FillArrayData*>(base_or_table); disp = tab_rec->offset; } if (entry->skeleton.prefix1 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix1); + code_buffer_.push_back(entry->skeleton.prefix1); if (entry->skeleton.prefix2 != 0) { - cu->code_buffer.push_back(entry->skeleton.prefix2); + code_buffer_.push_back(entry->skeleton.prefix2); } } else { DCHECK_EQ(0, entry->skeleton.prefix2); @@ -1119,50 +1108,48 @@ static void EmitPcRel(CompilationUnit* cu, const X86EncodingMap* entry, uint8_t } DCHECK_LT(reg, 8); if (entry->opcode == kX86PcRelLoadRA) { - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); DCHECK_EQ(0, entry->skeleton.extra_opcode1); DCHECK_EQ(0, entry->skeleton.extra_opcode2); uint8_t modrm = (2 << 6) | (reg << 3) | rX86_SP; - cu->code_buffer.push_back(modrm); + code_buffer_.push_back(modrm); DCHECK_LT(scale, 4); DCHECK_LT(index, 8); DCHECK_LT(base_or_table, 8); uint8_t base = static_cast<uint8_t>(base_or_table); uint8_t sib = (scale << 6) | (index << 3) | base; - cu->code_buffer.push_back(sib); + code_buffer_.push_back(sib); DCHECK_EQ(0, entry->skeleton.immediate_bytes); } else { - cu->code_buffer.push_back(entry->skeleton.opcode + reg); + code_buffer_.push_back(entry->skeleton.opcode + reg); } - cu->code_buffer.push_back(disp & 0xFF); - cu->code_buffer.push_back((disp >> 8) & 0xFF); - cu->code_buffer.push_back((disp >> 16) & 0xFF); - cu->code_buffer.push_back((disp >> 24) & 0xFF); + code_buffer_.push_back(disp & 0xFF); + code_buffer_.push_back((disp >> 8) & 0xFF); + code_buffer_.push_back((disp >> 16) & 0xFF); + code_buffer_.push_back((disp >> 24) & 0xFF); DCHECK_EQ(0, entry->skeleton.modrm_opcode); DCHECK_EQ(0, entry->skeleton.ax_opcode); } -static void EmitMacro(CompilationUnit* cu, const X86EncodingMap* entry, - uint8_t reg, int offset) { +void X86Mir2Lir::EmitMacro(const X86EncodingMap* entry, uint8_t reg, int offset) { DCHECK(entry->opcode == kX86StartOfMethod) << entry->name; - cu->code_buffer.push_back(0xE8); // call +0 - cu->code_buffer.push_back(0); - cu->code_buffer.push_back(0); - cu->code_buffer.push_back(0); - cu->code_buffer.push_back(0); + code_buffer_.push_back(0xE8); // call +0 + code_buffer_.push_back(0); + code_buffer_.push_back(0); + code_buffer_.push_back(0); + code_buffer_.push_back(0); DCHECK_LT(reg, 8); - cu->code_buffer.push_back(0x58 + reg); // pop reg + code_buffer_.push_back(0x58 + reg); // pop reg - EmitRegImm(cu, &X86Codegen::EncodingMap[kX86Sub32RI], reg, offset + 5 /* size of call +0 */); + EmitRegImm(&X86Mir2Lir::EncodingMap[kX86Sub32RI], reg, offset + 5 /* size of call +0 */); } -static void EmitUnimplemented(CompilationUnit* cu, const X86EncodingMap* entry, LIR* lir) { - Codegen* cg = cu->cg.get(); +void X86Mir2Lir::EmitUnimplemented(const X86EncodingMap* entry, LIR* lir) { UNIMPLEMENTED(WARNING) << "encoding kind for " << entry->name << " " - << cg->BuildInsnString(entry->fmt, lir, 0); - for (int i = 0; i < cg->GetInsnSize(lir); ++i) { - cu->code_buffer.push_back(0xCC); // push breakpoint instruction - int 3 + << BuildInsnString(entry->fmt, lir, 0); + for (int i = 0; i < GetInsnSize(lir); ++i) { + code_buffer_.push_back(0xCC); // push breakpoint instruction - int 3 } } @@ -1172,12 +1159,12 @@ static void EmitUnimplemented(CompilationUnit* cu, const X86EncodingMap* entry, * instruction. In those cases we will try to substitute a new code * sequence or request that the trace be shortened and retried. */ -AssemblerStatus X86Codegen::AssembleInstructions(CompilationUnit *cu, uintptr_t start_addr) { +AssemblerStatus X86Mir2Lir::AssembleInstructions(uintptr_t start_addr) { LIR *lir; AssemblerStatus res = kSuccess; // Assume success const bool kVerbosePcFixup = false; - for (lir = cu->first_lir_insn; lir != NULL; lir = NEXT_LIR(lir)) { + for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) { if (lir->opcode < 0) { continue; } @@ -1206,14 +1193,14 @@ AssemblerStatus X86Codegen::AssembleInstructions(CompilationUnit *cu, uintptr_t << " delta: " << delta << " old delta: " << lir->operands[0]; } lir->opcode = kX86Jcc32; - SetupResourceMasks(cu, lir); + SetupResourceMasks(lir); res = kRetryAll; } if (kVerbosePcFixup) { LOG(INFO) << "Source:"; - DumpLIRInsn(cu, lir, 0); + DumpLIRInsn(lir, 0); LOG(INFO) << "Target:"; - DumpLIRInsn(cu, target_lir, 0); + DumpLIRInsn(target_lir, 0); LOG(INFO) << "Delta " << delta; } lir->operands[0] = delta; @@ -1227,9 +1214,9 @@ AssemblerStatus X86Codegen::AssembleInstructions(CompilationUnit *cu, uintptr_t int delta = target - pc; if (kVerbosePcFixup) { LOG(INFO) << "Source:"; - DumpLIRInsn(cu, lir, 0); + DumpLIRInsn(lir, 0); LOG(INFO) << "Target:"; - DumpLIRInsn(cu, target_lir, 0); + DumpLIRInsn(target_lir, 0); LOG(INFO) << "Delta " << delta; } lir->operands[0] = delta; @@ -1247,7 +1234,7 @@ AssemblerStatus X86Codegen::AssembleInstructions(CompilationUnit *cu, uintptr_t } uintptr_t target = target_lir->offset; delta = target - pc; - if (!(cu->disable_opt & (1 << kSafeOptimizations)) && delta == 0) { + if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && delta == 0) { // Useless branch lir->flags.is_nop = true; if (kVerbosePcFixup) { @@ -1259,7 +1246,7 @@ AssemblerStatus X86Codegen::AssembleInstructions(CompilationUnit *cu, uintptr_t LOG(INFO) << "Retry for JMP growth at " << lir->offset; } lir->opcode = kX86Jmp32; - SetupResourceMasks(cu, lir); + SetupResourceMasks(lir); res = kRetryAll; } lir->operands[0] = delta; @@ -1287,21 +1274,21 @@ AssemblerStatus X86Codegen::AssembleInstructions(CompilationUnit *cu, uintptr_t if (res != kSuccess) { continue; } - CHECK_EQ(static_cast<size_t>(lir->offset), cu->code_buffer.size()); - const X86EncodingMap *entry = &X86Codegen::EncodingMap[lir->opcode]; - size_t starting_cbuf_size = cu->code_buffer.size(); + CHECK_EQ(static_cast<size_t>(lir->offset), code_buffer_.size()); + const X86EncodingMap *entry = &X86Mir2Lir::EncodingMap[lir->opcode]; + size_t starting_cbuf_size = code_buffer_.size(); switch (entry->kind) { case kData: // 4 bytes of data - cu->code_buffer.push_back(lir->operands[0]); + code_buffer_.push_back(lir->operands[0]); break; case kNullary: // 1 byte of opcode DCHECK_EQ(0, entry->skeleton.prefix1); DCHECK_EQ(0, entry->skeleton.prefix2); - cu->code_buffer.push_back(entry->skeleton.opcode); + code_buffer_.push_back(entry->skeleton.opcode); if (entry->skeleton.extra_opcode1 != 0) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode1); + code_buffer_.push_back(entry->skeleton.extra_opcode1); if (entry->skeleton.extra_opcode2 != 0) { - cu->code_buffer.push_back(entry->skeleton.extra_opcode2); + code_buffer_.push_back(entry->skeleton.extra_opcode2); } } else { DCHECK_EQ(0, entry->skeleton.extra_opcode2); @@ -1311,88 +1298,88 @@ AssemblerStatus X86Codegen::AssembleInstructions(CompilationUnit *cu, uintptr_t DCHECK_EQ(0, entry->skeleton.immediate_bytes); break; case kReg: // lir operands - 0: reg - EmitOpReg(cu, entry, lir->operands[0]); + EmitOpReg(entry, lir->operands[0]); break; case kMem: // lir operands - 0: base, 1: disp - EmitOpMem(cu, entry, lir->operands[0], lir->operands[1]); + EmitOpMem(entry, lir->operands[0], lir->operands[1]); break; case kMemReg: // lir operands - 0: base, 1: disp, 2: reg - EmitMemReg(cu, entry, lir->operands[0], lir->operands[1], lir->operands[2]); + EmitMemReg(entry, lir->operands[0], lir->operands[1], lir->operands[2]); break; case kArrayReg: // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg - EmitArrayReg(cu, entry, lir->operands[0], lir->operands[1], lir->operands[2], + EmitArrayReg(entry, lir->operands[0], lir->operands[1], lir->operands[2], lir->operands[3], lir->operands[4]); break; case kRegMem: // lir operands - 0: reg, 1: base, 2: disp - EmitRegMem(cu, entry, lir->operands[0], lir->operands[1], lir->operands[2]); + EmitRegMem(entry, lir->operands[0], lir->operands[1], lir->operands[2]); break; case kRegArray: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp - EmitRegArray(cu, entry, lir->operands[0], lir->operands[1], lir->operands[2], + EmitRegArray(entry, lir->operands[0], lir->operands[1], lir->operands[2], lir->operands[3], lir->operands[4]); break; case kRegThread: // lir operands - 0: reg, 1: disp - EmitRegThread(cu, entry, lir->operands[0], lir->operands[1]); + EmitRegThread(entry, lir->operands[0], lir->operands[1]); break; case kRegReg: // lir operands - 0: reg1, 1: reg2 - EmitRegReg(cu, entry, lir->operands[0], lir->operands[1]); + EmitRegReg(entry, lir->operands[0], lir->operands[1]); break; case kRegRegStore: // lir operands - 0: reg2, 1: reg1 - EmitRegReg(cu, entry, lir->operands[1], lir->operands[0]); + EmitRegReg(entry, lir->operands[1], lir->operands[0]); break; case kRegRegImm: - EmitRegRegImm(cu, entry, lir->operands[0], lir->operands[1], lir->operands[2]); + EmitRegRegImm(entry, lir->operands[0], lir->operands[1], lir->operands[2]); break; case kRegImm: // lir operands - 0: reg, 1: immediate - EmitRegImm(cu, entry, lir->operands[0], lir->operands[1]); + EmitRegImm(entry, lir->operands[0], lir->operands[1]); break; case kThreadImm: // lir operands - 0: disp, 1: immediate - EmitThreadImm(cu, entry, lir->operands[0], lir->operands[1]); + EmitThreadImm(entry, lir->operands[0], lir->operands[1]); break; case kMovRegImm: // lir operands - 0: reg, 1: immediate - EmitMovRegImm(cu, entry, lir->operands[0], lir->operands[1]); + EmitMovRegImm(entry, lir->operands[0], lir->operands[1]); break; case kShiftRegImm: // lir operands - 0: reg, 1: immediate - EmitShiftRegImm(cu, entry, lir->operands[0], lir->operands[1]); + EmitShiftRegImm(entry, lir->operands[0], lir->operands[1]); break; case kShiftRegCl: // lir operands - 0: reg, 1: cl - EmitShiftRegCl(cu, entry, lir->operands[0], lir->operands[1]); + EmitShiftRegCl(entry, lir->operands[0], lir->operands[1]); break; case kRegCond: // lir operands - 0: reg, 1: condition - EmitRegCond(cu, entry, lir->operands[0], lir->operands[1]); + EmitRegCond(entry, lir->operands[0], lir->operands[1]); break; case kJmp: // lir operands - 0: rel - EmitJmp(cu, entry, lir->operands[0]); + EmitJmp(entry, lir->operands[0]); break; case kJcc: // lir operands - 0: rel, 1: CC, target assigned - EmitJcc(cu, entry, lir->operands[0], lir->operands[1]); + EmitJcc(entry, lir->operands[0], lir->operands[1]); break; case kCall: switch (entry->opcode) { case kX86CallM: // lir operands - 0: base, 1: disp - EmitCallMem(cu, entry, lir->operands[0], lir->operands[1]); + EmitCallMem(entry, lir->operands[0], lir->operands[1]); break; case kX86CallT: // lir operands - 0: disp - EmitCallThread(cu, entry, lir->operands[0]); + EmitCallThread(entry, lir->operands[0]); break; default: - EmitUnimplemented(cu, entry, lir); + EmitUnimplemented(entry, lir); break; } break; case kPcRel: // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table - EmitPcRel(cu, entry, lir->operands[0], lir->operands[1], lir->operands[2], + EmitPcRel(entry, lir->operands[0], lir->operands[1], lir->operands[2], lir->operands[3], lir->operands[4]); break; case kMacro: - EmitMacro(cu, entry, lir->operands[0], lir->offset); + EmitMacro(entry, lir->operands[0], lir->offset); break; default: - EmitUnimplemented(cu, entry, lir); + EmitUnimplemented(entry, lir); break; } CHECK_EQ(static_cast<size_t>(GetInsnSize(lir)), - cu->code_buffer.size() - starting_cbuf_size) - << "Instruction size mismatch for entry: " << X86Codegen::EncodingMap[lir->opcode].name; + code_buffer_.size() - starting_cbuf_size) + << "Instruction size mismatch for entry: " << X86Mir2Lir::EncodingMap[lir->opcode].name; } return res; } diff --git a/src/compiler/dex/quick/x86/call_x86.cc b/src/compiler/dex/quick/x86/call_x86.cc index f30e966fb8..6b215f2b9c 100644 --- a/src/compiler/dex/quick/x86/call_x86.cc +++ b/src/compiler/dex/quick/x86/call_x86.cc @@ -17,13 +17,11 @@ /* This file contains codegen for the X86 ISA */ #include "codegen_x86.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "x86_lir.h" namespace art { -void X86Codegen::GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, +void X86Mir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, SpecialCaseHandler special_case) { // TODO @@ -33,24 +31,23 @@ void X86Codegen::GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, * The sparse table in the literal pool is an array of <key,displacement> * pairs. */ -void X86Codegen::GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, +void X86Mir2Lir::GenSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; - if (cu->verbose) { + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + if (cu_->verbose) { DumpSparseSwitchTable(table); } int entries = table[1]; const int* keys = reinterpret_cast<const int*>(&table[2]); const int* targets = &keys[entries]; - rl_src = LoadValue(cu, rl_src, kCoreReg); + rl_src = LoadValue(rl_src, kCoreReg); for (int i = 0; i < entries; i++) { int key = keys[i]; BasicBlock* case_block = - cu->mir_graph.get()->FindBlock(cu->current_dalvik_offset + targets[i]); - LIR* label_list = cu->block_label_list; - OpCmpImmBranch(cu, kCondEq, rl_src.low_reg, key, - &label_list[case_block->id]); + mir_graph_->FindBlock(current_dalvik_offset_ + targets[i]); + OpCmpImmBranch(kCondEq, rl_src.low_reg, key, + &block_label_list_[case_block->id]); } } @@ -70,53 +67,53 @@ void X86Codegen::GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_o * jmp r_start_of_method * done: */ -void X86Codegen::GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, +void X86Mir2Lir::GenPackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; - if (cu->verbose) { + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + if (cu_->verbose) { DumpPackedSwitchTable(table); } // Add the table to the list - we'll process it later SwitchTable *tab_rec = - static_cast<SwitchTable *>(NewMem(cu, sizeof(SwitchTable), true, kAllocData)); + static_cast<SwitchTable *>(NewMem(cu_, sizeof(SwitchTable), true, kAllocData)); tab_rec->table = table; - tab_rec->vaddr = cu->current_dalvik_offset; + tab_rec->vaddr = current_dalvik_offset_; int size = table[1]; - tab_rec->targets = static_cast<LIR**>(NewMem(cu, size * sizeof(LIR*), true, kAllocLIR)); - InsertGrowableList(cu, &cu->switch_tables, reinterpret_cast<uintptr_t>(tab_rec)); + tab_rec->targets = static_cast<LIR**>(NewMem(cu_, size * sizeof(LIR*), true, kAllocLIR)); + InsertGrowableList(cu_, &switch_tables_, reinterpret_cast<uintptr_t>(tab_rec)); // Get the switch value - rl_src = LoadValue(cu, rl_src, kCoreReg); - int start_of_method_reg = AllocTemp(cu); + rl_src = LoadValue(rl_src, kCoreReg); + int start_of_method_reg = AllocTemp(); // Materialize a pointer to the switch table - //NewLIR0(cu, kX86Bkpt); - NewLIR1(cu, kX86StartOfMethod, start_of_method_reg); + //NewLIR0(kX86Bkpt); + NewLIR1(kX86StartOfMethod, start_of_method_reg); int low_key = s4FromSwitchData(&table[2]); int keyReg; // Remove the bias, if necessary if (low_key == 0) { keyReg = rl_src.low_reg; } else { - keyReg = AllocTemp(cu); - OpRegRegImm(cu, kOpSub, keyReg, rl_src.low_reg, low_key); + keyReg = AllocTemp(); + OpRegRegImm(kOpSub, keyReg, rl_src.low_reg, low_key); } // Bounds check - if < 0 or >= size continue following switch - OpRegImm(cu, kOpCmp, keyReg, size-1); - LIR* branch_over = OpCondBranch(cu, kCondHi, NULL); + OpRegImm(kOpCmp, keyReg, size-1); + LIR* branch_over = OpCondBranch(kCondHi, NULL); // Load the displacement from the switch table - int disp_reg = AllocTemp(cu); - NewLIR5(cu, kX86PcRelLoadRA, disp_reg, start_of_method_reg, keyReg, 2, + int disp_reg = AllocTemp(); + NewLIR5(kX86PcRelLoadRA, disp_reg, start_of_method_reg, keyReg, 2, reinterpret_cast<uintptr_t>(tab_rec)); // Add displacement to start of method - OpRegReg(cu, kOpAdd, start_of_method_reg, disp_reg); + OpRegReg(kOpAdd, start_of_method_reg, disp_reg); // ..and go! - LIR* switch_branch = NewLIR1(cu, kX86JmpR, start_of_method_reg); + LIR* switch_branch = NewLIR1(kX86JmpR, start_of_method_reg); tab_rec->anchor = switch_branch; /* branch_over target here */ - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); branch_over->target = target; } @@ -130,98 +127,98 @@ void X86Codegen::GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_o * * Total size is 4+(width * size + 1)/2 16-bit code units. */ -void X86Codegen::GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, RegLocation rl_src) +void X86Mir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset; + const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; // Add the table to the list - we'll process it later FillArrayData *tab_rec = - static_cast<FillArrayData*>(NewMem(cu, sizeof(FillArrayData), true, kAllocData)); + static_cast<FillArrayData*>(NewMem(cu_, sizeof(FillArrayData), true, kAllocData)); tab_rec->table = table; - tab_rec->vaddr = cu->current_dalvik_offset; + tab_rec->vaddr = current_dalvik_offset_; uint16_t width = tab_rec->table[1]; uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16); tab_rec->size = (size * width) + 8; - InsertGrowableList(cu, &cu->fill_array_data, reinterpret_cast<uintptr_t>(tab_rec)); + InsertGrowableList(cu_, &fill_array_data_, reinterpret_cast<uintptr_t>(tab_rec)); // Making a call - use explicit registers - FlushAllRegs(cu); /* Everything to home location */ - LoadValueDirectFixed(cu, rl_src, rX86_ARG0); + FlushAllRegs(); /* Everything to home location */ + LoadValueDirectFixed(rl_src, rX86_ARG0); // Materialize a pointer to the fill data image - NewLIR1(cu, kX86StartOfMethod, rX86_ARG2); - NewLIR2(cu, kX86PcRelAdr, rX86_ARG1, reinterpret_cast<uintptr_t>(tab_rec)); - NewLIR2(cu, kX86Add32RR, rX86_ARG1, rX86_ARG2); - CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), rX86_ARG0, + NewLIR1(kX86StartOfMethod, rX86_ARG2); + NewLIR2(kX86PcRelAdr, rX86_ARG1, reinterpret_cast<uintptr_t>(tab_rec)); + NewLIR2(kX86Add32RR, rX86_ARG1, rX86_ARG2); + CallRuntimeHelperRegReg(ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), rX86_ARG0, rX86_ARG1, true); } -void X86Codegen::GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation rl_src) +void X86Mir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) { - FlushAllRegs(cu); - LoadValueDirectFixed(cu, rl_src, rCX); // Get obj - LockCallTemps(cu); // Prepare for explicit register usage - GenNullCheck(cu, rl_src.s_reg_low, rCX, opt_flags); + FlushAllRegs(); + LoadValueDirectFixed(rl_src, rCX); // Get obj + LockCallTemps(); // Prepare for explicit register usage + GenNullCheck(rl_src.s_reg_low, rCX, opt_flags); // If lock is unheld, try to grab it quickly with compare and exchange // TODO: copy and clear hash state? - NewLIR2(cu, kX86Mov32RT, rDX, Thread::ThinLockIdOffset().Int32Value()); - NewLIR2(cu, kX86Sal32RI, rDX, LW_LOCK_OWNER_SHIFT); - NewLIR2(cu, kX86Xor32RR, rAX, rAX); - NewLIR3(cu, kX86LockCmpxchgMR, rCX, mirror::Object::MonitorOffset().Int32Value(), rDX); - LIR* branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondEq); + NewLIR2(kX86Mov32RT, rDX, Thread::ThinLockIdOffset().Int32Value()); + NewLIR2(kX86Sal32RI, rDX, LW_LOCK_OWNER_SHIFT); + NewLIR2(kX86Xor32RR, rAX, rAX); + NewLIR3(kX86LockCmpxchgMR, rCX, mirror::Object::MonitorOffset().Int32Value(), rDX); + LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondEq); // If lock is held, go the expensive route - artLockObjectFromCode(self, obj); - CallRuntimeHelperReg(cu, ENTRYPOINT_OFFSET(pLockObjectFromCode), rCX, true); - branch->target = NewLIR0(cu, kPseudoTargetLabel); + CallRuntimeHelperReg(ENTRYPOINT_OFFSET(pLockObjectFromCode), rCX, true); + branch->target = NewLIR0(kPseudoTargetLabel); } -void X86Codegen::GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation rl_src) +void X86Mir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) { - FlushAllRegs(cu); - LoadValueDirectFixed(cu, rl_src, rAX); // Get obj - LockCallTemps(cu); // Prepare for explicit register usage - GenNullCheck(cu, rl_src.s_reg_low, rAX, opt_flags); + FlushAllRegs(); + LoadValueDirectFixed(rl_src, rAX); // Get obj + LockCallTemps(); // Prepare for explicit register usage + GenNullCheck(rl_src.s_reg_low, rAX, opt_flags); // If lock is held by the current thread, clear it to quickly release it // TODO: clear hash state? - NewLIR2(cu, kX86Mov32RT, rDX, Thread::ThinLockIdOffset().Int32Value()); - NewLIR2(cu, kX86Sal32RI, rDX, LW_LOCK_OWNER_SHIFT); - NewLIR3(cu, kX86Mov32RM, rCX, rAX, mirror::Object::MonitorOffset().Int32Value()); - OpRegReg(cu, kOpSub, rCX, rDX); - LIR* branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondNe); - NewLIR3(cu, kX86Mov32MR, rAX, mirror::Object::MonitorOffset().Int32Value(), rCX); - LIR* branch2 = NewLIR1(cu, kX86Jmp8, 0); - branch->target = NewLIR0(cu, kPseudoTargetLabel); + NewLIR2(kX86Mov32RT, rDX, Thread::ThinLockIdOffset().Int32Value()); + NewLIR2(kX86Sal32RI, rDX, LW_LOCK_OWNER_SHIFT); + NewLIR3(kX86Mov32RM, rCX, rAX, mirror::Object::MonitorOffset().Int32Value()); + OpRegReg(kOpSub, rCX, rDX); + LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondNe); + NewLIR3(kX86Mov32MR, rAX, mirror::Object::MonitorOffset().Int32Value(), rCX); + LIR* branch2 = NewLIR1(kX86Jmp8, 0); + branch->target = NewLIR0(kPseudoTargetLabel); // Otherwise, go the expensive route - UnlockObjectFromCode(obj); - CallRuntimeHelperReg(cu, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rAX, true); - branch2->target = NewLIR0(cu, kPseudoTargetLabel); + CallRuntimeHelperReg(ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rAX, true); + branch2->target = NewLIR0(kPseudoTargetLabel); } -void X86Codegen::GenMoveException(CompilationUnit* cu, RegLocation rl_dest) +void X86Mir2Lir::GenMoveException(RegLocation rl_dest) { int ex_offset = Thread::ExceptionOffset().Int32Value(); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - NewLIR2(cu, kX86Mov32RT, rl_result.low_reg, ex_offset); - NewLIR2(cu, kX86Mov32TI, ex_offset, 0); - StoreValue(cu, rl_dest, rl_result); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + NewLIR2(kX86Mov32RT, rl_result.low_reg, ex_offset); + NewLIR2(kX86Mov32TI, ex_offset, 0); + StoreValue(rl_dest, rl_result); } /* * Mark garbage collection card. Skip if the value we're storing is null. */ -void X86Codegen::MarkGCCard(CompilationUnit* cu, int val_reg, int tgt_addr_reg) +void X86Mir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg) { - int reg_card_base = AllocTemp(cu); - int reg_card_no = AllocTemp(cu); - LIR* branch_over = OpCmpImmBranch(cu, kCondEq, val_reg, 0, NULL); - NewLIR2(cu, kX86Mov32RT, reg_card_base, Thread::CardTableOffset().Int32Value()); - OpRegRegImm(cu, kOpLsr, reg_card_no, tgt_addr_reg, CardTable::kCardShift); - StoreBaseIndexed(cu, reg_card_base, reg_card_no, reg_card_base, 0, + int reg_card_base = AllocTemp(); + int reg_card_no = AllocTemp(); + LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL); + NewLIR2(kX86Mov32RT, reg_card_base, Thread::CardTableOffset().Int32Value()); + OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, CardTable::kCardShift); + StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte); - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); branch_over->target = target; - FreeTemp(cu, reg_card_base); - FreeTemp(cu, reg_card_no); + FreeTemp(reg_card_base); + FreeTemp(reg_card_no); } -void X86Codegen::GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl_method) +void X86Mir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) { /* * On entry, rX86_ARG0, rX86_ARG1, rX86_ARG2 are live. Let the register @@ -229,54 +226,54 @@ void X86Codegen::GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, Reg * expanding the frame or flushing. This leaves the utility * code with no spare temps. */ - LockTemp(cu, rX86_ARG0); - LockTemp(cu, rX86_ARG1); - LockTemp(cu, rX86_ARG2); + LockTemp(rX86_ARG0); + LockTemp(rX86_ARG1); + LockTemp(rX86_ARG2); /* Build frame, return address already on stack */ - OpRegImm(cu, kOpSub, rX86_SP, cu->frame_size - 4); + OpRegImm(kOpSub, rX86_SP, frame_size_ - 4); /* * We can safely skip the stack overflow check if we're * a leaf *and* our frame size < fudge factor. */ - bool skip_overflow_check = ((cu->attributes & METHOD_IS_LEAF) && - (static_cast<size_t>(cu->frame_size) < + bool skip_overflow_check = (mir_graph_->MethodIsLeaf() && + (static_cast<size_t>(frame_size_) < Thread::kStackOverflowReservedBytes)); - NewLIR0(cu, kPseudoMethodEntry); + NewLIR0(kPseudoMethodEntry); /* Spill core callee saves */ - SpillCoreRegs(cu); + SpillCoreRegs(); /* NOTE: promotion of FP regs currently unsupported, thus no FP spill */ - DCHECK_EQ(cu->num_fp_spills, 0); + DCHECK_EQ(num_fp_spills_, 0); if (!skip_overflow_check) { // cmp rX86_SP, fs:[stack_end_]; jcc throw_launchpad - LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kThrowStackOverflow, 0, 0, 0, 0); - OpRegThreadMem(cu, kOpCmp, rX86_SP, Thread::StackEndOffset().Int32Value()); - OpCondBranch(cu, kCondUlt, tgt); + LIR* tgt = RawLIR(0, kPseudoThrowTarget, kThrowStackOverflow, 0, 0, 0, 0); + OpRegThreadMem(kOpCmp, rX86_SP, Thread::StackEndOffset().Int32Value()); + OpCondBranch(kCondUlt, tgt); // Remember branch target - will process later - InsertGrowableList(cu, &cu->throw_launchpads, reinterpret_cast<uintptr_t>(tgt)); + InsertGrowableList(cu_, &throw_launchpads_, reinterpret_cast<uintptr_t>(tgt)); } - FlushIns(cu, ArgLocs, rl_method); + FlushIns(ArgLocs, rl_method); - FreeTemp(cu, rX86_ARG0); - FreeTemp(cu, rX86_ARG1); - FreeTemp(cu, rX86_ARG2); + FreeTemp(rX86_ARG0); + FreeTemp(rX86_ARG1); + FreeTemp(rX86_ARG2); } -void X86Codegen::GenExitSequence(CompilationUnit* cu) { +void X86Mir2Lir::GenExitSequence() { /* * In the exit path, rX86_RET0/rX86_RET1 are live - make sure they aren't * allocated by the register utilities as temps. */ - LockTemp(cu, rX86_RET0); - LockTemp(cu, rX86_RET1); + LockTemp(rX86_RET0); + LockTemp(rX86_RET1); - NewLIR0(cu, kPseudoMethodExit); - UnSpillCoreRegs(cu); + NewLIR0(kPseudoMethodExit); + UnSpillCoreRegs(); /* Remove frame except for return address */ - OpRegImm(cu, kOpAdd, rX86_SP, cu->frame_size - 4); - NewLIR0(cu, kX86Ret); + OpRegImm(kOpAdd, rX86_SP, frame_size_ - 4); + NewLIR0(kX86Ret); } } // namespace art diff --git a/src/compiler/dex/quick/x86/codegen_x86.h b/src/compiler/dex/quick/x86/codegen_x86.h index 35c976a4fb..93b6839566 100644 --- a/src/compiler/dex/quick/x86/codegen_x86.h +++ b/src/compiler/dex/quick/x86/codegen_x86.h @@ -22,64 +22,60 @@ namespace art { -class X86Codegen : public Codegen { +class X86Mir2Lir : public Mir2Lir { public: + + X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph); + // Required for target - codegen helpers. - virtual bool SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode, - RegLocation rl_src, RegLocation rl_dest, int lit); - virtual int LoadHelper(CompilationUnit* cu, int offset); - virtual LIR* LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest, - OpSize size, int s_reg); - virtual LIR* LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo, - int r_dest_hi, int s_reg); - virtual LIR* LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest, int scale, - OpSize size); - virtual LIR* LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, - int displacement, int r_dest, int r_dest_hi, OpSize size, - int s_reg); - virtual LIR* LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value); - virtual LIR* LoadConstantWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi, int64_t value); - virtual LIR* StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src, - OpSize size); - virtual LIR* StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_src_lo, - int r_src_hi); - virtual LIR* StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src, int scale, - OpSize size); - virtual LIR* StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, - int displacement, int r_src, int r_src_hi, OpSize size, - int s_reg); - virtual void MarkGCCard(CompilationUnit* cu, int val_reg, int tgt_addr_reg); + virtual bool SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src, + RegLocation rl_dest, int lit); + virtual int LoadHelper(int offset); + virtual LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg); + virtual LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi, + int s_reg); + virtual LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size); + virtual LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_dest, int r_dest_hi, OpSize size, int s_reg); + virtual LIR* LoadConstantNoClobber(int r_dest, int value); + virtual LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value); + virtual LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size); + virtual LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi); + virtual LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size); + virtual LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, + int r_src, int r_src_hi, OpSize size, int s_reg); + virtual void MarkGCCard(int val_reg, int tgt_addr_reg); // Required for target - register utilities. virtual bool IsFpReg(int reg); virtual bool SameRegType(int reg1, int reg2); - virtual int AllocTypedTemp(CompilationUnit* cu, bool fp_hint, int reg_class); - virtual int AllocTypedTempPair(CompilationUnit* cu, bool fp_hint, int reg_class); + virtual int AllocTypedTemp(bool fp_hint, int reg_class); + virtual int AllocTypedTempPair(bool fp_hint, int reg_class); virtual int S2d(int low_reg, int high_reg); virtual int TargetReg(SpecialTargetRegister reg); - virtual RegisterInfo* GetRegInfo(CompilationUnit* cu, int reg); - virtual RegLocation GetReturnAlt(CompilationUnit* cu); - virtual RegLocation GetReturnWideAlt(CompilationUnit* cu); + virtual RegisterInfo* GetRegInfo(int reg); + virtual RegLocation GetReturnAlt(); + virtual RegLocation GetReturnWideAlt(); virtual RegLocation LocCReturn(); virtual RegLocation LocCReturnDouble(); virtual RegLocation LocCReturnFloat(); virtual RegLocation LocCReturnWide(); virtual uint32_t FpRegMask(); - virtual uint64_t GetRegMaskCommon(CompilationUnit* cu, int reg); - virtual void AdjustSpillMask(CompilationUnit* cu); - virtual void ClobberCalleeSave(CompilationUnit *cu); - virtual void FlushReg(CompilationUnit* cu, int reg); - virtual void FlushRegWide(CompilationUnit* cu, int reg1, int reg2); - virtual void FreeCallTemps(CompilationUnit* cu); - virtual void FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, RegLocation rl_free); - virtual void LockCallTemps(CompilationUnit* cu); - virtual void MarkPreservedSingle(CompilationUnit* cu, int v_reg, int reg); - virtual void CompilerInitializeRegAlloc(CompilationUnit* cu); + virtual uint64_t GetRegMaskCommon(int reg); + virtual void AdjustSpillMask(); + virtual void ClobberCalleeSave(); + virtual void FlushReg(int reg); + virtual void FlushRegWide(int reg1, int reg2); + virtual void FreeCallTemps(); + virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free); + virtual void LockCallTemps(); + virtual void MarkPreservedSingle(int v_reg, int reg); + virtual void CompilerInitializeRegAlloc(); // Required for target - miscellaneous. - virtual AssemblerStatus AssembleInstructions(CompilationUnit* cu, uintptr_t start_addr); + virtual AssemblerStatus AssembleInstructions(uintptr_t start_addr); virtual void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix); - virtual void SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir); + virtual void SetupTargetResourceMasks(LIR* lir); virtual const char* GetTargetInstFmt(int opcode); virtual const char* GetTargetInstName(int opcode); virtual std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr); @@ -89,115 +85,119 @@ class X86Codegen : public Codegen { virtual bool IsUnconditionalBranch(LIR* lir); // Required for target - Dalvik-level generators. - virtual void GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, + virtual void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); - virtual void GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, + virtual void GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale); - virtual void GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, + virtual void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale); - virtual void GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, + virtual void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale); - virtual void GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_shift); - virtual void GenMulLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenAndLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenArithOpDouble(CompilationUnit* cu, Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest, + virtual void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_shift); + virtual void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenAndLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, + RegLocation rl_src1, RegLocation rl_src2); + virtual void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); - virtual void GenCmpFP(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); - virtual void GenConversion(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src); - virtual bool GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier); - virtual bool GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min); - virtual bool GenInlinedSqrt(CompilationUnit* cu, CallInfo* info); - virtual void GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenOrLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenXorLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual LIR* GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code, int reg1, int base, - int offset, ThrowKind kind); - virtual RegLocation GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int reg_hi, - bool is_div); - virtual RegLocation GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, int lit, - bool is_div); - virtual void GenCmpLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - virtual void GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi); - virtual void GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, - RegLocation rl_method); - virtual void GenExitSequence(CompilationUnit* cu); - virtual void GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, - RegLocation rl_src); - virtual void GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, bool gt_bias, - bool is_double); - virtual void GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir); - virtual void GenSelect(CompilationUnit* cu, BasicBlock* bb, MIR* mir); - virtual void GenMemBarrier(CompilationUnit* cu, MemBarrierKind barrier_kind); - virtual void GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation rl_src); - virtual void GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation rl_src); - virtual void GenMoveException(CompilationUnit* cu, RegLocation rl_dest); - virtual void GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src, - RegLocation rl_result, int lit, int first_bit, - int second_bit); - virtual void GenNegDouble(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenNegFloat(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src); - virtual void GenPackedSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, - RegLocation rl_src); - virtual void GenSparseSwitch(CompilationUnit* cu, MIR* mir, uint32_t table_offset, - RegLocation rl_src); - virtual void GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir, - SpecialCaseHandler special_case); + virtual void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2); + virtual void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src); + virtual bool GenInlinedCas32(CallInfo* info, bool need_write_barrier); + virtual bool GenInlinedMinMaxInt(CallInfo* info, bool is_min); + virtual bool GenInlinedSqrt(CallInfo* info); + virtual void GenNegLong(RegLocation rl_dest, RegLocation rl_src); + virtual void GenOrLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenXorLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset, + ThrowKind kind); + virtual RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div); + virtual RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div); + virtual void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + virtual void GenDivZeroCheck(int reg_lo, int reg_hi); + virtual void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method); + virtual void GenExitSequence(); + virtual void GenFillArrayData(uint32_t table_offset, RegLocation rl_src); + virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double); + virtual void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir); + virtual void GenSelect(BasicBlock* bb, MIR* mir); + virtual void GenMemBarrier(MemBarrierKind barrier_kind); + virtual void GenMonitorEnter(int opt_flags, RegLocation rl_src); + virtual void GenMonitorExit(int opt_flags, RegLocation rl_src); + virtual void GenMoveException(RegLocation rl_dest); + virtual void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, + int lit, int first_bit, int second_bit); + virtual void GenNegDouble(RegLocation rl_dest, RegLocation rl_src); + virtual void GenNegFloat(RegLocation rl_dest, RegLocation rl_src); + virtual void GenPackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src); + virtual void GenSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src); + virtual void GenSpecialCase(BasicBlock* bb, MIR* mir, SpecialCaseHandler special_case); // Single operation generators. - virtual LIR* OpUnconditionalBranch(CompilationUnit* cu, LIR* target); - virtual LIR* OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, int src2, - LIR* target); - virtual LIR* OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg, int check_value, - LIR* target); - virtual LIR* OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target); - virtual LIR* OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, - LIR* target); - virtual LIR* OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpIT(CompilationUnit* cu, ConditionCode cond, const char* guide); - virtual LIR* OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp); - virtual LIR* OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target); - virtual LIR* OpReg(CompilationUnit* cu, OpKind op, int r_dest_src); - virtual LIR* OpRegCopy(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpRegCopyNoInsert(CompilationUnit* cu, int r_dest, int r_src); - virtual LIR* OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value); - virtual LIR* OpRegMem(CompilationUnit* cu, OpKind op, int r_dest, int rBase, int offset); - virtual LIR* OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2); - virtual LIR* OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value); - virtual LIR* OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, - int r_src2); - virtual LIR* OpTestSuspend(CompilationUnit* cu, LIR* target); - virtual LIR* OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset); - virtual LIR* OpVldm(CompilationUnit* cu, int rBase, int count); - virtual LIR* OpVstm(CompilationUnit* cu, int rBase, int count); - virtual void OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, - int offset); - virtual void OpRegCopyWide(CompilationUnit* cu, int dest_lo, int dest_hi, int src_lo, - int src_hi); - virtual void OpTlsCmp(CompilationUnit* cu, int offset, int val); + virtual LIR* OpUnconditionalBranch(LIR* target); + virtual LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target); + virtual LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target); + virtual LIR* OpCondBranch(ConditionCode cc, LIR* target); + virtual LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target); + virtual LIR* OpFpRegCopy(int r_dest, int r_src); + virtual LIR* OpIT(ConditionCode cond, const char* guide); + virtual LIR* OpMem(OpKind op, int rBase, int disp); + virtual LIR* OpPcRelLoad(int reg, LIR* target); + virtual LIR* OpReg(OpKind op, int r_dest_src); + virtual LIR* OpRegCopy(int r_dest, int r_src); + virtual LIR* OpRegCopyNoInsert(int r_dest, int r_src); + virtual LIR* OpRegImm(OpKind op, int r_dest_src1, int value); + virtual LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset); + virtual LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2); + virtual LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value); + virtual LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2); + virtual LIR* OpTestSuspend(LIR* target); + virtual LIR* OpThreadMem(OpKind op, int thread_offset); + virtual LIR* OpVldm(int rBase, int count); + virtual LIR* OpVstm(int rBase, int count); + virtual void OpLea(int rBase, int reg1, int reg2, int scale, int offset); + virtual void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi); + virtual void OpTlsCmp(int offset, int val); - void OpRegThreadMem(CompilationUnit* cu, OpKind op, int r_dest, int thread_offset); - void SpillCoreRegs(CompilationUnit* cu); - void UnSpillCoreRegs(CompilationUnit* cu); + void OpRegThreadMem(OpKind op, int r_dest, int thread_offset); + void SpillCoreRegs(); + void UnSpillCoreRegs(); static const X86EncodingMap EncodingMap[kX86Last]; bool InexpensiveConstantInt(int32_t value); bool InexpensiveConstantFloat(int32_t value); bool InexpensiveConstantLong(int64_t value); bool InexpensiveConstantDouble(int64_t value); + + private: + void EmitDisp(int base, int disp); + void EmitOpReg(const X86EncodingMap* entry, uint8_t reg); + void EmitOpMem(const X86EncodingMap* entry, uint8_t base, int disp); + void EmitMemReg(const X86EncodingMap* entry, uint8_t base, int disp, uint8_t reg); + void EmitRegMem(const X86EncodingMap* entry, uint8_t reg, uint8_t base, int disp); + void EmitRegArray(const X86EncodingMap* entry, uint8_t reg, uint8_t base, uint8_t index, + int scale, int disp); + void EmitArrayReg(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp, + uint8_t reg); + void EmitRegThread(const X86EncodingMap* entry, uint8_t reg, int disp); + void EmitRegReg(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2); + void EmitRegRegImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm); + void EmitRegImm(const X86EncodingMap* entry, uint8_t reg, int imm); + void EmitThreadImm(const X86EncodingMap* entry, int disp, int imm); + void EmitMovRegImm(const X86EncodingMap* entry, uint8_t reg, int imm); + void EmitShiftRegImm(const X86EncodingMap* entry, uint8_t reg, int imm); + void EmitShiftRegCl(const X86EncodingMap* entry, uint8_t reg, uint8_t cl); + void EmitRegCond(const X86EncodingMap* entry, uint8_t reg, uint8_t condition); + void EmitJmp(const X86EncodingMap* entry, int rel); + void EmitJcc(const X86EncodingMap* entry, int rel, uint8_t cc); + void EmitCallMem(const X86EncodingMap* entry, uint8_t base, int disp); + void EmitCallThread(const X86EncodingMap* entry, int disp); + void EmitPcRel(const X86EncodingMap* entry, uint8_t reg, int base_or_table, uint8_t index, + int scale, int table_or_disp); + void EmitMacro(const X86EncodingMap* entry, uint8_t reg, int offset); + void EmitUnimplemented(const X86EncodingMap* entry, LIR* lir); }; } // namespace art diff --git a/src/compiler/dex/quick/x86/fp_x86.cc b/src/compiler/dex/quick/x86/fp_x86.cc index 888a4a6c84..db2cf289d8 100644 --- a/src/compiler/dex/quick/x86/fp_x86.cc +++ b/src/compiler/dex/quick/x86/fp_x86.cc @@ -15,13 +15,11 @@ */ #include "codegen_x86.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "x86_lir.h" namespace art { -void X86Codegen::GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode, +void X86Mir2Lir::GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { X86OpCode op = kX86Nop; RegLocation rl_result; @@ -49,33 +47,33 @@ void X86Codegen::GenArithOpFloat(CompilationUnit *cu, Instruction::Code opcode, break; case Instruction::REM_FLOAT_2ADDR: case Instruction::REM_FLOAT: - FlushAllRegs(cu); // Send everything to home location - CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false); - rl_result = GetReturn(cu, true); - StoreValue(cu, rl_dest, rl_result); + FlushAllRegs(); // Send everything to home location + CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmodf), rl_src1, rl_src2, false); + rl_result = GetReturn(true); + StoreValue(rl_dest, rl_result); return; case Instruction::NEG_FLOAT: - GenNegFloat(cu, rl_dest, rl_src1); + GenNegFloat(rl_dest, rl_src1); return; default: LOG(FATAL) << "Unexpected opcode: " << opcode; } - rl_src1 = LoadValue(cu, rl_src1, kFPReg); - rl_src2 = LoadValue(cu, rl_src2, kFPReg); - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); + rl_src1 = LoadValue(rl_src1, kFPReg); + rl_src2 = LoadValue(rl_src2, kFPReg); + rl_result = EvalLoc(rl_dest, kFPReg, true); int r_dest = rl_result.low_reg; int r_src1 = rl_src1.low_reg; int r_src2 = rl_src2.low_reg; if (r_dest == r_src2) { - r_src2 = AllocTempFloat(cu); - OpRegCopy(cu, r_src2, r_dest); + r_src2 = AllocTempFloat(); + OpRegCopy(r_src2, r_dest); } - OpRegCopy(cu, r_dest, r_src1); - NewLIR2(cu, op, r_dest, r_src2); - StoreValue(cu, rl_dest, rl_result); + OpRegCopy(r_dest, r_src1); + NewLIR2(op, r_dest, r_src2); + StoreValue(rl_dest, rl_result); } -void X86Codegen::GenArithOpDouble(CompilationUnit *cu, Instruction::Code opcode, +void X86Mir2Lir::GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { X86OpCode op = kX86Nop; RegLocation rl_result; @@ -99,37 +97,37 @@ void X86Codegen::GenArithOpDouble(CompilationUnit *cu, Instruction::Code opcode, break; case Instruction::REM_DOUBLE_2ADDR: case Instruction::REM_DOUBLE: - FlushAllRegs(cu); // Send everything to home location - CallRuntimeHelperRegLocationRegLocation(cu, ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false); - rl_result = GetReturnWide(cu, true); - StoreValueWide(cu, rl_dest, rl_result); + FlushAllRegs(); // Send everything to home location + CallRuntimeHelperRegLocationRegLocation(ENTRYPOINT_OFFSET(pFmod), rl_src1, rl_src2, false); + rl_result = GetReturnWide(true); + StoreValueWide(rl_dest, rl_result); return; case Instruction::NEG_DOUBLE: - GenNegDouble(cu, rl_dest, rl_src1); + GenNegDouble(rl_dest, rl_src1); return; default: LOG(FATAL) << "Unexpected opcode: " << opcode; } - rl_src1 = LoadValueWide(cu, rl_src1, kFPReg); + rl_src1 = LoadValueWide(rl_src1, kFPReg); DCHECK(rl_src1.wide); - rl_src2 = LoadValueWide(cu, rl_src2, kFPReg); + rl_src2 = LoadValueWide(rl_src2, kFPReg); DCHECK(rl_src2.wide); - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); + rl_result = EvalLoc(rl_dest, kFPReg, true); DCHECK(rl_dest.wide); DCHECK(rl_result.wide); int r_dest = S2d(rl_result.low_reg, rl_result.high_reg); int r_src1 = S2d(rl_src1.low_reg, rl_src1.high_reg); int r_src2 = S2d(rl_src2.low_reg, rl_src2.high_reg); if (r_dest == r_src2) { - r_src2 = AllocTempDouble(cu) | X86_FP_DOUBLE; - OpRegCopy(cu, r_src2, r_dest); + r_src2 = AllocTempDouble() | X86_FP_DOUBLE; + OpRegCopy(r_src2, r_dest); } - OpRegCopy(cu, r_dest, r_src1); - NewLIR2(cu, op, r_dest, r_src2); - StoreValueWide(cu, rl_dest, rl_result); + OpRegCopy(r_dest, r_src1); + NewLIR2(op, r_dest, r_src2); + StoreValueWide(rl_dest, rl_result); } -void X86Codegen::GenConversion(CompilationUnit *cu, Instruction::Code opcode, RegLocation rl_dest, +void X86Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) { RegisterClass rcSrc = kFPReg; X86OpCode op = kX86Nop; @@ -153,194 +151,193 @@ void X86Codegen::GenConversion(CompilationUnit *cu, Instruction::Code opcode, Re op = kX86Cvtsi2sdRR; break; case Instruction::FLOAT_TO_INT: { - rl_src = LoadValue(cu, rl_src, kFPReg); + rl_src = LoadValue(rl_src, kFPReg); src_reg = rl_src.low_reg; // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() - ClobberSReg(cu, rl_dest.s_reg_low); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int temp_reg = AllocTempFloat(cu); + ClobberSReg(rl_dest.s_reg_low); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + int temp_reg = AllocTempFloat(); - LoadConstant(cu, rl_result.low_reg, 0x7fffffff); - NewLIR2(cu, kX86Cvtsi2ssRR, temp_reg, rl_result.low_reg); - NewLIR2(cu, kX86ComissRR, src_reg, temp_reg); - LIR* branch_pos_overflow = NewLIR2(cu, kX86Jcc8, 0, kX86CondA); - LIR* branch_na_n = NewLIR2(cu, kX86Jcc8, 0, kX86CondP); - NewLIR2(cu, kX86Cvttss2siRR, rl_result.low_reg, src_reg); - LIR* branch_normal = NewLIR1(cu, kX86Jmp8, 0); - branch_na_n->target = NewLIR0(cu, kPseudoTargetLabel); - NewLIR2(cu, kX86Xor32RR, rl_result.low_reg, rl_result.low_reg); - branch_pos_overflow->target = NewLIR0(cu, kPseudoTargetLabel); - branch_normal->target = NewLIR0(cu, kPseudoTargetLabel); - StoreValue(cu, rl_dest, rl_result); + LoadConstant(rl_result.low_reg, 0x7fffffff); + NewLIR2(kX86Cvtsi2ssRR, temp_reg, rl_result.low_reg); + NewLIR2(kX86ComissRR, src_reg, temp_reg); + LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA); + LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); + NewLIR2(kX86Cvttss2siRR, rl_result.low_reg, src_reg); + LIR* branch_normal = NewLIR1(kX86Jmp8, 0); + branch_na_n->target = NewLIR0(kPseudoTargetLabel); + NewLIR2(kX86Xor32RR, rl_result.low_reg, rl_result.low_reg); + branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); + branch_normal->target = NewLIR0(kPseudoTargetLabel); + StoreValue(rl_dest, rl_result); return; } case Instruction::DOUBLE_TO_INT: { - rl_src = LoadValueWide(cu, rl_src, kFPReg); + rl_src = LoadValueWide(rl_src, kFPReg); src_reg = rl_src.low_reg; // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() - ClobberSReg(cu, rl_dest.s_reg_low); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - int temp_reg = AllocTempDouble(cu) | X86_FP_DOUBLE; + ClobberSReg(rl_dest.s_reg_low); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + int temp_reg = AllocTempDouble() | X86_FP_DOUBLE; - LoadConstant(cu, rl_result.low_reg, 0x7fffffff); - NewLIR2(cu, kX86Cvtsi2sdRR, temp_reg, rl_result.low_reg); - NewLIR2(cu, kX86ComisdRR, src_reg, temp_reg); - LIR* branch_pos_overflow = NewLIR2(cu, kX86Jcc8, 0, kX86CondA); - LIR* branch_na_n = NewLIR2(cu, kX86Jcc8, 0, kX86CondP); - NewLIR2(cu, kX86Cvttsd2siRR, rl_result.low_reg, src_reg); - LIR* branch_normal = NewLIR1(cu, kX86Jmp8, 0); - branch_na_n->target = NewLIR0(cu, kPseudoTargetLabel); - NewLIR2(cu, kX86Xor32RR, rl_result.low_reg, rl_result.low_reg); - branch_pos_overflow->target = NewLIR0(cu, kPseudoTargetLabel); - branch_normal->target = NewLIR0(cu, kPseudoTargetLabel); - StoreValue(cu, rl_dest, rl_result); + LoadConstant(rl_result.low_reg, 0x7fffffff); + NewLIR2(kX86Cvtsi2sdRR, temp_reg, rl_result.low_reg); + NewLIR2(kX86ComisdRR, src_reg, temp_reg); + LIR* branch_pos_overflow = NewLIR2(kX86Jcc8, 0, kX86CondA); + LIR* branch_na_n = NewLIR2(kX86Jcc8, 0, kX86CondP); + NewLIR2(kX86Cvttsd2siRR, rl_result.low_reg, src_reg); + LIR* branch_normal = NewLIR1(kX86Jmp8, 0); + branch_na_n->target = NewLIR0(kPseudoTargetLabel); + NewLIR2(kX86Xor32RR, rl_result.low_reg, rl_result.low_reg); + branch_pos_overflow->target = NewLIR0(kPseudoTargetLabel); + branch_normal->target = NewLIR0(kPseudoTargetLabel); + StoreValue(rl_dest, rl_result); return; } case Instruction::LONG_TO_DOUBLE: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src); return; case Instruction::LONG_TO_FLOAT: // TODO: inline by using memory as a 64-bit source. Be careful about promoted registers. - GenConversionCall(cu, ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src); return; case Instruction::FLOAT_TO_LONG: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src); return; case Instruction::DOUBLE_TO_LONG: - GenConversionCall(cu, ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src); + GenConversionCall(ENTRYPOINT_OFFSET(pD2l), rl_dest, rl_src); return; default: LOG(INFO) << "Unexpected opcode: " << opcode; } if (rl_src.wide) { - rl_src = LoadValueWide(cu, rl_src, rcSrc); + rl_src = LoadValueWide(rl_src, rcSrc); src_reg = S2d(rl_src.low_reg, rl_src.high_reg); } else { - rl_src = LoadValue(cu, rl_src, rcSrc); + rl_src = LoadValue(rl_src, rcSrc); src_reg = rl_src.low_reg; } if (rl_dest.wide) { - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg); - StoreValueWide(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(op, S2d(rl_result.low_reg, rl_result.high_reg), src_reg); + StoreValueWide(rl_dest, rl_result); } else { - rl_result = EvalLoc(cu, rl_dest, kFPReg, true); - NewLIR2(cu, op, rl_result.low_reg, src_reg); - StoreValue(cu, rl_dest, rl_result); + rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(op, rl_result.low_reg, src_reg); + StoreValue(rl_dest, rl_result); } } -void X86Codegen::GenCmpFP(CompilationUnit *cu, Instruction::Code code, RegLocation rl_dest, +void X86Mir2Lir::GenCmpFP(Instruction::Code code, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { bool single = (code == Instruction::CMPL_FLOAT) || (code == Instruction::CMPG_FLOAT); bool unordered_gt = (code == Instruction::CMPG_DOUBLE) || (code == Instruction::CMPG_FLOAT); int src_reg1; int src_reg2; if (single) { - rl_src1 = LoadValue(cu, rl_src1, kFPReg); + rl_src1 = LoadValue(rl_src1, kFPReg); src_reg1 = rl_src1.low_reg; - rl_src2 = LoadValue(cu, rl_src2, kFPReg); + rl_src2 = LoadValue(rl_src2, kFPReg); src_reg2 = rl_src2.low_reg; } else { - rl_src1 = LoadValueWide(cu, rl_src1, kFPReg); + rl_src1 = LoadValueWide(rl_src1, kFPReg); src_reg1 = S2d(rl_src1.low_reg, rl_src1.high_reg); - rl_src2 = LoadValueWide(cu, rl_src2, kFPReg); + rl_src2 = LoadValueWide(rl_src2, kFPReg); src_reg2 = S2d(rl_src2.low_reg, rl_src2.high_reg); } // In case result vreg is also src vreg, break association to avoid useless copy by EvalLoc() - ClobberSReg(cu, rl_dest.s_reg_low); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - LoadConstantNoClobber(cu, rl_result.low_reg, unordered_gt ? 1 : 0); + ClobberSReg(rl_dest.s_reg_low); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + LoadConstantNoClobber(rl_result.low_reg, unordered_gt ? 1 : 0); if (single) { - NewLIR2(cu, kX86UcomissRR, src_reg1, src_reg2); + NewLIR2(kX86UcomissRR, src_reg1, src_reg2); } else { - NewLIR2(cu, kX86UcomisdRR, src_reg1, src_reg2); + NewLIR2(kX86UcomisdRR, src_reg1, src_reg2); } LIR* branch = NULL; if (unordered_gt) { - branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondPE); + branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); } // If the result reg can't be byte accessed, use a jump and move instead of a set. if (rl_result.low_reg >= 4) { LIR* branch2 = NULL; if (unordered_gt) { - branch2 = NewLIR2(cu, kX86Jcc8, 0, kX86CondA); - NewLIR2(cu, kX86Mov32RI, rl_result.low_reg, 0x0); + branch2 = NewLIR2(kX86Jcc8, 0, kX86CondA); + NewLIR2(kX86Mov32RI, rl_result.low_reg, 0x0); } else { - branch2 = NewLIR2(cu, kX86Jcc8, 0, kX86CondBe); - NewLIR2(cu, kX86Mov32RI, rl_result.low_reg, 0x1); + branch2 = NewLIR2(kX86Jcc8, 0, kX86CondBe); + NewLIR2(kX86Mov32RI, rl_result.low_reg, 0x1); } - branch2->target = NewLIR0(cu, kPseudoTargetLabel); + branch2->target = NewLIR0(kPseudoTargetLabel); } else { - NewLIR2(cu, kX86Set8R, rl_result.low_reg, kX86CondA /* above - unsigned > */); + NewLIR2(kX86Set8R, rl_result.low_reg, kX86CondA /* above - unsigned > */); } - NewLIR2(cu, kX86Sbb32RI, rl_result.low_reg, 0); + NewLIR2(kX86Sbb32RI, rl_result.low_reg, 0); if (unordered_gt) { - branch->target = NewLIR0(cu, kPseudoTargetLabel); + branch->target = NewLIR0(kPseudoTargetLabel); } - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } -void X86Codegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir, bool gt_bias, +void X86Mir2Lir::GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) { - LIR* label_list = cu->block_label_list; - LIR* taken = &label_list[bb->taken->id]; - LIR* not_taken = &label_list[bb->fall_through->id]; + LIR* taken = &block_label_list_[bb->taken->id]; + LIR* not_taken = &block_label_list_[bb->fall_through->id]; LIR* branch = NULL; RegLocation rl_src1; RegLocation rl_src2; if (is_double) { - rl_src1 = GetSrcWide(cu, mir, 0); - rl_src2 = GetSrcWide(cu, mir, 2); - rl_src1 = LoadValueWide(cu, rl_src1, kFPReg); - rl_src2 = LoadValueWide(cu, rl_src2, kFPReg); - NewLIR2(cu, kX86UcomisdRR, S2d(rl_src1.low_reg, rl_src1.high_reg), + rl_src1 = mir_graph_->GetSrcWide(mir, 0); + rl_src2 = mir_graph_->GetSrcWide(mir, 2); + rl_src1 = LoadValueWide(rl_src1, kFPReg); + rl_src2 = LoadValueWide(rl_src2, kFPReg); + NewLIR2(kX86UcomisdRR, S2d(rl_src1.low_reg, rl_src1.high_reg), S2d(rl_src2.low_reg, rl_src2.high_reg)); } else { - rl_src1 = GetSrc(cu, mir, 0); - rl_src2 = GetSrc(cu, mir, 1); - rl_src1 = LoadValue(cu, rl_src1, kFPReg); - rl_src2 = LoadValue(cu, rl_src2, kFPReg); - NewLIR2(cu, kX86UcomissRR, rl_src1.low_reg, rl_src2.low_reg); + rl_src1 = mir_graph_->GetSrc(mir, 0); + rl_src2 = mir_graph_->GetSrc(mir, 1); + rl_src1 = LoadValue(rl_src1, kFPReg); + rl_src2 = LoadValue(rl_src2, kFPReg); + NewLIR2(kX86UcomissRR, rl_src1.low_reg, rl_src2.low_reg); } ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); switch (ccode) { case kCondEq: if (!gt_bias) { - branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondPE); + branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); branch->target = not_taken; } break; case kCondNe: if (!gt_bias) { - branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondPE); + branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); branch->target = taken; } break; case kCondLt: if (gt_bias) { - branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondPE); + branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); branch->target = not_taken; } ccode = kCondCs; break; case kCondLe: if (gt_bias) { - branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondPE); + branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); branch->target = not_taken; } ccode = kCondLs; break; case kCondGt: if (gt_bias) { - branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondPE); + branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); branch->target = taken; } ccode = kCondHi; break; case kCondGe: if (gt_bias) { - branch = NewLIR2(cu, kX86Jcc8, 0, kX86CondPE); + branch = NewLIR2(kX86Jcc8, 0, kX86CondPE); branch->target = taken; } ccode = kCondCc; @@ -348,30 +345,30 @@ void X86Codegen::GenFusedFPCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* m default: LOG(FATAL) << "Unexpected ccode: " << ccode; } - OpCondBranch(cu, ccode, taken); + OpCondBranch(ccode, taken); } -void X86Codegen::GenNegFloat(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src) +void X86Mir2Lir::GenNegFloat(RegLocation rl_dest, RegLocation rl_src) { RegLocation rl_result; - rl_src = LoadValue(cu, rl_src, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegRegImm(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000); - StoreValue(cu, rl_dest, rl_result); + rl_src = LoadValue(rl_src, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegRegImm(kOpAdd, rl_result.low_reg, rl_src.low_reg, 0x80000000); + StoreValue(rl_dest, rl_result); } -void X86Codegen::GenNegDouble(CompilationUnit *cu, RegLocation rl_dest, RegLocation rl_src) +void X86Mir2Lir::GenNegDouble(RegLocation rl_dest, RegLocation rl_src) { RegLocation rl_result; - rl_src = LoadValueWide(cu, rl_src, kCoreReg); - rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegRegImm(cu, kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000); - OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg); - StoreValueWide(cu, rl_dest, rl_result); + rl_src = LoadValueWide(rl_src, kCoreReg); + rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegRegImm(kOpAdd, rl_result.high_reg, rl_src.high_reg, 0x80000000); + OpRegCopy(rl_result.low_reg, rl_src.low_reg); + StoreValueWide(rl_dest, rl_result); } -bool X86Codegen::GenInlinedSqrt(CompilationUnit* cu, CallInfo* info) { - DCHECK_NE(cu->instruction_set, kThumb2); +bool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) { + DCHECK_NE(cu_->instruction_set, kThumb2); return false; } diff --git a/src/compiler/dex/quick/x86/int_x86.cc b/src/compiler/dex/quick/x86/int_x86.cc index 984eaefbef..9c72ad97ca 100644 --- a/src/compiler/dex/quick/x86/int_x86.cc +++ b/src/compiler/dex/quick/x86/int_x86.cc @@ -17,8 +17,6 @@ /* This file contains codegen for the X86 ISA */ #include "codegen_x86.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "x86_lir.h" namespace art { @@ -26,15 +24,15 @@ namespace art { /* * Perform register memory operation. */ -LIR* X86Codegen::GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code, +LIR* X86Mir2Lir::GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset, ThrowKind kind) { - LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind, - cu->current_dalvik_offset, reg1, base, offset); - OpRegMem(cu, kOpCmp, reg1, base, offset); - LIR* branch = OpCondBranch(cu, c_code, tgt); + LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, + current_dalvik_offset_, reg1, base, offset); + OpRegMem(kOpCmp, reg1, base, offset); + LIR* branch = OpCondBranch(c_code, tgt); // Remember branch target - will process later - InsertGrowableList(cu, &cu->throw_launchpads, reinterpret_cast<uintptr_t>(tgt)); + InsertGrowableList(cu_, &throw_launchpads_, reinterpret_cast<uintptr_t>(tgt)); return branch; } @@ -44,25 +42,25 @@ LIR* X86Codegen::GenRegMemCheck(CompilationUnit* cu, ConditionCode c_code, * x < y return -1 * x > y return 1 */ -void X86Codegen::GenCmpLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void X86Mir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { - FlushAllRegs(cu); - LockCallTemps(cu); // Prepare for explicit register usage - LoadValueDirectWideFixed(cu, rl_src1, r0, r1); - LoadValueDirectWideFixed(cu, rl_src2, r2, r3); + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage + LoadValueDirectWideFixed(rl_src1, r0, r1); + LoadValueDirectWideFixed(rl_src2, r2, r3); // Compute (r1:r0) = (r1:r0) - (r3:r2) - OpRegReg(cu, kOpSub, r0, r2); // r0 = r0 - r2 - OpRegReg(cu, kOpSbc, r1, r3); // r1 = r1 - r3 - CF - NewLIR2(cu, kX86Set8R, r2, kX86CondL); // r2 = (r1:r0) < (r3:r2) ? 1 : 0 - NewLIR2(cu, kX86Movzx8RR, r2, r2); - OpReg(cu, kOpNeg, r2); // r2 = -r2 - OpRegReg(cu, kOpOr, r0, r1); // r0 = high | low - sets ZF - NewLIR2(cu, kX86Set8R, r0, kX86CondNz); // r0 = (r1:r0) != (r3:r2) ? 1 : 0 - NewLIR2(cu, kX86Movzx8RR, r0, r0); - OpRegReg(cu, kOpOr, r0, r2); // r0 = r0 | r2 + OpRegReg(kOpSub, r0, r2); // r0 = r0 - r2 + OpRegReg(kOpSbc, r1, r3); // r1 = r1 - r3 - CF + NewLIR2(kX86Set8R, r2, kX86CondL); // r2 = (r1:r0) < (r3:r2) ? 1 : 0 + NewLIR2(kX86Movzx8RR, r2, r2); + OpReg(kOpNeg, r2); // r2 = -r2 + OpRegReg(kOpOr, r0, r1); // r0 = high | low - sets ZF + NewLIR2(kX86Set8R, r0, kX86CondNz); // r0 = (r1:r0) != (r3:r2) ? 1 : 0 + NewLIR2(kX86Movzx8RR, r0, r0); + OpRegReg(kOpOr, r0, r2); // r0 = r0 | r2 RegLocation rl_result = LocCReturn(); - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } X86ConditionCode X86ConditionEncoding(ConditionCode cond) { @@ -87,37 +85,37 @@ X86ConditionCode X86ConditionEncoding(ConditionCode cond) { return kX86CondO; } -LIR* X86Codegen::OpCmpBranch(CompilationUnit* cu, ConditionCode cond, int src1, int src2, +LIR* X86Mir2Lir::OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target) { - NewLIR2(cu, kX86Cmp32RR, src1, src2); + NewLIR2(kX86Cmp32RR, src1, src2); X86ConditionCode cc = X86ConditionEncoding(cond); - LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* lir operand for Jcc offset */ , + LIR* branch = NewLIR2(kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc); branch->target = target; return branch; } -LIR* X86Codegen::OpCmpImmBranch(CompilationUnit* cu, ConditionCode cond, int reg, +LIR* X86Mir2Lir::OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target) { if ((check_value == 0) && (cond == kCondEq || cond == kCondNe)) { // TODO: when check_value == 0 and reg is rCX, use the jcxz/nz opcode - NewLIR2(cu, kX86Test32RR, reg, reg); + NewLIR2(kX86Test32RR, reg, reg); } else { - NewLIR2(cu, IS_SIMM8(check_value) ? kX86Cmp32RI8 : kX86Cmp32RI, reg, check_value); + NewLIR2(IS_SIMM8(check_value) ? kX86Cmp32RI8 : kX86Cmp32RI, reg, check_value); } X86ConditionCode cc = X86ConditionEncoding(cond); - LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc); + LIR* branch = NewLIR2(kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc); branch->target = target; return branch; } -LIR* X86Codegen::OpRegCopyNoInsert(CompilationUnit *cu, int r_dest, int r_src) +LIR* X86Mir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) { if (X86_FPREG(r_dest) || X86_FPREG(r_src)) - return OpFpRegCopy(cu, r_dest, r_src); - LIR* res = RawLIR(cu, cu->current_dalvik_offset, kX86Mov32RR, + return OpFpRegCopy(r_dest, r_src); + LIR* res = RawLIR(current_dalvik_offset_, kX86Mov32RR, r_dest, r_src); if (r_dest == r_src) { res->flags.is_nop = true; @@ -125,14 +123,14 @@ LIR* X86Codegen::OpRegCopyNoInsert(CompilationUnit *cu, int r_dest, int r_src) return res; } -LIR* X86Codegen::OpRegCopy(CompilationUnit *cu, int r_dest, int r_src) +LIR* X86Mir2Lir::OpRegCopy(int r_dest, int r_src) { - LIR *res = OpRegCopyNoInsert(cu, r_dest, r_src); - AppendLIR(cu, res); + LIR *res = OpRegCopyNoInsert(r_dest, r_src); + AppendLIR(res); return res; } -void X86Codegen::OpRegCopyWide(CompilationUnit *cu, int dest_lo, int dest_hi, +void X86Mir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi) { bool dest_fp = X86_FPREG(dest_lo) && X86_FPREG(dest_hi); @@ -141,62 +139,61 @@ void X86Codegen::OpRegCopyWide(CompilationUnit *cu, int dest_lo, int dest_hi, assert(X86_FPREG(dest_lo) == X86_FPREG(dest_hi)); if (dest_fp) { if (src_fp) { - OpRegCopy(cu, S2d(dest_lo, dest_hi), S2d(src_lo, src_hi)); + OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi)); } else { // TODO: Prevent this from happening in the code. The result is often // unused or could have been loaded more easily from memory. - NewLIR2(cu, kX86MovdxrRR, dest_lo, src_lo); - NewLIR2(cu, kX86MovdxrRR, dest_hi, src_hi); - NewLIR2(cu, kX86PsllqRI, dest_hi, 32); - NewLIR2(cu, kX86OrpsRR, dest_lo, dest_hi); + NewLIR2(kX86MovdxrRR, dest_lo, src_lo); + NewLIR2(kX86MovdxrRR, dest_hi, src_hi); + NewLIR2(kX86PsllqRI, dest_hi, 32); + NewLIR2(kX86OrpsRR, dest_lo, dest_hi); } } else { if (src_fp) { - NewLIR2(cu, kX86MovdrxRR, dest_lo, src_lo); - NewLIR2(cu, kX86PsrlqRI, src_lo, 32); - NewLIR2(cu, kX86MovdrxRR, dest_hi, src_lo); + NewLIR2(kX86MovdrxRR, dest_lo, src_lo); + NewLIR2(kX86PsrlqRI, src_lo, 32); + NewLIR2(kX86MovdrxRR, dest_hi, src_lo); } else { // Handle overlap if (src_hi == dest_lo) { - OpRegCopy(cu, dest_hi, src_hi); - OpRegCopy(cu, dest_lo, src_lo); + OpRegCopy(dest_hi, src_hi); + OpRegCopy(dest_lo, src_lo); } else { - OpRegCopy(cu, dest_lo, src_lo); - OpRegCopy(cu, dest_hi, src_hi); + OpRegCopy(dest_lo, src_lo); + OpRegCopy(dest_hi, src_hi); } } } } -void X86Codegen::GenSelect(CompilationUnit* cu, BasicBlock* bb, MIR* mir) +void X86Mir2Lir::GenSelect(BasicBlock* bb, MIR* mir) { UNIMPLEMENTED(FATAL) << "Need codegen for GenSelect"; } -void X86Codegen::GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* mir) { - LIR* label_list = cu->block_label_list; - LIR* taken = &label_list[bb->taken->id]; - RegLocation rl_src1 = GetSrcWide(cu, mir, 0); - RegLocation rl_src2 = GetSrcWide(cu, mir, 2); - FlushAllRegs(cu); - LockCallTemps(cu); // Prepare for explicit register usage - LoadValueDirectWideFixed(cu, rl_src1, r0, r1); - LoadValueDirectWideFixed(cu, rl_src2, r2, r3); +void X86Mir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) { + LIR* taken = &block_label_list_[bb->taken->id]; + RegLocation rl_src1 = mir_graph_->GetSrcWide(mir, 0); + RegLocation rl_src2 = mir_graph_->GetSrcWide(mir, 2); + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage + LoadValueDirectWideFixed(rl_src1, r0, r1); + LoadValueDirectWideFixed(rl_src2, r2, r3); ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); // Swap operands and condition code to prevent use of zero flag. if (ccode == kCondLe || ccode == kCondGt) { // Compute (r3:r2) = (r3:r2) - (r1:r0) - OpRegReg(cu, kOpSub, r2, r0); // r2 = r2 - r0 - OpRegReg(cu, kOpSbc, r3, r1); // r3 = r3 - r1 - CF + OpRegReg(kOpSub, r2, r0); // r2 = r2 - r0 + OpRegReg(kOpSbc, r3, r1); // r3 = r3 - r1 - CF } else { // Compute (r1:r0) = (r1:r0) - (r3:r2) - OpRegReg(cu, kOpSub, r0, r2); // r0 = r0 - r2 - OpRegReg(cu, kOpSbc, r1, r3); // r1 = r1 - r3 - CF + OpRegReg(kOpSub, r0, r2); // r0 = r0 - r2 + OpRegReg(kOpSbc, r1, r3); // r1 = r1 - r3 - CF } switch (ccode) { case kCondEq: case kCondNe: - OpRegReg(cu, kOpOr, r0, r1); // r0 = r0 | r1 + OpRegReg(kOpOr, r0, r1); // r0 = r0 | r1 break; case kCondLe: ccode = kCondGe; @@ -210,229 +207,229 @@ void X86Codegen::GenFusedLongCmpBranch(CompilationUnit* cu, BasicBlock* bb, MIR* default: LOG(FATAL) << "Unexpected ccode: " << ccode; } - OpCondBranch(cu, ccode, taken); + OpCondBranch(ccode, taken); } -RegLocation X86Codegen::GenDivRemLit(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, +RegLocation X86Mir2Lir::GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div) { LOG(FATAL) << "Unexpected use of GenDivRemLit for x86"; return rl_dest; } -RegLocation X86Codegen::GenDivRem(CompilationUnit* cu, RegLocation rl_dest, int reg_lo, +RegLocation X86Mir2Lir::GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div) { LOG(FATAL) << "Unexpected use of GenDivRem for x86"; return rl_dest; } -bool X86Codegen::GenInlinedMinMaxInt(CompilationUnit *cu, CallInfo* info, bool is_min) +bool X86Mir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) { - DCHECK_EQ(cu->instruction_set, kX86); + DCHECK_EQ(cu_->instruction_set, kX86); RegLocation rl_src1 = info->args[0]; RegLocation rl_src2 = info->args[1]; - rl_src1 = LoadValue(cu, rl_src1, kCoreReg); - rl_src2 = LoadValue(cu, rl_src2, kCoreReg); - RegLocation rl_dest = InlineTarget(cu, info); - RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true); - OpRegReg(cu, kOpCmp, rl_src1.low_reg, rl_src2.low_reg); - DCHECK_EQ(cu->instruction_set, kX86); - LIR* branch = NewLIR2(cu, kX86Jcc8, 0, is_min ? kX86CondG : kX86CondL); - OpRegReg(cu, kOpMov, rl_result.low_reg, rl_src1.low_reg); - LIR* branch2 = NewLIR1(cu, kX86Jmp8, 0); - branch->target = NewLIR0(cu, kPseudoTargetLabel); - OpRegReg(cu, kOpMov, rl_result.low_reg, rl_src2.low_reg); - branch2->target = NewLIR0(cu, kPseudoTargetLabel); - StoreValue(cu, rl_dest, rl_result); + rl_src1 = LoadValue(rl_src1, kCoreReg); + rl_src2 = LoadValue(rl_src2, kCoreReg); + RegLocation rl_dest = InlineTarget(info); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg); + DCHECK_EQ(cu_->instruction_set, kX86); + LIR* branch = NewLIR2(kX86Jcc8, 0, is_min ? kX86CondG : kX86CondL); + OpRegReg(kOpMov, rl_result.low_reg, rl_src1.low_reg); + LIR* branch2 = NewLIR1(kX86Jmp8, 0); + branch->target = NewLIR0(kPseudoTargetLabel); + OpRegReg(kOpMov, rl_result.low_reg, rl_src2.low_reg); + branch2->target = NewLIR0(kPseudoTargetLabel); + StoreValue(rl_dest, rl_result); return true; } -void X86Codegen::OpLea(CompilationUnit* cu, int rBase, int reg1, int reg2, int scale, int offset) +void X86Mir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) { - NewLIR5(cu, kX86Lea32RA, rBase, reg1, reg2, scale, offset); + NewLIR5(kX86Lea32RA, rBase, reg1, reg2, scale, offset); } -void X86Codegen::OpTlsCmp(CompilationUnit* cu, int offset, int val) +void X86Mir2Lir::OpTlsCmp(int offset, int val) { - NewLIR2(cu, kX86Cmp16TI8, offset, val); + NewLIR2(kX86Cmp16TI8, offset, val); } -bool X86Codegen::GenInlinedCas32(CompilationUnit* cu, CallInfo* info, bool need_write_barrier) { - DCHECK_NE(cu->instruction_set, kThumb2); +bool X86Mir2Lir::GenInlinedCas32(CallInfo* info, bool need_write_barrier) { + DCHECK_NE(cu_->instruction_set, kThumb2); return false; } -LIR* X86Codegen::OpPcRelLoad(CompilationUnit* cu, int reg, LIR* target) { +LIR* X86Mir2Lir::OpPcRelLoad(int reg, LIR* target) { LOG(FATAL) << "Unexpected use of OpPcRelLoad for x86"; return NULL; } -LIR* X86Codegen::OpVldm(CompilationUnit* cu, int rBase, int count) +LIR* X86Mir2Lir::OpVldm(int rBase, int count) { LOG(FATAL) << "Unexpected use of OpVldm for x86"; return NULL; } -LIR* X86Codegen::OpVstm(CompilationUnit* cu, int rBase, int count) +LIR* X86Mir2Lir::OpVstm(int rBase, int count) { LOG(FATAL) << "Unexpected use of OpVstm for x86"; return NULL; } -void X86Codegen::GenMultiplyByTwoBitMultiplier(CompilationUnit* cu, RegLocation rl_src, +void X86Mir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit, int first_bit, int second_bit) { - int t_reg = AllocTemp(cu); - OpRegRegImm(cu, kOpLsl, t_reg, rl_src.low_reg, second_bit - first_bit); - OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, t_reg); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + OpRegRegImm(kOpLsl, t_reg, rl_src.low_reg, second_bit - first_bit); + OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src.low_reg, t_reg); + FreeTemp(t_reg); if (first_bit != 0) { - OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit); + OpRegRegImm(kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit); } } -void X86Codegen::GenDivZeroCheck(CompilationUnit* cu, int reg_lo, int reg_hi) +void X86Mir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) { - int t_reg = AllocTemp(cu); - OpRegRegReg(cu, kOpOr, t_reg, reg_lo, reg_hi); - GenImmedCheck(cu, kCondEq, t_reg, 0, kThrowDivZero); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + OpRegRegReg(kOpOr, t_reg, reg_lo, reg_hi); + GenImmedCheck(kCondEq, t_reg, 0, kThrowDivZero); + FreeTemp(t_reg); } // Test suspend flag, return target of taken suspend branch -LIR* X86Codegen::OpTestSuspend(CompilationUnit* cu, LIR* target) +LIR* X86Mir2Lir::OpTestSuspend(LIR* target) { - OpTlsCmp(cu, Thread::ThreadFlagsOffset().Int32Value(), 0); - return OpCondBranch(cu, (target == NULL) ? kCondNe : kCondEq, target); + OpTlsCmp(Thread::ThreadFlagsOffset().Int32Value(), 0); + return OpCondBranch((target == NULL) ? kCondNe : kCondEq, target); } // Decrement register and branch on condition -LIR* X86Codegen::OpDecAndBranch(CompilationUnit* cu, ConditionCode c_code, int reg, LIR* target) +LIR* X86Mir2Lir::OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) { - OpRegImm(cu, kOpSub, reg, 1); - return OpCmpImmBranch(cu, c_code, reg, 0, target); + OpRegImm(kOpSub, reg, 1); + return OpCmpImmBranch(c_code, reg, 0, target); } -bool X86Codegen::SmallLiteralDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode, +bool X86Mir2Lir::SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src, RegLocation rl_dest, int lit) { LOG(FATAL) << "Unexpected use of smallLiteralDive in x86"; return false; } -LIR* X86Codegen::OpIT(CompilationUnit* cu, ConditionCode cond, const char* guide) +LIR* X86Mir2Lir::OpIT(ConditionCode cond, const char* guide) { LOG(FATAL) << "Unexpected use of OpIT in x86"; return NULL; } -void X86Codegen::GenMulLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void X86Mir2Lir::GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { LOG(FATAL) << "Unexpected use of GenX86Long for x86"; } -void X86Codegen::GenAddLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void X86Mir2Lir::GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { // TODO: fixed register usage here as we only have 4 temps and temporary allocation isn't smart // enough. - FlushAllRegs(cu); - LockCallTemps(cu); // Prepare for explicit register usage - LoadValueDirectWideFixed(cu, rl_src1, r0, r1); - LoadValueDirectWideFixed(cu, rl_src2, r2, r3); + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage + LoadValueDirectWideFixed(rl_src1, r0, r1); + LoadValueDirectWideFixed(rl_src2, r2, r3); // Compute (r1:r0) = (r1:r0) + (r2:r3) - OpRegReg(cu, kOpAdd, r0, r2); // r0 = r0 + r2 - OpRegReg(cu, kOpAdc, r1, r3); // r1 = r1 + r3 + CF + OpRegReg(kOpAdd, r0, r2); // r0 = r0 + r2 + OpRegReg(kOpAdc, r1, r3); // r1 = r1 + r3 + CF RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1, INVALID_SREG, INVALID_SREG}; - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void X86Codegen::GenSubLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void X86Mir2Lir::GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { // TODO: fixed register usage here as we only have 4 temps and temporary allocation isn't smart // enough. - FlushAllRegs(cu); - LockCallTemps(cu); // Prepare for explicit register usage - LoadValueDirectWideFixed(cu, rl_src1, r0, r1); - LoadValueDirectWideFixed(cu, rl_src2, r2, r3); + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage + LoadValueDirectWideFixed(rl_src1, r0, r1); + LoadValueDirectWideFixed(rl_src2, r2, r3); // Compute (r1:r0) = (r1:r0) + (r2:r3) - OpRegReg(cu, kOpSub, r0, r2); // r0 = r0 - r2 - OpRegReg(cu, kOpSbc, r1, r3); // r1 = r1 - r3 - CF + OpRegReg(kOpSub, r0, r2); // r0 = r0 - r2 + OpRegReg(kOpSbc, r1, r3); // r1 = r1 - r3 - CF RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1, INVALID_SREG, INVALID_SREG}; - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void X86Codegen::GenAndLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src1, +void X86Mir2Lir::GenAndLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { // TODO: fixed register usage here as we only have 4 temps and temporary allocation isn't smart // enough. - FlushAllRegs(cu); - LockCallTemps(cu); // Prepare for explicit register usage - LoadValueDirectWideFixed(cu, rl_src1, r0, r1); - LoadValueDirectWideFixed(cu, rl_src2, r2, r3); + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage + LoadValueDirectWideFixed(rl_src1, r0, r1); + LoadValueDirectWideFixed(rl_src2, r2, r3); // Compute (r1:r0) = (r1:r0) & (r2:r3) - OpRegReg(cu, kOpAnd, r0, r2); // r0 = r0 & r2 - OpRegReg(cu, kOpAnd, r1, r3); // r1 = r1 & r3 + OpRegReg(kOpAnd, r0, r2); // r0 = r0 & r2 + OpRegReg(kOpAnd, r1, r3); // r1 = r1 & r3 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1, INVALID_SREG, INVALID_SREG}; - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void X86Codegen::GenOrLong(CompilationUnit* cu, RegLocation rl_dest, +void X86Mir2Lir::GenOrLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { // TODO: fixed register usage here as we only have 4 temps and temporary allocation isn't smart // enough. - FlushAllRegs(cu); - LockCallTemps(cu); // Prepare for explicit register usage - LoadValueDirectWideFixed(cu, rl_src1, r0, r1); - LoadValueDirectWideFixed(cu, rl_src2, r2, r3); + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage + LoadValueDirectWideFixed(rl_src1, r0, r1); + LoadValueDirectWideFixed(rl_src2, r2, r3); // Compute (r1:r0) = (r1:r0) | (r2:r3) - OpRegReg(cu, kOpOr, r0, r2); // r0 = r0 | r2 - OpRegReg(cu, kOpOr, r1, r3); // r1 = r1 | r3 + OpRegReg(kOpOr, r0, r2); // r0 = r0 | r2 + OpRegReg(kOpOr, r1, r3); // r1 = r1 | r3 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1, INVALID_SREG, INVALID_SREG}; - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void X86Codegen::GenXorLong(CompilationUnit* cu, RegLocation rl_dest, +void X86Mir2Lir::GenXorLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { // TODO: fixed register usage here as we only have 4 temps and temporary allocation isn't smart // enough. - FlushAllRegs(cu); - LockCallTemps(cu); // Prepare for explicit register usage - LoadValueDirectWideFixed(cu, rl_src1, r0, r1); - LoadValueDirectWideFixed(cu, rl_src2, r2, r3); + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage + LoadValueDirectWideFixed(rl_src1, r0, r1); + LoadValueDirectWideFixed(rl_src2, r2, r3); // Compute (r1:r0) = (r1:r0) ^ (r2:r3) - OpRegReg(cu, kOpXor, r0, r2); // r0 = r0 ^ r2 - OpRegReg(cu, kOpXor, r1, r3); // r1 = r1 ^ r3 + OpRegReg(kOpXor, r0, r2); // r0 = r0 ^ r2 + OpRegReg(kOpXor, r1, r3); // r1 = r1 ^ r3 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1, INVALID_SREG, INVALID_SREG}; - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void X86Codegen::GenNegLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src) +void X86Mir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) { - FlushAllRegs(cu); - LockCallTemps(cu); // Prepare for explicit register usage - LoadValueDirectWideFixed(cu, rl_src, r0, r1); + FlushAllRegs(); + LockCallTemps(); // Prepare for explicit register usage + LoadValueDirectWideFixed(rl_src, r0, r1); // Compute (r1:r0) = -(r1:r0) - OpRegReg(cu, kOpNeg, r0, r0); // r0 = -r0 - OpRegImm(cu, kOpAdc, r1, 0); // r1 = r1 + CF - OpRegReg(cu, kOpNeg, r1, r1); // r1 = -r1 + OpRegReg(kOpNeg, r0, r0); // r0 = -r0 + OpRegImm(kOpAdc, r1, 0); // r1 = r1 + CF + OpRegReg(kOpNeg, r1, r1); // r1 = -r1 RegLocation rl_result = {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r0, r1, INVALID_SREG, INVALID_SREG}; - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } -void X86Codegen::OpRegThreadMem(CompilationUnit* cu, OpKind op, int r_dest, int thread_offset) { +void X86Mir2Lir::OpRegThreadMem(OpKind op, int r_dest, int thread_offset) { X86OpCode opcode = kX86Bkpt; switch (op) { case kOpCmp: opcode = kX86Cmp32RT; break; @@ -441,21 +438,21 @@ void X86Codegen::OpRegThreadMem(CompilationUnit* cu, OpKind op, int r_dest, int LOG(FATAL) << "Bad opcode: " << op; break; } - NewLIR2(cu, opcode, r_dest, thread_offset); + NewLIR2(opcode, r_dest, thread_offset); } /* * Generate array load */ -void X86Codegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, +void X86Mir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset; RegLocation rl_result; - rl_array = LoadValue(cu, rl_array, kCoreReg); - rl_index = LoadValue(cu, rl_index, kCoreReg); + rl_array = LoadValue(rl_array, kCoreReg); + rl_index = LoadValue(rl_index, kCoreReg); if (size == kLong || size == kDouble) { data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value(); @@ -464,30 +461,30 @@ void X86Codegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, Re } /* null object? */ - GenNullCheck(cu, rl_array.s_reg_low, rl_array.low_reg, opt_flags); + GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags); if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) { /* if (rl_index >= [rl_array + len_offset]) goto kThrowArrayBounds */ - GenRegMemCheck(cu, kCondUge, rl_index.low_reg, rl_array.low_reg, + GenRegMemCheck(kCondUge, rl_index.low_reg, rl_array.low_reg, len_offset, kThrowArrayBounds); } if ((size == kLong) || (size == kDouble)) { - int reg_addr = AllocTemp(cu); - OpLea(cu, reg_addr, rl_array.low_reg, rl_index.low_reg, scale, data_offset); - FreeTemp(cu, rl_array.low_reg); - FreeTemp(cu, rl_index.low_reg); - rl_result = EvalLoc(cu, rl_dest, reg_class, true); - LoadBaseIndexedDisp(cu, reg_addr, INVALID_REG, 0, 0, rl_result.low_reg, + int reg_addr = AllocTemp(); + OpLea(reg_addr, rl_array.low_reg, rl_index.low_reg, scale, data_offset); + FreeTemp(rl_array.low_reg); + FreeTemp(rl_index.low_reg); + rl_result = EvalLoc(rl_dest, reg_class, true); + LoadBaseIndexedDisp(reg_addr, INVALID_REG, 0, 0, rl_result.low_reg, rl_result.high_reg, size, INVALID_SREG); - StoreValueWide(cu, rl_dest, rl_result); + StoreValueWide(rl_dest, rl_result); } else { - rl_result = EvalLoc(cu, rl_dest, reg_class, true); + rl_result = EvalLoc(rl_dest, reg_class, true); - LoadBaseIndexedDisp(cu, rl_array.low_reg, rl_index.low_reg, scale, + LoadBaseIndexedDisp(rl_array.low_reg, rl_index.low_reg, scale, data_offset, rl_result.low_reg, INVALID_REG, size, INVALID_SREG); - StoreValue(cu, rl_dest, rl_result); + StoreValue(rl_dest, rl_result); } } @@ -495,7 +492,7 @@ void X86Codegen::GenArrayGet(CompilationUnit* cu, int opt_flags, OpSize size, Re * Generate array store * */ -void X86Codegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, RegLocation rl_array, +void X86Mir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { RegisterClass reg_class = oat_reg_class_by_size(size); @@ -508,29 +505,29 @@ void X86Codegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, Re data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value(); } - rl_array = LoadValue(cu, rl_array, kCoreReg); - rl_index = LoadValue(cu, rl_index, kCoreReg); + rl_array = LoadValue(rl_array, kCoreReg); + rl_index = LoadValue(rl_index, kCoreReg); /* null object? */ - GenNullCheck(cu, rl_array.s_reg_low, rl_array.low_reg, opt_flags); + GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags); if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) { /* if (rl_index >= [rl_array + len_offset]) goto kThrowArrayBounds */ - GenRegMemCheck(cu, kCondUge, rl_index.low_reg, rl_array.low_reg, len_offset, kThrowArrayBounds); + GenRegMemCheck(kCondUge, rl_index.low_reg, rl_array.low_reg, len_offset, kThrowArrayBounds); } if ((size == kLong) || (size == kDouble)) { - rl_src = LoadValueWide(cu, rl_src, reg_class); + rl_src = LoadValueWide(rl_src, reg_class); } else { - rl_src = LoadValue(cu, rl_src, reg_class); + rl_src = LoadValue(rl_src, reg_class); } // If the src reg can't be byte accessed, move it to a temp first. if ((size == kSignedByte || size == kUnsignedByte) && rl_src.low_reg >= 4) { - int temp = AllocTemp(cu); - OpRegCopy(cu, temp, rl_src.low_reg); - StoreBaseIndexedDisp(cu, rl_array.low_reg, rl_index.low_reg, scale, data_offset, temp, + int temp = AllocTemp(); + OpRegCopy(temp, rl_src.low_reg); + StoreBaseIndexedDisp(rl_array.low_reg, rl_index.low_reg, scale, data_offset, temp, INVALID_REG, size, INVALID_SREG); } else { - StoreBaseIndexedDisp(cu, rl_array.low_reg, rl_index.low_reg, scale, data_offset, rl_src.low_reg, + StoreBaseIndexedDisp(rl_array.low_reg, rl_index.low_reg, scale, data_offset, rl_src.low_reg, rl_src.high_reg, size, INVALID_SREG); } } @@ -539,69 +536,69 @@ void X86Codegen::GenArrayPut(CompilationUnit* cu, int opt_flags, OpSize size, Re * Generate array store * */ -void X86Codegen::GenArrayObjPut(CompilationUnit* cu, int opt_flags, RegLocation rl_array, +void X86Mir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale) { int len_offset = mirror::Array::LengthOffset().Int32Value(); int data_offset = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(); - FlushAllRegs(cu); // Use explicit registers - LockCallTemps(cu); + FlushAllRegs(); // Use explicit registers + LockCallTemps(); int r_value = TargetReg(kArg0); // Register holding value int r_array_class = TargetReg(kArg1); // Register holding array's Class int r_array = TargetReg(kArg2); // Register holding array int r_index = TargetReg(kArg3); // Register holding index into array - LoadValueDirectFixed(cu, rl_array, r_array); // Grab array - LoadValueDirectFixed(cu, rl_src, r_value); // Grab value - LoadValueDirectFixed(cu, rl_index, r_index); // Grab index + LoadValueDirectFixed(rl_array, r_array); // Grab array + LoadValueDirectFixed(rl_src, r_value); // Grab value + LoadValueDirectFixed(rl_index, r_index); // Grab index - GenNullCheck(cu, rl_array.s_reg_low, r_array, opt_flags); // NPE? + GenNullCheck(rl_array.s_reg_low, r_array, opt_flags); // NPE? // Store of null? - LIR* null_value_check = OpCmpImmBranch(cu, kCondEq, r_value, 0, NULL); + LIR* null_value_check = OpCmpImmBranch(kCondEq, r_value, 0, NULL); // Get the array's class. - LoadWordDisp(cu, r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); - CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, + LoadWordDisp(r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class); + CallRuntimeHelperRegReg(ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value, r_array_class, true); // Redo LoadValues in case they didn't survive the call. - LoadValueDirectFixed(cu, rl_array, r_array); // Reload array - LoadValueDirectFixed(cu, rl_index, r_index); // Reload index - LoadValueDirectFixed(cu, rl_src, r_value); // Reload value + LoadValueDirectFixed(rl_array, r_array); // Reload array + LoadValueDirectFixed(rl_index, r_index); // Reload index + LoadValueDirectFixed(rl_src, r_value); // Reload value r_array_class = INVALID_REG; // Branch here if value to be stored == null - LIR* target = NewLIR0(cu, kPseudoTargetLabel); + LIR* target = NewLIR0(kPseudoTargetLabel); null_value_check->target = target; // make an extra temp available for card mark below - FreeTemp(cu, TargetReg(kArg1)); + FreeTemp(TargetReg(kArg1)); if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) { /* if (rl_index >= [rl_array + len_offset]) goto kThrowArrayBounds */ - GenRegMemCheck(cu, kCondUge, r_index, r_array, len_offset, kThrowArrayBounds); + GenRegMemCheck(kCondUge, r_index, r_array, len_offset, kThrowArrayBounds); } - StoreBaseIndexedDisp(cu, r_array, r_index, scale, + StoreBaseIndexedDisp(r_array, r_index, scale, data_offset, r_value, INVALID_REG, kWord, INVALID_SREG); - FreeTemp(cu, r_index); - if (!cu->mir_graph->IsConstantNullRef(rl_src)) { - MarkGCCard(cu, r_value, r_array); + FreeTemp(r_index); + if (!mir_graph_->IsConstantNullRef(rl_src)) { + MarkGCCard(r_value, r_array); } } -void X86Codegen::GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest, +void X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_shift) { // Default implementation is just to ignore the constant case. - GenShiftOpLong(cu, opcode, rl_dest, rl_src1, rl_shift); + GenShiftOpLong(opcode, rl_dest, rl_src1, rl_shift); } -void X86Codegen::GenArithImmOpLong(CompilationUnit* cu, Instruction::Code opcode, +void X86Mir2Lir::GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { // Default - bail to non-const handler. - GenArithOpLong(cu, opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); } } // namespace art diff --git a/src/compiler/dex/quick/x86/target_x86.cc b/src/compiler/dex/quick/x86/target_x86.cc index ed07220ef1..20074f1ae3 100644 --- a/src/compiler/dex/quick/x86/target_x86.cc +++ b/src/compiler/dex/quick/x86/target_x86.cc @@ -15,9 +15,7 @@ */ #include "codegen_x86.h" -#include "compiler/dex/quick/codegen_util.h" #include "compiler/dex/compiler_internals.h" -#include "compiler/dex/quick/ralloc_util.h" #include "x86_lir.h" #include <string> @@ -46,32 +44,32 @@ namespace art { #endif }; -RegLocation X86Codegen::LocCReturn() +RegLocation X86Mir2Lir::LocCReturn() { RegLocation res = X86_LOC_C_RETURN; return res; } -RegLocation X86Codegen::LocCReturnWide() +RegLocation X86Mir2Lir::LocCReturnWide() { RegLocation res = X86_LOC_C_RETURN_WIDE; return res; } -RegLocation X86Codegen::LocCReturnFloat() +RegLocation X86Mir2Lir::LocCReturnFloat() { RegLocation res = X86_LOC_C_RETURN_FLOAT; return res; } -RegLocation X86Codegen::LocCReturnDouble() +RegLocation X86Mir2Lir::LocCReturnDouble() { RegLocation res = X86_LOC_C_RETURN_DOUBLE; return res; } // Return a target-dependent special register. -int X86Codegen::TargetReg(SpecialTargetRegister reg) { +int X86Mir2Lir::TargetReg(SpecialTargetRegister reg) { int res = INVALID_REG; switch (reg) { case kSelf: res = rX86_SELF; break; @@ -96,19 +94,19 @@ int X86Codegen::TargetReg(SpecialTargetRegister reg) { } // Create a double from a pair of singles. -int X86Codegen::S2d(int low_reg, int high_reg) +int X86Mir2Lir::S2d(int low_reg, int high_reg) { return X86_S2D(low_reg, high_reg); } // Return mask to strip off fp reg flags and bias. -uint32_t X86Codegen::FpRegMask() +uint32_t X86Mir2Lir::FpRegMask() { return X86_FP_REG_MASK; } // True if both regs single, both core or both double. -bool X86Codegen::SameRegType(int reg1, int reg2) +bool X86Mir2Lir::SameRegType(int reg1, int reg2) { return (X86_REGTYPE(reg1) == X86_REGTYPE(reg2)); } @@ -116,7 +114,7 @@ bool X86Codegen::SameRegType(int reg1, int reg2) /* * Decode the register id. */ -uint64_t X86Codegen::GetRegMaskCommon(CompilationUnit* cu, int reg) +uint64_t X86Mir2Lir::GetRegMaskCommon(int reg) { uint64_t seed; int shift; @@ -132,7 +130,7 @@ uint64_t X86Codegen::GetRegMaskCommon(CompilationUnit* cu, int reg) return (seed << shift); } -uint64_t X86Codegen::GetPCUseDefEncoding() +uint64_t X86Mir2Lir::GetPCUseDefEncoding() { /* * FIXME: might make sense to use a virtual resource encoding bit for pc. Might be @@ -142,12 +140,12 @@ uint64_t X86Codegen::GetPCUseDefEncoding() return 0ULL; } -void X86Codegen::SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir) +void X86Mir2Lir::SetupTargetResourceMasks(LIR* lir) { - DCHECK_EQ(cu->instruction_set, kX86); + DCHECK_EQ(cu_->instruction_set, kX86); // X86-specific resource map setup here. - uint64_t flags = X86Codegen::EncodingMap[lir->opcode].flags; + uint64_t flags = X86Mir2Lir::EncodingMap[lir->opcode].flags; if (flags & REG_USE_SP) { lir->use_mask |= ENCODE_X86_REG_SP; @@ -158,22 +156,22 @@ void X86Codegen::SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir) } if (flags & REG_DEFA) { - SetupRegMask(cu, &lir->def_mask, rAX); + SetupRegMask(&lir->def_mask, rAX); } if (flags & REG_DEFD) { - SetupRegMask(cu, &lir->def_mask, rDX); + SetupRegMask(&lir->def_mask, rDX); } if (flags & REG_USEA) { - SetupRegMask(cu, &lir->use_mask, rAX); + SetupRegMask(&lir->use_mask, rAX); } if (flags & REG_USEC) { - SetupRegMask(cu, &lir->use_mask, rCX); + SetupRegMask(&lir->use_mask, rCX); } if (flags & REG_USED) { - SetupRegMask(cu, &lir->use_mask, rDX); + SetupRegMask(&lir->use_mask, rDX); } } @@ -206,7 +204,7 @@ static const char* x86CondName[] = { * Interpret a format string and build a string no longer than size * See format key in Assemble.cc. */ -std::string X86Codegen::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { +std::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { std::string buf; size_t i = 0; size_t fmt_len = strlen(fmt); @@ -264,7 +262,7 @@ std::string X86Codegen::BuildInsnString(const char *fmt, LIR *lir, unsigned char return buf; } -void X86Codegen::DumpResourceMask(LIR *x86LIR, uint64_t mask, const char *prefix) +void X86Mir2Lir::DumpResourceMask(LIR *x86LIR, uint64_t mask, const char *prefix) { char buf[256]; buf[0] = 0; @@ -306,10 +304,10 @@ void X86Codegen::DumpResourceMask(LIR *x86LIR, uint64_t mask, const char *prefix } } -void X86Codegen::AdjustSpillMask(CompilationUnit* cu) { +void X86Mir2Lir::AdjustSpillMask() { // Adjustment for LR spilling, x86 has no LR so nothing to do here - cu->core_spill_mask |= (1 << rRET); - cu->num_core_spills++; + core_spill_mask_ |= (1 << rRET); + num_core_spills_++; } /* @@ -318,7 +316,7 @@ void X86Codegen::AdjustSpillMask(CompilationUnit* cu) { * include any holes in the mask. Associate holes with * Dalvik register INVALID_VREG (0xFFFFU). */ -void X86Codegen::MarkPreservedSingle(CompilationUnit* cu, int v_reg, int reg) +void X86Mir2Lir::MarkPreservedSingle(int v_reg, int reg) { UNIMPLEMENTED(WARNING) << "MarkPreservedSingle"; #if 0 @@ -326,10 +324,10 @@ void X86Codegen::MarkPreservedSingle(CompilationUnit* cu, int v_reg, int reg) #endif } -void X86Codegen::FlushRegWide(CompilationUnit* cu, int reg1, int reg2) +void X86Mir2Lir::FlushRegWide(int reg1, int reg2) { - RegisterInfo* info1 = GetRegInfo(cu, reg1); - RegisterInfo* info2 = GetRegInfo(cu, reg2); + RegisterInfo* info1 = GetRegInfo(reg1); + RegisterInfo* info2 = GetRegInfo(reg2); DCHECK(info1 && info2 && info1->pair && info2->pair && (info1->partner == info2->reg) && (info2->partner == info1->reg)); @@ -341,93 +339,93 @@ void X86Codegen::FlushRegWide(CompilationUnit* cu, int reg1, int reg2) info1->dirty = false; info2->dirty = false; - if (cu->mir_graph->SRegToVReg(info2->s_reg) < cu->mir_graph->SRegToVReg(info1->s_reg)) + if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg)) info1 = info2; - int v_reg = cu->mir_graph->SRegToVReg(info1->s_reg); - StoreBaseDispWide(cu, rX86_SP, VRegOffset(cu, v_reg), info1->reg, info1->partner); + int v_reg = mir_graph_->SRegToVReg(info1->s_reg); + StoreBaseDispWide(rX86_SP, VRegOffset(v_reg), info1->reg, info1->partner); } } -void X86Codegen::FlushReg(CompilationUnit* cu, int reg) +void X86Mir2Lir::FlushReg(int reg) { - RegisterInfo* info = GetRegInfo(cu, reg); + RegisterInfo* info = GetRegInfo(reg); if (info->live && info->dirty) { info->dirty = false; - int v_reg = cu->mir_graph->SRegToVReg(info->s_reg); - StoreBaseDisp(cu, rX86_SP, VRegOffset(cu, v_reg), reg, kWord); + int v_reg = mir_graph_->SRegToVReg(info->s_reg); + StoreBaseDisp(rX86_SP, VRegOffset(v_reg), reg, kWord); } } /* Give access to the target-dependent FP register encoding to common code */ -bool X86Codegen::IsFpReg(int reg) { +bool X86Mir2Lir::IsFpReg(int reg) { return X86_FPREG(reg); } /* Clobber all regs that might be used by an external C call */ -void X86Codegen::ClobberCalleeSave(CompilationUnit *cu) +void X86Mir2Lir::ClobberCalleeSave() { - Clobber(cu, rAX); - Clobber(cu, rCX); - Clobber(cu, rDX); + Clobber(rAX); + Clobber(rCX); + Clobber(rDX); } -RegLocation X86Codegen::GetReturnWideAlt(CompilationUnit* cu) { +RegLocation X86Mir2Lir::GetReturnWideAlt() { RegLocation res = LocCReturnWide(); CHECK(res.low_reg == rAX); CHECK(res.high_reg == rDX); - Clobber(cu, rAX); - Clobber(cu, rDX); - MarkInUse(cu, rAX); - MarkInUse(cu, rDX); - MarkPair(cu, res.low_reg, res.high_reg); + Clobber(rAX); + Clobber(rDX); + MarkInUse(rAX); + MarkInUse(rDX); + MarkPair(res.low_reg, res.high_reg); return res; } -RegLocation X86Codegen::GetReturnAlt(CompilationUnit* cu) +RegLocation X86Mir2Lir::GetReturnAlt() { RegLocation res = LocCReturn(); res.low_reg = rDX; - Clobber(cu, rDX); - MarkInUse(cu, rDX); + Clobber(rDX); + MarkInUse(rDX); return res; } -RegisterInfo* X86Codegen::GetRegInfo(CompilationUnit* cu, int reg) +X86Mir2Lir::RegisterInfo* X86Mir2Lir::GetRegInfo(int reg) { - return X86_FPREG(reg) ? &cu->reg_pool->FPRegs[reg & X86_FP_REG_MASK] - : &cu->reg_pool->core_regs[reg]; + return X86_FPREG(reg) ? ®_pool_->FPRegs[reg & X86_FP_REG_MASK] + : ®_pool_->core_regs[reg]; } /* To be used when explicitly managing register use */ -void X86Codegen::LockCallTemps(CompilationUnit* cu) +void X86Mir2Lir::LockCallTemps() { - LockTemp(cu, rX86_ARG0); - LockTemp(cu, rX86_ARG1); - LockTemp(cu, rX86_ARG2); - LockTemp(cu, rX86_ARG3); + LockTemp(rX86_ARG0); + LockTemp(rX86_ARG1); + LockTemp(rX86_ARG2); + LockTemp(rX86_ARG3); } /* To be used when explicitly managing register use */ -void X86Codegen::FreeCallTemps(CompilationUnit* cu) +void X86Mir2Lir::FreeCallTemps() { - FreeTemp(cu, rX86_ARG0); - FreeTemp(cu, rX86_ARG1); - FreeTemp(cu, rX86_ARG2); - FreeTemp(cu, rX86_ARG3); + FreeTemp(rX86_ARG0); + FreeTemp(rX86_ARG1); + FreeTemp(rX86_ARG2); + FreeTemp(rX86_ARG3); } -void X86Codegen::GenMemBarrier(CompilationUnit *cu, MemBarrierKind barrier_kind) +void X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { #if ANDROID_SMP != 0 // TODO: optimize fences - NewLIR0(cu, kX86Mfence); + NewLIR0(kX86Mfence); #endif } /* * Alloc a pair of core registers, or a double. Low reg in low byte, * high reg in next byte. */ -int X86Codegen::AllocTypedTempPair(CompilationUnit *cu, bool fp_hint, +int X86Mir2Lir::AllocTypedTempPair(bool fp_hint, int reg_class) { int high_reg; @@ -435,136 +433,135 @@ int X86Codegen::AllocTypedTempPair(CompilationUnit *cu, bool fp_hint, int res = 0; if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { - low_reg = AllocTempDouble(cu); + low_reg = AllocTempDouble(); high_reg = low_reg + 1; res = (low_reg & 0xff) | ((high_reg & 0xff) << 8); return res; } - low_reg = AllocTemp(cu); - high_reg = AllocTemp(cu); + low_reg = AllocTemp(); + high_reg = AllocTemp(); res = (low_reg & 0xff) | ((high_reg & 0xff) << 8); return res; } -int X86Codegen::AllocTypedTemp(CompilationUnit *cu, bool fp_hint, int reg_class) { +int X86Mir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) { if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { - return AllocTempFloat(cu); + return AllocTempFloat(); } - return AllocTemp(cu); + return AllocTemp(); } -void X86Codegen::CompilerInitializeRegAlloc(CompilationUnit* cu) { +void X86Mir2Lir::CompilerInitializeRegAlloc() { int num_regs = sizeof(core_regs)/sizeof(*core_regs); int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs); int num_temps = sizeof(core_temps)/sizeof(*core_temps); int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs); int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps); - RegisterPool *pool = - static_cast<RegisterPool*>(NewMem(cu, sizeof(*pool), true, kAllocRegAlloc)); - cu->reg_pool = pool; - pool->num_core_regs = num_regs; - pool->core_regs = - static_cast<RegisterInfo*>(NewMem(cu, num_regs * sizeof(*cu->reg_pool->core_regs), + reg_pool_ = static_cast<RegisterPool*>(NewMem(cu_, sizeof(*reg_pool_), true, kAllocRegAlloc)); + reg_pool_->num_core_regs = num_regs; + reg_pool_->core_regs = + static_cast<RegisterInfo*>(NewMem(cu_, num_regs * sizeof(*reg_pool_->core_regs), true, kAllocRegAlloc)); - pool->num_fp_regs = num_fp_regs; - pool->FPRegs = - static_cast<RegisterInfo *>(NewMem(cu, num_fp_regs * sizeof(*cu->reg_pool->FPRegs), + reg_pool_->num_fp_regs = num_fp_regs; + reg_pool_->FPRegs = + static_cast<RegisterInfo *>(NewMem(cu_, num_fp_regs * sizeof(*reg_pool_->FPRegs), true, kAllocRegAlloc)); - CompilerInitPool(pool->core_regs, core_regs, pool->num_core_regs); - CompilerInitPool(pool->FPRegs, FpRegs, pool->num_fp_regs); + CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs); + CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs); // Keep special registers from being allocated for (int i = 0; i < num_reserved; i++) { - MarkInUse(cu, ReservedRegs[i]); + MarkInUse(ReservedRegs[i]); } // Mark temp regs - all others not in use can be used for promotion for (int i = 0; i < num_temps; i++) { - MarkTemp(cu, core_temps[i]); + MarkTemp(core_temps[i]); } for (int i = 0; i < num_fp_temps; i++) { - MarkTemp(cu, fp_temps[i]); + MarkTemp(fp_temps[i]); } } -void X86Codegen::FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep, +void X86Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) { if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) && (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) { // No overlap, free both - FreeTemp(cu, rl_free.low_reg); - FreeTemp(cu, rl_free.high_reg); + FreeTemp(rl_free.low_reg); + FreeTemp(rl_free.high_reg); } } -void X86Codegen::SpillCoreRegs(CompilationUnit* cu) { - if (cu->num_core_spills == 0) { +void X86Mir2Lir::SpillCoreRegs() { + if (num_core_spills_ == 0) { return; } // Spill mask not including fake return address register - uint32_t mask = cu->core_spill_mask & ~(1 << rRET); - int offset = cu->frame_size - (4 * cu->num_core_spills); + uint32_t mask = core_spill_mask_ & ~(1 << rRET); + int offset = frame_size_ - (4 * num_core_spills_); for (int reg = 0; mask; mask >>= 1, reg++) { if (mask & 0x1) { - StoreWordDisp(cu, rX86_SP, offset, reg); + StoreWordDisp(rX86_SP, offset, reg); offset += 4; } } } -void X86Codegen::UnSpillCoreRegs(CompilationUnit* cu) { - if (cu->num_core_spills == 0) { +void X86Mir2Lir::UnSpillCoreRegs() { + if (num_core_spills_ == 0) { return; } // Spill mask not including fake return address register - uint32_t mask = cu->core_spill_mask & ~(1 << rRET); - int offset = cu->frame_size - (4 * cu->num_core_spills); + uint32_t mask = core_spill_mask_ & ~(1 << rRET); + int offset = frame_size_ - (4 * num_core_spills_); for (int reg = 0; mask; mask >>= 1, reg++) { if (mask & 0x1) { - LoadWordDisp(cu, rX86_SP, offset, reg); + LoadWordDisp(rX86_SP, offset, reg); offset += 4; } } } -bool X86Codegen::IsUnconditionalBranch(LIR* lir) +bool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) { return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32); } -/* Common initialization routine for an architecture family */ -bool InitX86Codegen(CompilationUnit* cu) { - cu->cg.reset(new X86Codegen()); +X86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph) : Mir2Lir(cu, mir_graph) { for (int i = 0; i < kX86Last; i++) { - if (X86Codegen::EncodingMap[i].opcode != i) { - LOG(FATAL) << "Encoding order for " << X86Codegen::EncodingMap[i].name + if (X86Mir2Lir::EncodingMap[i].opcode != i) { + LOG(FATAL) << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name << " is wrong: expecting " << i << ", seeing " - << static_cast<int>(X86Codegen::EncodingMap[i].opcode); + << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode); } } - return true; +} + +Mir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph) { + return new X86Mir2Lir(cu, mir_graph); } // Not used in x86 -int X86Codegen::LoadHelper(CompilationUnit* cu, int offset) +int X86Mir2Lir::LoadHelper(int offset) { LOG(FATAL) << "Unexpected use of LoadHelper in x86"; return INVALID_REG; } -uint64_t X86Codegen::GetTargetInstFlags(int opcode) +uint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) { - return X86Codegen::EncodingMap[opcode].flags; + return X86Mir2Lir::EncodingMap[opcode].flags; } -const char* X86Codegen::GetTargetInstName(int opcode) +const char* X86Mir2Lir::GetTargetInstName(int opcode) { - return X86Codegen::EncodingMap[opcode].name; + return X86Mir2Lir::EncodingMap[opcode].name; } -const char* X86Codegen::GetTargetInstFmt(int opcode) +const char* X86Mir2Lir::GetTargetInstFmt(int opcode) { - return X86Codegen::EncodingMap[opcode].fmt; + return X86Mir2Lir::EncodingMap[opcode].fmt; } } // namespace art diff --git a/src/compiler/dex/quick/x86/utility_x86.cc b/src/compiler/dex/quick/x86/utility_x86.cc index fa40635db8..45c0e9cb41 100644 --- a/src/compiler/dex/quick/x86/utility_x86.cc +++ b/src/compiler/dex/quick/x86/utility_x86.cc @@ -15,15 +15,13 @@ */ #include "codegen_x86.h" -#include "compiler/dex/quick/codegen_util.h" -#include "compiler/dex/quick/ralloc_util.h" #include "x86_lir.h" namespace art { /* This file contains codegen for the X86 ISA */ -LIR* X86Codegen::OpFpRegCopy(CompilationUnit *cu, int r_dest, int r_src) +LIR* X86Mir2Lir::OpFpRegCopy(int r_dest, int r_src) { int opcode; /* must be both DOUBLE or both not DOUBLE */ @@ -43,29 +41,29 @@ LIR* X86Codegen::OpFpRegCopy(CompilationUnit *cu, int r_dest, int r_src) } } DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL); - LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src); + LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src); if (r_dest == r_src) { res->flags.is_nop = true; } return res; } -bool X86Codegen::InexpensiveConstantInt(int32_t value) +bool X86Mir2Lir::InexpensiveConstantInt(int32_t value) { return true; } -bool X86Codegen::InexpensiveConstantFloat(int32_t value) +bool X86Mir2Lir::InexpensiveConstantFloat(int32_t value) { return false; } -bool X86Codegen::InexpensiveConstantLong(int64_t value) +bool X86Mir2Lir::InexpensiveConstantLong(int64_t value) { return true; } -bool X86Codegen::InexpensiveConstantDouble(int64_t value) +bool X86Mir2Lir::InexpensiveConstantDouble(int64_t value) { return false; // TUNING } @@ -79,49 +77,49 @@ bool X86Codegen::InexpensiveConstantDouble(int64_t value) * 1) r_dest is freshly returned from AllocTemp or * 2) The codegen is under fixed register usage */ -LIR* X86Codegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value) +LIR* X86Mir2Lir::LoadConstantNoClobber(int r_dest, int value) { int r_dest_save = r_dest; if (X86_FPREG(r_dest)) { if (value == 0) { - return NewLIR2(cu, kX86XorpsRR, r_dest, r_dest); + return NewLIR2(kX86XorpsRR, r_dest, r_dest); } DCHECK(X86_SINGLEREG(r_dest)); - r_dest = AllocTemp(cu); + r_dest = AllocTemp(); } LIR *res; if (value == 0) { - res = NewLIR2(cu, kX86Xor32RR, r_dest, r_dest); + res = NewLIR2(kX86Xor32RR, r_dest, r_dest); } else { // Note, there is no byte immediate form of a 32 bit immediate move. - res = NewLIR2(cu, kX86Mov32RI, r_dest, value); + res = NewLIR2(kX86Mov32RI, r_dest, value); } if (X86_FPREG(r_dest_save)) { - NewLIR2(cu, kX86MovdxrRR, r_dest_save, r_dest); - FreeTemp(cu, r_dest); + NewLIR2(kX86MovdxrRR, r_dest_save, r_dest); + FreeTemp(r_dest); } return res; } -LIR* X86Codegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target) +LIR* X86Mir2Lir::OpUnconditionalBranch(LIR* target) { - LIR* res = NewLIR1(cu, kX86Jmp8, 0 /* offset to be patched during assembly*/ ); + LIR* res = NewLIR1(kX86Jmp8, 0 /* offset to be patched during assembly*/ ); res->target = target; return res; } -LIR* X86Codegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target) +LIR* X86Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) { - LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* offset to be patched */, + LIR* branch = NewLIR2(kX86Jcc8, 0 /* offset to be patched */, X86ConditionEncoding(cc)); branch->target = target; return branch; } -LIR* X86Codegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src) +LIR* X86Mir2Lir::OpReg(OpKind op, int r_dest_src) { X86OpCode opcode = kX86Bkpt; switch (op) { @@ -131,10 +129,10 @@ LIR* X86Codegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src) default: LOG(FATAL) << "Bad case in OpReg " << op; } - return NewLIR1(cu, opcode, r_dest_src); + return NewLIR1(opcode, r_dest_src); } -LIR* X86Codegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1, int value) +LIR* X86Mir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value) { X86OpCode opcode = kX86Bkpt; bool byte_imm = IS_SIMM8(value); @@ -151,28 +149,28 @@ LIR* X86Codegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1, int v case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break; case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break; case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break; - case kOpMov: return LoadConstantNoClobber(cu, r_dest_src1, value); + case kOpMov: return LoadConstantNoClobber(r_dest_src1, value); case kOpMul: opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI; - return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, value); + return NewLIR3(opcode, r_dest_src1, r_dest_src1, value); default: LOG(FATAL) << "Bad case in OpRegImm " << op; } - return NewLIR2(cu, opcode, r_dest_src1, value); + return NewLIR2(opcode, r_dest_src1, value); } -LIR* X86Codegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2) +LIR* X86Mir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) { X86OpCode opcode = kX86Nop; bool src2_must_be_cx = false; switch (op) { // X86 unary opcodes case kOpMvn: - OpRegCopy(cu, r_dest_src1, r_src2); - return OpReg(cu, kOpNot, r_dest_src1); + OpRegCopy(r_dest_src1, r_src2); + return OpReg(kOpNot, r_dest_src1); case kOpNeg: - OpRegCopy(cu, r_dest_src1, r_src2); - return OpReg(cu, kOpNeg, r_dest_src1); + OpRegCopy(r_dest_src1, r_src2); + return OpReg(kOpNeg, r_dest_src1); // X86 binary opcodes case kOpSub: opcode = kX86Sub32RR; break; case kOpSbc: opcode = kX86Sbb32RR; break; @@ -189,9 +187,9 @@ LIR* X86Codegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r case kOp2Byte: // Use shifts instead of a byte operand if the source can't be byte accessed. if (r_src2 >= 4) { - NewLIR2(cu, kX86Mov32RR, r_dest_src1, r_src2); - NewLIR2(cu, kX86Sal32RI, r_dest_src1, 24); - return NewLIR2(cu, kX86Sar32RI, r_dest_src1, 24); + NewLIR2(kX86Mov32RR, r_dest_src1, r_src2); + NewLIR2(kX86Sal32RI, r_dest_src1, 24); + return NewLIR2(kX86Sar32RI, r_dest_src1, 24); } else { opcode = kX86Movsx8RR; } @@ -204,10 +202,10 @@ LIR* X86Codegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r break; } CHECK(!src2_must_be_cx || r_src2 == rCX); - return NewLIR2(cu, opcode, r_dest_src1, r_src2); + return NewLIR2(opcode, r_dest_src1, r_src2); } -LIR* X86Codegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, +LIR* X86Mir2Lir::OpRegMem(OpKind op, int r_dest, int rBase, int offset) { X86OpCode opcode = kX86Nop; @@ -228,43 +226,43 @@ LIR* X86Codegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, LOG(FATAL) << "Bad case in OpRegMem " << op; break; } - return NewLIR3(cu, opcode, r_dest, rBase, offset); + return NewLIR3(opcode, r_dest, rBase, offset); } -LIR* X86Codegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1, +LIR* X86Mir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2) { if (r_dest != r_src1 && r_dest != r_src2) { if (op == kOpAdd) { // lea special case, except can't encode rbp as base if (r_src1 == r_src2) { - OpRegCopy(cu, r_dest, r_src1); - return OpRegImm(cu, kOpLsl, r_dest, 1); + OpRegCopy(r_dest, r_src1); + return OpRegImm(kOpLsl, r_dest, 1); } else if (r_src1 != rBP) { - return NewLIR5(cu, kX86Lea32RA, r_dest, r_src1 /* base */, + return NewLIR5(kX86Lea32RA, r_dest, r_src1 /* base */, r_src2 /* index */, 0 /* scale */, 0 /* disp */); } else { - return NewLIR5(cu, kX86Lea32RA, r_dest, r_src2 /* base */, + return NewLIR5(kX86Lea32RA, r_dest, r_src2 /* base */, r_src1 /* index */, 0 /* scale */, 0 /* disp */); } } else { - OpRegCopy(cu, r_dest, r_src1); - return OpRegReg(cu, op, r_dest, r_src2); + OpRegCopy(r_dest, r_src1); + return OpRegReg(op, r_dest, r_src2); } } else if (r_dest == r_src1) { - return OpRegReg(cu, op, r_dest, r_src2); + return OpRegReg(op, r_dest, r_src2); } else { // r_dest == r_src2 switch (op) { case kOpSub: // non-commutative - OpReg(cu, kOpNeg, r_dest); + OpReg(kOpNeg, r_dest); op = kOpAdd; break; case kOpSbc: case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: { - int t_reg = AllocTemp(cu); - OpRegCopy(cu, t_reg, r_src1); - OpRegReg(cu, op, t_reg, r_src2); - LIR* res = OpRegCopy(cu, r_dest, t_reg); - FreeTemp(cu, t_reg); + int t_reg = AllocTemp(); + OpRegCopy(t_reg, r_src1); + OpRegReg(op, t_reg, r_src2); + LIR* res = OpRegCopy(r_dest, t_reg); + FreeTemp(t_reg); return res; } case kOpAdd: // commutative @@ -276,38 +274,38 @@ LIR* X86Codegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_s default: LOG(FATAL) << "Bad case in OpRegRegReg " << op; } - return OpRegReg(cu, op, r_dest, r_src1); + return OpRegReg(op, r_dest, r_src1); } } -LIR* X86Codegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src, +LIR* X86Mir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src, int value) { if (op == kOpMul) { X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI; - return NewLIR3(cu, opcode, r_dest, r_src, value); + return NewLIR3(opcode, r_dest, r_src, value); } else if (op == kOpAnd) { if (value == 0xFF && r_src < 4) { - return NewLIR2(cu, kX86Movzx8RR, r_dest, r_src); + return NewLIR2(kX86Movzx8RR, r_dest, r_src); } else if (value == 0xFFFF) { - return NewLIR2(cu, kX86Movzx16RR, r_dest, r_src); + return NewLIR2(kX86Movzx16RR, r_dest, r_src); } } if (r_dest != r_src) { if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case // TODO: fix bug in LEA encoding when disp == 0 - return NewLIR5(cu, kX86Lea32RA, r_dest, r5sib_no_base /* base */, + return NewLIR5(kX86Lea32RA, r_dest, r5sib_no_base /* base */, r_src /* index */, value /* scale */, 0 /* disp */); } else if (op == kOpAdd) { // lea add special case - return NewLIR5(cu, kX86Lea32RA, r_dest, r_src /* base */, + return NewLIR5(kX86Lea32RA, r_dest, r_src /* base */, r4sib_no_index /* index */, 0 /* scale */, value /* disp */); } - OpRegCopy(cu, r_dest, r_src); + OpRegCopy(r_dest, r_src); } - return OpRegImm(cu, op, r_dest, value); + return OpRegImm(op, r_dest, value); } -LIR* X86Codegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset) +LIR* X86Mir2Lir::OpThreadMem(OpKind op, int thread_offset) { X86OpCode opcode = kX86Bkpt; switch (op) { @@ -316,10 +314,10 @@ LIR* X86Codegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset) LOG(FATAL) << "Bad opcode: " << op; break; } - return NewLIR1(cu, opcode, thread_offset); + return NewLIR1(opcode, thread_offset); } -LIR* X86Codegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp) +LIR* X86Mir2Lir::OpMem(OpKind op, int rBase, int disp) { X86OpCode opcode = kX86Bkpt; switch (op) { @@ -328,10 +326,10 @@ LIR* X86Codegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp) LOG(FATAL) << "Bad opcode: " << op; break; } - return NewLIR2(cu, opcode, rBase, disp); + return NewLIR2(opcode, rBase, disp); } -LIR* X86Codegen::LoadConstantWide(CompilationUnit *cu, int r_dest_lo, int r_dest_hi, int64_t value) +LIR* X86Mir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) { int32_t val_lo = Low32Bits(value); int32_t val_hi = High32Bits(value); @@ -339,27 +337,27 @@ LIR* X86Codegen::LoadConstantWide(CompilationUnit *cu, int r_dest_lo, int r_dest if (X86_FPREG(r_dest_lo)) { DCHECK(X86_FPREG(r_dest_hi)); // ignore r_dest_hi if (value == 0) { - return NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo); + return NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo); } else { if (val_lo == 0) { - res = NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo); + res = NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo); } else { - res = LoadConstantNoClobber(cu, r_dest_lo, val_lo); + res = LoadConstantNoClobber(r_dest_lo, val_lo); } if (val_hi != 0) { - LoadConstantNoClobber(cu, r_dest_hi, val_hi); - NewLIR2(cu, kX86PsllqRI, r_dest_hi, 32); - NewLIR2(cu, kX86OrpsRR, r_dest_lo, r_dest_hi); + LoadConstantNoClobber(r_dest_hi, val_hi); + NewLIR2(kX86PsllqRI, r_dest_hi, 32); + NewLIR2(kX86OrpsRR, r_dest_lo, r_dest_hi); } } } else { - res = LoadConstantNoClobber(cu, r_dest_lo, val_lo); - LoadConstantNoClobber(cu, r_dest_hi, val_hi); + res = LoadConstantNoClobber(r_dest_lo, val_lo); + LoadConstantNoClobber(r_dest_hi, val_hi); } return res; } -LIR* X86Codegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, +LIR* X86Mir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, int r_dest, int r_dest_hi, OpSize size, int s_reg) { LIR *load = NULL; @@ -416,40 +414,40 @@ LIR* X86Codegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index if (!is_array) { if (!pair) { - load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET); + load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET); } else { if (rBase == r_dest) { - load2 = NewLIR3(cu, opcode, r_dest_hi, rBase, + load2 = NewLIR3(opcode, r_dest_hi, rBase, displacement + HIWORD_OFFSET); - load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET); + load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET); } else { - load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET); - load2 = NewLIR3(cu, opcode, r_dest_hi, rBase, + load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET); + load2 = NewLIR3(opcode, r_dest_hi, rBase, displacement + HIWORD_OFFSET); } } if (rBase == rX86_SP) { - AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, + AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, true /* is_load */, is64bit); if (pair) { - AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2, + AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2, true /* is_load */, is64bit); } } } else { if (!pair) { - load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale, + load = NewLIR5(opcode, r_dest, rBase, r_index, scale, displacement + LOWORD_OFFSET); } else { if (rBase == r_dest) { - load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale, + load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale, displacement + HIWORD_OFFSET); - load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale, + load = NewLIR5(opcode, r_dest, rBase, r_index, scale, displacement + LOWORD_OFFSET); } else { - load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale, + load = NewLIR5(opcode, r_dest, rBase, r_index, scale, displacement + LOWORD_OFFSET); - load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale, + load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale, displacement + HIWORD_OFFSET); } } @@ -459,25 +457,25 @@ LIR* X86Codegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index } /* Load value from base + scaled index. */ -LIR* X86Codegen::LoadBaseIndexed(CompilationUnit *cu, int rBase, +LIR* X86Mir2Lir::LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size) { - return LoadBaseIndexedDisp(cu, rBase, r_index, scale, 0, + return LoadBaseIndexedDisp(rBase, r_index, scale, 0, r_dest, INVALID_REG, size, INVALID_SREG); } -LIR* X86Codegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement, +LIR* X86Mir2Lir::LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg) { - return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement, + return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement, r_dest, INVALID_REG, size, s_reg); } -LIR* X86Codegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement, +LIR* X86Mir2Lir::LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi, int s_reg) { - return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement, + return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement, r_dest_lo, r_dest_hi, kLong, s_reg); } -LIR* X86Codegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale, +LIR* X86Mir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement, int r_src, int r_src_hi, OpSize size, int s_reg) { LIR *store = NULL; @@ -529,27 +527,27 @@ LIR* X86Codegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_inde if (!is_array) { if (!pair) { - store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src); + store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src); } else { - store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src); - store2 = NewLIR3(cu, opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi); + store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src); + store2 = NewLIR3(opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi); } if (rBase == rX86_SP) { - AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, + AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, false /* is_load */, is64bit); if (pair) { - AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2, + AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2, false /* is_load */, is64bit); } } } else { if (!pair) { - store = NewLIR5(cu, opcode, rBase, r_index, scale, + store = NewLIR5(opcode, rBase, r_index, scale, displacement + LOWORD_OFFSET, r_src); } else { - store = NewLIR5(cu, opcode, rBase, r_index, scale, + store = NewLIR5(opcode, rBase, r_index, scale, displacement + LOWORD_OFFSET, r_src); - store2 = NewLIR5(cu, opcode, rBase, r_index, scale, + store2 = NewLIR5(opcode, rBase, r_index, scale, displacement + HIWORD_OFFSET, r_src_hi); } } @@ -558,25 +556,25 @@ LIR* X86Codegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_inde } /* store value base base + scaled index. */ -LIR* X86Codegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src, +LIR* X86Mir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size) { - return StoreBaseIndexedDisp(cu, rBase, r_index, scale, 0, + return StoreBaseIndexedDisp(rBase, r_index, scale, 0, r_src, INVALID_REG, size, INVALID_SREG); } -LIR* X86Codegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement, +LIR* X86Mir2Lir::StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size) { - return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0, + return StoreBaseIndexedDisp(rBase, INVALID_REG, 0, displacement, r_src, INVALID_REG, size, INVALID_SREG); } -LIR* X86Codegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement, +LIR* X86Mir2Lir::StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi) { - return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement, + return StoreBaseIndexedDisp(rBase, INVALID_REG, 0, displacement, r_src_lo, r_src_hi, kLong, INVALID_SREG); } diff --git a/src/compiler/dex/ssa_transformation.cc b/src/compiler/dex/ssa_transformation.cc index b13cf0563f..d8341e3444 100644 --- a/src/compiler/dex/ssa_transformation.cc +++ b/src/compiler/dex/ssa_transformation.cc @@ -17,6 +17,8 @@ #include "compiler_internals.h" #include "dataflow_iterator.h" +#define NOTVISITED (-1) + namespace art { BasicBlock* MIRGraph::NeedsVisit(BasicBlock* bb) { @@ -179,7 +181,7 @@ void MIRGraph::ComputeDomPostOrderTraversal(BasicBlock* bb) /* hacky loop detection */ if (bb->taken && IsBitSet(bb->dominators, bb->taken->id)) { - cu_->attributes |= METHOD_HAS_LOOP; + attributes_ |= METHOD_HAS_LOOP; } } @@ -352,9 +354,6 @@ bool MIRGraph::SetDominators(BasicBlock* bb) DCHECK_NE(idom_dfs_idx, NOTVISITED); int i_dom_idx = dfs_post_order_.elem_list[idom_dfs_idx]; BasicBlock* i_dom = GetBasicBlock(i_dom_idx); - if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) { - DCHECK_EQ(bb->i_dom->id, i_dom->id); - } bb->i_dom = i_dom; /* Add bb to the i_dominated set of the immediate dominator block */ SetBit(cu_, i_dom->i_dominated, bb->id); @@ -674,45 +673,43 @@ void MIRGraph::SSATransformation() /* Compute the DFS order */ ComputeDFSOrders(); - if (!cu_->disable_dataflow) { - /* Compute the dominator info */ - ComputeDominators(); - } + /* Compute the dominator info */ + ComputeDominators(); /* Allocate data structures in preparation for SSA conversion */ CompilerInitializeSSAConversion(); - if (!cu_->disable_dataflow) { - /* Find out the "Dalvik reg def x block" relation */ - ComputeDefBlockMatrix(); + /* Find out the "Dalvik reg def x block" relation */ + ComputeDefBlockMatrix(); - /* Insert phi nodes to dominance frontiers for all variables */ - InsertPhiNodes(); - } + /* Insert phi nodes to dominance frontiers for all variables */ + InsertPhiNodes(); /* Rename register names by local defs and phi nodes */ - AllNodesIterator iter(this, false /* not iterative */); - for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { + AllNodesIterator iter1(this, false /* not iterative */); + for (BasicBlock* bb = iter1.Next(); bb != NULL; bb = iter1.Next()) { ClearVisitedFlag(bb); } DoDFSPreOrderSSARename(GetEntryBlock()); - if (!cu_->disable_dataflow) { - /* - * Shared temp bit vector used by each block to count the number of defs - * from all the predecessor blocks. - */ - temp_ssa_register_v_ = AllocBitVector(cu_, GetNumSSARegs(), false, kBitMapTempSSARegisterV); + /* + * Shared temp bit vector used by each block to count the number of defs + * from all the predecessor blocks. + */ + temp_ssa_register_v_ = AllocBitVector(cu_, GetNumSSARegs(), false, kBitMapTempSSARegisterV); - /* Insert phi-operands with latest SSA names from predecessor blocks */ - ReachableNodesIterator iter(this, false /* not iterative */); - for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { - InsertPhiNodeOperands(bb); - } + /* Insert phi-operands with latest SSA names from predecessor blocks */ + ReachableNodesIterator iter2(this, false /* not iterative */); + for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) { + InsertPhiNodeOperands(bb); } + if (cu_->enable_debug & (1 << kDebugDumpCFG)) { DumpCFG("/sdcard/3_post_ssa_cfg/", false); } + if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) { + VerifyDataflow(); + } } } // namespace art diff --git a/src/compiler/dex/vreg_analysis.cc b/src/compiler/dex/vreg_analysis.cc index 08f1f35dc3..36daaeaf38 100644 --- a/src/compiler/dex/vreg_analysis.cc +++ b/src/compiler/dex/vreg_analysis.cc @@ -16,53 +16,52 @@ #include "compiler_internals.h" #include "dataflow_iterator.h" -#include "quick/ralloc_util.h" namespace art { -static bool SetFp(CompilationUnit* cu, int index, bool is_fp) { +bool MIRGraph::SetFp(int index, bool is_fp) { bool change = false; - if (is_fp && !cu->reg_location[index].fp) { - cu->reg_location[index].fp = true; - cu->reg_location[index].defined = true; + if (is_fp && !reg_location_[index].fp) { + reg_location_[index].fp = true; + reg_location_[index].defined = true; change = true; } return change; } -static bool SetCore(CompilationUnit* cu, int index, bool is_core) { +bool MIRGraph::SetCore(int index, bool is_core) { bool change = false; - if (is_core && !cu->reg_location[index].defined) { - cu->reg_location[index].core = true; - cu->reg_location[index].defined = true; + if (is_core && !reg_location_[index].defined) { + reg_location_[index].core = true; + reg_location_[index].defined = true; change = true; } return change; } -static bool SetRef(CompilationUnit* cu, int index, bool is_ref) { +bool MIRGraph::SetRef(int index, bool is_ref) { bool change = false; - if (is_ref && !cu->reg_location[index].defined) { - cu->reg_location[index].ref = true; - cu->reg_location[index].defined = true; + if (is_ref && !reg_location_[index].defined) { + reg_location_[index].ref = true; + reg_location_[index].defined = true; change = true; } return change; } -static bool SetWide(CompilationUnit* cu, int index, bool is_wide) { +bool MIRGraph::SetWide(int index, bool is_wide) { bool change = false; - if (is_wide && !cu->reg_location[index].wide) { - cu->reg_location[index].wide = true; + if (is_wide && !reg_location_[index].wide) { + reg_location_[index].wide = true; change = true; } return change; } -static bool SetHigh(CompilationUnit* cu, int index, bool is_high) { +bool MIRGraph::SetHigh(int index, bool is_high) { bool change = false; - if (is_high && !cu->reg_location[index].high_word) { - cu->reg_location[index].high_word = true; + if (is_high && !reg_location_[index].high_word) { + reg_location_[index].high_word = true; change = true; } return change; @@ -85,20 +84,20 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { SSARepresentation *ssa_rep = mir->ssa_rep; if (ssa_rep) { - int attrs = oat_data_flow_attributes[mir->dalvikInsn.opcode]; + int attrs = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; // Handle defs if (attrs & DF_DA) { if (attrs & DF_CORE_A) { - changed |= SetCore(cu_, ssa_rep->defs[0], true); + changed |= SetCore(ssa_rep->defs[0], true); } if (attrs & DF_REF_A) { - changed |= SetRef(cu_, ssa_rep->defs[0], true); + changed |= SetRef(ssa_rep->defs[0], true); } if (attrs & DF_A_WIDE) { - cu_->reg_location[ssa_rep->defs[0]].wide = true; - cu_->reg_location[ssa_rep->defs[1]].wide = true; - cu_->reg_location[ssa_rep->defs[1]].high_word = true; + reg_location_[ssa_rep->defs[0]].wide = true; + reg_location_[ssa_rep->defs[1]].wide = true; + reg_location_[ssa_rep->defs[1]].high_word = true; DCHECK_EQ(SRegToVReg(ssa_rep->defs[0])+1, SRegToVReg(ssa_rep->defs[1])); } @@ -108,15 +107,15 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) int next = 0; if (attrs & DF_UA) { if (attrs & DF_CORE_A) { - changed |= SetCore(cu_, ssa_rep->uses[next], true); + changed |= SetCore(ssa_rep->uses[next], true); } if (attrs & DF_REF_A) { - changed |= SetRef(cu_, ssa_rep->uses[next], true); + changed |= SetRef(ssa_rep->uses[next], true); } if (attrs & DF_A_WIDE) { - cu_->reg_location[ssa_rep->uses[next]].wide = true; - cu_->reg_location[ssa_rep->uses[next + 1]].wide = true; - cu_->reg_location[ssa_rep->uses[next + 1]].high_word = true; + reg_location_[ssa_rep->uses[next]].wide = true; + reg_location_[ssa_rep->uses[next + 1]].wide = true; + reg_location_[ssa_rep->uses[next + 1]].high_word = true; DCHECK_EQ(SRegToVReg(ssa_rep->uses[next])+1, SRegToVReg(ssa_rep->uses[next + 1])); next += 2; @@ -126,15 +125,15 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) } if (attrs & DF_UB) { if (attrs & DF_CORE_B) { - changed |= SetCore(cu_, ssa_rep->uses[next], true); + changed |= SetCore(ssa_rep->uses[next], true); } if (attrs & DF_REF_B) { - changed |= SetRef(cu_, ssa_rep->uses[next], true); + changed |= SetRef(ssa_rep->uses[next], true); } if (attrs & DF_B_WIDE) { - cu_->reg_location[ssa_rep->uses[next]].wide = true; - cu_->reg_location[ssa_rep->uses[next + 1]].wide = true; - cu_->reg_location[ssa_rep->uses[next + 1]].high_word = true; + reg_location_[ssa_rep->uses[next]].wide = true; + reg_location_[ssa_rep->uses[next + 1]].wide = true; + reg_location_[ssa_rep->uses[next + 1]].high_word = true; DCHECK_EQ(SRegToVReg(ssa_rep->uses[next])+1, SRegToVReg(ssa_rep->uses[next + 1])); next += 2; @@ -144,15 +143,15 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) } if (attrs & DF_UC) { if (attrs & DF_CORE_C) { - changed |= SetCore(cu_, ssa_rep->uses[next], true); + changed |= SetCore(ssa_rep->uses[next], true); } if (attrs & DF_REF_C) { - changed |= SetRef(cu_, ssa_rep->uses[next], true); + changed |= SetRef(ssa_rep->uses[next], true); } if (attrs & DF_C_WIDE) { - cu_->reg_location[ssa_rep->uses[next]].wide = true; - cu_->reg_location[ssa_rep->uses[next + 1]].wide = true; - cu_->reg_location[ssa_rep->uses[next + 1]].high_word = true; + reg_location_[ssa_rep->uses[next]].wide = true; + reg_location_[ssa_rep->uses[next + 1]].wide = true; + reg_location_[ssa_rep->uses[next + 1]].high_word = true; DCHECK_EQ(SRegToVReg(ssa_rep->uses[next])+1, SRegToVReg(ssa_rep->uses[next + 1])); } @@ -164,27 +163,27 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) { switch(cu_->shorty[0]) { case 'I': - changed |= SetCore(cu_, ssa_rep->uses[0], true); + changed |= SetCore(ssa_rep->uses[0], true); break; case 'J': - changed |= SetCore(cu_, ssa_rep->uses[0], true); - changed |= SetCore(cu_, ssa_rep->uses[1], true); - cu_->reg_location[ssa_rep->uses[0]].wide = true; - cu_->reg_location[ssa_rep->uses[1]].wide = true; - cu_->reg_location[ssa_rep->uses[1]].high_word = true; + changed |= SetCore(ssa_rep->uses[0], true); + changed |= SetCore(ssa_rep->uses[1], true); + reg_location_[ssa_rep->uses[0]].wide = true; + reg_location_[ssa_rep->uses[1]].wide = true; + reg_location_[ssa_rep->uses[1]].high_word = true; break; case 'F': - changed |= SetFp(cu_, ssa_rep->uses[0], true); + changed |= SetFp(ssa_rep->uses[0], true); break; case 'D': - changed |= SetFp(cu_, ssa_rep->uses[0], true); - changed |= SetFp(cu_, ssa_rep->uses[1], true); - cu_->reg_location[ssa_rep->uses[0]].wide = true; - cu_->reg_location[ssa_rep->uses[1]].wide = true; - cu_->reg_location[ssa_rep->uses[1]].high_word = true; + changed |= SetFp(ssa_rep->uses[0], true); + changed |= SetFp(ssa_rep->uses[1], true); + reg_location_[ssa_rep->uses[0]].wide = true; + reg_location_[ssa_rep->uses[1]].wide = true; + reg_location_[ssa_rep->uses[1]].high_word = true; break; case 'L': - changed |= SetRef(cu_, ssa_rep->uses[0], true); + changed |= SetRef(ssa_rep->uses[0], true); break; default: break; } @@ -198,7 +197,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) { DCHECK_EQ(next, 0); int target_idx = mir->dalvikInsn.vB; - const char* shorty = GetShortyFromTargetIdx(cu_, target_idx); + const char* shorty = GetShortyFromTargetIdx(target_idx); // Handle result type if floating point if ((shorty[0] == 'F') || (shorty[0] == 'D')) { MIR* move_result_mir = FindMoveResult(bb, mir); @@ -208,10 +207,10 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) SSARepresentation* tgt_rep = move_result_mir->ssa_rep; DCHECK(tgt_rep != NULL); tgt_rep->fp_def[0] = true; - changed |= SetFp(cu_, tgt_rep->defs[0], true); + changed |= SetFp(tgt_rep->defs[0], true); if (shorty[0] == 'D') { tgt_rep->fp_def[1] = true; - changed |= SetFp(cu_, tgt_rep->defs[1], true); + changed |= SetFp(tgt_rep->defs[1], true); } } } @@ -219,8 +218,8 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) // If this is a non-static invoke, mark implicit "this" if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) && (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) { - cu_->reg_location[ssa_rep->uses[next]].defined = true; - cu_->reg_location[ssa_rep->uses[next]].ref = true; + reg_location_[ssa_rep->uses[next]].defined = true; + reg_location_[ssa_rep->uses[next]].ref = true; next++; } uint32_t cpos = 1; @@ -231,28 +230,28 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) case 'D': ssa_rep->fp_use[i] = true; ssa_rep->fp_use[i+1] = true; - cu_->reg_location[ssa_rep->uses[i]].wide = true; - cu_->reg_location[ssa_rep->uses[i+1]].wide = true; - cu_->reg_location[ssa_rep->uses[i+1]].high_word = true; + reg_location_[ssa_rep->uses[i]].wide = true; + reg_location_[ssa_rep->uses[i+1]].wide = true; + reg_location_[ssa_rep->uses[i+1]].high_word = true; DCHECK_EQ(SRegToVReg(ssa_rep->uses[i])+1, SRegToVReg(ssa_rep->uses[i+1])); i++; break; case 'J': - cu_->reg_location[ssa_rep->uses[i]].wide = true; - cu_->reg_location[ssa_rep->uses[i+1]].wide = true; - cu_->reg_location[ssa_rep->uses[i+1]].high_word = true; + reg_location_[ssa_rep->uses[i]].wide = true; + reg_location_[ssa_rep->uses[i+1]].wide = true; + reg_location_[ssa_rep->uses[i+1]].high_word = true; DCHECK_EQ(SRegToVReg(ssa_rep->uses[i])+1, SRegToVReg(ssa_rep->uses[i+1])); - changed |= SetCore(cu_, ssa_rep->uses[i],true); + changed |= SetCore(ssa_rep->uses[i],true); i++; break; case 'F': ssa_rep->fp_use[i] = true; break; case 'L': - changed |= SetRef(cu_,ssa_rep->uses[i], true); + changed |= SetRef(ssa_rep->uses[i], true); break; default: - changed |= SetCore(cu_,ssa_rep->uses[i], true); + changed |= SetCore(ssa_rep->uses[i], true); break; } i++; @@ -262,11 +261,11 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) for (int i=0; ssa_rep->fp_use && i< ssa_rep->num_uses; i++) { if (ssa_rep->fp_use[i]) - changed |= SetFp(cu_, ssa_rep->uses[i], true); + changed |= SetFp(ssa_rep->uses[i], true); } for (int i=0; ssa_rep->fp_def && i< ssa_rep->num_defs; i++) { if (ssa_rep->fp_def[i]) - changed |= SetFp(cu_, ssa_rep->defs[i], true); + changed |= SetFp(ssa_rep->defs[i], true); } // Special-case handling for moves & Phi if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) { @@ -278,14 +277,14 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) */ bool is_phi = (static_cast<int>(mir->dalvikInsn.opcode) == kMirOpPhi); - RegLocation rl_temp = cu_->reg_location[ssa_rep->defs[0]]; + RegLocation rl_temp = reg_location_[ssa_rep->defs[0]]; bool defined_fp = rl_temp.defined && rl_temp.fp; bool defined_core = rl_temp.defined && rl_temp.core; bool defined_ref = rl_temp.defined && rl_temp.ref; bool is_wide = rl_temp.wide || ((attrs & DF_A_WIDE) != 0); bool is_high = is_phi && rl_temp.wide && rl_temp.high_word; for (int i = 0; i < ssa_rep->num_uses;i++) { - rl_temp = cu_->reg_location[ssa_rep->uses[i]]; + rl_temp = reg_location_[ssa_rep->uses[i]]; defined_fp |= rl_temp.defined && rl_temp.fp; defined_core |= rl_temp.defined && rl_temp.core; defined_ref |= rl_temp.defined && rl_temp.ref; @@ -313,26 +312,26 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb) << " has both fp and core/ref uses for same def."; cu_->disable_opt |= (1 << kPromoteRegs); } - changed |= SetFp(cu_, ssa_rep->defs[0], defined_fp); - changed |= SetCore(cu_, ssa_rep->defs[0], defined_core); - changed |= SetRef(cu_, ssa_rep->defs[0], defined_ref); - changed |= SetWide(cu_, ssa_rep->defs[0], is_wide); - changed |= SetHigh(cu_, ssa_rep->defs[0], is_high); + changed |= SetFp(ssa_rep->defs[0], defined_fp); + changed |= SetCore(ssa_rep->defs[0], defined_core); + changed |= SetRef(ssa_rep->defs[0], defined_ref); + changed |= SetWide(ssa_rep->defs[0], is_wide); + changed |= SetHigh(ssa_rep->defs[0], is_high); if (attrs & DF_A_WIDE) { - changed |= SetWide(cu_, ssa_rep->defs[1], true); - changed |= SetHigh(cu_, ssa_rep->defs[1], true); + changed |= SetWide(ssa_rep->defs[1], true); + changed |= SetHigh(ssa_rep->defs[1], true); } for (int i = 0; i < ssa_rep->num_uses; i++) { - changed |= SetFp(cu_, ssa_rep->uses[i], defined_fp); - changed |= SetCore(cu_, ssa_rep->uses[i], defined_core); - changed |= SetRef(cu_, ssa_rep->uses[i], defined_ref); - changed |= SetWide(cu_, ssa_rep->uses[i], is_wide); - changed |= SetHigh(cu_, ssa_rep->uses[i], is_high); + changed |= SetFp(ssa_rep->uses[i], defined_fp); + changed |= SetCore(ssa_rep->uses[i], defined_core); + changed |= SetRef(ssa_rep->uses[i], defined_ref); + changed |= SetWide(ssa_rep->uses[i], is_wide); + changed |= SetHigh(ssa_rep->uses[i], is_high); } if (attrs & DF_A_WIDE) { DCHECK_EQ(ssa_rep->num_uses, 2); - changed |= SetWide(cu_, ssa_rep->uses[1], true); - changed |= SetHigh(cu_, ssa_rep->uses[1], true); + changed |= SetWide(ssa_rep->uses[1], true); + changed |= SetHigh(ssa_rep->uses[1], true); } } } @@ -344,7 +343,8 @@ static const char* storage_name[] = {" Frame ", "PhysReg", " Spill "}; void MIRGraph::DumpRegLocTable(RegLocation* table, int count) { - Codegen* cg = cu_->cg.get(); + //FIXME: Quick-specific. Move to Quick (and make a generic version for MIRGraph? + Mir2Lir* cg = static_cast<Mir2Lir*>(cu_->cg.get()); if (cg != NULL) { for (int i = 0; i < count; i++) { LOG(INFO) << StringPrintf("Loc[%02d] : %s, %c %c %c %c %c %c %c%d %c%d S%d", @@ -376,17 +376,6 @@ static const RegLocation fresh_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0, INVALID_REG, INVALID_REG, INVALID_SREG, INVALID_SREG}; -int MIRGraph::ComputeFrameSize() { - /* Figure out the frame size */ - static const uint32_t kAlignMask = kStackAlignment - 1; - uint32_t size = (cu_->num_core_spills + cu_->num_fp_spills + - 1 /* filler word */ + cu_->num_regs + cu_->num_outs + - cu_->num_compiler_temps + 1 /* cur_method* */) - * sizeof(uint32_t); - /* Align and set */ - return (size + kAlignMask) & ~(kAlignMask); -} - /* * Simple register allocation. Some Dalvik virtual registers may * be promoted to physical registers. Most of the work for temp @@ -408,21 +397,17 @@ void MIRGraph::BuildRegLocations() } /* Patch up the locations for Method* and the compiler temps */ - loc[cu_->method_sreg].location = kLocCompilerTemp; - loc[cu_->method_sreg].defined = true; + loc[method_sreg_].location = kLocCompilerTemp; + loc[method_sreg_].defined = true; for (i = 0; i < cu_->num_compiler_temps; i++) { - CompilerTemp* ct = reinterpret_cast<CompilerTemp*>(cu_->compiler_temps.elem_list[i]); + CompilerTemp* ct = reinterpret_cast<CompilerTemp*>(compiler_temps_.elem_list[i]); loc[ct->s_reg].location = kLocCompilerTemp; loc[ct->s_reg].defined = true; } - cu_->reg_location = loc; + reg_location_ = loc; - /* Allocation the promotion map */ int num_regs = cu_->num_dalvik_registers; - cu_->promotion_map = static_cast<PromotionMap*> - (NewMem(cu_, (num_regs + cu_->num_compiler_temps + 1) * sizeof(cu_->promotion_map[0]), - true, kAllocRegAlloc)); /* Add types of incoming arguments based on signature */ int num_ins = cu_->num_ins; @@ -430,8 +415,8 @@ void MIRGraph::BuildRegLocations() int s_reg = num_regs - num_ins; if ((cu_->access_flags & kAccStatic) == 0) { // For non-static, skip past "this" - cu_->reg_location[s_reg].defined = true; - cu_->reg_location[s_reg].ref = true; + reg_location_[s_reg].defined = true; + reg_location_[s_reg].ref = true; s_reg++; } const char* shorty = cu_->shorty; @@ -439,33 +424,33 @@ void MIRGraph::BuildRegLocations() for (int i = 1; i < shorty_len; i++) { switch (shorty[i]) { case 'D': - cu_->reg_location[s_reg].wide = true; - cu_->reg_location[s_reg+1].high_word = true; - cu_->reg_location[s_reg+1].fp = true; + reg_location_[s_reg].wide = true; + reg_location_[s_reg+1].high_word = true; + reg_location_[s_reg+1].fp = true; DCHECK_EQ(SRegToVReg(s_reg)+1, SRegToVReg(s_reg+1)); - cu_->reg_location[s_reg].fp = true; - cu_->reg_location[s_reg].defined = true; + reg_location_[s_reg].fp = true; + reg_location_[s_reg].defined = true; s_reg++; break; case 'J': - cu_->reg_location[s_reg].wide = true; - cu_->reg_location[s_reg+1].high_word = true; + reg_location_[s_reg].wide = true; + reg_location_[s_reg+1].high_word = true; DCHECK_EQ(SRegToVReg(s_reg)+1, SRegToVReg(s_reg+1)); - cu_->reg_location[s_reg].core = true; - cu_->reg_location[s_reg].defined = true; + reg_location_[s_reg].core = true; + reg_location_[s_reg].defined = true; s_reg++; break; case 'F': - cu_->reg_location[s_reg].fp = true; - cu_->reg_location[s_reg].defined = true; + reg_location_[s_reg].fp = true; + reg_location_[s_reg].defined = true; break; case 'L': - cu_->reg_location[s_reg].ref = true; - cu_->reg_location[s_reg].defined = true; + reg_location_[s_reg].ref = true; + reg_location_[s_reg].defined = true; break; default: - cu_->reg_location[s_reg].core = true; - cu_->reg_location[s_reg].defined = true; + reg_location_[s_reg].core = true; + reg_location_[s_reg].defined = true; break; } s_reg++; @@ -485,10 +470,10 @@ void MIRGraph::BuildRegLocations() * allocator, remove this remapping. */ for (i=0; i < GetNumSSARegs(); i++) { - if (cu_->reg_location[i].location != kLocCompilerTemp) { - int orig_sreg = cu_->reg_location[i].s_reg_low; - cu_->reg_location[i].orig_sreg = orig_sreg; - cu_->reg_location[i].s_reg_low = SRegToVReg(orig_sreg); + if (reg_location_[i].location != kLocCompilerTemp) { + int orig_sreg = reg_location_[i].s_reg_low; + reg_location_[i].orig_sreg = orig_sreg; + reg_location_[i].s_reg_low = SRegToVReg(orig_sreg); } } } diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h index f398e31265..af04cbfb17 100644 --- a/src/compiler/driver/compiler_driver.h +++ b/src/compiler/driver/compiler_driver.h @@ -41,7 +41,8 @@ class TimingLogger; enum CompilerBackend { kQuick, - kPortable + kPortable, + kNoBackend }; // Thread-local storage compiler worker threads diff --git a/src/compiler/llvm/gbc_expander.cc b/src/compiler/llvm/gbc_expander.cc index 24f2032319..94eb741039 100644 --- a/src/compiler/llvm/gbc_expander.cc +++ b/src/compiler/llvm/gbc_expander.cc @@ -28,7 +28,7 @@ #include "compiler/dex/mir_graph.h" #include "compiler/dex/compiler_ir.h" -#include "compiler/dex/quick/codegen.h" +#include "compiler/dex/quick/mir_to_lir.h" using art::kMIRIgnoreNullCheck; using art::kMIRIgnoreRangeCheck; |