diff options
| author | 2012-02-03 22:56:04 +0800 | |
|---|---|---|
| committer | 2012-02-19 02:13:43 -0800 | |
| commit | 7caf37e2aebdb9e6f10f691a8148dd3d3405f157 (patch) | |
| tree | 686ac056dacd0e926e5af1f0b016975f980f5e08 /src/compiler_llvm | |
| parent | e73b6212e87d9fc3ba91456894806bb1b8c570e3 (diff) | |
Implement invoke-interface instruction.
Change-Id: I3634c90a3aa3391c022ce142532bca7afed07d14
Diffstat (limited to 'src/compiler_llvm')
| -rw-r--r-- | src/compiler_llvm/method_compiler.cc | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc index 3db83f66a2..f549589241 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -2839,7 +2839,49 @@ void MethodCompiler::EmitInsn_InvokeStaticDirect(uint32_t dex_pc, void MethodCompiler::EmitInsn_InvokeInterface(uint32_t dex_pc, Instruction const* insn, bool is_range) { - // UNIMPLEMENTED(WARNING); + + Instruction::DecodedInstruction dec_insn(insn); + + uint32_t callee_method_idx = dec_insn.vB_; + + // Resolve callee method + Method* callee_method = ResolveMethod(callee_method_idx); + + // Test: Is "this" pointer equal to null? + llvm::Value* this_addr = EmitLoadCalleeThis(dec_insn, is_range); + EmitGuard_NullPointerException(dex_pc, this_addr); + + // Resolve the callee method object address at runtime + llvm::Value* runtime_func = irb_.GetRuntime(FindInterfaceMethod); + + llvm::Value* method_object_addr = EmitLoadMethodObjectAddr(); + + llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx); + + llvm::Value* callee_method_object_addr = + irb_.CreateCall2(runtime_func, callee_method_idx_value, method_object_addr); + + EmitGuard_ExceptionLandingPad(dex_pc); + + llvm::Value* code_addr = + EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false); + + // Load the actual parameter + std::vector<llvm::Value*> args; + args.push_back(callee_method_object_addr); + args.push_back(this_addr); + EmitLoadActualParameters(args, callee_method_idx, dec_insn, is_range, false); + + // Emit the code to invoke callee + llvm::Value* retval = irb_.CreateCall(code_addr, args); + EmitGuard_ExceptionLandingPad(dex_pc); + + MethodHelper method_helper(callee_method); + char ret_shorty = method_helper.GetShorty()[0]; + if (ret_shorty != 'V') { + EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval); + } + irb_.CreateBr(GetNextBasicBlock(dex_pc)); } |