Quick compiler: Single .so for all targets
With this CL, all targets can be built into a single .so (but
we're not yet doing so - the compiler driver needs to be reworked).
A new Codgen class is introduced (see compiler/codegen/codegen.h),
along with target-specific sub-classes ArmCodegen, MipsCodegens and
X86Codegen (see compiler/codegen/*/codegen_[Arm|Mips|X86].h).
Additional minor code, comment and format refactoring. Some source
files combined, temporary header files deleted and a few file
renames to better identify their function.
Next up is combining the Quick and Portable .so files.
Note: building all targets into libdvm-compiler.so increases its
size by 140K bytes. I'm inclined to not bother introducing conditional
compilation to limit code to the specific target - the added build and
testing complexity doesn't doesn't seem worth such a modest size savings.
Change-Id: Id9c5b4502ad6b77cdb31f71d3126f51a4f2e9dfe
diff --git a/src/compiler/compiler_ir.h b/src/compiler/compiler_ir.h
index e7a5e73..2923587 100644
--- a/src/compiler/compiler_ir.h
+++ b/src/compiler/compiler_ir.h
@@ -36,7 +36,7 @@
#define EXERCISE_SLOWEST_STRING_PATH (cu->enable_debug & \
(1 << kDebugSlowestStringPath))
-// Minimum field size to contain Dalvik v_reg number
+// Minimum field size to contain Dalvik v_reg number.
#define VREG_NUM_WIDTH 16
struct ArenaBitVector;
@@ -55,17 +55,17 @@
RegLocationType location:3;
unsigned wide:1;
unsigned defined:1; // Do we know the type?
- unsigned is_const:1; // Constant, value in cu->constant_values[]
+ unsigned is_const:1; // Constant, value in cu->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 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
+ 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 {
@@ -74,19 +74,19 @@
};
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 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
+ 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
+ RegLocation target; // Target of following move_result.
bool skip_this;
bool is_range;
- int offset; // Dalvik offset
+ int offset; // Dalvik offset.
};
/*
@@ -97,15 +97,15 @@
*/
struct RegisterInfo {
int reg; // Reg number
- bool in_use; // Has it been allocated?
- bool is_temp; // Can allocate as temp?
+ 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
+ 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
+ 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 {
@@ -138,21 +138,21 @@
#define MANY_BLOCKS_INITIALIZER 1000 /* Threshold for switching dataflow off */
#define MANY_BLOCKS 4000 /* Non-initializer threshold */
-/* Utility macros to traverse the LIR list */
+// 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) */
+// 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 */
+// Common resource macros.
#define ENCODE_CCODE (1ULL << kCCode)
#define ENCODE_FP_STATUS (1ULL << kFPStatus)
-/* Abstract memory locations */
+// Abstract memory locations.
#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
#define ENCODE_LITERAL (1ULL << kLiteral)
#define ENCODE_HEAP_REF (1ULL << kHeapRef)
@@ -165,22 +165,22 @@
#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
+ 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]
+ 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; // in bytes
+ 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
+ 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];
@@ -214,9 +214,9 @@
SSARepresentation* ssa_rep;
int optimization_flags;
union {
- // Used to quickly locate all Phi opcodes
+ // Used to quickly locate all Phi opcodes.
MIR* phi_next;
- // Establish link between two halves of throwing instructions
+ // Establish link between two halves of throwing instructions.
MIR* throw_insn;
} meta;
};
@@ -239,14 +239,14 @@
MIR* last_mir_insn;
BasicBlock* fall_through;
BasicBlock* taken;
- BasicBlock* i_dom; // Immediate dominator
+ 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
+ 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;
};
@@ -266,6 +266,7 @@
struct RegisterPool;
struct ArenaMemBlock;
struct Memstats;
+class Codegen;
#define NOTVISITED (-1)
@@ -360,29 +361,30 @@
#ifndef NDEBUG
live_sreg(0),
#endif
- opcode_count(NULL) {}
+ opcode_count(NULL),
+ cg(NULL) {}
int num_blocks;
GrowableList block_list;
- Compiler* compiler; // Compiler driving this compiler
- ClassLinker* class_linker; // Linker to resolve fields and methods
- const DexFile* dex_file; // DexFile containing the method being compiled
- jobject class_loader; // compiling method's class loader
- uint32_t method_idx; // compiling method's index into method_ids of DexFile
- const DexFile::CodeItem* code_item; // compiling method's DexFile code_item
- uint32_t access_flags; // compiling method's access flags
- InvokeType invoke_type; // compiling method's invocation type
- const char* shorty; // compiling method's shorty
+ Compiler* compiler; // Compiler driving this compiler.
+ ClassLinker* class_linker; // Linker to resolve fields and methods.
+ const DexFile* dex_file; // DexFile containing the method being compiled.
+ jobject class_loader; // compiling method's class loader.
+ uint32_t method_idx; // compiling method's index into method_ids of DexFile.
+ const DexFile::CodeItem* code_item; // compiling method's DexFile code_item.
+ uint32_t access_flags; // compiling method's access flags.
+ InvokeType invoke_type; // compiling method's invocation type.
+ const char* shorty; // compiling method's shorty.
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
- uint32_t disable_opt; // opt_control_vector flags
- uint32_t enable_debug; // debugControlVector flags
- int data_offset; // starting offset of literal pool
- int total_size; // header + code size
- AssemblerStatus assembler_status; // Success or fix and retry
+ LIR* literal_list; // Constants.
+ LIR* method_literal_list; // Method literals requiring patching.
+ LIR* code_literal_list; // Code literals requiring patching.
+ uint32_t disable_opt; // opt_control_vector flags.
+ uint32_t enable_debug; // debugControlVector flags.
+ int data_offset; // starting offset of literal pool.
+ int total_size; // header + code size.
+ AssemblerStatus assembler_status; // Success or fix and retry.
int assembler_retries;
std::vector<uint8_t> code_buffer;
/*
@@ -401,46 +403,45 @@
std::vector<uint32_t> fp_vmap_table;
std::vector<uint8_t> native_gc_map;
bool verbose;
- bool has_loop; // Contains a loop
- bool has_invoke; // Contains an invoke instruction
- bool qd_mode; // Compile for code size/compile time
+ bool has_loop; // Contains a loop.
+ bool has_invoke; // Contains an invoke instruction.
+ bool qd_mode; // Compile for code size/compile time.
RegisterPool* reg_pool;
InstructionSet instruction_set;
- /* Number of total regs used in the whole cu after SSA transformation */
+ // Number of total regs used in the whole cu after SSA transformation .
int num_ssa_regs;
- /* Map SSA reg i to the base virtual register/subscript */
+ // Map SSA reg i to the base virtual register/subscript.
GrowableList* ssa_base_vregs;
GrowableList* ssa_subscripts;
GrowableList* ssa_strings;
- /* The following are new data structures to support SSA representations */
- /* Map original Dalvik virtual reg i to the current SSA name */
- int* vreg_to_ssa_map; // length == method->registers_size
- int* ssa_last_defs; // length == method->registers_size
- ArenaBitVector* is_constant_v; // length == num_ssa_reg
- int* constant_values; // length == num_ssa_reg
- int* phi_alias_map; // length == num_ssa_reg
+ // Map original Dalvik virtual reg i to the current SSA name.
+ int* vreg_to_ssa_map; // length == method->registers_size
+ int* ssa_last_defs; // length == method->registers_size
+ ArenaBitVector* is_constant_v; // length == num_ssa_reg
+ int* constant_values; // length == num_ssa_reg
+ int* phi_alias_map; // length == num_ssa_reg
MIR* phi_list;
- /* Use counts of ssa names */
- GrowableList use_counts; // Weighted by nesting depth
- GrowableList raw_use_counts; // Not weighted
+ // Use counts of ssa names.
+ GrowableList use_counts; // Weighted by nesting depth
+ GrowableList raw_use_counts; // Not weighted
- /* Optimization support */
+ // Optimization support.
GrowableList loop_headers;
- /* Map SSA names to location */
+ // Map SSA names to location.
RegLocation* reg_location;
- /* Keep track of Dalvik v_reg to physical register mappings */
+ // Keep track of Dalvik v_reg to physical register mappings.
PromotionMap* promotion_map;
- /* SSA name for Method* */
+ // SSA name for Method*.
int method_sreg;
- RegLocation method_loc; // Describes location of method*
+ RegLocation method_loc; // Describes location of method*.
int num_reachable_blocks;
- int num_dalvik_registers; // method->registers_size
+ int num_dalvik_registers; // method->registers_size.
BasicBlock* entry_block;
BasicBlock* exit_block;
BasicBlock* cur_block;
@@ -453,11 +454,11 @@
GrowableList compiler_temps;
int* i_dom_list;
ArenaBitVector* try_block_addr;
- ArenaBitVector** def_block_matrix; // num_dalvik_register x num_blocks
+ ArenaBitVector** def_block_matrix; // num_dalvik_register x num_blocks.
ArenaBitVector* temp_block_v;
ArenaBitVector* temp_dalvik_register_v;
- ArenaBitVector* temp_ssa_register_v; // num_ssa_regs
- int* temp_ssa_block_id_v; // working storage for Phi labels
+ ArenaBitVector* temp_ssa_register_v; // num_ssa_regs.
+ int* temp_ssa_block_id_v; // working storage for Phi labels.
LIR* block_label_list;
/*
* Frame layout details.
@@ -467,7 +468,7 @@
*/
int num_ins;
int num_outs;
- int num_regs; // Unlike num_dalvik_registers, does not include ins
+ int num_regs; // Unlike num_dalvik_registers, does not include ins.
int num_core_spills;
int num_fp_spills;
int num_compiler_temps;
@@ -476,14 +477,13 @@
unsigned int fp_spill_mask;
unsigned int attrs;
/*
- * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
+ * 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. Should
- * be rewritten.
+ * The low-level LIR creation utilites will pull it from here. Rework this.
*/
int current_dalvik_offset;
GrowableList switch_tables;
@@ -491,10 +491,10 @@
const uint16_t* insns;
uint32_t insns_size;
bool disable_dataflow; // Skip dataflow analysis if possible
- SafeMap<unsigned int, BasicBlock*> block_map; // FindBlock lookup cache
- SafeMap<unsigned int, unsigned int> block_id_map; // Block collapse lookup cache
- SafeMap<unsigned int, LIR*> boundary_map; // boundary lookup cache
- int def_count; // Used to estimate number of SSA names
+ SafeMap<unsigned int, BasicBlock*> block_map; // FindBlock lookup cache.
+ SafeMap<unsigned int, unsigned int> block_id_map; // Block collapse lookup cache.
+ SafeMap<unsigned int, LIR*> boundary_map; // boundary lookup cache.
+ int def_count; // Used to estimate number of SSA names.
// If non-empty, apply optimizer/debug flags only to matching methods.
std::string compiler_method_match;
@@ -518,9 +518,9 @@
std::string bitcode_filename;
GrowableList llvm_values;
int32_t temp_name;
- SafeMap<llvm::BasicBlock*, LIR*> block_to_label_map; // llvm bb -> LIR label
- SafeMap<int32_t, llvm::BasicBlock*> id_to_block_map; // block id -> llvm bb
- SafeMap<llvm::Value*, RegLocation> loc_map; // llvm Value to loc rec
+ SafeMap<llvm::BasicBlock*, LIR*> block_to_label_map; // llvm bb -> LIR label.
+ SafeMap<int32_t, llvm::BasicBlock*> id_to_block_map; // block id -> llvm bb.
+ SafeMap<llvm::Value*, RegLocation> loc_map; // llvm Value to loc rec.
int num_shadow_frame_entries;
int* shadow_map;
std::set<llvm::BasicBlock*> llvm_blocks;
@@ -533,22 +533,23 @@
int live_sreg;
#endif
std::set<uint32_t> catches;
- int* opcode_count; // Count Dalvik opcodes for tuning
+ int* opcode_count; // Count Dalvik opcodes for tuning.
+ UniquePtr<Codegen> cg;
};
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
+ 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
+ const uint16_t* table; // Original dex table.
int size;
- int vaddr; // Dalvik offset of FILL_ARRAY_DATA opcode
+ int vaddr; // Dalvik offset of FILL_ARRAY_DATA opcode.
};
#define MAX_PATTERN_LEN 5
@@ -583,24 +584,6 @@
{{Instruction::RETURN_WIDE}, kIdentity},
};
-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);
-
-MIR* FindMoveResult(CompilationUnit* cu, BasicBlock* bb, MIR* mir);
-/* Debug Utilities */
-void DumpCompilationUnit(CompilationUnit* cu);
-
} // namespace art
#endif // ART_SRC_COMPILER_COMPILER_IR_H_