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 /compiler/dex/frontend.cc | |
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
Diffstat (limited to 'compiler/dex/frontend.cc')
-rw-r--r-- | compiler/dex/frontend.cc | 376 |
1 files changed, 376 insertions, 0 deletions
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; |