blob: 90731d686ab39e64717951f143fd5a5bd4687dac [file] [log] [blame]
Shih-wei Liaod1fec812012-02-13 09:51:10 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "method_compiler.h"
18
Logan Chienfca7e872011-12-20 20:08:22 +080019#include "backend_types.h"
Logan Chien8b977d32012-02-21 19:14:55 +080020#include "compilation_unit.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080021#include "compiler.h"
Logan Chiena78e3c82011-12-27 17:59:35 +080022#include "inferred_reg_category_map.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080023#include "ir_builder.h"
24#include "logging.h"
Logan Chien4dd96f52012-02-29 01:26:58 +080025#include "oat_compilation_unit.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080026#include "object.h"
27#include "object_utils.h"
Logan Chien42e0e152012-01-13 15:42:36 +080028#include "runtime_support_func.h"
TDYa1275bb86012012-04-11 05:57:28 -070029#include "runtime_support_llvm.h"
Logan Chien1b0a1b72012-03-15 06:20:17 +080030#include "shadow_frame.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080031#include "stl_util.h"
Logan Chien0b827102011-12-20 19:46:14 +080032#include "stringprintf.h"
33#include "utils_llvm.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070034#include "verifier/method_verifier.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080035
36#include <iomanip>
37
Logan Chienc670a8d2011-12-20 21:25:56 +080038#include <llvm/BasicBlock.h>
Shih-wei Liaod1fec812012-02-13 09:51:10 -080039#include <llvm/Function.h>
Logan Chiena85fb2f2012-01-16 12:52:56 +080040#include <llvm/GlobalVariable.h>
41#include <llvm/Intrinsics.h>
Shih-wei Liaod1fec812012-02-13 09:51:10 -080042
Logan Chien83426162011-12-09 09:29:50 +080043namespace art {
44namespace compiler_llvm {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080045
Logan Chien42e0e152012-01-13 15:42:36 +080046using namespace runtime_support;
47
Shih-wei Liaod1fec812012-02-13 09:51:10 -080048
Logan Chien8b977d32012-02-21 19:14:55 +080049MethodCompiler::MethodCompiler(CompilationUnit* cunit,
Logan Chien83426162011-12-09 09:29:50 +080050 Compiler* compiler,
Logan Chien4dd96f52012-02-29 01:26:58 +080051 OatCompilationUnit* oat_compilation_unit)
Logan Chien8b977d32012-02-21 19:14:55 +080052 : cunit_(cunit), compiler_(compiler),
53 class_linker_(oat_compilation_unit->class_linker_),
54 class_loader_(oat_compilation_unit->class_loader_),
55 dex_file_(oat_compilation_unit->dex_file_),
56 dex_cache_(oat_compilation_unit->dex_cache_),
57 code_item_(oat_compilation_unit->code_item_),
58 oat_compilation_unit_(oat_compilation_unit),
Logan Chien8b977d32012-02-21 19:14:55 +080059 method_idx_(oat_compilation_unit->method_idx_),
60 access_flags_(oat_compilation_unit->access_flags_),
61 module_(cunit->GetModule()),
62 context_(cunit->GetLLVMContext()),
63 irb_(*cunit->GetIRBuilder()), func_(NULL), retval_reg_(NULL),
Ian Rogers776ac1f2012-04-13 23:36:36 -070064 basic_block_stack_overflow_(NULL),
Logan Chien8b977d32012-02-21 19:14:55 +080065 basic_block_reg_alloca_(NULL), basic_block_shadow_frame_alloca_(NULL),
Logan Chienef4a6562012-04-24 18:02:24 +080066 basic_block_reg_arg_init_(NULL),
Logan Chien8b977d32012-02-21 19:14:55 +080067 basic_blocks_(code_item_->insns_size_in_code_units_),
68 basic_block_landing_pads_(code_item_->tries_size_, NULL),
69 basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
Logan Chien937105a2012-04-02 02:37:37 +080070 shadow_frame_(NULL), elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080071}
72
73
74MethodCompiler::~MethodCompiler() {
Logan Chienc670a8d2011-12-20 21:25:56 +080075 STLDeleteElements(&regs_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -080076}
77
78
Logan Chien0b827102011-12-20 19:46:14 +080079void MethodCompiler::CreateFunction() {
80 // LLVM function name
Logan Chien937105a2012-04-02 02:37:37 +080081 std::string func_name(ElfFuncName(elf_func_idx_));
Logan Chien0b827102011-12-20 19:46:14 +080082
83 // Get function type
84 llvm::FunctionType* func_type =
Logan Chiendd361c92012-04-10 23:40:37 +080085 GetFunctionType(method_idx_, oat_compilation_unit_->IsStatic());
Logan Chien0b827102011-12-20 19:46:14 +080086
87 // Create function
88 func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
89 func_name, module_);
90
91 // Set argument name
92 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
93 llvm::Function::arg_iterator arg_end(func_->arg_end());
94
95 DCHECK_NE(arg_iter, arg_end);
96 arg_iter->setName("method");
97 ++arg_iter;
98
Logan Chiendd361c92012-04-10 23:40:37 +080099 if (!oat_compilation_unit_->IsStatic()) {
Logan Chien0b827102011-12-20 19:46:14 +0800100 DCHECK_NE(arg_iter, arg_end);
101 arg_iter->setName("this");
102 ++arg_iter;
103 }
104
105 for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
106 arg_iter->setName(StringPrintf("a%u", i));
107 }
108}
109
110
111llvm::FunctionType* MethodCompiler::GetFunctionType(uint32_t method_idx,
112 bool is_static) {
113 // Get method signature
114 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
115
Logan Chien8faf8022012-02-24 12:25:29 +0800116 uint32_t shorty_size;
Logan Chien0b827102011-12-20 19:46:14 +0800117 char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
Logan Chien8faf8022012-02-24 12:25:29 +0800118 CHECK_GE(shorty_size, 1u);
Logan Chien0b827102011-12-20 19:46:14 +0800119
120 // Get return type
121 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
122
123 // Get argument type
124 std::vector<llvm::Type*> args_type;
125
126 args_type.push_back(irb_.getJObjectTy()); // method object pointer
127
128 if (!is_static) {
129 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
130 }
131
Logan Chien8faf8022012-02-24 12:25:29 +0800132 for (uint32_t i = 1; i < shorty_size; ++i) {
Logan Chien0b827102011-12-20 19:46:14 +0800133 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
134 }
135
136 return llvm::FunctionType::get(ret_type, args_type, false);
137}
138
139
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800140void MethodCompiler::EmitPrologue() {
Logan Chienc670a8d2011-12-20 21:25:56 +0800141 // Create basic blocks for prologue
142 basic_block_reg_alloca_ =
143 llvm::BasicBlock::Create(*context_, "prologue.alloca", func_);
144
TDYa12797339c42012-04-29 01:26:35 -0700145 basic_block_stack_overflow_ =
146 llvm::BasicBlock::Create(*context_, "prologue.stack_overflow_check", func_);
147
Logan Chien8dfcbea2012-02-17 18:50:32 +0800148 basic_block_shadow_frame_alloca_ =
149 llvm::BasicBlock::Create(*context_, "prologue.shadowframe", func_);
150
Logan Chiend6ececa2011-12-27 16:20:15 +0800151 basic_block_reg_arg_init_ =
152 llvm::BasicBlock::Create(*context_, "prologue.arginit", func_);
153
Logan Chienc670a8d2011-12-20 21:25:56 +0800154 // Create register array
155 for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
156 regs_.push_back(DalvikReg::CreateLocalVarReg(*this, r));
157 }
158
159 retval_reg_.reset(DalvikReg::CreateRetValReg(*this));
Logan Chiend6ececa2011-12-27 16:20:15 +0800160
Logan Chien8dfcbea2012-02-17 18:50:32 +0800161 // Create Shadow Frame
162 EmitPrologueAllocShadowFrame();
163
Logan Chiend6ececa2011-12-27 16:20:15 +0800164 // Store argument to dalvik register
165 irb_.SetInsertPoint(basic_block_reg_arg_init_);
166 EmitPrologueAssignArgRegister();
167
168 // Branch to start address
169 irb_.CreateBr(GetBasicBlock(0));
Logan Chienc670a8d2011-12-20 21:25:56 +0800170}
171
172
TDYa1274165a832012-04-03 17:47:16 -0700173void MethodCompiler::EmitStackOverflowCheck() {
174 irb_.SetInsertPoint(basic_block_stack_overflow_);
175
176 // Call llvm intrinsic function to get frame address.
177 llvm::Function* frameaddress =
178 llvm::Intrinsic::getDeclaration(module_, llvm::Intrinsic::frameaddress);
179
180 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
181 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
182
183 // Cast i8* to int
184 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
185
186 // Get thread.stack_end_
187 llvm::Value* thread_object_addr =
188 irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
189
TDYa127ee1f59b2012-04-25 00:56:40 -0700190 llvm::Value* stack_end =
191 irb_.LoadFromObjectOffset(thread_object_addr,
192 Thread::StackEndOffset().Int32Value(),
193 irb_.getPtrEquivIntTy());
TDYa1274165a832012-04-03 17:47:16 -0700194
195 // Check the frame address < thread.stack_end_ ?
196 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
197
198 llvm::BasicBlock* block_exception =
199 llvm::BasicBlock::Create(*context_, "stack_overflow", func_);
200
201 llvm::BasicBlock* block_continue =
202 llvm::BasicBlock::Create(*context_, "stack_overflow_cont", func_);
203
204 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue);
205
206 // If stack overflow, throw exception.
207 irb_.SetInsertPoint(block_exception);
208 irb_.CreateCall(irb_.GetRuntime(ThrowStackOverflowException));
209
210 // Unwind.
Logan Chiendd361c92012-04-10 23:40:37 +0800211 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
TDYa1274165a832012-04-03 17:47:16 -0700212 if (ret_shorty == 'V') {
213 irb_.CreateRetVoid();
214 } else {
215 irb_.CreateRet(irb_.getJZero(ret_shorty));
216 }
217
218 basic_block_stack_overflow_ = block_continue;
219}
220
221
Logan Chienc670a8d2011-12-20 21:25:56 +0800222void MethodCompiler::EmitPrologueLastBranch() {
223 irb_.SetInsertPoint(basic_block_reg_alloca_);
TDYa12797339c42012-04-29 01:26:35 -0700224 irb_.CreateBr(basic_block_stack_overflow_);
225
226 EmitStackOverflowCheck();
227
228 irb_.SetInsertPoint(basic_block_stack_overflow_);
Logan Chien8dfcbea2012-02-17 18:50:32 +0800229 irb_.CreateBr(basic_block_shadow_frame_alloca_);
230
231 irb_.SetInsertPoint(basic_block_shadow_frame_alloca_);
Logan Chiend6ececa2011-12-27 16:20:15 +0800232 irb_.CreateBr(basic_block_reg_arg_init_);
233}
234
235
Logan Chien8dfcbea2012-02-17 18:50:32 +0800236void MethodCompiler::EmitPrologueAllocShadowFrame() {
237 irb_.SetInsertPoint(basic_block_shadow_frame_alloca_);
238
239 // Allocate the shadow frame now!
240 uint32_t sirt_size = code_item_->registers_size_;
241 // TODO: registers_size_ is a bad approximation. Compute a
242 // tighter approximation at Dex verifier while performing data-flow
243 // analysis.
244
245 llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
246 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
247
248 // Zero-initialization of the shadow frame
249 llvm::ConstantAggregateZero* zero_initializer =
250 llvm::ConstantAggregateZero::get(shadow_frame_type);
251
252 irb_.CreateStore(zero_initializer, shadow_frame_);
253
TDYa127ee1f59b2012-04-25 00:56:40 -0700254 // Get method object
Logan Chien8dfcbea2012-02-17 18:50:32 +0800255 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
TDYa127ee1f59b2012-04-25 00:56:40 -0700256
257 // Store the method pointer
258 irb_.StoreToObjectOffset(shadow_frame_,
259 ShadowFrame::MethodOffset(),
260 method_object_addr);
Logan Chien8dfcbea2012-02-17 18:50:32 +0800261
262 // Store the number of the pointer slots
TDYa127ee1f59b2012-04-25 00:56:40 -0700263 irb_.StoreToObjectOffset(shadow_frame_,
264 ShadowFrame::NumberOfReferencesOffset(),
265 irb_.getJInt(sirt_size));
Logan Chien8dfcbea2012-02-17 18:50:32 +0800266
267 // Push the shadow frame
268 llvm::Value* shadow_frame_upcast =
269 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
270
271 irb_.CreateCall(irb_.GetRuntime(PushShadowFrame), shadow_frame_upcast);
272}
273
274
Logan Chiend6ececa2011-12-27 16:20:15 +0800275void MethodCompiler::EmitPrologueAssignArgRegister() {
276 uint16_t arg_reg = code_item_->registers_size_ - code_item_->ins_size_;
277
278 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
279 llvm::Function::arg_iterator arg_end(func_->arg_end());
280
Logan Chiendd361c92012-04-10 23:40:37 +0800281 uint32_t shorty_size = 0;
282 char const* shorty = oat_compilation_unit_->GetShorty(&shorty_size);
283 CHECK_GE(shorty_size, 1u);
Logan Chiend6ececa2011-12-27 16:20:15 +0800284
285 ++arg_iter; // skip method object
286
Logan Chiendd361c92012-04-10 23:40:37 +0800287 if (!oat_compilation_unit_->IsStatic()) {
Logan Chiend6ececa2011-12-27 16:20:15 +0800288 EmitStoreDalvikReg(arg_reg, kObject, kAccurate, arg_iter);
289 ++arg_iter;
290 ++arg_reg;
291 }
292
Logan Chiendd361c92012-04-10 23:40:37 +0800293 for (uint32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
Logan Chiend6ececa2011-12-27 16:20:15 +0800294 EmitStoreDalvikReg(arg_reg, shorty[i], kAccurate, arg_iter);
295
296 ++arg_reg;
297 if (shorty[i] == 'J' || shorty[i] == 'D') {
298 // Wide types, such as long and double, are using a pair of registers
299 // to store the value, so we have to increase arg_reg again.
300 ++arg_reg;
301 }
302 }
303
304 DCHECK_EQ(arg_end, arg_iter);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800305}
306
307
Logan Chien83426162011-12-09 09:29:50 +0800308void MethodCompiler::EmitInstructions() {
Logan Chiend6c239a2011-12-23 15:11:45 +0800309 uint32_t dex_pc = 0;
310 while (dex_pc < code_item_->insns_size_in_code_units_) {
311 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
312 EmitInstruction(dex_pc, insn);
313 dex_pc += insn->SizeInCodeUnits();
314 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800315}
316
317
Logan Chien83426162011-12-09 09:29:50 +0800318void MethodCompiler::EmitInstruction(uint32_t dex_pc,
319 Instruction const* insn) {
Logan Chiend6c239a2011-12-23 15:11:45 +0800320
321 // Set the IRBuilder insertion point
322 irb_.SetInsertPoint(GetBasicBlock(dex_pc));
323
Logan Chien70f94b42011-12-27 17:49:11 +0800324#define ARGS dex_pc, insn
325
326 // Dispatch the instruction
327 switch (insn->Opcode()) {
328 case Instruction::NOP:
329 EmitInsn_Nop(ARGS);
330 break;
331
332 case Instruction::MOVE:
333 case Instruction::MOVE_FROM16:
334 case Instruction::MOVE_16:
335 EmitInsn_Move(ARGS, kInt);
336 break;
337
338 case Instruction::MOVE_WIDE:
339 case Instruction::MOVE_WIDE_FROM16:
340 case Instruction::MOVE_WIDE_16:
341 EmitInsn_Move(ARGS, kLong);
342 break;
343
344 case Instruction::MOVE_OBJECT:
345 case Instruction::MOVE_OBJECT_FROM16:
346 case Instruction::MOVE_OBJECT_16:
347 EmitInsn_Move(ARGS, kObject);
348 break;
349
350 case Instruction::MOVE_RESULT:
351 EmitInsn_MoveResult(ARGS, kInt);
352 break;
353
354 case Instruction::MOVE_RESULT_WIDE:
355 EmitInsn_MoveResult(ARGS, kLong);
356 break;
357
358 case Instruction::MOVE_RESULT_OBJECT:
359 EmitInsn_MoveResult(ARGS, kObject);
360 break;
361
362 case Instruction::MOVE_EXCEPTION:
363 EmitInsn_MoveException(ARGS);
364 break;
365
366 case Instruction::RETURN_VOID:
367 EmitInsn_ReturnVoid(ARGS);
368 break;
369
370 case Instruction::RETURN:
371 case Instruction::RETURN_WIDE:
372 case Instruction::RETURN_OBJECT:
373 EmitInsn_Return(ARGS);
374 break;
375
376 case Instruction::CONST_4:
377 case Instruction::CONST_16:
378 case Instruction::CONST:
379 case Instruction::CONST_HIGH16:
380 EmitInsn_LoadConstant(ARGS, kInt);
381 break;
382
383 case Instruction::CONST_WIDE_16:
384 case Instruction::CONST_WIDE_32:
385 case Instruction::CONST_WIDE:
386 case Instruction::CONST_WIDE_HIGH16:
387 EmitInsn_LoadConstant(ARGS, kLong);
388 break;
389
390 case Instruction::CONST_STRING:
391 case Instruction::CONST_STRING_JUMBO:
392 EmitInsn_LoadConstantString(ARGS);
393 break;
394
395 case Instruction::CONST_CLASS:
396 EmitInsn_LoadConstantClass(ARGS);
397 break;
398
399 case Instruction::MONITOR_ENTER:
400 EmitInsn_MonitorEnter(ARGS);
401 break;
402
403 case Instruction::MONITOR_EXIT:
404 EmitInsn_MonitorExit(ARGS);
405 break;
406
407 case Instruction::CHECK_CAST:
408 EmitInsn_CheckCast(ARGS);
409 break;
410
411 case Instruction::INSTANCE_OF:
412 EmitInsn_InstanceOf(ARGS);
413 break;
414
415 case Instruction::ARRAY_LENGTH:
416 EmitInsn_ArrayLength(ARGS);
417 break;
418
419 case Instruction::NEW_INSTANCE:
420 EmitInsn_NewInstance(ARGS);
421 break;
422
423 case Instruction::NEW_ARRAY:
424 EmitInsn_NewArray(ARGS);
425 break;
426
427 case Instruction::FILLED_NEW_ARRAY:
428 EmitInsn_FilledNewArray(ARGS, false);
429 break;
430
431 case Instruction::FILLED_NEW_ARRAY_RANGE:
432 EmitInsn_FilledNewArray(ARGS, true);
433 break;
434
435 case Instruction::FILL_ARRAY_DATA:
436 EmitInsn_FillArrayData(ARGS);
437 break;
438
439 case Instruction::THROW:
440 EmitInsn_ThrowException(ARGS);
441 break;
442
443 case Instruction::GOTO:
444 case Instruction::GOTO_16:
445 case Instruction::GOTO_32:
446 EmitInsn_UnconditionalBranch(ARGS);
447 break;
448
449 case Instruction::PACKED_SWITCH:
450 EmitInsn_PackedSwitch(ARGS);
451 break;
452
453 case Instruction::SPARSE_SWITCH:
454 EmitInsn_SparseSwitch(ARGS);
455 break;
456
457 case Instruction::CMPL_FLOAT:
458 EmitInsn_FPCompare(ARGS, kFloat, false);
459 break;
460
461 case Instruction::CMPG_FLOAT:
462 EmitInsn_FPCompare(ARGS, kFloat, true);
463 break;
464
465 case Instruction::CMPL_DOUBLE:
466 EmitInsn_FPCompare(ARGS, kDouble, false);
467 break;
468
469 case Instruction::CMPG_DOUBLE:
470 EmitInsn_FPCompare(ARGS, kDouble, true);
471 break;
472
473 case Instruction::CMP_LONG:
474 EmitInsn_LongCompare(ARGS);
475 break;
476
477 case Instruction::IF_EQ:
478 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_EQ);
479 break;
480
481 case Instruction::IF_NE:
482 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_NE);
483 break;
484
485 case Instruction::IF_LT:
486 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_LT);
487 break;
488
489 case Instruction::IF_GE:
490 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_GE);
491 break;
492
493 case Instruction::IF_GT:
494 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_GT);
495 break;
496
497 case Instruction::IF_LE:
498 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_LE);
499 break;
500
501 case Instruction::IF_EQZ:
502 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_EQ);
503 break;
504
505 case Instruction::IF_NEZ:
506 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_NE);
507 break;
508
509 case Instruction::IF_LTZ:
510 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_LT);
511 break;
512
513 case Instruction::IF_GEZ:
514 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_GE);
515 break;
516
517 case Instruction::IF_GTZ:
518 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_GT);
519 break;
520
521 case Instruction::IF_LEZ:
522 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_LE);
523 break;
524
525 case Instruction::AGET:
526 EmitInsn_AGet(ARGS, kInt);
527 break;
528
529 case Instruction::AGET_WIDE:
530 EmitInsn_AGet(ARGS, kLong);
531 break;
532
533 case Instruction::AGET_OBJECT:
534 EmitInsn_AGet(ARGS, kObject);
535 break;
536
537 case Instruction::AGET_BOOLEAN:
538 EmitInsn_AGet(ARGS, kBoolean);
539 break;
540
541 case Instruction::AGET_BYTE:
542 EmitInsn_AGet(ARGS, kByte);
543 break;
544
545 case Instruction::AGET_CHAR:
546 EmitInsn_AGet(ARGS, kChar);
547 break;
548
549 case Instruction::AGET_SHORT:
550 EmitInsn_AGet(ARGS, kShort);
551 break;
552
553 case Instruction::APUT:
554 EmitInsn_APut(ARGS, kInt);
555 break;
556
557 case Instruction::APUT_WIDE:
558 EmitInsn_APut(ARGS, kLong);
559 break;
560
561 case Instruction::APUT_OBJECT:
562 EmitInsn_APut(ARGS, kObject);
563 break;
564
565 case Instruction::APUT_BOOLEAN:
566 EmitInsn_APut(ARGS, kBoolean);
567 break;
568
569 case Instruction::APUT_BYTE:
570 EmitInsn_APut(ARGS, kByte);
571 break;
572
573 case Instruction::APUT_CHAR:
574 EmitInsn_APut(ARGS, kChar);
575 break;
576
577 case Instruction::APUT_SHORT:
578 EmitInsn_APut(ARGS, kShort);
579 break;
580
581 case Instruction::IGET:
582 EmitInsn_IGet(ARGS, kInt);
583 break;
584
585 case Instruction::IGET_WIDE:
586 EmitInsn_IGet(ARGS, kLong);
587 break;
588
589 case Instruction::IGET_OBJECT:
590 EmitInsn_IGet(ARGS, kObject);
591 break;
592
593 case Instruction::IGET_BOOLEAN:
594 EmitInsn_IGet(ARGS, kBoolean);
595 break;
596
597 case Instruction::IGET_BYTE:
598 EmitInsn_IGet(ARGS, kByte);
599 break;
600
601 case Instruction::IGET_CHAR:
602 EmitInsn_IGet(ARGS, kChar);
603 break;
604
605 case Instruction::IGET_SHORT:
606 EmitInsn_IGet(ARGS, kShort);
607 break;
608
609 case Instruction::IPUT:
610 EmitInsn_IPut(ARGS, kInt);
611 break;
612
613 case Instruction::IPUT_WIDE:
614 EmitInsn_IPut(ARGS, kLong);
615 break;
616
617 case Instruction::IPUT_OBJECT:
618 EmitInsn_IPut(ARGS, kObject);
619 break;
620
621 case Instruction::IPUT_BOOLEAN:
622 EmitInsn_IPut(ARGS, kBoolean);
623 break;
624
625 case Instruction::IPUT_BYTE:
626 EmitInsn_IPut(ARGS, kByte);
627 break;
628
629 case Instruction::IPUT_CHAR:
630 EmitInsn_IPut(ARGS, kChar);
631 break;
632
633 case Instruction::IPUT_SHORT:
634 EmitInsn_IPut(ARGS, kShort);
635 break;
636
637 case Instruction::SGET:
638 EmitInsn_SGet(ARGS, kInt);
639 break;
640
641 case Instruction::SGET_WIDE:
642 EmitInsn_SGet(ARGS, kLong);
643 break;
644
645 case Instruction::SGET_OBJECT:
646 EmitInsn_SGet(ARGS, kObject);
647 break;
648
649 case Instruction::SGET_BOOLEAN:
650 EmitInsn_SGet(ARGS, kBoolean);
651 break;
652
653 case Instruction::SGET_BYTE:
654 EmitInsn_SGet(ARGS, kByte);
655 break;
656
657 case Instruction::SGET_CHAR:
658 EmitInsn_SGet(ARGS, kChar);
659 break;
660
661 case Instruction::SGET_SHORT:
662 EmitInsn_SGet(ARGS, kShort);
663 break;
664
665 case Instruction::SPUT:
666 EmitInsn_SPut(ARGS, kInt);
667 break;
668
669 case Instruction::SPUT_WIDE:
670 EmitInsn_SPut(ARGS, kLong);
671 break;
672
673 case Instruction::SPUT_OBJECT:
674 EmitInsn_SPut(ARGS, kObject);
675 break;
676
677 case Instruction::SPUT_BOOLEAN:
678 EmitInsn_SPut(ARGS, kBoolean);
679 break;
680
681 case Instruction::SPUT_BYTE:
682 EmitInsn_SPut(ARGS, kByte);
683 break;
684
685 case Instruction::SPUT_CHAR:
686 EmitInsn_SPut(ARGS, kChar);
687 break;
688
689 case Instruction::SPUT_SHORT:
690 EmitInsn_SPut(ARGS, kShort);
691 break;
692
693
694 case Instruction::INVOKE_VIRTUAL:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800695 EmitInsn_Invoke(ARGS, kVirtual, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800696 break;
697
698 case Instruction::INVOKE_SUPER:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800699 EmitInsn_Invoke(ARGS, kSuper, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800700 break;
701
702 case Instruction::INVOKE_DIRECT:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800703 EmitInsn_Invoke(ARGS, kDirect, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800704 break;
705
706 case Instruction::INVOKE_STATIC:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800707 EmitInsn_Invoke(ARGS, kStatic, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800708 break;
709
710 case Instruction::INVOKE_INTERFACE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800711 EmitInsn_Invoke(ARGS, kInterface, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800712 break;
713
714 case Instruction::INVOKE_VIRTUAL_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800715 EmitInsn_Invoke(ARGS, kVirtual, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800716 break;
717
718 case Instruction::INVOKE_SUPER_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800719 EmitInsn_Invoke(ARGS, kSuper, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800720 break;
721
722 case Instruction::INVOKE_DIRECT_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800723 EmitInsn_Invoke(ARGS, kDirect, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800724 break;
725
726 case Instruction::INVOKE_STATIC_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800727 EmitInsn_Invoke(ARGS, kStatic, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800728 break;
729
730 case Instruction::INVOKE_INTERFACE_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800731 EmitInsn_Invoke(ARGS, kInterface, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800732 break;
733
734 case Instruction::NEG_INT:
735 EmitInsn_Neg(ARGS, kInt);
736 break;
737
738 case Instruction::NOT_INT:
739 EmitInsn_Not(ARGS, kInt);
740 break;
741
742 case Instruction::NEG_LONG:
743 EmitInsn_Neg(ARGS, kLong);
744 break;
745
746 case Instruction::NOT_LONG:
747 EmitInsn_Not(ARGS, kLong);
748 break;
749
750 case Instruction::NEG_FLOAT:
751 EmitInsn_FNeg(ARGS, kFloat);
752 break;
753
754 case Instruction::NEG_DOUBLE:
755 EmitInsn_FNeg(ARGS, kDouble);
756 break;
757
758 case Instruction::INT_TO_LONG:
759 EmitInsn_SExt(ARGS);
760 break;
761
762 case Instruction::INT_TO_FLOAT:
763 EmitInsn_IntToFP(ARGS, kInt, kFloat);
764 break;
765
766 case Instruction::INT_TO_DOUBLE:
767 EmitInsn_IntToFP(ARGS, kInt, kDouble);
768 break;
769
770 case Instruction::LONG_TO_INT:
771 EmitInsn_Trunc(ARGS);
772 break;
773
774 case Instruction::LONG_TO_FLOAT:
775 EmitInsn_IntToFP(ARGS, kLong, kFloat);
776 break;
777
778 case Instruction::LONG_TO_DOUBLE:
779 EmitInsn_IntToFP(ARGS, kLong, kDouble);
780 break;
781
782 case Instruction::FLOAT_TO_INT:
TDYa127a4746872012-04-11 23:48:55 -0700783 EmitInsn_FPToInt(ARGS, kFloat, kInt, F2I);
Logan Chien70f94b42011-12-27 17:49:11 +0800784 break;
785
786 case Instruction::FLOAT_TO_LONG:
TDYa127a4746872012-04-11 23:48:55 -0700787 EmitInsn_FPToInt(ARGS, kFloat, kLong, F2L);
Logan Chien70f94b42011-12-27 17:49:11 +0800788 break;
789
790 case Instruction::FLOAT_TO_DOUBLE:
791 EmitInsn_FExt(ARGS);
792 break;
793
794 case Instruction::DOUBLE_TO_INT:
TDYa127a4746872012-04-11 23:48:55 -0700795 EmitInsn_FPToInt(ARGS, kDouble, kInt, D2I);
Logan Chien70f94b42011-12-27 17:49:11 +0800796 break;
797
798 case Instruction::DOUBLE_TO_LONG:
TDYa127a4746872012-04-11 23:48:55 -0700799 EmitInsn_FPToInt(ARGS, kDouble, kLong, D2L);
Logan Chien70f94b42011-12-27 17:49:11 +0800800 break;
801
802 case Instruction::DOUBLE_TO_FLOAT:
803 EmitInsn_FTrunc(ARGS);
804 break;
805
806 case Instruction::INT_TO_BYTE:
807 EmitInsn_TruncAndSExt(ARGS, 8);
808 break;
809
810 case Instruction::INT_TO_CHAR:
811 EmitInsn_TruncAndZExt(ARGS, 16);
812 break;
813
814 case Instruction::INT_TO_SHORT:
815 EmitInsn_TruncAndSExt(ARGS, 16);
816 break;
817
818 case Instruction::ADD_INT:
819 EmitInsn_IntArithm(ARGS, kIntArithm_Add, kInt, false);
820 break;
821
822 case Instruction::SUB_INT:
823 EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kInt, false);
824 break;
825
826 case Instruction::MUL_INT:
827 EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kInt, false);
828 break;
829
830 case Instruction::DIV_INT:
831 EmitInsn_IntArithm(ARGS, kIntArithm_Div, kInt, false);
832 break;
833
834 case Instruction::REM_INT:
835 EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kInt, false);
836 break;
837
838 case Instruction::AND_INT:
839 EmitInsn_IntArithm(ARGS, kIntArithm_And, kInt, false);
840 break;
841
842 case Instruction::OR_INT:
843 EmitInsn_IntArithm(ARGS, kIntArithm_Or, kInt, false);
844 break;
845
846 case Instruction::XOR_INT:
847 EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kInt, false);
848 break;
849
850 case Instruction::SHL_INT:
Logan Chien5539ad02012-04-02 14:36:55 +0800851 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800852 break;
853
854 case Instruction::SHR_INT:
Logan Chien5539ad02012-04-02 14:36:55 +0800855 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800856 break;
857
858 case Instruction::USHR_INT:
Logan Chien5539ad02012-04-02 14:36:55 +0800859 EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800860 break;
861
862 case Instruction::ADD_LONG:
863 EmitInsn_IntArithm(ARGS, kIntArithm_Add, kLong, false);
864 break;
865
866 case Instruction::SUB_LONG:
867 EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kLong, false);
868 break;
869
870 case Instruction::MUL_LONG:
871 EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kLong, false);
872 break;
873
874 case Instruction::DIV_LONG:
875 EmitInsn_IntArithm(ARGS, kIntArithm_Div, kLong, false);
876 break;
877
878 case Instruction::REM_LONG:
879 EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kLong, false);
880 break;
881
882 case Instruction::AND_LONG:
883 EmitInsn_IntArithm(ARGS, kIntArithm_And, kLong, false);
884 break;
885
886 case Instruction::OR_LONG:
887 EmitInsn_IntArithm(ARGS, kIntArithm_Or, kLong, false);
888 break;
889
890 case Instruction::XOR_LONG:
891 EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kLong, false);
892 break;
893
894 case Instruction::SHL_LONG:
Logan Chien5539ad02012-04-02 14:36:55 +0800895 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800896 break;
897
898 case Instruction::SHR_LONG:
Logan Chien5539ad02012-04-02 14:36:55 +0800899 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800900 break;
901
902 case Instruction::USHR_LONG:
Logan Chien5539ad02012-04-02 14:36:55 +0800903 EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800904 break;
905
906 case Instruction::ADD_FLOAT:
907 EmitInsn_FPArithm(ARGS, kFPArithm_Add, kFloat, false);
908 break;
909
910 case Instruction::SUB_FLOAT:
911 EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kFloat, false);
912 break;
913
914 case Instruction::MUL_FLOAT:
915 EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kFloat, false);
916 break;
917
918 case Instruction::DIV_FLOAT:
919 EmitInsn_FPArithm(ARGS, kFPArithm_Div, kFloat, false);
920 break;
921
922 case Instruction::REM_FLOAT:
923 EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kFloat, false);
924 break;
925
926 case Instruction::ADD_DOUBLE:
927 EmitInsn_FPArithm(ARGS, kFPArithm_Add, kDouble, false);
928 break;
929
930 case Instruction::SUB_DOUBLE:
931 EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kDouble, false);
932 break;
933
934 case Instruction::MUL_DOUBLE:
935 EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kDouble, false);
936 break;
937
938 case Instruction::DIV_DOUBLE:
939 EmitInsn_FPArithm(ARGS, kFPArithm_Div, kDouble, false);
940 break;
941
942 case Instruction::REM_DOUBLE:
943 EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kDouble, false);
944 break;
945
946 case Instruction::ADD_INT_2ADDR:
947 EmitInsn_IntArithm(ARGS, kIntArithm_Add, kInt, true);
948 break;
949
950 case Instruction::SUB_INT_2ADDR:
951 EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kInt, true);
952 break;
953
954 case Instruction::MUL_INT_2ADDR:
955 EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kInt, true);
956 break;
957
958 case Instruction::DIV_INT_2ADDR:
959 EmitInsn_IntArithm(ARGS, kIntArithm_Div, kInt, true);
960 break;
961
962 case Instruction::REM_INT_2ADDR:
963 EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kInt, true);
964 break;
965
966 case Instruction::AND_INT_2ADDR:
967 EmitInsn_IntArithm(ARGS, kIntArithm_And, kInt, true);
968 break;
969
970 case Instruction::OR_INT_2ADDR:
971 EmitInsn_IntArithm(ARGS, kIntArithm_Or, kInt, true);
972 break;
973
974 case Instruction::XOR_INT_2ADDR:
975 EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kInt, true);
976 break;
977
978 case Instruction::SHL_INT_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +0800979 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, true);
Logan Chien70f94b42011-12-27 17:49:11 +0800980 break;
981
982 case Instruction::SHR_INT_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +0800983 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, true);
Logan Chien70f94b42011-12-27 17:49:11 +0800984 break;
985
986 case Instruction::USHR_INT_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +0800987 EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, true);
Logan Chien70f94b42011-12-27 17:49:11 +0800988 break;
989
990 case Instruction::ADD_LONG_2ADDR:
991 EmitInsn_IntArithm(ARGS, kIntArithm_Add, kLong, true);
992 break;
993
994 case Instruction::SUB_LONG_2ADDR:
995 EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kLong, true);
996 break;
997
998 case Instruction::MUL_LONG_2ADDR:
999 EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kLong, true);
1000 break;
1001
1002 case Instruction::DIV_LONG_2ADDR:
1003 EmitInsn_IntArithm(ARGS, kIntArithm_Div, kLong, true);
1004 break;
1005
1006 case Instruction::REM_LONG_2ADDR:
1007 EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kLong, true);
1008 break;
1009
1010 case Instruction::AND_LONG_2ADDR:
1011 EmitInsn_IntArithm(ARGS, kIntArithm_And, kLong, true);
1012 break;
1013
1014 case Instruction::OR_LONG_2ADDR:
1015 EmitInsn_IntArithm(ARGS, kIntArithm_Or, kLong, true);
1016 break;
1017
1018 case Instruction::XOR_LONG_2ADDR:
1019 EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kLong, true);
1020 break;
1021
1022 case Instruction::SHL_LONG_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +08001023 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, true);
Logan Chien70f94b42011-12-27 17:49:11 +08001024 break;
1025
1026 case Instruction::SHR_LONG_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +08001027 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, true);
Logan Chien70f94b42011-12-27 17:49:11 +08001028 break;
1029
1030 case Instruction::USHR_LONG_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +08001031 EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, true);
Logan Chien70f94b42011-12-27 17:49:11 +08001032 break;
1033
1034 case Instruction::ADD_FLOAT_2ADDR:
1035 EmitInsn_FPArithm(ARGS, kFPArithm_Add, kFloat, true);
1036 break;
1037
1038 case Instruction::SUB_FLOAT_2ADDR:
1039 EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kFloat, true);
1040 break;
1041
1042 case Instruction::MUL_FLOAT_2ADDR:
1043 EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kFloat, true);
1044 break;
1045
1046 case Instruction::DIV_FLOAT_2ADDR:
1047 EmitInsn_FPArithm(ARGS, kFPArithm_Div, kFloat, true);
1048 break;
1049
1050 case Instruction::REM_FLOAT_2ADDR:
1051 EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kFloat, true);
1052 break;
1053
1054 case Instruction::ADD_DOUBLE_2ADDR:
1055 EmitInsn_FPArithm(ARGS, kFPArithm_Add, kDouble, true);
1056 break;
1057
1058 case Instruction::SUB_DOUBLE_2ADDR:
1059 EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kDouble, true);
1060 break;
1061
1062 case Instruction::MUL_DOUBLE_2ADDR:
1063 EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kDouble, true);
1064 break;
1065
1066 case Instruction::DIV_DOUBLE_2ADDR:
1067 EmitInsn_FPArithm(ARGS, kFPArithm_Div, kDouble, true);
1068 break;
1069
1070 case Instruction::REM_DOUBLE_2ADDR:
1071 EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kDouble, true);
1072 break;
1073
1074 case Instruction::ADD_INT_LIT16:
1075 case Instruction::ADD_INT_LIT8:
1076 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Add);
1077 break;
1078
1079 case Instruction::RSUB_INT:
1080 case Instruction::RSUB_INT_LIT8:
1081 EmitInsn_RSubImmediate(ARGS);
1082 break;
1083
1084 case Instruction::MUL_INT_LIT16:
1085 case Instruction::MUL_INT_LIT8:
1086 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Mul);
1087 break;
1088
1089 case Instruction::DIV_INT_LIT16:
1090 case Instruction::DIV_INT_LIT8:
1091 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Div);
1092 break;
1093
1094 case Instruction::REM_INT_LIT16:
1095 case Instruction::REM_INT_LIT8:
1096 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Rem);
1097 break;
1098
1099 case Instruction::AND_INT_LIT16:
1100 case Instruction::AND_INT_LIT8:
1101 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_And);
1102 break;
1103
1104 case Instruction::OR_INT_LIT16:
1105 case Instruction::OR_INT_LIT8:
1106 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Or);
1107 break;
1108
1109 case Instruction::XOR_INT_LIT16:
1110 case Instruction::XOR_INT_LIT8:
1111 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Xor);
1112 break;
1113
1114 case Instruction::SHL_INT_LIT8:
Logan Chien5539ad02012-04-02 14:36:55 +08001115 EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shl);
Logan Chien70f94b42011-12-27 17:49:11 +08001116 break;
1117
1118 case Instruction::SHR_INT_LIT8:
Logan Chien5539ad02012-04-02 14:36:55 +08001119 EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shr);
Logan Chien70f94b42011-12-27 17:49:11 +08001120 break;
1121
1122 case Instruction::USHR_INT_LIT8:
Logan Chien5539ad02012-04-02 14:36:55 +08001123 EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_UShr);
Logan Chien70f94b42011-12-27 17:49:11 +08001124 break;
1125
Logan Chien9e5f5c12012-04-10 13:51:45 +08001126 case Instruction::THROW_VERIFICATION_ERROR:
1127 EmitInsn_ThrowVerificationError(ARGS);
1128 break;
1129
Logan Chien70f94b42011-12-27 17:49:11 +08001130 case Instruction::UNUSED_3E:
1131 case Instruction::UNUSED_3F:
1132 case Instruction::UNUSED_40:
1133 case Instruction::UNUSED_41:
1134 case Instruction::UNUSED_42:
1135 case Instruction::UNUSED_43:
1136 case Instruction::UNUSED_73:
1137 case Instruction::UNUSED_79:
1138 case Instruction::UNUSED_7A:
1139 case Instruction::UNUSED_E3:
1140 case Instruction::UNUSED_E4:
1141 case Instruction::UNUSED_E5:
1142 case Instruction::UNUSED_E6:
1143 case Instruction::UNUSED_E7:
1144 case Instruction::UNUSED_E8:
1145 case Instruction::UNUSED_E9:
1146 case Instruction::UNUSED_EA:
1147 case Instruction::UNUSED_EB:
1148 case Instruction::UNUSED_EC:
Logan Chien70f94b42011-12-27 17:49:11 +08001149 case Instruction::UNUSED_EE:
1150 case Instruction::UNUSED_EF:
1151 case Instruction::UNUSED_F0:
1152 case Instruction::UNUSED_F1:
1153 case Instruction::UNUSED_F2:
1154 case Instruction::UNUSED_F3:
1155 case Instruction::UNUSED_F4:
1156 case Instruction::UNUSED_F5:
1157 case Instruction::UNUSED_F6:
1158 case Instruction::UNUSED_F7:
1159 case Instruction::UNUSED_F8:
1160 case Instruction::UNUSED_F9:
1161 case Instruction::UNUSED_FA:
1162 case Instruction::UNUSED_FB:
1163 case Instruction::UNUSED_FC:
1164 case Instruction::UNUSED_FD:
1165 case Instruction::UNUSED_FE:
1166 case Instruction::UNUSED_FF:
1167 LOG(FATAL) << "Dex file contains UNUSED bytecode: " << insn->Opcode();
1168 break;
1169 }
1170
1171#undef ARGS
1172}
1173
1174
1175void MethodCompiler::EmitInsn_Nop(uint32_t dex_pc,
1176 Instruction const* insn) {
Logan Chiene09a6b72011-12-27 17:50:21 +08001177
1178 uint16_t insn_signature = code_item_->insns_[dex_pc];
1179
1180 if (insn_signature == Instruction::kPackedSwitchSignature ||
1181 insn_signature == Instruction::kSparseSwitchSignature ||
1182 insn_signature == Instruction::kArrayDataSignature) {
1183 irb_.CreateUnreachable();
Elliott Hughesb25c3f62012-03-26 16:35:06 -07001184 } else {
Logan Chiene09a6b72011-12-27 17:50:21 +08001185 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1186 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -08001187}
1188
1189
Logan Chien70f94b42011-12-27 17:49:11 +08001190void MethodCompiler::EmitInsn_Move(uint32_t dex_pc,
1191 Instruction const* insn,
1192 JType jty) {
Logan Chien48173132011-12-27 17:51:13 +08001193
Elliott Hughesadb8c672012-03-06 16:49:32 -08001194 DecodedInstruction dec_insn(insn);
Logan Chien48173132011-12-27 17:51:13 +08001195
Elliott Hughesadb8c672012-03-06 16:49:32 -08001196 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, jty, kReg);
1197 EmitStoreDalvikReg(dec_insn.vA, jty, kReg, src_value);
Logan Chien48173132011-12-27 17:51:13 +08001198
Logan Chien70f94b42011-12-27 17:49:11 +08001199 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1200}
1201
1202
1203void MethodCompiler::EmitInsn_MoveResult(uint32_t dex_pc,
1204 Instruction const* insn,
1205 JType jty) {
Logan Chien48173132011-12-27 17:51:13 +08001206
Elliott Hughesadb8c672012-03-06 16:49:32 -08001207 DecodedInstruction dec_insn(insn);
Logan Chien48173132011-12-27 17:51:13 +08001208
1209 llvm::Value* src_value = EmitLoadDalvikRetValReg(jty, kReg);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001210 EmitStoreDalvikReg(dec_insn.vA, jty, kReg, src_value);
Logan Chien48173132011-12-27 17:51:13 +08001211
Logan Chien70f94b42011-12-27 17:49:11 +08001212 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1213}
1214
1215
1216void MethodCompiler::EmitInsn_MoveException(uint32_t dex_pc,
1217 Instruction const* insn) {
Logan Chien3354cec2012-01-13 14:29:03 +08001218
Elliott Hughesadb8c672012-03-06 16:49:32 -08001219 DecodedInstruction dec_insn(insn);
Logan Chien3354cec2012-01-13 14:29:03 +08001220
TDYa127ee1f59b2012-04-25 00:56:40 -07001221 // Get thread
Logan Chien3354cec2012-01-13 14:29:03 +08001222 llvm::Value* thread_object_addr =
1223 irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1224
TDYa127ee1f59b2012-04-25 00:56:40 -07001225 // Get thread-local exception field address
1226 llvm::Value* exception_object_addr =
1227 irb_.LoadFromObjectOffset(thread_object_addr,
1228 Thread::ExceptionOffset().Int32Value(),
1229 irb_.getJObjectTy());
Logan Chien3354cec2012-01-13 14:29:03 +08001230
1231 // Set thread-local exception field address to NULL
TDYa127ee1f59b2012-04-25 00:56:40 -07001232 irb_.StoreToObjectOffset(thread_object_addr,
1233 Thread::ExceptionOffset().Int32Value(),
1234 irb_.getJNull());
Logan Chien3354cec2012-01-13 14:29:03 +08001235
1236 // Keep the exception object in the Dalvik register
Elliott Hughesadb8c672012-03-06 16:49:32 -08001237 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, exception_object_addr);
Logan Chien3354cec2012-01-13 14:29:03 +08001238
Logan Chien70f94b42011-12-27 17:49:11 +08001239 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1240}
1241
1242
1243void MethodCompiler::EmitInsn_ThrowException(uint32_t dex_pc,
1244 Instruction const* insn) {
Logan Chien6c6f12d2012-01-13 19:26:27 +08001245
Elliott Hughesadb8c672012-03-06 16:49:32 -08001246 DecodedInstruction dec_insn(insn);
Logan Chien6c6f12d2012-01-13 19:26:27 +08001247
1248 llvm::Value* exception_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001249 EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chien6c6f12d2012-01-13 19:26:27 +08001250
TDYa127c8dc1012012-04-19 07:03:33 -07001251 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001252
Logan Chien6c6f12d2012-01-13 19:26:27 +08001253 irb_.CreateCall(irb_.GetRuntime(ThrowException), exception_addr);
1254
1255 EmitBranchExceptionLandingPad(dex_pc);
Logan Chien70f94b42011-12-27 17:49:11 +08001256}
1257
1258
Logan Chien9e5f5c12012-04-10 13:51:45 +08001259void MethodCompiler::EmitInsn_ThrowVerificationError(uint32_t dex_pc,
1260 Instruction const* insn) {
1261
1262 DecodedInstruction dec_insn(insn);
1263
TDYa127c8dc1012012-04-19 07:03:33 -07001264 EmitUpdateDexPC(dex_pc);
Logan Chien9e5f5c12012-04-10 13:51:45 +08001265
1266 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1267 llvm::Value* kind_value = irb_.getInt32(dec_insn.vA);
1268 llvm::Value* ref_value = irb_.getInt32(dec_insn.vB);
1269
1270 irb_.CreateCall3(irb_.GetRuntime(ThrowVerificationError),
1271 method_object_addr, kind_value, ref_value);
1272
1273 EmitBranchExceptionLandingPad(dex_pc);
1274}
1275
1276
Logan Chien70f94b42011-12-27 17:49:11 +08001277void MethodCompiler::EmitInsn_ReturnVoid(uint32_t dex_pc,
1278 Instruction const* insn) {
Logan Chien8898a272011-12-27 17:51:56 +08001279 // Garbage collection safe-point
1280 EmitGuard_GarbageCollectionSuspend(dex_pc);
1281
Logan Chien8dfcbea2012-02-17 18:50:32 +08001282 // Pop the shadow frame
1283 EmitPopShadowFrame();
1284
Logan Chien8898a272011-12-27 17:51:56 +08001285 // Return!
1286 irb_.CreateRetVoid();
Logan Chien70f94b42011-12-27 17:49:11 +08001287}
1288
1289
1290void MethodCompiler::EmitInsn_Return(uint32_t dex_pc,
1291 Instruction const* insn) {
Logan Chien8898a272011-12-27 17:51:56 +08001292
Elliott Hughesadb8c672012-03-06 16:49:32 -08001293 DecodedInstruction dec_insn(insn);
Logan Chien8898a272011-12-27 17:51:56 +08001294
1295 // Garbage collection safe-point
1296 EmitGuard_GarbageCollectionSuspend(dex_pc);
1297
Logan Chien8dfcbea2012-02-17 18:50:32 +08001298 // Pop the shadow frame
1299 EmitPopShadowFrame();
1300 // NOTE: It is important to keep this AFTER the GC safe-point. Otherwise,
1301 // the return value might be collected since the shadow stack is popped.
1302
Logan Chien8898a272011-12-27 17:51:56 +08001303 // Return!
Logan Chiendd361c92012-04-10 23:40:37 +08001304 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
Elliott Hughesadb8c672012-03-06 16:49:32 -08001305 llvm::Value* retval = EmitLoadDalvikReg(dec_insn.vA, ret_shorty, kAccurate);
Logan Chien8898a272011-12-27 17:51:56 +08001306
1307 irb_.CreateRet(retval);
Logan Chien70f94b42011-12-27 17:49:11 +08001308}
1309
1310
1311void MethodCompiler::EmitInsn_LoadConstant(uint32_t dex_pc,
1312 Instruction const* insn,
1313 JType imm_jty) {
Shih-wei Liao798366e2012-02-16 09:25:33 -08001314
Elliott Hughesadb8c672012-03-06 16:49:32 -08001315 DecodedInstruction dec_insn(insn);
Shih-wei Liao798366e2012-02-16 09:25:33 -08001316
1317 DCHECK(imm_jty == kInt || imm_jty == kLong) << imm_jty;
1318
1319 int64_t imm = 0;
1320
1321 switch (insn->Opcode()) {
1322 // 32-bit Immediate
1323 case Instruction::CONST_4:
1324 case Instruction::CONST_16:
1325 case Instruction::CONST:
1326 case Instruction::CONST_WIDE_16:
1327 case Instruction::CONST_WIDE_32:
Elliott Hughesadb8c672012-03-06 16:49:32 -08001328 imm = static_cast<int64_t>(static_cast<int32_t>(dec_insn.vB));
Shih-wei Liao798366e2012-02-16 09:25:33 -08001329 break;
1330
1331 case Instruction::CONST_HIGH16:
1332 imm = static_cast<int64_t>(static_cast<int32_t>(
Elliott Hughesadb8c672012-03-06 16:49:32 -08001333 static_cast<uint32_t>(static_cast<uint16_t>(dec_insn.vB)) << 16));
Shih-wei Liao798366e2012-02-16 09:25:33 -08001334 break;
1335
1336 // 64-bit Immediate
1337 case Instruction::CONST_WIDE:
Elliott Hughesadb8c672012-03-06 16:49:32 -08001338 imm = static_cast<int64_t>(dec_insn.vB_wide);
Shih-wei Liao798366e2012-02-16 09:25:33 -08001339 break;
1340
1341 case Instruction::CONST_WIDE_HIGH16:
1342 imm = static_cast<int64_t>(
Elliott Hughesadb8c672012-03-06 16:49:32 -08001343 static_cast<uint64_t>(static_cast<uint16_t>(dec_insn.vB)) << 48);
Shih-wei Liao798366e2012-02-16 09:25:33 -08001344 break;
1345
1346 // Unknown opcode for load constant (unreachable)
1347 default:
1348 LOG(FATAL) << "Unknown opcode for load constant: " << insn->Opcode();
1349 break;
1350 }
1351
1352 // Store the non-object register
1353 llvm::Type* imm_type = irb_.getJType(imm_jty, kAccurate);
1354 llvm::Constant* imm_value = llvm::ConstantInt::getSigned(imm_type, imm);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001355 EmitStoreDalvikReg(dec_insn.vA, imm_jty, kAccurate, imm_value);
Shih-wei Liao798366e2012-02-16 09:25:33 -08001356
1357 // Store the object register if it is possible to be null.
1358 if (imm_jty == kInt && imm == 0) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08001359 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, irb_.getJNull());
Shih-wei Liao798366e2012-02-16 09:25:33 -08001360 }
1361
Logan Chien70f94b42011-12-27 17:49:11 +08001362 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1363}
1364
1365
1366void MethodCompiler::EmitInsn_LoadConstantString(uint32_t dex_pc,
1367 Instruction const* insn) {
Logan Chienc3b4ba12012-01-16 19:52:53 +08001368
Elliott Hughesadb8c672012-03-06 16:49:32 -08001369 DecodedInstruction dec_insn(insn);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001370
Elliott Hughesadb8c672012-03-06 16:49:32 -08001371 uint32_t string_idx = dec_insn.vB;
Logan Chienc3b4ba12012-01-16 19:52:53 +08001372
1373 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1374
1375 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr);
1376
1377 if (!compiler_->CanAssumeStringIsPresentInDexCache(dex_cache_, string_idx)) {
1378 llvm::BasicBlock* block_str_exist =
1379 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1380
1381 llvm::BasicBlock* block_str_resolve =
1382 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1383
1384 // Test: Is the string resolved and in the dex cache?
1385 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1386
TDYa127a849cb62012-04-01 05:59:34 -07001387 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001388
1389 // String is resolved, go to next basic block.
1390 irb_.SetInsertPoint(block_str_exist);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001391 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, string_addr);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001392 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1393
1394 // String is not resolved yet, resolve it now.
1395 irb_.SetInsertPoint(block_str_resolve);
1396
1397 llvm::Function* runtime_func = irb_.GetRuntime(ResolveString);
1398
1399 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1400
1401 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1402
TDYa127c8dc1012012-04-19 07:03:33 -07001403 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001404
1405 string_addr = irb_.CreateCall2(runtime_func, method_object_addr,
1406 string_idx_value);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001407
1408 EmitGuard_ExceptionLandingPad(dex_pc);
1409 }
1410
1411 // Store the string object to the Dalvik register
Elliott Hughesadb8c672012-03-06 16:49:32 -08001412 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, string_addr);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001413
Logan Chien70f94b42011-12-27 17:49:11 +08001414 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1415}
1416
1417
Logan Chien27b30252012-01-14 03:43:35 +08001418llvm::Value* MethodCompiler::EmitLoadConstantClass(uint32_t dex_pc,
1419 uint32_t type_idx) {
1420 if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
1421 *dex_file_, type_idx)) {
1422 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1423
1424 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1425
TDYa127706e9b62012-04-19 12:24:26 -07001426 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1427
Logan Chien27b30252012-01-14 03:43:35 +08001428 llvm::Function* runtime_func =
1429 irb_.GetRuntime(InitializeTypeAndVerifyAccess);
1430
TDYa127c8dc1012012-04-19 07:03:33 -07001431 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001432
Logan Chien27b30252012-01-14 03:43:35 +08001433 llvm::Value* type_object_addr =
TDYa127706e9b62012-04-19 12:24:26 -07001434 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
Logan Chien27b30252012-01-14 03:43:35 +08001435
1436 EmitGuard_ExceptionLandingPad(dex_pc);
1437
1438 return type_object_addr;
1439
1440 } else {
1441 // Try to load the class (type) object from the test cache.
1442 llvm::Value* type_field_addr =
1443 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1444
1445 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr);
1446
1447 if (compiler_->CanAssumeTypeIsPresentInDexCache(dex_cache_, type_idx)) {
1448 return type_object_addr;
1449 }
1450
1451 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1452
1453 // Test whether class (type) object is in the dex cache or not
1454 llvm::Value* equal_null =
1455 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1456
1457 llvm::BasicBlock* block_cont =
1458 CreateBasicBlockWithDexPC(dex_pc, "cont");
1459
1460 llvm::BasicBlock* block_load_class =
1461 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1462
1463 irb_.CreateCondBr(equal_null, block_load_class, block_cont);
1464
1465 // Failback routine to load the class object
1466 irb_.SetInsertPoint(block_load_class);
1467
1468 llvm::Function* runtime_func = irb_.GetRuntime(InitializeType);
1469
1470 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1471
1472 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1473
TDYa127706e9b62012-04-19 12:24:26 -07001474 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1475
TDYa127c8dc1012012-04-19 07:03:33 -07001476 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001477
Logan Chien27b30252012-01-14 03:43:35 +08001478 llvm::Value* loaded_type_object_addr =
TDYa127706e9b62012-04-19 12:24:26 -07001479 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
Logan Chien27b30252012-01-14 03:43:35 +08001480
1481 EmitGuard_ExceptionLandingPad(dex_pc);
1482
1483 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1484
1485 irb_.CreateBr(block_cont);
1486
1487 // Now the class object must be loaded
1488 irb_.SetInsertPoint(block_cont);
1489
1490 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1491
1492 phi->addIncoming(type_object_addr, block_original);
1493 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1494
1495 return phi;
1496 }
1497}
1498
1499
Logan Chien70f94b42011-12-27 17:49:11 +08001500void MethodCompiler::EmitInsn_LoadConstantClass(uint32_t dex_pc,
1501 Instruction const* insn) {
Logan Chien27b30252012-01-14 03:43:35 +08001502
Elliott Hughesadb8c672012-03-06 16:49:32 -08001503 DecodedInstruction dec_insn(insn);
Logan Chien27b30252012-01-14 03:43:35 +08001504
Elliott Hughesadb8c672012-03-06 16:49:32 -08001505 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB);
1506 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, type_object_addr);
Logan Chien27b30252012-01-14 03:43:35 +08001507
Logan Chien70f94b42011-12-27 17:49:11 +08001508 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1509}
1510
1511
1512void MethodCompiler::EmitInsn_MonitorEnter(uint32_t dex_pc,
1513 Instruction const* insn) {
Logan Chien9e0dbe42012-01-13 12:11:37 +08001514
Elliott Hughesadb8c672012-03-06 16:49:32 -08001515 DecodedInstruction dec_insn(insn);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001516
1517 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001518 EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001519
1520 // TODO: Slow path always. May not need NullPointerException check.
1521 EmitGuard_NullPointerException(dex_pc, object_addr);
1522
TDYa127c8dc1012012-04-19 07:03:33 -07001523 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001524
TDYa127706e9b62012-04-19 12:24:26 -07001525 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1526
1527 irb_.CreateCall2(irb_.GetRuntime(LockObject), object_addr, thread_object_addr);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001528 EmitGuard_ExceptionLandingPad(dex_pc);
1529
Logan Chien70f94b42011-12-27 17:49:11 +08001530 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1531}
1532
1533
1534void MethodCompiler::EmitInsn_MonitorExit(uint32_t dex_pc,
1535 Instruction const* insn) {
Logan Chien9e0dbe42012-01-13 12:11:37 +08001536
Elliott Hughesadb8c672012-03-06 16:49:32 -08001537 DecodedInstruction dec_insn(insn);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001538
1539 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001540 EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001541
1542 EmitGuard_NullPointerException(dex_pc, object_addr);
1543
TDYa127c8dc1012012-04-19 07:03:33 -07001544 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001545
TDYa127706e9b62012-04-19 12:24:26 -07001546 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1547
1548 irb_.CreateCall2(irb_.GetRuntime(UnlockObject), object_addr, thread_object_addr);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001549 EmitGuard_ExceptionLandingPad(dex_pc);
1550
Logan Chien70f94b42011-12-27 17:49:11 +08001551 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1552}
1553
1554
1555void MethodCompiler::EmitInsn_CheckCast(uint32_t dex_pc,
1556 Instruction const* insn) {
Logan Chienfc880952012-01-15 23:53:10 +08001557
Elliott Hughesadb8c672012-03-06 16:49:32 -08001558 DecodedInstruction dec_insn(insn);
Logan Chienfc880952012-01-15 23:53:10 +08001559
1560 llvm::BasicBlock* block_test_class =
1561 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1562
1563 llvm::BasicBlock* block_test_sub_class =
1564 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1565
1566 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001567 EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chienfc880952012-01-15 23:53:10 +08001568
1569 // Test: Is the reference equal to null? Act as no-op when it is null.
1570 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1571
1572 irb_.CreateCondBr(equal_null,
1573 GetNextBasicBlock(dex_pc),
1574 block_test_class);
1575
1576 // Test: Is the object instantiated from the given class?
1577 irb_.SetInsertPoint(block_test_class);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001578 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB);
Logan Chienfc880952012-01-15 23:53:10 +08001579 DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
1580
1581 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1582
1583 llvm::Value* object_type_field_addr =
1584 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1585
1586 llvm::Value* object_type_object_addr =
1587 irb_.CreateLoad(object_type_field_addr);
1588
1589 llvm::Value* equal_class =
1590 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1591
1592 irb_.CreateCondBr(equal_class,
1593 GetNextBasicBlock(dex_pc),
1594 block_test_sub_class);
1595
1596 // Test: Is the object instantiated from the subclass of the given class?
1597 irb_.SetInsertPoint(block_test_sub_class);
1598
TDYa127c8dc1012012-04-19 07:03:33 -07001599 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001600
Logan Chienfc880952012-01-15 23:53:10 +08001601 irb_.CreateCall2(irb_.GetRuntime(CheckCast),
1602 type_object_addr, object_type_object_addr);
1603
1604 EmitGuard_ExceptionLandingPad(dex_pc);
1605
Logan Chien70f94b42011-12-27 17:49:11 +08001606 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1607}
1608
1609
1610void MethodCompiler::EmitInsn_InstanceOf(uint32_t dex_pc,
1611 Instruction const* insn) {
Logan Chien68725e22012-01-15 22:25:34 +08001612
Elliott Hughesadb8c672012-03-06 16:49:32 -08001613 DecodedInstruction dec_insn(insn);
Logan Chien68725e22012-01-15 22:25:34 +08001614
1615 llvm::Constant* zero = irb_.getJInt(0);
1616 llvm::Constant* one = irb_.getJInt(1);
1617
1618 llvm::BasicBlock* block_nullp = CreateBasicBlockWithDexPC(dex_pc, "nullp");
1619
1620 llvm::BasicBlock* block_test_class =
1621 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1622
1623 llvm::BasicBlock* block_class_equals =
1624 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
1625
1626 llvm::BasicBlock* block_test_sub_class =
1627 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1628
1629 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001630 EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
Logan Chien68725e22012-01-15 22:25:34 +08001631
1632 // Overview of the following code :
1633 // We check for null, if so, then false, otherwise check for class == . If so
1634 // then true, otherwise do callout slowpath.
1635 //
1636 // Test: Is the reference equal to null? Set 0 when it is null.
1637 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1638
1639 irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
1640
1641 irb_.SetInsertPoint(block_nullp);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001642 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, zero);
Logan Chien68725e22012-01-15 22:25:34 +08001643 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1644
1645 // Test: Is the object instantiated from the given class?
1646 irb_.SetInsertPoint(block_test_class);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001647 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vC);
Logan Chien68725e22012-01-15 22:25:34 +08001648 DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
1649
1650 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1651
1652 llvm::Value* object_type_field_addr =
1653 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1654
1655 llvm::Value* object_type_object_addr =
1656 irb_.CreateLoad(object_type_field_addr);
1657
1658 llvm::Value* equal_class =
1659 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1660
1661 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
1662
1663 irb_.SetInsertPoint(block_class_equals);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001664 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, one);
Logan Chien68725e22012-01-15 22:25:34 +08001665 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1666
1667 // Test: Is the object instantiated from the subclass of the given class?
1668 irb_.SetInsertPoint(block_test_sub_class);
1669
1670 llvm::Value* result =
1671 irb_.CreateCall2(irb_.GetRuntime(IsAssignable),
1672 type_object_addr, object_type_object_addr);
1673
Elliott Hughesadb8c672012-03-06 16:49:32 -08001674 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
Logan Chien68725e22012-01-15 22:25:34 +08001675
Logan Chien70f94b42011-12-27 17:49:11 +08001676 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1677}
1678
1679
Logan Chien61bb6142012-02-03 15:34:53 +08001680llvm::Value* MethodCompiler::EmitLoadArrayLength(llvm::Value* array) {
Logan Chien61bb6142012-02-03 15:34:53 +08001681 // Load array length
TDYa127ee1f59b2012-04-25 00:56:40 -07001682 return irb_.LoadFromObjectOffset(array,
1683 Array::LengthOffset().Int32Value(),
1684 irb_.getJIntTy());
Logan Chien61bb6142012-02-03 15:34:53 +08001685}
1686
1687
Logan Chien70f94b42011-12-27 17:49:11 +08001688void MethodCompiler::EmitInsn_ArrayLength(uint32_t dex_pc,
1689 Instruction const* insn) {
Logan Chien61bb6142012-02-03 15:34:53 +08001690
Elliott Hughesadb8c672012-03-06 16:49:32 -08001691 DecodedInstruction dec_insn(insn);
Logan Chien61bb6142012-02-03 15:34:53 +08001692
1693 // Get the array object address
Elliott Hughesadb8c672012-03-06 16:49:32 -08001694 llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
Logan Chien61bb6142012-02-03 15:34:53 +08001695 EmitGuard_NullPointerException(dex_pc, array_addr);
1696
1697 // Get the array length and store it to the register
1698 llvm::Value* array_len = EmitLoadArrayLength(array_addr);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001699 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, array_len);
Logan Chien61bb6142012-02-03 15:34:53 +08001700
Logan Chien70f94b42011-12-27 17:49:11 +08001701 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1702}
1703
1704
1705void MethodCompiler::EmitInsn_NewInstance(uint32_t dex_pc,
1706 Instruction const* insn) {
Logan Chien032bdad2012-01-16 09:59:23 +08001707
Elliott Hughesadb8c672012-03-06 16:49:32 -08001708 DecodedInstruction dec_insn(insn);
Logan Chien032bdad2012-01-16 09:59:23 +08001709
1710 llvm::Function* runtime_func;
Logan Chien1a032b12012-04-11 11:43:04 +08001711 if (compiler_->CanAccessInstantiableTypeWithoutChecks(
1712 method_idx_, dex_cache_, *dex_file_, dec_insn.vB)) {
Logan Chien032bdad2012-01-16 09:59:23 +08001713 runtime_func = irb_.GetRuntime(AllocObject);
1714 } else {
1715 runtime_func = irb_.GetRuntime(AllocObjectWithAccessCheck);
1716 }
1717
Elliott Hughesadb8c672012-03-06 16:49:32 -08001718 llvm::Constant* type_index_value = irb_.getInt32(dec_insn.vB);
Logan Chien032bdad2012-01-16 09:59:23 +08001719
1720 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1721
TDYa127da83d972012-04-18 00:21:49 -07001722 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1723
TDYa127c8dc1012012-04-19 07:03:33 -07001724 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001725
Logan Chien032bdad2012-01-16 09:59:23 +08001726 llvm::Value* object_addr =
TDYa127da83d972012-04-18 00:21:49 -07001727 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
Logan Chien032bdad2012-01-16 09:59:23 +08001728
1729 EmitGuard_ExceptionLandingPad(dex_pc);
1730
Elliott Hughesadb8c672012-03-06 16:49:32 -08001731 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, object_addr);
Logan Chien032bdad2012-01-16 09:59:23 +08001732
Logan Chien70f94b42011-12-27 17:49:11 +08001733 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1734}
1735
1736
Logan Chiena2cc6a32012-01-16 10:38:41 +08001737llvm::Value* MethodCompiler::EmitAllocNewArray(uint32_t dex_pc,
1738 int32_t length,
1739 uint32_t type_idx,
1740 bool is_filled_new_array) {
1741 llvm::Function* runtime_func;
1742
1743 bool skip_access_check =
1744 compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
1745 *dex_file_, type_idx);
1746
TDYa127a849cb62012-04-01 05:59:34 -07001747 llvm::Value* array_length_value;
1748
Logan Chiena2cc6a32012-01-16 10:38:41 +08001749 if (is_filled_new_array) {
1750 runtime_func = skip_access_check ?
1751 irb_.GetRuntime(CheckAndAllocArray) :
1752 irb_.GetRuntime(CheckAndAllocArrayWithAccessCheck);
TDYa127a849cb62012-04-01 05:59:34 -07001753 array_length_value = irb_.getInt32(length);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001754 } else {
1755 runtime_func = skip_access_check ?
1756 irb_.GetRuntime(AllocArray) :
1757 irb_.GetRuntime(AllocArrayWithAccessCheck);
TDYa127a849cb62012-04-01 05:59:34 -07001758 array_length_value = EmitLoadDalvikReg(length, kInt, kAccurate);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001759 }
1760
1761 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
1762
1763 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1764
TDYa127da83d972012-04-18 00:21:49 -07001765 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1766
TDYa127c8dc1012012-04-19 07:03:33 -07001767 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001768
Logan Chiena2cc6a32012-01-16 10:38:41 +08001769 llvm::Value* object_addr =
TDYa127da83d972012-04-18 00:21:49 -07001770 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
1771 array_length_value, thread_object_addr);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001772
1773 EmitGuard_ExceptionLandingPad(dex_pc);
1774
1775 return object_addr;
1776}
1777
1778
Logan Chien70f94b42011-12-27 17:49:11 +08001779void MethodCompiler::EmitInsn_NewArray(uint32_t dex_pc,
1780 Instruction const* insn) {
Logan Chiena2cc6a32012-01-16 10:38:41 +08001781
Elliott Hughesadb8c672012-03-06 16:49:32 -08001782 DecodedInstruction dec_insn(insn);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001783
1784 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001785 EmitAllocNewArray(dex_pc, dec_insn.vB, dec_insn.vC, false);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001786
Elliott Hughesadb8c672012-03-06 16:49:32 -08001787 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, object_addr);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001788
Logan Chien70f94b42011-12-27 17:49:11 +08001789 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1790}
1791
1792
1793void MethodCompiler::EmitInsn_FilledNewArray(uint32_t dex_pc,
1794 Instruction const* insn,
1795 bool is_range) {
Logan Chiena85fb2f2012-01-16 12:52:56 +08001796
Elliott Hughesadb8c672012-03-06 16:49:32 -08001797 DecodedInstruction dec_insn(insn);
Logan Chiena85fb2f2012-01-16 12:52:56 +08001798
1799 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001800 EmitAllocNewArray(dex_pc, dec_insn.vA, dec_insn.vB, true);
Logan Chiena85fb2f2012-01-16 12:52:56 +08001801
Elliott Hughesadb8c672012-03-06 16:49:32 -08001802 if (dec_insn.vA > 0) {
Logan Chiendd361c92012-04-10 23:40:37 +08001803 // Resolve the element type
TDYa127183cf262012-04-11 07:53:21 -07001804 Class* klass = dex_cache_->GetResolvedType(dec_insn.vB)->GetComponentType();
Logan Chiendd361c92012-04-10 23:40:37 +08001805 // TODO: Avoid the usage of the dex_cache_. Try to figure out a better
1806 // way to distinguish [I and [L.
Logan Chiena85fb2f2012-01-16 12:52:56 +08001807 CHECK_NE(klass, static_cast<Class*>(NULL));
Logan Chiena85fb2f2012-01-16 12:52:56 +08001808
Logan Chiendd361c92012-04-10 23:40:37 +08001809 uint32_t alignment;
1810 llvm::Constant* elem_size;
1811 llvm::PointerType* field_type;
Logan Chiena85fb2f2012-01-16 12:52:56 +08001812
Logan Chiendd361c92012-04-10 23:40:37 +08001813 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
1814 // as the element, thus we are only checking 2 cases: primitive int and
1815 // non-primitive type.
Logan Chiena85fb2f2012-01-16 12:52:56 +08001816 if (klass->IsPrimitiveInt()) {
Logan Chiendd361c92012-04-10 23:40:37 +08001817 alignment = sizeof(int32_t);
1818 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
Logan Chiena85fb2f2012-01-16 12:52:56 +08001819 field_type = irb_.getJIntTy()->getPointerTo();
1820 } else {
1821 CHECK(!klass->IsPrimitive());
Logan Chiendd361c92012-04-10 23:40:37 +08001822 alignment = irb_.getSizeOfPtrEquivInt();
1823 elem_size = irb_.getSizeOfPtrEquivIntValue();
Logan Chiena85fb2f2012-01-16 12:52:56 +08001824 field_type = irb_.getJObjectTy()->getPointerTo();
1825 }
1826
Logan Chiendd361c92012-04-10 23:40:37 +08001827 llvm::Value* data_field_offset =
1828 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
1829
1830 llvm::Value* data_field_addr =
1831 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
1832
Logan Chiena85fb2f2012-01-16 12:52:56 +08001833 // TODO: Tune this code. Currently we are generating one instruction for
1834 // one element which may be very space consuming. Maybe changing to use
1835 // memcpy may help; however, since we can't guarantee that the alloca of
1836 // dalvik register are continuous, we can't perform such optimization yet.
Elliott Hughesadb8c672012-03-06 16:49:32 -08001837 for (uint32_t i = 0; i < dec_insn.vA; ++i) {
Logan Chiena85fb2f2012-01-16 12:52:56 +08001838 int reg_index;
1839 if (is_range) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08001840 reg_index = dec_insn.vC + i;
Logan Chiena85fb2f2012-01-16 12:52:56 +08001841 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08001842 reg_index = dec_insn.arg[i];
Logan Chiena85fb2f2012-01-16 12:52:56 +08001843 }
1844
1845 llvm::Value* reg_value;
1846 if (klass->IsPrimitiveInt()) {
1847 reg_value = EmitLoadDalvikReg(reg_index, kInt, kAccurate);
1848 } else {
1849 reg_value = EmitLoadDalvikReg(reg_index, kObject, kAccurate);
1850 }
1851
1852 irb_.CreateStore(reg_value, data_field_addr);
1853
Logan Chiendd361c92012-04-10 23:40:37 +08001854 data_field_addr =
1855 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
Logan Chiena85fb2f2012-01-16 12:52:56 +08001856 }
1857 }
1858
1859 EmitStoreDalvikRetValReg(kObject, kAccurate, object_addr);
1860
Logan Chien70f94b42011-12-27 17:49:11 +08001861 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1862}
1863
1864
1865void MethodCompiler::EmitInsn_FillArrayData(uint32_t dex_pc,
1866 Instruction const* insn) {
Logan Chiene58b6582012-01-16 17:13:13 +08001867
Elliott Hughesadb8c672012-03-06 16:49:32 -08001868 DecodedInstruction dec_insn(insn);
Logan Chiene58b6582012-01-16 17:13:13 +08001869
1870 // Read the payload
Logan Chiene58b6582012-01-16 17:13:13 +08001871 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
Elliott Hughesadb8c672012-03-06 16:49:32 -08001872 static_cast<int32_t>(dec_insn.vB);
Logan Chiene58b6582012-01-16 17:13:13 +08001873
Logan Chien19c350a2012-05-01 19:21:32 +08001874 const Instruction::ArrayDataPayload* payload =
1875 reinterpret_cast<const Instruction::ArrayDataPayload*>(
1876 code_item_->insns_ + payload_offset);
Logan Chiene58b6582012-01-16 17:13:13 +08001877
Logan Chien86f50672012-04-24 13:08:45 +08001878 // Load array object
Elliott Hughesadb8c672012-03-06 16:49:32 -08001879 llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chiene58b6582012-01-16 17:13:13 +08001880
Logan Chien86f50672012-04-24 13:08:45 +08001881 if (payload->element_count == 0) {
1882 // When the number of the elements in the payload is zero, we don't have
1883 // to copy any numbers. However, we should check whether the array object
1884 // address is equal to null or not.
1885 EmitGuard_NullPointerException(dex_pc, array_addr);
1886 } else {
1887 // To save the code size, we are going to call the runtime function to
1888 // copy the content from DexFile.
Logan Chiene58b6582012-01-16 17:13:13 +08001889
Logan Chien86f50672012-04-24 13:08:45 +08001890 // NOTE: We will check for the NullPointerException in the runtime.
Logan Chiene58b6582012-01-16 17:13:13 +08001891
Logan Chien86f50672012-04-24 13:08:45 +08001892 llvm::Function* runtime_func = irb_.GetRuntime(FillArrayData);
Logan Chiene58b6582012-01-16 17:13:13 +08001893
Logan Chien86f50672012-04-24 13:08:45 +08001894 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
Logan Chiene58b6582012-01-16 17:13:13 +08001895
Logan Chien86f50672012-04-24 13:08:45 +08001896 EmitUpdateDexPC(dex_pc);
Logan Chiene58b6582012-01-16 17:13:13 +08001897
Logan Chien86f50672012-04-24 13:08:45 +08001898 irb_.CreateCall4(runtime_func,
1899 method_object_addr, irb_.getInt32(dex_pc),
1900 array_addr, irb_.getInt32(payload_offset));
Logan Chiene58b6582012-01-16 17:13:13 +08001901
Logan Chien86f50672012-04-24 13:08:45 +08001902 EmitGuard_ExceptionLandingPad(dex_pc);
Logan Chiene58b6582012-01-16 17:13:13 +08001903 }
1904
Logan Chien70f94b42011-12-27 17:49:11 +08001905 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1906}
1907
1908
1909void MethodCompiler::EmitInsn_UnconditionalBranch(uint32_t dex_pc,
1910 Instruction const* insn) {
Logan Chiena466c162011-12-27 17:55:46 +08001911
Elliott Hughesadb8c672012-03-06 16:49:32 -08001912 DecodedInstruction dec_insn(insn);
Logan Chiena466c162011-12-27 17:55:46 +08001913
Elliott Hughesadb8c672012-03-06 16:49:32 -08001914 int32_t branch_offset = dec_insn.vA;
Logan Chiena466c162011-12-27 17:55:46 +08001915
1916 if (branch_offset <= 0) {
1917 // Garbage collection safe-point on backward branch
1918 EmitGuard_GarbageCollectionSuspend(dex_pc);
1919 }
1920
1921 irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
Logan Chien70f94b42011-12-27 17:49:11 +08001922}
1923
1924
1925void MethodCompiler::EmitInsn_PackedSwitch(uint32_t dex_pc,
1926 Instruction const* insn) {
Logan Chien7a89b6d2011-12-27 17:56:56 +08001927
Elliott Hughesadb8c672012-03-06 16:49:32 -08001928 DecodedInstruction dec_insn(insn);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001929
Logan Chien7a89b6d2011-12-27 17:56:56 +08001930 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
Elliott Hughesadb8c672012-03-06 16:49:32 -08001931 static_cast<int32_t>(dec_insn.vB);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001932
Logan Chien19c350a2012-05-01 19:21:32 +08001933 const Instruction::PackedSwitchPayload* payload =
1934 reinterpret_cast<const Instruction::PackedSwitchPayload*>(
1935 code_item_->insns_ + payload_offset);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001936
Elliott Hughesadb8c672012-03-06 16:49:32 -08001937 llvm::Value* value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001938
1939 llvm::SwitchInst* sw =
Logan Chien19c350a2012-05-01 19:21:32 +08001940 irb_.CreateSwitch(value, GetNextBasicBlock(dex_pc), payload->case_count);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001941
Logan Chien19c350a2012-05-01 19:21:32 +08001942 for (uint16_t i = 0; i < payload->case_count; ++i) {
1943 sw->addCase(irb_.getInt32(payload->first_key + i),
1944 GetBasicBlock(dex_pc + payload->targets[i]));
Logan Chien7a89b6d2011-12-27 17:56:56 +08001945 }
Logan Chien70f94b42011-12-27 17:49:11 +08001946}
1947
1948
1949void MethodCompiler::EmitInsn_SparseSwitch(uint32_t dex_pc,
1950 Instruction const* insn) {
Logan Chien7a89b6d2011-12-27 17:56:56 +08001951
Elliott Hughesadb8c672012-03-06 16:49:32 -08001952 DecodedInstruction dec_insn(insn);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001953
Logan Chien7a89b6d2011-12-27 17:56:56 +08001954 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
Elliott Hughesadb8c672012-03-06 16:49:32 -08001955 static_cast<int32_t>(dec_insn.vB);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001956
Logan Chien19c350a2012-05-01 19:21:32 +08001957 const Instruction::SparseSwitchPayload* payload =
1958 reinterpret_cast<const Instruction::SparseSwitchPayload*>(
1959 code_item_->insns_ + payload_offset);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001960
Logan Chien19c350a2012-05-01 19:21:32 +08001961 const int32_t* keys = payload->GetKeys();
1962 const int32_t* targets = payload->GetTargets();
Logan Chien7a89b6d2011-12-27 17:56:56 +08001963
Elliott Hughesadb8c672012-03-06 16:49:32 -08001964 llvm::Value* value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001965
1966 llvm::SwitchInst* sw =
Logan Chien19c350a2012-05-01 19:21:32 +08001967 irb_.CreateSwitch(value, GetNextBasicBlock(dex_pc), payload->case_count);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001968
Logan Chien19c350a2012-05-01 19:21:32 +08001969 for (size_t i = 0; i < payload->case_count; ++i) {
Logan Chien7a89b6d2011-12-27 17:56:56 +08001970 sw->addCase(irb_.getInt32(keys[i]), GetBasicBlock(dex_pc + targets[i]));
1971 }
Logan Chien70f94b42011-12-27 17:49:11 +08001972}
1973
1974
1975void MethodCompiler::EmitInsn_FPCompare(uint32_t dex_pc,
1976 Instruction const* insn,
1977 JType fp_jty,
1978 bool gt_bias) {
Logan Chien2c37e8e2011-12-27 17:58:46 +08001979
Elliott Hughesadb8c672012-03-06 16:49:32 -08001980 DecodedInstruction dec_insn(insn);
Logan Chien2c37e8e2011-12-27 17:58:46 +08001981
1982 DCHECK(fp_jty == kFloat || fp_jty == kDouble) << "JType: " << fp_jty;
1983
Elliott Hughesadb8c672012-03-06 16:49:32 -08001984 llvm::Value* src1_value = EmitLoadDalvikReg(dec_insn.vB, fp_jty, kAccurate);
1985 llvm::Value* src2_value = EmitLoadDalvikReg(dec_insn.vC, fp_jty, kAccurate);
Logan Chien2c37e8e2011-12-27 17:58:46 +08001986
1987 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1988 llvm::Value* cmp_lt;
1989
1990 if (gt_bias) {
1991 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1992 } else {
1993 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1994 }
1995
1996 llvm::Value* result = EmitCompareResultSelection(cmp_eq, cmp_lt);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001997 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
Logan Chien2c37e8e2011-12-27 17:58:46 +08001998
Logan Chien70f94b42011-12-27 17:49:11 +08001999 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2000}
2001
2002
2003void MethodCompiler::EmitInsn_LongCompare(uint32_t dex_pc,
2004 Instruction const* insn) {
Logan Chien2c37e8e2011-12-27 17:58:46 +08002005
Elliott Hughesadb8c672012-03-06 16:49:32 -08002006 DecodedInstruction dec_insn(insn);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002007
Elliott Hughesadb8c672012-03-06 16:49:32 -08002008 llvm::Value* src1_value = EmitLoadDalvikReg(dec_insn.vB, kLong, kAccurate);
2009 llvm::Value* src2_value = EmitLoadDalvikReg(dec_insn.vC, kLong, kAccurate);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002010
2011 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
2012 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
2013
2014 llvm::Value* result = EmitCompareResultSelection(cmp_eq, cmp_lt);
Elliott Hughesadb8c672012-03-06 16:49:32 -08002015 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002016
Logan Chien70f94b42011-12-27 17:49:11 +08002017 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2018}
2019
2020
Logan Chien2c37e8e2011-12-27 17:58:46 +08002021llvm::Value* MethodCompiler::EmitCompareResultSelection(llvm::Value* cmp_eq,
2022 llvm::Value* cmp_lt) {
2023
2024 llvm::Constant* zero = irb_.getJInt(0);
2025 llvm::Constant* pos1 = irb_.getJInt(1);
2026 llvm::Constant* neg1 = irb_.getJInt(-1);
2027
2028 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
2029 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
2030
2031 return result_eq;
2032}
2033
2034
Logan Chien70f94b42011-12-27 17:49:11 +08002035void MethodCompiler::EmitInsn_BinaryConditionalBranch(uint32_t dex_pc,
2036 Instruction const* insn,
2037 CondBranchKind cond) {
Logan Chiena78e3c82011-12-27 17:59:35 +08002038
Elliott Hughesadb8c672012-03-06 16:49:32 -08002039 DecodedInstruction dec_insn(insn);
Logan Chiena78e3c82011-12-27 17:59:35 +08002040
Elliott Hughesadb8c672012-03-06 16:49:32 -08002041 int8_t src1_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vA);
2042 int8_t src2_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vB);
Logan Chiena78e3c82011-12-27 17:59:35 +08002043
2044 DCHECK_NE(kRegUnknown, src1_reg_cat);
2045 DCHECK_NE(kRegUnknown, src2_reg_cat);
2046 DCHECK_NE(kRegCat2, src1_reg_cat);
2047 DCHECK_NE(kRegCat2, src2_reg_cat);
2048
Elliott Hughesadb8c672012-03-06 16:49:32 -08002049 int32_t branch_offset = dec_insn.vC;
Logan Chiena78e3c82011-12-27 17:59:35 +08002050
2051 if (branch_offset <= 0) {
2052 // Garbage collection safe-point on backward branch
2053 EmitGuard_GarbageCollectionSuspend(dex_pc);
2054 }
2055
Logan Chiena78e3c82011-12-27 17:59:35 +08002056 llvm::Value* src1_value;
2057 llvm::Value* src2_value;
2058
TDYa1278e9b4492012-04-24 15:50:27 -07002059 if (src1_reg_cat == kRegZero && src2_reg_cat == kRegZero) {
2060 src1_value = irb_.getInt32(0);
2061 src2_value = irb_.getInt32(0);
2062 } else if (src1_reg_cat != kRegZero && src2_reg_cat != kRegZero) {
Logan Chiena78e3c82011-12-27 17:59:35 +08002063 CHECK_EQ(src1_reg_cat, src2_reg_cat);
2064
2065 if (src1_reg_cat == kRegCat1nr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002066 src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
2067 src2_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002068 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002069 src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
2070 src2_value = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002071 }
2072 } else {
2073 DCHECK(src1_reg_cat == kRegZero ||
2074 src2_reg_cat == kRegZero);
2075
2076 if (src1_reg_cat == kRegZero) {
2077 if (src2_reg_cat == kRegCat1nr) {
2078 src1_value = irb_.getJInt(0);
Elliott Hughesadb8c672012-03-06 16:49:32 -08002079 src2_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002080 } else {
2081 src1_value = irb_.getJNull();
Elliott Hughesadb8c672012-03-06 16:49:32 -08002082 src2_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002083 }
2084 } else { // src2_reg_cat == kRegZero
2085 if (src2_reg_cat == kRegCat1nr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002086 src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002087 src2_value = irb_.getJInt(0);
2088 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002089 src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002090 src2_value = irb_.getJNull();
2091 }
2092 }
2093 }
2094
2095 llvm::Value* cond_value =
2096 EmitConditionResult(src1_value, src2_value, cond);
2097
2098 irb_.CreateCondBr(cond_value,
2099 GetBasicBlock(dex_pc + branch_offset),
2100 GetNextBasicBlock(dex_pc));
Logan Chien70f94b42011-12-27 17:49:11 +08002101}
2102
2103
2104void MethodCompiler::EmitInsn_UnaryConditionalBranch(uint32_t dex_pc,
2105 Instruction const* insn,
2106 CondBranchKind cond) {
Logan Chiena78e3c82011-12-27 17:59:35 +08002107
Elliott Hughesadb8c672012-03-06 16:49:32 -08002108 DecodedInstruction dec_insn(insn);
Logan Chiena78e3c82011-12-27 17:59:35 +08002109
Elliott Hughesadb8c672012-03-06 16:49:32 -08002110 int8_t src_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vA);
Logan Chiena78e3c82011-12-27 17:59:35 +08002111
2112 DCHECK_NE(kRegUnknown, src_reg_cat);
2113 DCHECK_NE(kRegCat2, src_reg_cat);
2114
Elliott Hughesadb8c672012-03-06 16:49:32 -08002115 int32_t branch_offset = dec_insn.vB;
Logan Chiena78e3c82011-12-27 17:59:35 +08002116
2117 if (branch_offset <= 0) {
2118 // Garbage collection safe-point on backward branch
2119 EmitGuard_GarbageCollectionSuspend(dex_pc);
2120 }
2121
Logan Chiena78e3c82011-12-27 17:59:35 +08002122 llvm::Value* src1_value;
2123 llvm::Value* src2_value;
2124
TDYa1278e9b4492012-04-24 15:50:27 -07002125 if (src_reg_cat == kRegZero) {
2126 src1_value = irb_.getInt32(0);
2127 src2_value = irb_.getInt32(0);
2128 } else if (src_reg_cat == kRegCat1nr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002129 src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002130 src2_value = irb_.getInt32(0);
2131 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002132 src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002133 src2_value = irb_.getJNull();
2134 }
2135
2136 llvm::Value* cond_value =
2137 EmitConditionResult(src1_value, src2_value, cond);
2138
2139 irb_.CreateCondBr(cond_value,
2140 GetBasicBlock(dex_pc + branch_offset),
2141 GetNextBasicBlock(dex_pc));
2142}
2143
2144
2145RegCategory MethodCompiler::GetInferredRegCategory(uint32_t dex_pc,
2146 uint16_t reg_idx) {
Logan Chiendd361c92012-04-10 23:40:37 +08002147
2148 Compiler::MethodReference mref(dex_file_, method_idx_);
2149
2150 InferredRegCategoryMap const* map =
Ian Rogers776ac1f2012-04-13 23:36:36 -07002151 verifier::MethodVerifier::GetInferredRegCategoryMap(mref);
Logan Chiendd361c92012-04-10 23:40:37 +08002152
Logan Chiena78e3c82011-12-27 17:59:35 +08002153 CHECK_NE(map, static_cast<InferredRegCategoryMap*>(NULL));
2154
2155 return map->GetRegCategory(dex_pc, reg_idx);
2156}
2157
2158
2159llvm::Value* MethodCompiler::EmitConditionResult(llvm::Value* lhs,
2160 llvm::Value* rhs,
2161 CondBranchKind cond) {
2162 switch (cond) {
2163 case kCondBranch_EQ:
2164 return irb_.CreateICmpEQ(lhs, rhs);
2165
2166 case kCondBranch_NE:
2167 return irb_.CreateICmpNE(lhs, rhs);
2168
2169 case kCondBranch_LT:
2170 return irb_.CreateICmpSLT(lhs, rhs);
2171
2172 case kCondBranch_GE:
2173 return irb_.CreateICmpSGE(lhs, rhs);
2174
2175 case kCondBranch_GT:
2176 return irb_.CreateICmpSGT(lhs, rhs);
2177
2178 case kCondBranch_LE:
2179 return irb_.CreateICmpSLE(lhs, rhs);
2180
2181 default: // Unreachable
2182 LOG(FATAL) << "Unknown conditional branch kind: " << cond;
2183 return NULL;
2184 }
Logan Chien70f94b42011-12-27 17:49:11 +08002185}
2186
TDYa12783bb6622012-04-17 02:20:34 -07002187void MethodCompiler::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2188 // Using runtime support, let the target can override by InlineAssembly.
2189 llvm::Function* runtime_func = irb_.GetRuntime(MarkGCCard);
2190
2191 irb_.CreateCall2(runtime_func, value, target_addr);
2192}
Logan Chien70f94b42011-12-27 17:49:11 +08002193
Logan Chiene27fdbb2012-01-02 23:27:26 +08002194void
2195MethodCompiler::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2196 llvm::Value* array,
2197 llvm::Value* index) {
2198 llvm::Value* array_len = EmitLoadArrayLength(array);
2199
2200 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
2201
2202 llvm::BasicBlock* block_exception =
2203 CreateBasicBlockWithDexPC(dex_pc, "overflow");
2204
2205 llvm::BasicBlock* block_continue =
2206 CreateBasicBlockWithDexPC(dex_pc, "cont");
2207
2208 irb_.CreateCondBr(cmp, block_exception, block_continue);
2209
2210 irb_.SetInsertPoint(block_exception);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002211
TDYa127c8dc1012012-04-19 07:03:33 -07002212 EmitUpdateDexPC(dex_pc);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002213 irb_.CreateCall2(irb_.GetRuntime(ThrowIndexOutOfBounds), index, array_len);
2214 EmitBranchExceptionLandingPad(dex_pc);
2215
2216 irb_.SetInsertPoint(block_continue);
2217}
2218
2219
2220void MethodCompiler::EmitGuard_ArrayException(uint32_t dex_pc,
2221 llvm::Value* array,
2222 llvm::Value* index) {
2223 EmitGuard_NullPointerException(dex_pc, array);
2224 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
2225}
2226
2227
2228// Emit Array GetElementPtr
2229llvm::Value* MethodCompiler::EmitArrayGEP(llvm::Value* array_addr,
2230 llvm::Value* index_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08002231 llvm::Type* elem_type,
2232 JType elem_jty) {
2233
2234 int data_offset;
2235 if (elem_jty == kLong || elem_jty == kDouble ||
2236 (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
2237 data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
2238 } else {
2239 data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
2240 }
Logan Chiene27fdbb2012-01-02 23:27:26 +08002241
2242 llvm::Constant* data_offset_value =
Ian Rogers04ec04e2012-02-28 16:15:33 -08002243 irb_.getPtrEquivInt(data_offset);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002244
2245 llvm::Value* array_data_addr =
2246 irb_.CreatePtrDisp(array_addr, data_offset_value,
2247 elem_type->getPointerTo());
2248
2249 return irb_.CreateGEP(array_data_addr, index_value);
2250}
2251
2252
Logan Chien70f94b42011-12-27 17:49:11 +08002253void MethodCompiler::EmitInsn_AGet(uint32_t dex_pc,
2254 Instruction const* insn,
2255 JType elem_jty) {
Logan Chiene27fdbb2012-01-02 23:27:26 +08002256
Elliott Hughesadb8c672012-03-06 16:49:32 -08002257 DecodedInstruction dec_insn(insn);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002258
Elliott Hughesadb8c672012-03-06 16:49:32 -08002259 llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
2260 llvm::Value* index_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002261
2262 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
2263
2264 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
2265
2266 llvm::Value* array_elem_addr =
Ian Rogers04ec04e2012-02-28 16:15:33 -08002267 EmitArrayGEP(array_addr, index_value, elem_type, elem_jty);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002268
2269 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr);
2270
Elliott Hughesadb8c672012-03-06 16:49:32 -08002271 EmitStoreDalvikReg(dec_insn.vA, elem_jty, kArray, array_elem_value);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002272
Logan Chien70f94b42011-12-27 17:49:11 +08002273 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2274}
2275
2276
2277void MethodCompiler::EmitInsn_APut(uint32_t dex_pc,
2278 Instruction const* insn,
2279 JType elem_jty) {
Logan Chien8dabb432012-01-02 23:29:32 +08002280
Elliott Hughesadb8c672012-03-06 16:49:32 -08002281 DecodedInstruction dec_insn(insn);
Logan Chien8dabb432012-01-02 23:29:32 +08002282
Elliott Hughesadb8c672012-03-06 16:49:32 -08002283 llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
2284 llvm::Value* index_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
Logan Chien8dabb432012-01-02 23:29:32 +08002285
2286 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
2287
2288 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
2289
2290 llvm::Value* array_elem_addr =
Ian Rogers04ec04e2012-02-28 16:15:33 -08002291 EmitArrayGEP(array_addr, index_value, elem_type, elem_jty);
Logan Chien8dabb432012-01-02 23:29:32 +08002292
Elliott Hughesadb8c672012-03-06 16:49:32 -08002293 llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, elem_jty, kArray);
Logan Chien8dabb432012-01-02 23:29:32 +08002294
TDYa12783bb6622012-04-17 02:20:34 -07002295 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
TDYa1271b86d072012-04-05 17:38:56 -07002296 llvm::Function* runtime_func = irb_.GetRuntime(CheckPutArrayElement);
2297
2298 irb_.CreateCall2(runtime_func, new_value, array_addr);
2299
2300 EmitGuard_ExceptionLandingPad(dex_pc);
TDYa12783bb6622012-04-17 02:20:34 -07002301
2302 EmitMarkGCCard(new_value, array_addr);
TDYa1271b86d072012-04-05 17:38:56 -07002303 }
2304
Logan Chien8dabb432012-01-02 23:29:32 +08002305 irb_.CreateStore(new_value, array_elem_addr);
2306
Logan Chien70f94b42011-12-27 17:49:11 +08002307 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2308}
2309
2310
2311void MethodCompiler::EmitInsn_IGet(uint32_t dex_pc,
2312 Instruction const* insn,
2313 JType field_jty) {
Logan Chien48f1d2a2012-01-02 22:49:53 +08002314
Elliott Hughesadb8c672012-03-06 16:49:32 -08002315 DecodedInstruction dec_insn(insn);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002316
Elliott Hughesadb8c672012-03-06 16:49:32 -08002317 uint32_t reg_idx = dec_insn.vB;
2318 uint32_t field_idx = dec_insn.vC;
Logan Chien48f1d2a2012-01-02 22:49:53 +08002319
Logan Chien48f1d2a2012-01-02 22:49:53 +08002320 llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
2321
2322 EmitGuard_NullPointerException(dex_pc, object_addr);
2323
2324 llvm::Value* field_value;
2325
Logan Chien933abf82012-04-11 12:24:31 +08002326 int field_offset;
2327 bool is_volatile;
2328 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
2329 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002330
Logan Chien933abf82012-04-11 12:24:31 +08002331 if (!is_fast_path) {
Logan Chien48f1d2a2012-01-02 22:49:53 +08002332 llvm::Function* runtime_func;
2333
2334 if (field_jty == kObject) {
Logan Chien3b2b2e72012-03-06 16:11:45 +08002335 runtime_func = irb_.GetRuntime(GetObjectInstance);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002336 } else if (field_jty == kLong || field_jty == kDouble) {
Logan Chien3b2b2e72012-03-06 16:11:45 +08002337 runtime_func = irb_.GetRuntime(Get64Instance);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002338 } else {
Logan Chien3b2b2e72012-03-06 16:11:45 +08002339 runtime_func = irb_.GetRuntime(Get32Instance);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002340 }
2341
2342 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
2343
2344 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2345
TDYa127c8dc1012012-04-19 07:03:33 -07002346 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002347
Logan Chien3b2b2e72012-03-06 16:11:45 +08002348 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
2349 method_object_addr, object_addr);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002350
2351 EmitGuard_ExceptionLandingPad(dex_pc);
2352
2353 } else {
Logan Chien933abf82012-04-11 12:24:31 +08002354 DCHECK_GE(field_offset, 0);
2355
Logan Chien48f1d2a2012-01-02 22:49:53 +08002356 llvm::PointerType* field_type =
2357 irb_.getJType(field_jty, kField)->getPointerTo();
2358
Logan Chien933abf82012-04-11 12:24:31 +08002359 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002360
2361 llvm::Value* field_addr =
Logan Chien933abf82012-04-11 12:24:31 +08002362 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002363
Logan Chien933abf82012-04-11 12:24:31 +08002364 // TODO: Check is_volatile. We need to generate atomic load instruction
2365 // when is_volatile is true.
Logan Chien48f1d2a2012-01-02 22:49:53 +08002366 field_value = irb_.CreateLoad(field_addr);
2367 }
2368
Elliott Hughesadb8c672012-03-06 16:49:32 -08002369 EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, field_value);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002370
Logan Chien70f94b42011-12-27 17:49:11 +08002371 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2372}
2373
2374
2375void MethodCompiler::EmitInsn_IPut(uint32_t dex_pc,
2376 Instruction const* insn,
2377 JType field_jty) {
Logan Chiendd6aa872012-01-03 16:06:32 +08002378
Elliott Hughesadb8c672012-03-06 16:49:32 -08002379 DecodedInstruction dec_insn(insn);
Logan Chiendd6aa872012-01-03 16:06:32 +08002380
Elliott Hughesadb8c672012-03-06 16:49:32 -08002381 uint32_t reg_idx = dec_insn.vB;
2382 uint32_t field_idx = dec_insn.vC;
Logan Chiendd6aa872012-01-03 16:06:32 +08002383
Logan Chiendd6aa872012-01-03 16:06:32 +08002384 llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
2385
2386 EmitGuard_NullPointerException(dex_pc, object_addr);
2387
Elliott Hughesadb8c672012-03-06 16:49:32 -08002388 llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
Logan Chiendd6aa872012-01-03 16:06:32 +08002389
Logan Chien933abf82012-04-11 12:24:31 +08002390 int field_offset;
2391 bool is_volatile;
2392 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
2393 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
Logan Chiendd6aa872012-01-03 16:06:32 +08002394
Logan Chien933abf82012-04-11 12:24:31 +08002395 if (!is_fast_path) {
Logan Chiendd6aa872012-01-03 16:06:32 +08002396 llvm::Function* runtime_func;
2397
2398 if (field_jty == kObject) {
2399 runtime_func = irb_.GetRuntime(SetObjectInstance);
2400 } else if (field_jty == kLong || field_jty == kDouble) {
2401 runtime_func = irb_.GetRuntime(Set64Instance);
2402 } else {
2403 runtime_func = irb_.GetRuntime(Set32Instance);
2404 }
2405
2406 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
2407
2408 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2409
TDYa127c8dc1012012-04-19 07:03:33 -07002410 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002411
Logan Chien3b2b2e72012-03-06 16:11:45 +08002412 irb_.CreateCall4(runtime_func, field_idx_value,
2413 method_object_addr, object_addr, new_value);
Logan Chiendd6aa872012-01-03 16:06:32 +08002414
2415 EmitGuard_ExceptionLandingPad(dex_pc);
2416
2417 } else {
Logan Chien933abf82012-04-11 12:24:31 +08002418 DCHECK_GE(field_offset, 0);
2419
Logan Chiendd6aa872012-01-03 16:06:32 +08002420 llvm::PointerType* field_type =
2421 irb_.getJType(field_jty, kField)->getPointerTo();
2422
Logan Chien933abf82012-04-11 12:24:31 +08002423 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
Logan Chiendd6aa872012-01-03 16:06:32 +08002424
2425 llvm::Value* field_addr =
Logan Chien933abf82012-04-11 12:24:31 +08002426 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
Logan Chiendd6aa872012-01-03 16:06:32 +08002427
Logan Chien933abf82012-04-11 12:24:31 +08002428 // TODO: Check is_volatile. We need to generate atomic store instruction
2429 // when is_volatile is true.
Logan Chiendd6aa872012-01-03 16:06:32 +08002430 irb_.CreateStore(new_value, field_addr);
TDYa12783bb6622012-04-17 02:20:34 -07002431
2432 if (field_jty == kObject) { // If put an object, mark the GC card table.
2433 EmitMarkGCCard(new_value, object_addr);
2434 }
Logan Chiendd6aa872012-01-03 16:06:32 +08002435 }
2436
Logan Chien70f94b42011-12-27 17:49:11 +08002437 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2438}
2439
2440
Logan Chien438c4b62012-01-17 16:06:00 +08002441llvm::Value* MethodCompiler::EmitLoadStaticStorage(uint32_t dex_pc,
2442 uint32_t type_idx) {
2443 llvm::BasicBlock* block_load_static =
2444 CreateBasicBlockWithDexPC(dex_pc, "load_static");
2445
2446 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2447
2448 // Load static storage from dex cache
2449 llvm::Value* storage_field_addr =
2450 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
2451
2452 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr);
2453
2454 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
2455
2456 // Test: Is the static storage of this class initialized?
2457 llvm::Value* equal_null =
2458 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
2459
2460 irb_.CreateCondBr(equal_null, block_load_static, block_cont);
2461
2462 // Failback routine to load the class object
2463 irb_.SetInsertPoint(block_load_static);
2464
2465 llvm::Function* runtime_func =
2466 irb_.GetRuntime(InitializeStaticStorage);
2467
2468 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
2469
2470 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2471
TDYa127706e9b62012-04-19 12:24:26 -07002472 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
2473
TDYa127c8dc1012012-04-19 07:03:33 -07002474 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002475
Logan Chien438c4b62012-01-17 16:06:00 +08002476 llvm::Value* loaded_storage_object_addr =
TDYa127706e9b62012-04-19 12:24:26 -07002477 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
Logan Chien438c4b62012-01-17 16:06:00 +08002478
2479 EmitGuard_ExceptionLandingPad(dex_pc);
2480
2481 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
2482
2483 irb_.CreateBr(block_cont);
2484
2485 // Now the class object must be loaded
2486 irb_.SetInsertPoint(block_cont);
2487
2488 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
2489
2490 phi->addIncoming(storage_object_addr, block_original);
2491 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
2492
2493 return phi;
2494}
2495
2496
Logan Chien70f94b42011-12-27 17:49:11 +08002497void MethodCompiler::EmitInsn_SGet(uint32_t dex_pc,
2498 Instruction const* insn,
2499 JType field_jty) {
Logan Chien438c4b62012-01-17 16:06:00 +08002500
Elliott Hughesadb8c672012-03-06 16:49:32 -08002501 DecodedInstruction dec_insn(insn);
Logan Chien438c4b62012-01-17 16:06:00 +08002502
Logan Chien933abf82012-04-11 12:24:31 +08002503 uint32_t field_idx = dec_insn.vB;
Logan Chien438c4b62012-01-17 16:06:00 +08002504
Logan Chien933abf82012-04-11 12:24:31 +08002505 int field_offset;
2506 int ssb_index;
2507 bool is_referrers_class;
2508 bool is_volatile;
2509
2510 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
2511 field_idx, oat_compilation_unit_, field_offset, ssb_index,
2512 is_referrers_class, is_volatile, false);
Logan Chien438c4b62012-01-17 16:06:00 +08002513
2514 llvm::Value* static_field_value;
2515
Logan Chien933abf82012-04-11 12:24:31 +08002516 if (!is_fast_path) {
Logan Chien438c4b62012-01-17 16:06:00 +08002517 llvm::Function* runtime_func;
2518
2519 if (field_jty == kObject) {
2520 runtime_func = irb_.GetRuntime(GetObjectStatic);
2521 } else if (field_jty == kLong || field_jty == kDouble) {
2522 runtime_func = irb_.GetRuntime(Get64Static);
2523 } else {
2524 runtime_func = irb_.GetRuntime(Get32Static);
2525 }
2526
Elliott Hughesadb8c672012-03-06 16:49:32 -08002527 llvm::Constant* field_idx_value = irb_.getInt32(dec_insn.vB);
Logan Chien438c4b62012-01-17 16:06:00 +08002528
2529 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2530
TDYa127c8dc1012012-04-19 07:03:33 -07002531 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002532
Logan Chien438c4b62012-01-17 16:06:00 +08002533 static_field_value =
2534 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
2535
2536 EmitGuard_ExceptionLandingPad(dex_pc);
2537
2538 } else {
Logan Chien933abf82012-04-11 12:24:31 +08002539 DCHECK_GE(field_offset, 0);
Logan Chien438c4b62012-01-17 16:06:00 +08002540
Logan Chien933abf82012-04-11 12:24:31 +08002541 llvm::Value* static_storage_addr = NULL;
2542
2543 if (is_referrers_class) {
2544 // Fast path, static storage base is this method's class
2545 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2546
TDYa127ee1f59b2012-04-25 00:56:40 -07002547 static_storage_addr =
2548 irb_.LoadFromObjectOffset(method_object_addr,
2549 Method::DeclaringClassOffset().Int32Value(),
2550 irb_.getJObjectTy());
Logan Chien933abf82012-04-11 12:24:31 +08002551 } else {
2552 // Medium path, static storage base in a different class which
2553 // requires checks that the other class is initialized
2554 DCHECK_GE(ssb_index, 0);
2555 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
2556 }
2557
2558 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
Logan Chien438c4b62012-01-17 16:06:00 +08002559
2560 llvm::Value* static_field_addr =
2561 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
2562 irb_.getJType(field_jty, kField)->getPointerTo());
2563
Logan Chien933abf82012-04-11 12:24:31 +08002564 // TODO: Check is_volatile. We need to generate atomic load instruction
2565 // when is_volatile is true.
Logan Chien438c4b62012-01-17 16:06:00 +08002566 static_field_value = irb_.CreateLoad(static_field_addr);
2567 }
2568
Elliott Hughesadb8c672012-03-06 16:49:32 -08002569 EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, static_field_value);
Logan Chien438c4b62012-01-17 16:06:00 +08002570
Logan Chien70f94b42011-12-27 17:49:11 +08002571 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2572}
2573
2574
2575void MethodCompiler::EmitInsn_SPut(uint32_t dex_pc,
2576 Instruction const* insn,
2577 JType field_jty) {
Logan Chien14179c82012-01-17 17:06:34 +08002578
Elliott Hughesadb8c672012-03-06 16:49:32 -08002579 DecodedInstruction dec_insn(insn);
Logan Chien14179c82012-01-17 17:06:34 +08002580
Logan Chien933abf82012-04-11 12:24:31 +08002581 uint32_t field_idx = dec_insn.vB;
Logan Chien14179c82012-01-17 17:06:34 +08002582
Elliott Hughesadb8c672012-03-06 16:49:32 -08002583 llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
Logan Chien14179c82012-01-17 17:06:34 +08002584
Logan Chien933abf82012-04-11 12:24:31 +08002585 int field_offset;
2586 int ssb_index;
2587 bool is_referrers_class;
2588 bool is_volatile;
2589
2590 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
2591 field_idx, oat_compilation_unit_, field_offset, ssb_index,
2592 is_referrers_class, is_volatile, true);
2593
2594 if (!is_fast_path) {
Logan Chien14179c82012-01-17 17:06:34 +08002595 llvm::Function* runtime_func;
2596
2597 if (field_jty == kObject) {
2598 runtime_func = irb_.GetRuntime(SetObjectStatic);
2599 } else if (field_jty == kLong || field_jty == kDouble) {
2600 runtime_func = irb_.GetRuntime(Set64Static);
2601 } else {
2602 runtime_func = irb_.GetRuntime(Set32Static);
2603 }
2604
Elliott Hughesadb8c672012-03-06 16:49:32 -08002605 llvm::Constant* field_idx_value = irb_.getInt32(dec_insn.vB);
Logan Chien14179c82012-01-17 17:06:34 +08002606
2607 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2608
TDYa127c8dc1012012-04-19 07:03:33 -07002609 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002610
Logan Chien14179c82012-01-17 17:06:34 +08002611 irb_.CreateCall3(runtime_func, field_idx_value,
2612 method_object_addr, new_value);
2613
2614 EmitGuard_ExceptionLandingPad(dex_pc);
2615
2616 } else {
Logan Chien933abf82012-04-11 12:24:31 +08002617 DCHECK_GE(field_offset, 0);
Logan Chien14179c82012-01-17 17:06:34 +08002618
Logan Chien933abf82012-04-11 12:24:31 +08002619 llvm::Value* static_storage_addr = NULL;
2620
2621 if (is_referrers_class) {
2622 // Fast path, static storage base is this method's class
2623 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2624
TDYa127ee1f59b2012-04-25 00:56:40 -07002625 static_storage_addr =
2626 irb_.LoadFromObjectOffset(method_object_addr,
2627 Method::DeclaringClassOffset().Int32Value(),
2628 irb_.getJObjectTy());
Logan Chien933abf82012-04-11 12:24:31 +08002629 } else {
2630 // Medium path, static storage base in a different class which
2631 // requires checks that the other class is initialized
2632 DCHECK_GE(ssb_index, 0);
2633 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
2634 }
2635
2636 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
Logan Chien14179c82012-01-17 17:06:34 +08002637
2638 llvm::Value* static_field_addr =
2639 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
2640 irb_.getJType(field_jty, kField)->getPointerTo());
2641
Logan Chien933abf82012-04-11 12:24:31 +08002642 // TODO: Check is_volatile. We need to generate atomic store instruction
2643 // when is_volatile is true.
Logan Chien14179c82012-01-17 17:06:34 +08002644 irb_.CreateStore(new_value, static_field_addr);
TDYa12783bb6622012-04-17 02:20:34 -07002645
2646 if (field_jty == kObject) { // If put an object, mark the GC card table.
2647 EmitMarkGCCard(new_value, static_storage_addr);
2648 }
Logan Chien14179c82012-01-17 17:06:34 +08002649 }
2650
Logan Chien70f94b42011-12-27 17:49:11 +08002651 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2652}
2653
2654
Logan Chien1a121b92012-02-15 22:23:42 +08002655void MethodCompiler::
2656EmitLoadActualParameters(std::vector<llvm::Value*>& args,
2657 uint32_t callee_method_idx,
Elliott Hughesadb8c672012-03-06 16:49:32 -08002658 DecodedInstruction const& dec_insn,
Logan Chien7e7fabc2012-04-10 18:59:11 +08002659 InvokeArgFmt arg_fmt,
Logan Chien1a121b92012-02-15 22:23:42 +08002660 bool is_static) {
2661
2662 // Get method signature
2663 DexFile::MethodId const& method_id =
2664 dex_file_->GetMethodId(callee_method_idx);
2665
Logan Chien8faf8022012-02-24 12:25:29 +08002666 uint32_t shorty_size;
Logan Chien1a121b92012-02-15 22:23:42 +08002667 char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
Logan Chien8faf8022012-02-24 12:25:29 +08002668 CHECK_GE(shorty_size, 1u);
Logan Chien1a121b92012-02-15 22:23:42 +08002669
2670 // Load argument values according to the shorty (without "this")
2671 uint16_t reg_count = 0;
2672
2673 if (!is_static) {
2674 ++reg_count; // skip the "this" pointer
2675 }
2676
Logan Chien7e7fabc2012-04-10 18:59:11 +08002677 bool is_range = (arg_fmt == kArgRange);
2678
Logan Chien8faf8022012-02-24 12:25:29 +08002679 for (uint32_t i = 1; i < shorty_size; ++i) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002680 uint32_t reg_idx = (is_range) ? (dec_insn.vC + reg_count)
2681 : (dec_insn.arg[reg_count]);
Logan Chien1a121b92012-02-15 22:23:42 +08002682
2683 args.push_back(EmitLoadDalvikReg(reg_idx, shorty[i], kAccurate));
2684
2685 ++reg_count;
2686 if (shorty[i] == 'J' || shorty[i] == 'D') {
2687 // Wide types, such as long and double, are using a pair of registers
2688 // to store the value, so we have to increase arg_reg again.
2689 ++reg_count;
2690 }
2691 }
2692
Elliott Hughesadb8c672012-03-06 16:49:32 -08002693 DCHECK_EQ(reg_count, dec_insn.vA)
Logan Chien1a121b92012-02-15 22:23:42 +08002694 << "Actual argument mismatch for callee: "
2695 << PrettyMethod(callee_method_idx, *dex_file_);
2696}
2697
TDYa1270b686e52012-04-09 22:43:35 -07002698llvm::Value* MethodCompiler::EmitFixStub(llvm::Value* callee_method_object_addr,
2699 uint32_t method_idx,
2700 bool is_static) {
2701 // TODO: Remove this after we solve the link and trampoline related problems.
2702 llvm::Value* code_addr = irb_.CreateCall(irb_.GetRuntime(FixStub), callee_method_object_addr);
2703
2704 llvm::FunctionType* method_type = GetFunctionType(method_idx, is_static);
2705
2706 return irb_.CreatePointerCast(code_addr, method_type->getPointerTo());
TDYa12785321912012-04-01 15:24:56 -07002707}
Logan Chien1a121b92012-02-15 22:23:42 +08002708
Shih-wei Liao399ed3f2012-03-08 01:27:04 -08002709
Logan Chien7e7fabc2012-04-10 18:59:11 +08002710void MethodCompiler::EmitInsn_Invoke(uint32_t dex_pc,
2711 Instruction const* insn,
2712 InvokeType invoke_type,
2713 InvokeArgFmt arg_fmt) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002714 DecodedInstruction dec_insn(insn);
Logan Chien46fbb412012-02-15 22:29:08 +08002715
Logan Chien61c65dc2012-02-29 03:22:30 +08002716 bool is_static = (invoke_type == kStatic);
Logan Chien7e7fabc2012-04-10 18:59:11 +08002717 uint32_t callee_method_idx = dec_insn.vB;
Logan Chien61c65dc2012-02-29 03:22:30 +08002718
Logan Chien7e7fabc2012-04-10 18:59:11 +08002719 // Compute invoke related information for compiler decision
2720 int vtable_idx = -1;
Logan Chien92ad16d2012-03-18 05:48:55 +08002721 uintptr_t direct_code = 0; // Currently unused
Logan Chienfca64372012-04-23 14:57:01 +08002722 uintptr_t direct_method = 0;
Logan Chien61c65dc2012-02-29 03:22:30 +08002723 bool is_fast_path = compiler_->
Logan Chien7e7fabc2012-04-10 18:59:11 +08002724 ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
Logan Chien92ad16d2012-03-18 05:48:55 +08002725 invoke_type, vtable_idx, direct_code, direct_method);
Logan Chien61c65dc2012-02-29 03:22:30 +08002726
Logan Chien7e7fabc2012-04-10 18:59:11 +08002727 // Load *this* actual parameter
Logan Chien1a121b92012-02-15 22:23:42 +08002728 llvm::Value* this_addr = NULL;
2729
2730 if (!is_static) {
2731 // Test: Is *this* parameter equal to null?
Logan Chien7e7fabc2012-04-10 18:59:11 +08002732 this_addr = (arg_fmt == kArgReg) ?
2733 EmitLoadDalvikReg(dec_insn.arg[0], kObject, kAccurate):
2734 EmitLoadDalvikReg(dec_insn.vC + 0, kObject, kAccurate);
2735
Logan Chien1a121b92012-02-15 22:23:42 +08002736 EmitGuard_NullPointerException(dex_pc, this_addr);
2737 }
2738
Logan Chien7e7fabc2012-04-10 18:59:11 +08002739 // Load the method object
TDYa1274e42a592012-04-10 20:13:54 -07002740 llvm::Value* callee_method_object_addr = NULL;
Logan Chien7e7fabc2012-04-10 18:59:11 +08002741
2742 if (!is_fast_path) {
TDYa1274e42a592012-04-10 20:13:54 -07002743 callee_method_object_addr =
Logan Chien7e7fabc2012-04-10 18:59:11 +08002744 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
2745 this_addr, dex_pc, is_fast_path);
2746 } else {
2747 switch (invoke_type) {
2748 case kStatic:
2749 case kDirect:
Logan Chienfca64372012-04-23 14:57:01 +08002750 if (direct_method != 0u &&
2751 direct_method != static_cast<uintptr_t>(-1)) {
2752 callee_method_object_addr =
TDYa12717826bf2012-04-24 01:15:10 -07002753 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
2754 irb_.getJObjectTy());
Logan Chienfca64372012-04-23 14:57:01 +08002755 } else {
2756 callee_method_object_addr =
2757 EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
2758 }
Logan Chien7e7fabc2012-04-10 18:59:11 +08002759 break;
2760
2761 case kVirtual:
2762 DCHECK(vtable_idx != -1);
TDYa1274e42a592012-04-10 20:13:54 -07002763 callee_method_object_addr =
Logan Chien7e7fabc2012-04-10 18:59:11 +08002764 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
2765 break;
2766
2767 case kSuper:
2768 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
2769 "the fast path.";
2770 break;
2771
2772 case kInterface:
TDYa1274e42a592012-04-10 20:13:54 -07002773 callee_method_object_addr =
Logan Chien7e7fabc2012-04-10 18:59:11 +08002774 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
2775 invoke_type, this_addr,
2776 dex_pc, is_fast_path);
2777 break;
2778 }
2779 }
2780
Logan Chien7e7fabc2012-04-10 18:59:11 +08002781 llvm::Value* code_addr =
TDYa127ee1f59b2012-04-25 00:56:40 -07002782 irb_.LoadFromObjectOffset(callee_method_object_addr,
2783 Method::GetCodeOffset().Int32Value(),
2784 GetFunctionType(callee_method_idx, is_static)->getPointerTo());
TDYa12785321912012-04-01 15:24:56 -07002785
Logan Chien1a121b92012-02-15 22:23:42 +08002786 // Load the actual parameter
2787 std::vector<llvm::Value*> args;
2788
2789 args.push_back(callee_method_object_addr); // method object for callee
2790
2791 if (!is_static) {
Logan Chien7e7fabc2012-04-10 18:59:11 +08002792 DCHECK(this_addr != NULL);
Logan Chien1a121b92012-02-15 22:23:42 +08002793 args.push_back(this_addr); // "this" object for callee
2794 }
2795
2796 EmitLoadActualParameters(args, callee_method_idx, dec_insn,
Logan Chien7e7fabc2012-04-10 18:59:11 +08002797 arg_fmt, is_static);
Logan Chien1a121b92012-02-15 22:23:42 +08002798
TDYa1275bb86012012-04-11 05:57:28 -07002799#if 0
Logan Chien8dfcbea2012-02-17 18:50:32 +08002800 // Invoke callee
TDYa127c8dc1012012-04-19 07:03:33 -07002801 EmitUpdateDexPC(dex_pc);
Logan Chien1a121b92012-02-15 22:23:42 +08002802 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2803 EmitGuard_ExceptionLandingPad(dex_pc);
2804
Logan Chien7e7fabc2012-04-10 18:59:11 +08002805 uint32_t callee_access_flags = is_static ? kAccStatic : 0;
2806 UniquePtr<OatCompilationUnit> callee_oat_compilation_unit(
2807 oat_compilation_unit_->GetCallee(callee_method_idx, callee_access_flags));
2808
2809 char ret_shorty = callee_oat_compilation_unit->GetShorty()[0];
Shih-wei Liao90d50992012-02-19 03:32:05 -08002810 if (ret_shorty != 'V') {
Logan Chien1a121b92012-02-15 22:23:42 +08002811 EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
2812 }
TDYa1275bb86012012-04-11 05:57:28 -07002813#else
2814 uint32_t callee_access_flags = is_static ? kAccStatic : 0;
2815 UniquePtr<OatCompilationUnit> callee_oat_compilation_unit(
2816 oat_compilation_unit_->GetCallee(callee_method_idx, callee_access_flags));
2817
2818 char ret_shorty = callee_oat_compilation_unit->GetShorty()[0];
2819
2820
TDYa127c8dc1012012-04-19 07:03:33 -07002821 EmitUpdateDexPC(dex_pc);
TDYa1275bb86012012-04-11 05:57:28 -07002822
2823
2824 llvm::BasicBlock* block_normal = CreateBasicBlockWithDexPC(dex_pc, "normal");
TDYa127ce154722012-04-21 16:43:29 -07002825 llvm::BasicBlock* block_stub = CreateBasicBlockWithDexPC(dex_pc, "stub");
TDYa1275bb86012012-04-11 05:57:28 -07002826 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2827
2828 llvm::Type* accurate_ret_type = irb_.getJType(ret_shorty, kAccurate);
2829 llvm::Value* retval_addr = NULL;
2830 if (ret_shorty != 'V') {
2831 retval_addr = irb_.CreateAlloca(accurate_ret_type);
2832 }
2833
2834
TDYa1275bb86012012-04-11 05:57:28 -07002835 llvm::Value* code_addr_int = irb_.CreatePtrToInt(code_addr, irb_.getPtrEquivIntTy());
TDYa127ce154722012-04-21 16:43:29 -07002836 llvm::Value* max_stub_int = irb_.getPtrEquivInt(special_stub::kMaxSpecialStub);
2837 llvm::Value* is_stub = irb_.CreateICmpULT(code_addr_int, max_stub_int);
2838 irb_.CreateCondBr(is_stub, block_stub, block_normal);
TDYa1275bb86012012-04-11 05:57:28 -07002839
2840
2841 irb_.SetInsertPoint(block_normal);
2842 {
2843 // Invoke callee
TDYa127ce154722012-04-21 16:43:29 -07002844 llvm::Value* retval = irb_.CreateCall(code_addr, args);
TDYa1275bb86012012-04-11 05:57:28 -07002845 if (ret_shorty != 'V') {
TDYa127ce154722012-04-21 16:43:29 -07002846 EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
TDYa1275bb86012012-04-11 05:57:28 -07002847 }
2848 }
2849 irb_.CreateBr(block_continue);
2850
2851
TDYa127ce154722012-04-21 16:43:29 -07002852 irb_.SetInsertPoint(block_stub);
TDYa1275bb86012012-04-11 05:57:28 -07002853 {
TDYa127ce154722012-04-21 16:43:29 -07002854 { // lazy link
2855 // TODO: Remove this after we solve the link problem.
2856 llvm::BasicBlock* block_proxy_stub = CreateBasicBlockWithDexPC(dex_pc, "proxy");
2857 llvm::BasicBlock* block_link = CreateBasicBlockWithDexPC(dex_pc, "link");
2858
2859 irb_.CreateCondBr(irb_.CreateIsNull(code_addr), block_link, block_proxy_stub);
2860
2861
2862 irb_.SetInsertPoint(block_link);
2863 code_addr = EmitFixStub(callee_method_object_addr, callee_method_idx, is_static);
2864
2865 EmitGuard_ExceptionLandingPad(dex_pc);
2866
2867 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2868 if (ret_shorty != 'V') {
2869 EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
2870 }
2871 irb_.CreateBr(block_continue);
2872
2873
2874 irb_.SetInsertPoint(block_proxy_stub);
TDYa1275bb86012012-04-11 05:57:28 -07002875 }
TDYa127ce154722012-04-21 16:43:29 -07002876 { // proxy stub
2877 llvm::Value* temp_space_addr;
2878 if (ret_shorty != 'V') {
2879 temp_space_addr = irb_.CreateAlloca(irb_.getJValueTy());
2880 args.push_back(temp_space_addr);
2881 }
2882 // TODO: Remove this after we solve the proxy trampoline calling convention problem.
2883 irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
2884 if (ret_shorty != 'V') {
2885 llvm::Value* result_addr =
2886 irb_.CreateBitCast(temp_space_addr, accurate_ret_type->getPointerTo());
2887 llvm::Value* retval = irb_.CreateLoad(result_addr);
2888 EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
2889 }
TDYa1275bb86012012-04-11 05:57:28 -07002890 }
2891 }
2892 irb_.CreateBr(block_continue);
2893
2894
2895 irb_.SetInsertPoint(block_continue);
2896
TDYa1275bb86012012-04-11 05:57:28 -07002897 EmitGuard_ExceptionLandingPad(dex_pc);
2898#endif
Logan Chien1a121b92012-02-15 22:23:42 +08002899
Logan Chien70f94b42011-12-27 17:49:11 +08002900 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2901}
2902
2903
Logan Chien7e7fabc2012-04-10 18:59:11 +08002904llvm::Value* MethodCompiler::
2905EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
2906 llvm::Value* callee_method_object_field_addr =
2907 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
Logan Chien7caf37e2012-02-03 22:56:04 +08002908
Logan Chien7e7fabc2012-04-10 18:59:11 +08002909 return irb_.CreateLoad(callee_method_object_field_addr);
2910}
Logan Chien7caf37e2012-02-03 22:56:04 +08002911
Logan Chien7caf37e2012-02-03 22:56:04 +08002912
Logan Chien7e7fabc2012-04-10 18:59:11 +08002913llvm::Value* MethodCompiler::
2914EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
2915 llvm::Value* this_addr) {
2916 // Load class object of *this* pointer
TDYa127ee1f59b2012-04-25 00:56:40 -07002917 llvm::Value* class_object_addr =
2918 irb_.LoadFromObjectOffset(this_addr,
2919 Object::ClassOffset().Int32Value(),
2920 irb_.getJObjectTy());
Logan Chien7caf37e2012-02-03 22:56:04 +08002921
Logan Chien7e7fabc2012-04-10 18:59:11 +08002922 // Load vtable address
TDYa127ee1f59b2012-04-25 00:56:40 -07002923 llvm::Value* vtable_addr =
2924 irb_.LoadFromObjectOffset(class_object_addr,
2925 Class::VTableOffset().Int32Value(),
2926 irb_.getJObjectTy());
Logan Chien7e7fabc2012-04-10 18:59:11 +08002927
2928 // Load callee method object
2929 llvm::Value* vtable_idx_value =
2930 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
2931
2932 llvm::Value* method_field_addr =
2933 EmitArrayGEP(vtable_addr, vtable_idx_value, irb_.getJObjectTy(), kObject);
2934
2935 return irb_.CreateLoad(method_field_addr);
2936}
2937
2938
2939llvm::Value* MethodCompiler::
2940EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
2941 InvokeType invoke_type,
2942 llvm::Value* this_addr,
2943 uint32_t dex_pc,
2944 bool is_fast_path) {
2945
2946 llvm::Function* runtime_func = NULL;
2947
2948 switch (invoke_type) {
2949 case kStatic:
2950 runtime_func = irb_.GetRuntime(FindStaticMethodWithAccessCheck);
2951 break;
2952
2953 case kDirect:
2954 runtime_func = irb_.GetRuntime(FindDirectMethodWithAccessCheck);
2955 break;
2956
2957 case kVirtual:
2958 runtime_func = irb_.GetRuntime(FindVirtualMethodWithAccessCheck);
2959 break;
2960
2961 case kSuper:
2962 runtime_func = irb_.GetRuntime(FindSuperMethodWithAccessCheck);
2963 break;
2964
2965 case kInterface:
2966 if (is_fast_path) {
2967 runtime_func = irb_.GetRuntime(FindInterfaceMethod);
2968 } else {
2969 runtime_func = irb_.GetRuntime(FindInterfaceMethodWithAccessCheck);
2970 }
2971 break;
2972 }
Logan Chien7caf37e2012-02-03 22:56:04 +08002973
2974 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2975
Logan Chien7e7fabc2012-04-10 18:59:11 +08002976 if (this_addr == NULL) {
2977 DCHECK_EQ(invoke_type, kStatic);
2978 this_addr = irb_.getJNull();
2979 }
2980
2981 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2982
TDYa127da83d972012-04-18 00:21:49 -07002983 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
2984
TDYa127c8dc1012012-04-19 07:03:33 -07002985 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002986
TDYa1270b686e52012-04-09 22:43:35 -07002987 llvm::Value* callee_method_object_addr =
TDYa127da83d972012-04-18 00:21:49 -07002988 irb_.CreateCall4(runtime_func,
Logan Chien7e7fabc2012-04-10 18:59:11 +08002989 callee_method_idx_value,
2990 this_addr,
TDYa127da83d972012-04-18 00:21:49 -07002991 caller_method_object_addr,
2992 thread_object_addr);
Logan Chien7caf37e2012-02-03 22:56:04 +08002993
2994 EmitGuard_ExceptionLandingPad(dex_pc);
2995
Logan Chien7e7fabc2012-04-10 18:59:11 +08002996 return callee_method_object_addr;
Logan Chien70f94b42011-12-27 17:49:11 +08002997}
2998
2999
3000void MethodCompiler::EmitInsn_Neg(uint32_t dex_pc,
3001 Instruction const* insn,
3002 JType op_jty) {
Logan Chien1b5685f2011-12-27 18:01:14 +08003003
Elliott Hughesadb8c672012-03-06 16:49:32 -08003004 DecodedInstruction dec_insn(insn);
Logan Chien1b5685f2011-12-27 18:01:14 +08003005
3006 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3007
Elliott Hughesadb8c672012-03-06 16:49:32 -08003008 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chien1b5685f2011-12-27 18:01:14 +08003009 llvm::Value* result_value = irb_.CreateNeg(src_value);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003010 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chien1b5685f2011-12-27 18:01:14 +08003011
Logan Chien70f94b42011-12-27 17:49:11 +08003012 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3013}
3014
3015
3016void MethodCompiler::EmitInsn_Not(uint32_t dex_pc,
3017 Instruction const* insn,
3018 JType op_jty) {
Logan Chiene53750d2011-12-27 18:02:27 +08003019
Elliott Hughesadb8c672012-03-06 16:49:32 -08003020 DecodedInstruction dec_insn(insn);
Logan Chiene53750d2011-12-27 18:02:27 +08003021
3022 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3023
Elliott Hughesadb8c672012-03-06 16:49:32 -08003024 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chiene53750d2011-12-27 18:02:27 +08003025 llvm::Value* result_value =
3026 irb_.CreateXor(src_value, static_cast<uint64_t>(-1));
3027
Elliott Hughesadb8c672012-03-06 16:49:32 -08003028 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chiene53750d2011-12-27 18:02:27 +08003029
Logan Chien70f94b42011-12-27 17:49:11 +08003030 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3031}
3032
3033
3034void MethodCompiler::EmitInsn_SExt(uint32_t dex_pc,
3035 Instruction const* insn) {
Logan Chien61752ad2011-12-27 18:03:51 +08003036
Elliott Hughesadb8c672012-03-06 16:49:32 -08003037 DecodedInstruction dec_insn(insn);
Logan Chien61752ad2011-12-27 18:03:51 +08003038
Elliott Hughesadb8c672012-03-06 16:49:32 -08003039 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chien61752ad2011-12-27 18:03:51 +08003040 llvm::Value* result_value = irb_.CreateSExt(src_value, irb_.getJLongTy());
Elliott Hughesadb8c672012-03-06 16:49:32 -08003041 EmitStoreDalvikReg(dec_insn.vA, kLong, kAccurate, result_value);
Logan Chien61752ad2011-12-27 18:03:51 +08003042
Logan Chien70f94b42011-12-27 17:49:11 +08003043 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3044}
3045
3046
3047void MethodCompiler::EmitInsn_Trunc(uint32_t dex_pc,
3048 Instruction const* insn) {
Logan Chien17a57662011-12-27 18:05:14 +08003049
Elliott Hughesadb8c672012-03-06 16:49:32 -08003050 DecodedInstruction dec_insn(insn);
Logan Chien17a57662011-12-27 18:05:14 +08003051
Elliott Hughesadb8c672012-03-06 16:49:32 -08003052 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kLong, kAccurate);
Logan Chien17a57662011-12-27 18:05:14 +08003053 llvm::Value* result_value = irb_.CreateTrunc(src_value, irb_.getJIntTy());
Elliott Hughesadb8c672012-03-06 16:49:32 -08003054 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chien17a57662011-12-27 18:05:14 +08003055
Logan Chien70f94b42011-12-27 17:49:11 +08003056 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3057}
3058
3059
3060void MethodCompiler::EmitInsn_TruncAndSExt(uint32_t dex_pc,
3061 Instruction const* insn,
3062 unsigned N) {
Logan Chienb6744c52011-12-27 18:06:26 +08003063
Elliott Hughesadb8c672012-03-06 16:49:32 -08003064 DecodedInstruction dec_insn(insn);
Logan Chienb6744c52011-12-27 18:06:26 +08003065
Elliott Hughesadb8c672012-03-06 16:49:32 -08003066 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chienb6744c52011-12-27 18:06:26 +08003067
3068 llvm::Value* trunc_value =
3069 irb_.CreateTrunc(src_value, llvm::Type::getIntNTy(*context_, N));
3070
3071 llvm::Value* result_value = irb_.CreateSExt(trunc_value, irb_.getJIntTy());
3072
Elliott Hughesadb8c672012-03-06 16:49:32 -08003073 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chienb6744c52011-12-27 18:06:26 +08003074
Logan Chien70f94b42011-12-27 17:49:11 +08003075 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3076}
3077
3078
3079void MethodCompiler::EmitInsn_TruncAndZExt(uint32_t dex_pc,
3080 Instruction const* insn,
3081 unsigned N) {
Logan Chienb6744c52011-12-27 18:06:26 +08003082
Elliott Hughesadb8c672012-03-06 16:49:32 -08003083 DecodedInstruction dec_insn(insn);
Logan Chienb6744c52011-12-27 18:06:26 +08003084
Elliott Hughesadb8c672012-03-06 16:49:32 -08003085 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chienb6744c52011-12-27 18:06:26 +08003086
3087 llvm::Value* trunc_value =
3088 irb_.CreateTrunc(src_value, llvm::Type::getIntNTy(*context_, N));
3089
3090 llvm::Value* result_value = irb_.CreateZExt(trunc_value, irb_.getJIntTy());
3091
Elliott Hughesadb8c672012-03-06 16:49:32 -08003092 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chienb6744c52011-12-27 18:06:26 +08003093
Logan Chien70f94b42011-12-27 17:49:11 +08003094 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3095}
3096
3097
3098void MethodCompiler::EmitInsn_FNeg(uint32_t dex_pc,
3099 Instruction const* insn,
3100 JType op_jty) {
Logan Chien7a48b092011-12-27 18:07:45 +08003101
Elliott Hughesadb8c672012-03-06 16:49:32 -08003102 DecodedInstruction dec_insn(insn);
Logan Chien7a48b092011-12-27 18:07:45 +08003103
3104 DCHECK(op_jty == kFloat || op_jty == kDouble) << op_jty;
3105
Elliott Hughesadb8c672012-03-06 16:49:32 -08003106 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chien7a48b092011-12-27 18:07:45 +08003107 llvm::Value* result_value = irb_.CreateFNeg(src_value);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003108 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chien7a48b092011-12-27 18:07:45 +08003109
Logan Chien70f94b42011-12-27 17:49:11 +08003110 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3111}
3112
3113
3114void MethodCompiler::EmitInsn_IntToFP(uint32_t dex_pc,
3115 Instruction const* insn,
3116 JType src_jty,
3117 JType dest_jty) {
Logan Chien62dd4532011-12-27 18:09:00 +08003118
Elliott Hughesadb8c672012-03-06 16:49:32 -08003119 DecodedInstruction dec_insn(insn);
Logan Chien62dd4532011-12-27 18:09:00 +08003120
3121 DCHECK(src_jty == kInt || src_jty == kLong) << src_jty;
3122 DCHECK(dest_jty == kFloat || dest_jty == kDouble) << dest_jty;
3123
Elliott Hughesadb8c672012-03-06 16:49:32 -08003124 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
Logan Chien62dd4532011-12-27 18:09:00 +08003125 llvm::Type* dest_type = irb_.getJType(dest_jty, kAccurate);
3126 llvm::Value* dest_value = irb_.CreateSIToFP(src_value, dest_type);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003127 EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
Logan Chien62dd4532011-12-27 18:09:00 +08003128
Logan Chien70f94b42011-12-27 17:49:11 +08003129 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3130}
3131
3132
3133void MethodCompiler::EmitInsn_FPToInt(uint32_t dex_pc,
3134 Instruction const* insn,
3135 JType src_jty,
TDYa127a4746872012-04-11 23:48:55 -07003136 JType dest_jty,
3137 runtime_support::RuntimeId runtime_func_id) {
Logan Chien12dc1752011-12-27 18:10:15 +08003138
Elliott Hughesadb8c672012-03-06 16:49:32 -08003139 DecodedInstruction dec_insn(insn);
Logan Chien12dc1752011-12-27 18:10:15 +08003140
3141 DCHECK(src_jty == kFloat || src_jty == kDouble) << src_jty;
3142 DCHECK(dest_jty == kInt || dest_jty == kLong) << dest_jty;
3143
Elliott Hughesadb8c672012-03-06 16:49:32 -08003144 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
TDYa127a4746872012-04-11 23:48:55 -07003145 llvm::Value* dest_value = irb_.CreateCall(irb_.GetRuntime(runtime_func_id), src_value);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003146 EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
Logan Chien12dc1752011-12-27 18:10:15 +08003147
Logan Chien70f94b42011-12-27 17:49:11 +08003148 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3149}
3150
3151
3152void MethodCompiler::EmitInsn_FExt(uint32_t dex_pc,
3153 Instruction const* insn) {
Logan Chienc56ded92011-12-27 18:10:57 +08003154
Elliott Hughesadb8c672012-03-06 16:49:32 -08003155 DecodedInstruction dec_insn(insn);
Logan Chienc56ded92011-12-27 18:10:57 +08003156
Elliott Hughesadb8c672012-03-06 16:49:32 -08003157 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kFloat, kAccurate);
Logan Chienc56ded92011-12-27 18:10:57 +08003158 llvm::Value* result_value = irb_.CreateFPExt(src_value, irb_.getJDoubleTy());
Elliott Hughesadb8c672012-03-06 16:49:32 -08003159 EmitStoreDalvikReg(dec_insn.vA, kDouble, kAccurate, result_value);
Logan Chienc56ded92011-12-27 18:10:57 +08003160
Logan Chien70f94b42011-12-27 17:49:11 +08003161 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3162}
3163
3164
3165void MethodCompiler::EmitInsn_FTrunc(uint32_t dex_pc,
3166 Instruction const* insn) {
Logan Chien927744f2011-12-27 18:11:52 +08003167
Elliott Hughesadb8c672012-03-06 16:49:32 -08003168 DecodedInstruction dec_insn(insn);
Logan Chien927744f2011-12-27 18:11:52 +08003169
Elliott Hughesadb8c672012-03-06 16:49:32 -08003170 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kDouble, kAccurate);
Logan Chien927744f2011-12-27 18:11:52 +08003171 llvm::Value* result_value = irb_.CreateFPTrunc(src_value, irb_.getJFloatTy());
Elliott Hughesadb8c672012-03-06 16:49:32 -08003172 EmitStoreDalvikReg(dec_insn.vA, kFloat, kAccurate, result_value);
Logan Chien927744f2011-12-27 18:11:52 +08003173
Logan Chien70f94b42011-12-27 17:49:11 +08003174 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3175}
3176
3177
3178void MethodCompiler::EmitInsn_IntArithm(uint32_t dex_pc,
3179 Instruction const* insn,
3180 IntArithmKind arithm,
3181 JType op_jty,
3182 bool is_2addr) {
Logan Chienc3f7d962011-12-27 18:13:18 +08003183
Elliott Hughesadb8c672012-03-06 16:49:32 -08003184 DecodedInstruction dec_insn(insn);
Logan Chienc3f7d962011-12-27 18:13:18 +08003185
3186 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3187
3188 llvm::Value* src1_value;
3189 llvm::Value* src2_value;
3190
3191 if (is_2addr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08003192 src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
3193 src2_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chienc3f7d962011-12-27 18:13:18 +08003194 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08003195 src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
3196 src2_value = EmitLoadDalvikReg(dec_insn.vC, op_jty, kAccurate);
Logan Chienc3f7d962011-12-27 18:13:18 +08003197 }
3198
3199 llvm::Value* result_value =
3200 EmitIntArithmResultComputation(dex_pc, src1_value, src2_value,
3201 arithm, op_jty);
3202
Elliott Hughesadb8c672012-03-06 16:49:32 -08003203 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chienc3f7d962011-12-27 18:13:18 +08003204
Logan Chien70f94b42011-12-27 17:49:11 +08003205 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3206}
3207
3208
3209void MethodCompiler::EmitInsn_IntArithmImmediate(uint32_t dex_pc,
3210 Instruction const* insn,
3211 IntArithmKind arithm) {
Logan Chienc3f7d962011-12-27 18:13:18 +08003212
Elliott Hughesadb8c672012-03-06 16:49:32 -08003213 DecodedInstruction dec_insn(insn);
Logan Chienc3f7d962011-12-27 18:13:18 +08003214
Elliott Hughesadb8c672012-03-06 16:49:32 -08003215 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chienc3f7d962011-12-27 18:13:18 +08003216
Elliott Hughesadb8c672012-03-06 16:49:32 -08003217 llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
Logan Chienc3f7d962011-12-27 18:13:18 +08003218
3219 llvm::Value* result_value =
3220 EmitIntArithmResultComputation(dex_pc, src_value, imm_value, arithm, kInt);
3221
Elliott Hughesadb8c672012-03-06 16:49:32 -08003222 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chienc3f7d962011-12-27 18:13:18 +08003223
Logan Chien70f94b42011-12-27 17:49:11 +08003224 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3225}
3226
3227
Logan Chienc3f7d962011-12-27 18:13:18 +08003228llvm::Value*
3229MethodCompiler::EmitIntArithmResultComputation(uint32_t dex_pc,
3230 llvm::Value* lhs,
3231 llvm::Value* rhs,
3232 IntArithmKind arithm,
3233 JType op_jty) {
3234 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3235
3236 switch (arithm) {
3237 case kIntArithm_Add:
3238 return irb_.CreateAdd(lhs, rhs);
3239
3240 case kIntArithm_Sub:
3241 return irb_.CreateSub(lhs, rhs);
3242
3243 case kIntArithm_Mul:
3244 return irb_.CreateMul(lhs, rhs);
3245
3246 case kIntArithm_Div:
Logan Chienc3f7d962011-12-27 18:13:18 +08003247 case kIntArithm_Rem:
TDYa127f8641ce2012-04-02 06:40:40 -07003248 return EmitIntDivRemResultComputation(dex_pc, lhs, rhs, arithm, op_jty);
Logan Chienc3f7d962011-12-27 18:13:18 +08003249
3250 case kIntArithm_And:
3251 return irb_.CreateAnd(lhs, rhs);
3252
3253 case kIntArithm_Or:
3254 return irb_.CreateOr(lhs, rhs);
3255
3256 case kIntArithm_Xor:
3257 return irb_.CreateXor(lhs, rhs);
3258
Logan Chienc3f7d962011-12-27 18:13:18 +08003259 default:
3260 LOG(FATAL) << "Unknown integer arithmetic kind: " << arithm;
3261 return NULL;
3262 }
3263}
3264
3265
TDYa127f8641ce2012-04-02 06:40:40 -07003266llvm::Value*
3267MethodCompiler::EmitIntDivRemResultComputation(uint32_t dex_pc,
3268 llvm::Value* dividend,
3269 llvm::Value* divisor,
3270 IntArithmKind arithm,
3271 JType op_jty) {
3272 // Throw exception if the divisor is 0.
3273 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
3274
3275 // Check the special case: MININT / -1 = MININT
3276 // That case will cause overflow, which is undefined behavior in llvm.
3277 // So we check the divisor is -1 or not, if the divisor is -1, we do
3278 // the special path to avoid undefined behavior.
3279 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
3280 llvm::Value* zero = irb_.getJZero(op_jty);
3281 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
3282 llvm::Value* result = irb_.CreateAlloca(op_type);
3283
3284 llvm::BasicBlock* eq_neg_one = CreateBasicBlockWithDexPC(dex_pc, "eq_neg_one");
3285 llvm::BasicBlock* ne_neg_one = CreateBasicBlockWithDexPC(dex_pc, "ne_neg_one");
3286 llvm::BasicBlock* neg_one_cont = CreateBasicBlockWithDexPC(dex_pc, "neg_one_cont");
3287
3288 llvm::Value* is_equal_neg_one = EmitConditionResult(divisor, neg_one, kCondBranch_EQ);
3289 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one);
3290
3291 // If divisor == -1
3292 irb_.SetInsertPoint(eq_neg_one);
3293 llvm::Value* eq_result;
3294 if (arithm == kIntArithm_Div) {
3295 // We can just change from "dividend div -1" to "neg dividend".
3296 // The sub don't care the sign/unsigned because of two's complement representation.
3297 // And the behavior is what we want:
3298 // -(2^n) (2^n)-1
3299 // MININT < k <= MAXINT -> mul k -1 = -k
3300 // MININT == k -> mul k -1 = k
3301 //
3302 // LLVM use sub to represent 'neg'
3303 eq_result = irb_.CreateSub(zero, dividend);
3304 } else {
3305 // Everything modulo -1 will be 0.
3306 eq_result = zero;
3307 }
3308 irb_.CreateStore(eq_result, result);
3309 irb_.CreateBr(neg_one_cont);
3310
3311 // If divisor != -1, just do the division.
3312 irb_.SetInsertPoint(ne_neg_one);
3313 llvm::Value* ne_result;
3314 if (arithm == kIntArithm_Div) {
3315 ne_result = irb_.CreateSDiv(dividend, divisor);
3316 } else {
3317 ne_result = irb_.CreateSRem(dividend, divisor);
3318 }
3319 irb_.CreateStore(ne_result, result);
3320 irb_.CreateBr(neg_one_cont);
3321
3322 irb_.SetInsertPoint(neg_one_cont);
3323 return irb_.CreateLoad(result);
3324}
3325
3326
Logan Chien5539ad02012-04-02 14:36:55 +08003327void MethodCompiler::EmitInsn_IntShiftArithm(uint32_t dex_pc,
3328 Instruction const* insn,
3329 IntShiftArithmKind arithm,
3330 JType op_jty,
3331 bool is_2addr) {
3332
3333 DecodedInstruction dec_insn(insn);
3334
3335 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3336
3337 llvm::Value* src1_value;
3338 llvm::Value* src2_value;
3339
3340 // NOTE: The 2nd operand of the shift arithmetic instruction is
3341 // 32-bit integer regardless of the 1st operand.
3342 if (is_2addr) {
3343 src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
3344 src2_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
3345 } else {
3346 src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
3347 src2_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
3348 }
3349
3350 llvm::Value* result_value =
3351 EmitIntShiftArithmResultComputation(dex_pc, src1_value, src2_value,
3352 arithm, op_jty);
3353
3354 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
3355
3356 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3357}
3358
3359
3360void MethodCompiler::
3361EmitInsn_IntShiftArithmImmediate(uint32_t dex_pc,
3362 Instruction const* insn,
3363 IntShiftArithmKind arithm) {
3364
3365 DecodedInstruction dec_insn(insn);
3366
3367 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
3368
3369 llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
3370
3371 llvm::Value* result_value =
3372 EmitIntShiftArithmResultComputation(dex_pc, src_value, imm_value,
3373 arithm, kInt);
3374
3375 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
3376
3377 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3378}
3379
3380
3381llvm::Value*
3382MethodCompiler::EmitIntShiftArithmResultComputation(uint32_t dex_pc,
3383 llvm::Value* lhs,
3384 llvm::Value* rhs,
3385 IntShiftArithmKind arithm,
3386 JType op_jty) {
3387 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3388
3389 if (op_jty == kInt) {
3390 rhs = irb_.CreateAnd(rhs, 0x1f);
3391 } else {
3392 llvm::Value* masked_rhs = irb_.CreateAnd(rhs, 0x3f);
3393 rhs = irb_.CreateZExt(masked_rhs, irb_.getJLongTy());
3394 }
3395
3396 switch (arithm) {
3397 case kIntArithm_Shl:
3398 return irb_.CreateShl(lhs, rhs);
3399
3400 case kIntArithm_Shr:
3401 return irb_.CreateAShr(lhs, rhs);
3402
3403 case kIntArithm_UShr:
3404 return irb_.CreateLShr(lhs, rhs);
3405
3406 default:
3407 LOG(FATAL) << "Unknown integer shift arithmetic kind: " << arithm;
3408 return NULL;
3409 }
3410}
3411
3412
Logan Chien70f94b42011-12-27 17:49:11 +08003413void MethodCompiler::EmitInsn_RSubImmediate(uint32_t dex_pc,
3414 Instruction const* insn) {
Logan Chien65c62d42011-12-27 18:14:18 +08003415
Elliott Hughesadb8c672012-03-06 16:49:32 -08003416 DecodedInstruction dec_insn(insn);
Logan Chien65c62d42011-12-27 18:14:18 +08003417
Elliott Hughesadb8c672012-03-06 16:49:32 -08003418 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
3419 llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
Logan Chien65c62d42011-12-27 18:14:18 +08003420 llvm::Value* result_value = irb_.CreateSub(imm_value, src_value);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003421 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chien65c62d42011-12-27 18:14:18 +08003422
Logan Chien70f94b42011-12-27 17:49:11 +08003423 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3424}
3425
3426
3427void MethodCompiler::EmitInsn_FPArithm(uint32_t dex_pc,
3428 Instruction const* insn,
3429 FPArithmKind arithm,
3430 JType op_jty,
3431 bool is_2addr) {
Logan Chien76e1c792011-12-27 18:15:01 +08003432
Elliott Hughesadb8c672012-03-06 16:49:32 -08003433 DecodedInstruction dec_insn(insn);
Logan Chien76e1c792011-12-27 18:15:01 +08003434
3435 DCHECK(op_jty == kFloat || op_jty == kDouble) << op_jty;
3436
3437 llvm::Value* src1_value;
3438 llvm::Value* src2_value;
3439
3440 if (is_2addr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08003441 src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
3442 src2_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chien76e1c792011-12-27 18:15:01 +08003443 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08003444 src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
3445 src2_value = EmitLoadDalvikReg(dec_insn.vC, op_jty, kAccurate);
Logan Chien76e1c792011-12-27 18:15:01 +08003446 }
3447
3448 llvm::Value* result_value =
3449 EmitFPArithmResultComputation(dex_pc, src1_value, src2_value, arithm);
3450
Elliott Hughesadb8c672012-03-06 16:49:32 -08003451 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chien76e1c792011-12-27 18:15:01 +08003452
Logan Chien70f94b42011-12-27 17:49:11 +08003453 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3454}
3455
3456
Logan Chien76e1c792011-12-27 18:15:01 +08003457llvm::Value*
3458MethodCompiler::EmitFPArithmResultComputation(uint32_t dex_pc,
3459 llvm::Value *lhs,
3460 llvm::Value *rhs,
3461 FPArithmKind arithm) {
3462 switch (arithm) {
3463 case kFPArithm_Add:
3464 return irb_.CreateFAdd(lhs, rhs);
3465
3466 case kFPArithm_Sub:
3467 return irb_.CreateFSub(lhs, rhs);
3468
3469 case kFPArithm_Mul:
3470 return irb_.CreateFMul(lhs, rhs);
3471
3472 case kFPArithm_Div:
3473 return irb_.CreateFDiv(lhs, rhs);
3474
3475 case kFPArithm_Rem:
3476 return irb_.CreateFRem(lhs, rhs);
3477
3478 default:
3479 LOG(FATAL) << "Unknown floating-point arithmetic kind: " << arithm;
3480 return NULL;
3481 }
3482}
3483
3484
Logan Chienc3f7d962011-12-27 18:13:18 +08003485void MethodCompiler::EmitGuard_DivZeroException(uint32_t dex_pc,
3486 llvm::Value* denominator,
3487 JType op_jty) {
3488 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3489
3490 llvm::Constant* zero = irb_.getJZero(op_jty);
3491
3492 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
3493
3494 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
3495
3496 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
3497
3498 irb_.CreateCondBr(equal_zero, block_exception, block_continue);
3499
3500 irb_.SetInsertPoint(block_exception);
TDYa127c8dc1012012-04-19 07:03:33 -07003501 EmitUpdateDexPC(dex_pc);
Logan Chienc3f7d962011-12-27 18:13:18 +08003502 irb_.CreateCall(irb_.GetRuntime(ThrowDivZeroException));
3503 EmitBranchExceptionLandingPad(dex_pc);
3504
3505 irb_.SetInsertPoint(block_continue);
3506}
3507
3508
Logan Chien61bb6142012-02-03 15:34:53 +08003509void MethodCompiler::EmitGuard_NullPointerException(uint32_t dex_pc,
3510 llvm::Value* object) {
3511 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
3512
3513 llvm::BasicBlock* block_exception =
3514 CreateBasicBlockWithDexPC(dex_pc, "nullp");
3515
3516 llvm::BasicBlock* block_continue =
3517 CreateBasicBlockWithDexPC(dex_pc, "cont");
3518
3519 irb_.CreateCondBr(equal_null, block_exception, block_continue);
3520
3521 irb_.SetInsertPoint(block_exception);
TDYa127c8dc1012012-04-19 07:03:33 -07003522 EmitUpdateDexPC(dex_pc);
TDYa1273f9137d2012-04-08 15:59:19 -07003523 irb_.CreateCall(irb_.GetRuntime(ThrowNullPointerException), irb_.getInt32(dex_pc));
Logan Chien61bb6142012-02-03 15:34:53 +08003524 EmitBranchExceptionLandingPad(dex_pc);
3525
3526 irb_.SetInsertPoint(block_continue);
3527}
3528
3529
Logan Chienbb4d12a2012-02-17 14:10:01 +08003530llvm::Value* MethodCompiler::EmitLoadDexCacheAddr(MemberOffset offset) {
3531 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
3532
TDYa127ee1f59b2012-04-25 00:56:40 -07003533 return irb_.LoadFromObjectOffset(method_object_addr,
3534 offset.Int32Value(),
3535 irb_.getJObjectTy());
Logan Chienbb4d12a2012-02-17 14:10:01 +08003536}
3537
3538
Logan Chienbb4d12a2012-02-17 14:10:01 +08003539llvm::Value* MethodCompiler::
3540EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
3541 llvm::Value* static_storage_dex_cache_addr =
3542 EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
3543
3544 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
3545
3546 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08003547 irb_.getJObjectTy(), kObject);
Logan Chienbb4d12a2012-02-17 14:10:01 +08003548}
3549
3550
3551llvm::Value* MethodCompiler::
3552EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
3553 llvm::Value* resolved_type_dex_cache_addr =
3554 EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
3555
3556 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
3557
3558 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08003559 irb_.getJObjectTy(), kObject);
Logan Chienbb4d12a2012-02-17 14:10:01 +08003560}
3561
3562
3563llvm::Value* MethodCompiler::
Logan Chien61c65dc2012-02-29 03:22:30 +08003564EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
3565 llvm::Value* resolved_method_dex_cache_addr =
3566 EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
3567
3568 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
3569
3570 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08003571 irb_.getJObjectTy(), kObject);
Logan Chien61c65dc2012-02-29 03:22:30 +08003572}
3573
3574
3575llvm::Value* MethodCompiler::
Logan Chienbb4d12a2012-02-17 14:10:01 +08003576EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
3577 llvm::Value* string_dex_cache_addr =
3578 EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
3579
3580 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
3581
3582 return EmitArrayGEP(string_dex_cache_addr, string_idx_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08003583 irb_.getJObjectTy(), kObject);
Logan Chienbb4d12a2012-02-17 14:10:01 +08003584}
3585
3586
Logan Chien83426162011-12-09 09:29:50 +08003587CompiledMethod *MethodCompiler::Compile() {
Logan Chien0b827102011-12-20 19:46:14 +08003588 // Code generation
3589 CreateFunction();
3590
3591 EmitPrologue();
3592 EmitInstructions();
Logan Chienc670a8d2011-12-20 21:25:56 +08003593 EmitPrologueLastBranch();
Logan Chien0b827102011-12-20 19:46:14 +08003594
Logan Chiend6c239a2011-12-23 15:11:45 +08003595 // Verify the generated bitcode
TDYa127853cd092012-04-21 22:15:31 -07003596 VERIFY_LLVM_FUNCTION(*func_);
Logan Chiend6c239a2011-12-23 15:11:45 +08003597
Logan Chien8b977d32012-02-21 19:14:55 +08003598 // Add the memory usage approximation of the compilation unit
3599 cunit_->AddMemUsageApproximation(code_item_->insns_size_in_code_units_ * 900);
3600 // NOTE: From statistic, the bitcode size is 4.5 times bigger than the
3601 // Dex file. Besides, we have to convert the code unit into bytes.
3602 // Thus, we got our magic number 9.
3603
Logan Chien110bcba2012-04-16 19:11:28 +08003604 CompiledMethod* compiled_method =
3605 new CompiledMethod(cunit_->GetInstructionSet(),
3606 cunit_->GetElfIndex(),
3607 elf_func_idx_);
3608
3609 cunit_->RegisterCompiledMethod(func_, compiled_method);
3610
3611 return compiled_method;
Logan Chien0b827102011-12-20 19:46:14 +08003612}
3613
3614
3615llvm::Value* MethodCompiler::EmitLoadMethodObjectAddr() {
3616 return func_->arg_begin();
Shih-wei Liaod1fec812012-02-13 09:51:10 -08003617}
Logan Chien83426162011-12-09 09:29:50 +08003618
3619
Logan Chien5bcc04e2012-01-30 14:15:12 +08003620void MethodCompiler::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
3621 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
3622 irb_.CreateBr(lpad);
3623 } else {
3624 irb_.CreateBr(GetUnwindBasicBlock());
3625 }
3626}
3627
3628
3629void MethodCompiler::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
3630 llvm::Value* exception_pending =
3631 irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));
3632
3633 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
3634
3635 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
3636 irb_.CreateCondBr(exception_pending, lpad, block_cont);
3637 } else {
3638 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont);
3639 }
3640
3641 irb_.SetInsertPoint(block_cont);
3642}
3643
3644
Logan Chien924072f2012-01-30 15:07:24 +08003645void MethodCompiler::EmitGuard_GarbageCollectionSuspend(uint32_t dex_pc) {
3646 llvm::Value* runtime_func = irb_.GetRuntime(TestSuspend);
TDYa127853cd092012-04-21 22:15:31 -07003647
3648 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
3649
TDYa127c8dc1012012-04-19 07:03:33 -07003650 EmitUpdateDexPC(dex_pc);
TDYa127853cd092012-04-21 22:15:31 -07003651
3652 irb_.CreateCall(runtime_func, thread_object_addr);
Logan Chien924072f2012-01-30 15:07:24 +08003653
3654 EmitGuard_ExceptionLandingPad(dex_pc);
3655}
3656
3657
Logan Chiend6c239a2011-12-23 15:11:45 +08003658llvm::BasicBlock* MethodCompiler::
3659CreateBasicBlockWithDexPC(uint32_t dex_pc, char const* postfix) {
3660 std::string name;
3661
3662 if (postfix) {
3663 StringAppendF(&name, "B%u.%s", dex_pc, postfix);
3664 } else {
3665 StringAppendF(&name, "B%u", dex_pc);
3666 }
3667
3668 return llvm::BasicBlock::Create(*context_, name, func_);
3669}
3670
3671
3672llvm::BasicBlock* MethodCompiler::GetBasicBlock(uint32_t dex_pc) {
3673 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
3674
3675 llvm::BasicBlock* basic_block = basic_blocks_[dex_pc];
3676
3677 if (!basic_block) {
3678 basic_block = CreateBasicBlockWithDexPC(dex_pc);
3679 basic_blocks_[dex_pc] = basic_block;
3680 }
3681
3682 return basic_block;
3683}
3684
3685
3686llvm::BasicBlock*
3687MethodCompiler::GetNextBasicBlock(uint32_t dex_pc) {
3688 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
3689 return GetBasicBlock(dex_pc + insn->SizeInCodeUnits());
3690}
3691
3692
Logan Chien5bcc04e2012-01-30 14:15:12 +08003693int32_t MethodCompiler::GetTryItemOffset(uint32_t dex_pc) {
3694 // TODO: Since we are emitting the dex instructions in ascending order
3695 // w.r.t. address, we can cache the lastest try item offset so that we
3696 // don't have to do binary search for every query.
3697
3698 int32_t min = 0;
3699 int32_t max = code_item_->tries_size_ - 1;
3700
3701 while (min <= max) {
3702 int32_t mid = min + (max - min) / 2;
3703
3704 DexFile::TryItem const* ti = DexFile::GetTryItems(*code_item_, mid);
3705 uint32_t start = ti->start_addr_;
3706 uint32_t end = start + ti->insn_count_;
3707
3708 if (dex_pc < start) {
3709 max = mid - 1;
3710 } else if (dex_pc >= end) {
3711 min = mid + 1;
3712 } else {
3713 return mid; // found
3714 }
3715 }
3716
3717 return -1; // not found
3718}
3719
3720
3721llvm::BasicBlock* MethodCompiler::GetLandingPadBasicBlock(uint32_t dex_pc) {
3722 // Find the try item for this address in this method
3723 int32_t ti_offset = GetTryItemOffset(dex_pc);
3724
3725 if (ti_offset == -1) {
3726 return NULL; // No landing pad is available for this address.
3727 }
3728
3729 // Check for the existing landing pad basic block
3730 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
3731 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
3732
3733 if (block_lpad) {
3734 // We have generated landing pad for this try item already. Return the
3735 // same basic block.
3736 return block_lpad;
3737 }
3738
3739 // Get try item from code item
3740 DexFile::TryItem const* ti = DexFile::GetTryItems(*code_item_, ti_offset);
3741
3742 // Create landing pad basic block
3743 block_lpad = llvm::BasicBlock::Create(*context_,
3744 StringPrintf("lpad%d", ti_offset),
3745 func_);
3746
3747 // Change IRBuilder insert point
3748 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
3749 irb_.SetInsertPoint(block_lpad);
3750
3751 // Find catch block with matching type
3752 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
3753
Logan Chien736df022012-04-27 16:25:57 +08003754 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
Logan Chien5bcc04e2012-01-30 14:15:12 +08003755
3756 llvm::Value* catch_handler_index_value =
3757 irb_.CreateCall2(irb_.GetRuntime(FindCatchBlock),
Logan Chien736df022012-04-27 16:25:57 +08003758 method_object_addr, ti_offset_value);
Logan Chien5bcc04e2012-01-30 14:15:12 +08003759
3760 // Switch instruction (Go to unwind basic block by default)
3761 llvm::SwitchInst* sw =
3762 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
3763
3764 // Cases with matched catch block
3765 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
3766
3767 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
3768 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
3769 }
3770
3771 // Restore the orignal insert point for IRBuilder
3772 irb_.restoreIP(irb_ip_original);
3773
3774 // Cache this landing pad
3775 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
3776 basic_block_landing_pads_[ti_offset] = block_lpad;
3777
3778 return block_lpad;
3779}
3780
3781
3782llvm::BasicBlock* MethodCompiler::GetUnwindBasicBlock() {
3783 // Check the existing unwinding baisc block block
3784 if (basic_block_unwind_ != NULL) {
3785 return basic_block_unwind_;
3786 }
3787
3788 // Create new basic block for unwinding
3789 basic_block_unwind_ =
3790 llvm::BasicBlock::Create(*context_, "exception_unwind", func_);
3791
3792 // Change IRBuilder insert point
3793 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
3794 irb_.SetInsertPoint(basic_block_unwind_);
3795
Logan Chien8dfcbea2012-02-17 18:50:32 +08003796 // Pop the shadow frame
3797 EmitPopShadowFrame();
3798
Logan Chien5bcc04e2012-01-30 14:15:12 +08003799 // Emit the code to return default value (zero) for the given return type.
Logan Chiendd361c92012-04-10 23:40:37 +08003800 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
Logan Chien5bcc04e2012-01-30 14:15:12 +08003801 if (ret_shorty == 'V') {
3802 irb_.CreateRetVoid();
3803 } else {
3804 irb_.CreateRet(irb_.getJZero(ret_shorty));
3805 }
3806
3807 // Restore the orignal insert point for IRBuilder
3808 irb_.restoreIP(irb_ip_original);
3809
3810 return basic_block_unwind_;
3811}
3812
3813
Logan Chienc670a8d2011-12-20 21:25:56 +08003814llvm::Value* MethodCompiler::AllocDalvikLocalVarReg(RegCategory cat,
3815 uint32_t reg_idx) {
3816
3817 // Save current IR builder insert point
3818 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
3819
3820 // Alloca
3821 llvm::Value* reg_addr = NULL;
3822
3823 switch (cat) {
3824 case kRegCat1nr:
3825 irb_.SetInsertPoint(basic_block_reg_alloca_);
3826 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0,
3827 StringPrintf("r%u", reg_idx));
Logan Chienc670a8d2011-12-20 21:25:56 +08003828 break;
3829
3830 case kRegCat2:
3831 irb_.SetInsertPoint(basic_block_reg_alloca_);
3832 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0,
3833 StringPrintf("w%u", reg_idx));
Logan Chienc670a8d2011-12-20 21:25:56 +08003834 break;
3835
3836 case kRegObject:
Logan Chien8dfcbea2012-02-17 18:50:32 +08003837 {
3838 irb_.SetInsertPoint(basic_block_shadow_frame_alloca_);
Logan Chienc670a8d2011-12-20 21:25:56 +08003839
Logan Chien8dfcbea2012-02-17 18:50:32 +08003840 llvm::Value* gep_index[] = {
3841 irb_.getInt32(0), // No pointer displacement
3842 irb_.getInt32(1), // SIRT
3843 irb_.getInt32(reg_idx) // Pointer field
3844 };
3845
3846 reg_addr = irb_.CreateGEP(shadow_frame_, gep_index,
3847 StringPrintf("p%u", reg_idx));
Logan Chien8dfcbea2012-02-17 18:50:32 +08003848 }
Logan Chienc670a8d2011-12-20 21:25:56 +08003849 break;
3850
3851 default:
3852 LOG(FATAL) << "Unknown register category for allocation: " << cat;
3853 }
3854
3855 // Restore IRBuilder insert point
3856 irb_.restoreIP(irb_ip_original);
3857
3858 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
3859 return reg_addr;
3860}
3861
3862
3863llvm::Value* MethodCompiler::AllocDalvikRetValReg(RegCategory cat) {
3864 // Save current IR builder insert point
3865 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
3866
3867 // Alloca
3868 llvm::Value* reg_addr = NULL;
3869
3870 switch (cat) {
3871 case kRegCat1nr:
3872 irb_.SetInsertPoint(basic_block_reg_alloca_);
3873 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0, "r_res");
3874 break;
3875
3876 case kRegCat2:
3877 irb_.SetInsertPoint(basic_block_reg_alloca_);
3878 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0, "w_res");
3879 break;
3880
3881 case kRegObject:
3882 irb_.SetInsertPoint(basic_block_reg_alloca_);
3883 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0, "p_res");
3884 break;
3885
3886 default:
3887 LOG(FATAL) << "Unknown register category for allocation: " << cat;
3888 }
3889
3890 // Restore IRBuilder insert point
3891 irb_.restoreIP(irb_ip_original);
3892
3893 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
3894 return reg_addr;
3895}
3896
3897
Logan Chien8dfcbea2012-02-17 18:50:32 +08003898void MethodCompiler::EmitPopShadowFrame() {
3899 irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
3900}
3901
3902
TDYa127c8dc1012012-04-19 07:03:33 -07003903void MethodCompiler::EmitUpdateDexPC(uint32_t dex_pc) {
3904 irb_.StoreToObjectOffset(shadow_frame_,
3905 ShadowFrame::DexPCOffset(),
3906 irb_.getInt32(dex_pc));
Logan Chien8dfcbea2012-02-17 18:50:32 +08003907}
3908
3909
Logan Chien83426162011-12-09 09:29:50 +08003910} // namespace compiler_llvm
3911} // namespace art