diff options
author | Zheng Xu <zheng.xu@arm.com> | 2014-05-06 18:06:07 +0100 |
---|---|---|
committer | Zheng Xu <zheng.xu@arm.com> | 2014-05-07 15:06:29 +0100 |
commit | 9e06c8cd4a2e1471754470e09aaab63c0795b4af (patch) | |
tree | c8f7889b9740c9189ac0f11720ff9e18a41b1102 | |
parent | 7189fee4268c70d7ed0151e988ff7c7cd85f2a30 (diff) | |
download | art-9e06c8cd4a2e1471754470e09aaab63c0795b4af.tar.gz art-9e06c8cd4a2e1471754470e09aaab63c0795b4af.tar.bz2 art-9e06c8cd4a2e1471754470e09aaab63c0795b4af.zip |
AArch64: Add fake arm64 backend, and disable it by method filter.
Just create an ArmCodeGenerator for arm64, but currently no code will
be generated for arm64.
The method filter can:
1. Skip methods with unsupported prototype.
2. Skip methods with unsupported dalvik byte code.
3. Skip methods with invocation to unsupported prototype.
These are temporary codes and should be removed later. But with this
patch, it won't break anything when we merge partly implemented arm64
backend later.
Change-Id: Ib9180d7b8a978f0a5ebaf6b4893e7e3724897113
-rw-r--r-- | compiler/compilers.cc | 4 | ||||
-rw-r--r-- | compiler/dex/frontend.cc | 376 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 2 |
3 files changed, 381 insertions, 1 deletions
diff --git a/compiler/compilers.cc b/compiler/compilers.cc index 188ce6ff6..6bf005819 100644 --- a/compiler/compilers.cc +++ b/compiler/compilers.cc @@ -101,6 +101,10 @@ Backend* QuickCompiler::GetCodeGenerator(CompilationUnit* cu, void* compilation_ case kThumb2: mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena); break; + case kArm64: + // TODO(Arm64): replace the generator below with a proper one. + mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena); + break; case kMips: mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena); break; diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc index 5e1372277..89c642d21 100644 --- a/compiler/dex/frontend.cc +++ b/compiler/dex/frontend.cc @@ -131,6 +131,370 @@ void CompilationUnit::EndTiming() { } } +// TODO: Remove this when we are able to compile everything. +int arm64_support_list[] = { + Instruction::NOP, + // Instruction::MOVE, + // Instruction::MOVE_FROM16, + // Instruction::MOVE_16, + // Instruction::MOVE_WIDE, + // Instruction::MOVE_WIDE_FROM16, + // Instruction::MOVE_WIDE_16, + // Instruction::MOVE_OBJECT, + // Instruction::MOVE_OBJECT_FROM16, + // Instruction::MOVE_OBJECT_16, + // Instruction::MOVE_RESULT, + // Instruction::MOVE_RESULT_WIDE, + // Instruction::MOVE_RESULT_OBJECT, + // Instruction::MOVE_EXCEPTION, + // Instruction::RETURN_VOID, + // Instruction::RETURN, + // Instruction::RETURN_WIDE, + // Instruction::RETURN_OBJECT, + // Instruction::CONST_4, + // Instruction::CONST_16, + // Instruction::CONST, + // Instruction::CONST_HIGH16, + // Instruction::CONST_WIDE_16, + // Instruction::CONST_WIDE_32, + // Instruction::CONST_WIDE, + // Instruction::CONST_WIDE_HIGH16, + // Instruction::CONST_STRING, + // Instruction::CONST_STRING_JUMBO, + // Instruction::CONST_CLASS, + // Instruction::MONITOR_ENTER, + // Instruction::MONITOR_EXIT, + // Instruction::CHECK_CAST, + // Instruction::INSTANCE_OF, + // Instruction::ARRAY_LENGTH, + // Instruction::NEW_INSTANCE, + // Instruction::NEW_ARRAY, + // Instruction::FILLED_NEW_ARRAY, + // Instruction::FILLED_NEW_ARRAY_RANGE, + // Instruction::FILL_ARRAY_DATA, + // Instruction::THROW, + // Instruction::GOTO, + // Instruction::GOTO_16, + // Instruction::GOTO_32, + // Instruction::PACKED_SWITCH, + // Instruction::SPARSE_SWITCH, + // Instruction::CMPL_FLOAT, + // Instruction::CMPG_FLOAT, + // Instruction::CMPL_DOUBLE, + // Instruction::CMPG_DOUBLE, + // Instruction::CMP_LONG, + // Instruction::IF_EQ, + // Instruction::IF_NE, + // Instruction::IF_LT, + // Instruction::IF_GE, + // Instruction::IF_GT, + // Instruction::IF_LE, + // Instruction::IF_EQZ, + // Instruction::IF_NEZ, + // Instruction::IF_LTZ, + // Instruction::IF_GEZ, + // Instruction::IF_GTZ, + // Instruction::IF_LEZ, + // Instruction::UNUSED_3E, + // Instruction::UNUSED_3F, + // Instruction::UNUSED_40, + // Instruction::UNUSED_41, + // Instruction::UNUSED_42, + // Instruction::UNUSED_43, + // Instruction::AGET, + // Instruction::AGET_WIDE, + // Instruction::AGET_OBJECT, + // Instruction::AGET_BOOLEAN, + // Instruction::AGET_BYTE, + // Instruction::AGET_CHAR, + // Instruction::AGET_SHORT, + // Instruction::APUT, + // Instruction::APUT_WIDE, + // Instruction::APUT_OBJECT, + // Instruction::APUT_BOOLEAN, + // Instruction::APUT_BYTE, + // Instruction::APUT_CHAR, + // Instruction::APUT_SHORT, + // Instruction::IGET, + // Instruction::IGET_WIDE, + // Instruction::IGET_OBJECT, + // Instruction::IGET_BOOLEAN, + // Instruction::IGET_BYTE, + // Instruction::IGET_CHAR, + // Instruction::IGET_SHORT, + // Instruction::IPUT, + // Instruction::IPUT_WIDE, + // Instruction::IPUT_OBJECT, + // Instruction::IPUT_BOOLEAN, + // Instruction::IPUT_BYTE, + // Instruction::IPUT_CHAR, + // Instruction::IPUT_SHORT, + // Instruction::SGET, + // Instruction::SGET_WIDE, + // Instruction::SGET_OBJECT, + // Instruction::SGET_BOOLEAN, + // Instruction::SGET_BYTE, + // Instruction::SGET_CHAR, + // Instruction::SGET_SHORT, + // Instruction::SPUT, + // Instruction::SPUT_WIDE, + // Instruction::SPUT_OBJECT, + // Instruction::SPUT_BOOLEAN, + // Instruction::SPUT_BYTE, + // Instruction::SPUT_CHAR, + // Instruction::SPUT_SHORT, + Instruction::INVOKE_VIRTUAL, + Instruction::INVOKE_SUPER, + Instruction::INVOKE_DIRECT, + Instruction::INVOKE_STATIC, + Instruction::INVOKE_INTERFACE, + // Instruction::RETURN_VOID_BARRIER, + // Instruction::INVOKE_VIRTUAL_RANGE, + // Instruction::INVOKE_SUPER_RANGE, + // Instruction::INVOKE_DIRECT_RANGE, + // Instruction::INVOKE_STATIC_RANGE, + // Instruction::INVOKE_INTERFACE_RANGE, + // Instruction::UNUSED_79, + // Instruction::UNUSED_7A, + // Instruction::NEG_INT, + // Instruction::NOT_INT, + // Instruction::NEG_LONG, + // Instruction::NOT_LONG, + // Instruction::NEG_FLOAT, + // Instruction::NEG_DOUBLE, + // Instruction::INT_TO_LONG, + // Instruction::INT_TO_FLOAT, + // Instruction::INT_TO_DOUBLE, + // Instruction::LONG_TO_INT, + // Instruction::LONG_TO_FLOAT, + // Instruction::LONG_TO_DOUBLE, + // Instruction::FLOAT_TO_INT, + // Instruction::FLOAT_TO_LONG, + // Instruction::FLOAT_TO_DOUBLE, + // Instruction::DOUBLE_TO_INT, + // Instruction::DOUBLE_TO_LONG, + // Instruction::DOUBLE_TO_FLOAT, + // Instruction::INT_TO_BYTE, + // Instruction::INT_TO_CHAR, + // Instruction::INT_TO_SHORT, + // Instruction::ADD_INT, + // Instruction::SUB_INT, + // Instruction::MUL_INT, + // Instruction::DIV_INT, + // Instruction::REM_INT, + // Instruction::AND_INT, + // Instruction::OR_INT, + // Instruction::XOR_INT, + // Instruction::SHL_INT, + // Instruction::SHR_INT, + // Instruction::USHR_INT, + // Instruction::ADD_LONG, + // Instruction::SUB_LONG, + // Instruction::MUL_LONG, + // Instruction::DIV_LONG, + // Instruction::REM_LONG, + // Instruction::AND_LONG, + // Instruction::OR_LONG, + // Instruction::XOR_LONG, + // Instruction::SHL_LONG, + // Instruction::SHR_LONG, + // Instruction::USHR_LONG, + // Instruction::ADD_FLOAT, + // Instruction::SUB_FLOAT, + // Instruction::MUL_FLOAT, + // Instruction::DIV_FLOAT, + // Instruction::REM_FLOAT, + // Instruction::ADD_DOUBLE, + // Instruction::SUB_DOUBLE, + // Instruction::MUL_DOUBLE, + // Instruction::DIV_DOUBLE, + // Instruction::REM_DOUBLE, + // Instruction::ADD_INT_2ADDR, + // Instruction::SUB_INT_2ADDR, + // Instruction::MUL_INT_2ADDR, + // Instruction::DIV_INT_2ADDR, + // Instruction::REM_INT_2ADDR, + // Instruction::AND_INT_2ADDR, + // Instruction::OR_INT_2ADDR, + // Instruction::XOR_INT_2ADDR, + // Instruction::SHL_INT_2ADDR, + // Instruction::SHR_INT_2ADDR, + // Instruction::USHR_INT_2ADDR, + // Instruction::ADD_LONG_2ADDR, + // Instruction::SUB_LONG_2ADDR, + // Instruction::MUL_LONG_2ADDR, + // Instruction::DIV_LONG_2ADDR, + // Instruction::REM_LONG_2ADDR, + // Instruction::AND_LONG_2ADDR, + // Instruction::OR_LONG_2ADDR, + // Instruction::XOR_LONG_2ADDR, + // Instruction::SHL_LONG_2ADDR, + // Instruction::SHR_LONG_2ADDR, + // Instruction::USHR_LONG_2ADDR, + // Instruction::ADD_FLOAT_2ADDR, + // Instruction::SUB_FLOAT_2ADDR, + // Instruction::MUL_FLOAT_2ADDR, + // Instruction::DIV_FLOAT_2ADDR, + // Instruction::REM_FLOAT_2ADDR, + // Instruction::ADD_DOUBLE_2ADDR, + // Instruction::SUB_DOUBLE_2ADDR, + // Instruction::MUL_DOUBLE_2ADDR, + // Instruction::DIV_DOUBLE_2ADDR, + // Instruction::REM_DOUBLE_2ADDR, + // Instruction::ADD_INT_LIT16, + // Instruction::RSUB_INT, + // Instruction::MUL_INT_LIT16, + // Instruction::DIV_INT_LIT16, + // Instruction::REM_INT_LIT16, + // Instruction::AND_INT_LIT16, + // Instruction::OR_INT_LIT16, + // Instruction::XOR_INT_LIT16, + // Instruction::ADD_INT_LIT8, + // Instruction::RSUB_INT_LIT8, + // Instruction::MUL_INT_LIT8, + // Instruction::DIV_INT_LIT8, + // Instruction::REM_INT_LIT8, + // Instruction::AND_INT_LIT8, + // Instruction::OR_INT_LIT8, + // Instruction::XOR_INT_LIT8, + // Instruction::SHL_INT_LIT8, + // Instruction::SHR_INT_LIT8, + // Instruction::USHR_INT_LIT8, + // Instruction::IGET_QUICK, + // Instruction::IGET_WIDE_QUICK, + // Instruction::IGET_OBJECT_QUICK, + // Instruction::IPUT_QUICK, + // Instruction::IPUT_WIDE_QUICK, + // Instruction::IPUT_OBJECT_QUICK, + // Instruction::INVOKE_VIRTUAL_QUICK, + // Instruction::INVOKE_VIRTUAL_RANGE_QUICK, + // Instruction::UNUSED_EB, + // Instruction::UNUSED_EC, + // Instruction::UNUSED_ED, + // Instruction::UNUSED_EE, + // Instruction::UNUSED_EF, + // Instruction::UNUSED_F0, + // Instruction::UNUSED_F1, + // Instruction::UNUSED_F2, + // Instruction::UNUSED_F3, + // Instruction::UNUSED_F4, + // Instruction::UNUSED_F5, + // Instruction::UNUSED_F6, + // Instruction::UNUSED_F7, + // Instruction::UNUSED_F8, + // Instruction::UNUSED_F9, + // Instruction::UNUSED_FA, + // Instruction::UNUSED_FB, + // Instruction::UNUSED_FC, + // Instruction::UNUSED_FD, + // Instruction::UNUSED_FE, + // Instruction::UNUSED_FF, + + // ----- ExtendedMIROpcode ----- + // kMirOpPhi, + // kMirOpCopy, + // kMirOpFusedCmplFloat, + // kMirOpFusedCmpgFloat, + // kMirOpFusedCmplDouble, + // kMirOpFusedCmpgDouble, + // kMirOpFusedCmpLong, + // kMirOpNop, + // kMirOpNullCheck, + // kMirOpRangeCheck, + // kMirOpDivZeroCheck, + // kMirOpCheck, + // kMirOpCheckPart2, + // kMirOpSelect, + // kMirOpLast, +}; + +// TODO: Remove this when we are able to compile everything. +static bool CanCompileShorty(const char* shorty) { + uint32_t shorty_size = strlen(shorty); + CHECK_GE(shorty_size, 1u); + // Set a limitation on maximum number of parameters. + // Note : there is an implied "method*" parameter, and probably "this" as well. + // 1 is for the return type. Currently, we only accept 2 parameters at the most. + if (shorty_size > (1 + 2)) { + return false; + } + // Z : boolean + // B : byte + // S : short + // C : char + // I : int + // L : long + // F : float + // D : double + // L : reference(object, array) + // V : void + // Current calling conversion only support 32bit softfp + // which has problems with long, float, double + constexpr char supported_types[] = "ZBSCILV"; + for (uint32_t i = 0; i < shorty_size; i++) { + if (strchr(supported_types, shorty[i]) == nullptr) { + return false; + } + } + return true; +}; + +// TODO: Remove this when we are able to compile everything. +// Skip the method that we do not support currently. +static bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, + CompilationUnit& cu) { + // There is some limitation with current ARM 64 backend. + if (cu.instruction_set == kArm64) { + // Check if we can compile the prototype. + const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx)); + if (!CanCompileShorty(shorty)) { + VLOG(compiler) << "Unsupported shorty : " << shorty; + return false; + } + + for (int idx = 0; idx < cu.mir_graph->GetNumBlocks(); idx++) { + BasicBlock *bb = cu.mir_graph->GetBasicBlock(idx); + if (bb == NULL) continue; + if (bb->block_type == kDead) continue; + for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) { + int opcode = mir->dalvikInsn.opcode; + // Check if we support the byte code. + if (std::find(arm64_support_list, arm64_support_list + arraysize(arm64_support_list), + opcode) == arm64_support_list + arraysize(arm64_support_list)) { + if (opcode < kMirOpFirst) { + VLOG(compiler) << "Unsupported dalvik byte code : " + << mir->dalvikInsn.opcode; + } else { + VLOG(compiler) << "Unsupported extended MIR opcode : " + << MIRGraph::extended_mir_op_names_[opcode - kMirOpFirst]; + } + return false; + } + // Check if it invokes a prototype that we cannot support. + if (Instruction::INVOKE_VIRTUAL == opcode || + Instruction::INVOKE_SUPER == opcode || + Instruction::INVOKE_DIRECT == opcode || + Instruction::INVOKE_STATIC == opcode || + Instruction::INVOKE_INTERFACE == opcode) { + uint32_t invoke_method_idx = mir->dalvikInsn.vB; + const char* invoke_method_shorty = dex_file.GetMethodShorty( + dex_file.GetMethodId(invoke_method_idx)); + if (!CanCompileShorty(invoke_method_shorty)) { + VLOG(compiler) << "Unsupported to invoke '" + << PrettyMethod(invoke_method_idx, dex_file) + << "' with shorty : " << invoke_method_shorty; + return false; + } + } + } + } + + LOG(INFO) << "Using experimental instruction set A64 for " + << PrettyMethod(method_idx, dex_file); + } + return true; +} + static CompiledMethod* CompileMethod(CompilerDriver& driver, Compiler* compiler, const DexFile::CodeItem* code_item, @@ -162,6 +526,7 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, cu.compiler = compiler; // TODO: x86_64 & arm64 are not yet implemented. CHECK((cu.instruction_set == kThumb2) || + (cu.instruction_set == kArm64) || (cu.instruction_set == kX86) || (cu.instruction_set == kX86_64) || (cu.instruction_set == kMips)); @@ -214,6 +579,11 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, (1 << kPromoteCompilerTemps)); } + if (cu.instruction_set == kArm64) { + // TODO(Arm64): enable optimizations once backend is mature enough. + cu.disable_opt = ~(uint32_t)0; + } + cu.StartTimingSplit("BuildMIRGraph"); cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena)); @@ -241,6 +611,12 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, class_loader, dex_file); + // TODO(Arm64): Remove this when we are able to compile everything. + if (!CanCompileMethod(method_idx, dex_file, cu)) { + VLOG(compiler) << "Cannot compile method : " << PrettyMethod(method_idx, dex_file); + return nullptr; + } + cu.NewTimingSplit("MIROpt:CheckFilters"); if (cu.mir_graph->SkipCompilation()) { return NULL; diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index cdf26f189..7c0befcf6 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1010,7 +1010,7 @@ static int dex2oat(int argc, char** argv) { } if (compiler_filter_string == NULL) { - if (instruction_set == kX86_64 || instruction_set == kArm64 || instruction_set == kMips) { + if (instruction_set == kX86_64 || instruction_set == kMips) { // TODO: implement/fix compilers for these architectures. compiler_filter_string = "interpret-only"; } else if (image) { |