blob: 8d6b251ada8a886c0e93b8b1fb1396a00470aaaf [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>
Logan Chienfca64372012-04-23 14:57:01 +080039#include <llvm/DerivedTypes.h>
Shih-wei Liaod1fec812012-02-13 09:51:10 -080040#include <llvm/Function.h>
Logan Chiena85fb2f2012-01-16 12:52:56 +080041#include <llvm/GlobalVariable.h>
42#include <llvm/Intrinsics.h>
Logan Chienfca64372012-04-23 14:57:01 +080043#include <llvm/Module.h>
44#include <llvm/Type.h>
Shih-wei Liaod1fec812012-02-13 09:51:10 -080045
Logan Chien83426162011-12-09 09:29:50 +080046namespace art {
47namespace compiler_llvm {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080048
Logan Chien42e0e152012-01-13 15:42:36 +080049using namespace runtime_support;
50
Shih-wei Liaod1fec812012-02-13 09:51:10 -080051
Logan Chien8b977d32012-02-21 19:14:55 +080052MethodCompiler::MethodCompiler(CompilationUnit* cunit,
Logan Chien83426162011-12-09 09:29:50 +080053 Compiler* compiler,
Logan Chien4dd96f52012-02-29 01:26:58 +080054 OatCompilationUnit* oat_compilation_unit)
Logan Chien8b977d32012-02-21 19:14:55 +080055 : cunit_(cunit), compiler_(compiler),
56 class_linker_(oat_compilation_unit->class_linker_),
57 class_loader_(oat_compilation_unit->class_loader_),
58 dex_file_(oat_compilation_unit->dex_file_),
59 dex_cache_(oat_compilation_unit->dex_cache_),
60 code_item_(oat_compilation_unit->code_item_),
61 oat_compilation_unit_(oat_compilation_unit),
Logan Chien8b977d32012-02-21 19:14:55 +080062 method_idx_(oat_compilation_unit->method_idx_),
63 access_flags_(oat_compilation_unit->access_flags_),
64 module_(cunit->GetModule()),
65 context_(cunit->GetLLVMContext()),
66 irb_(*cunit->GetIRBuilder()), func_(NULL), retval_reg_(NULL),
Ian Rogers776ac1f2012-04-13 23:36:36 -070067 basic_block_stack_overflow_(NULL),
Logan Chien8b977d32012-02-21 19:14:55 +080068 basic_block_reg_alloca_(NULL), basic_block_shadow_frame_alloca_(NULL),
69 basic_block_reg_zero_init_(NULL), basic_block_reg_arg_init_(NULL),
70 basic_blocks_(code_item_->insns_size_in_code_units_),
71 basic_block_landing_pads_(code_item_->tries_size_, NULL),
72 basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
Logan Chien937105a2012-04-02 02:37:37 +080073 shadow_frame_(NULL), elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080074}
75
76
77MethodCompiler::~MethodCompiler() {
Logan Chienc670a8d2011-12-20 21:25:56 +080078 STLDeleteElements(&regs_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -080079}
80
81
Logan Chien0b827102011-12-20 19:46:14 +080082void MethodCompiler::CreateFunction() {
83 // LLVM function name
Logan Chien937105a2012-04-02 02:37:37 +080084 std::string func_name(ElfFuncName(elf_func_idx_));
Logan Chien0b827102011-12-20 19:46:14 +080085
86 // Get function type
87 llvm::FunctionType* func_type =
Logan Chiendd361c92012-04-10 23:40:37 +080088 GetFunctionType(method_idx_, oat_compilation_unit_->IsStatic());
Logan Chien0b827102011-12-20 19:46:14 +080089
90 // Create function
91 func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
92 func_name, module_);
93
94 // Set argument name
95 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
96 llvm::Function::arg_iterator arg_end(func_->arg_end());
97
98 DCHECK_NE(arg_iter, arg_end);
99 arg_iter->setName("method");
100 ++arg_iter;
101
Logan Chiendd361c92012-04-10 23:40:37 +0800102 if (!oat_compilation_unit_->IsStatic()) {
Logan Chien0b827102011-12-20 19:46:14 +0800103 DCHECK_NE(arg_iter, arg_end);
104 arg_iter->setName("this");
105 ++arg_iter;
106 }
107
108 for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
109 arg_iter->setName(StringPrintf("a%u", i));
110 }
111}
112
113
114llvm::FunctionType* MethodCompiler::GetFunctionType(uint32_t method_idx,
115 bool is_static) {
116 // Get method signature
117 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
118
Logan Chien8faf8022012-02-24 12:25:29 +0800119 uint32_t shorty_size;
Logan Chien0b827102011-12-20 19:46:14 +0800120 char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
Logan Chien8faf8022012-02-24 12:25:29 +0800121 CHECK_GE(shorty_size, 1u);
Logan Chien0b827102011-12-20 19:46:14 +0800122
123 // Get return type
124 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
125
126 // Get argument type
127 std::vector<llvm::Type*> args_type;
128
129 args_type.push_back(irb_.getJObjectTy()); // method object pointer
130
131 if (!is_static) {
132 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
133 }
134
Logan Chien8faf8022012-02-24 12:25:29 +0800135 for (uint32_t i = 1; i < shorty_size; ++i) {
Logan Chien0b827102011-12-20 19:46:14 +0800136 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
137 }
138
139 return llvm::FunctionType::get(ret_type, args_type, false);
140}
141
142
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800143void MethodCompiler::EmitPrologue() {
Logan Chienc670a8d2011-12-20 21:25:56 +0800144 // Create basic blocks for prologue
TDYa1274165a832012-04-03 17:47:16 -0700145 basic_block_stack_overflow_ =
146 llvm::BasicBlock::Create(*context_, "prologue.stack_overflow_check", func_);
147
Logan Chienc670a8d2011-12-20 21:25:56 +0800148 basic_block_reg_alloca_ =
149 llvm::BasicBlock::Create(*context_, "prologue.alloca", func_);
150
Logan Chien8dfcbea2012-02-17 18:50:32 +0800151 basic_block_shadow_frame_alloca_ =
152 llvm::BasicBlock::Create(*context_, "prologue.shadowframe", func_);
153
Logan Chienc670a8d2011-12-20 21:25:56 +0800154 basic_block_reg_zero_init_ =
155 llvm::BasicBlock::Create(*context_, "prologue.zeroinit", func_);
156
Logan Chiend6ececa2011-12-27 16:20:15 +0800157 basic_block_reg_arg_init_ =
158 llvm::BasicBlock::Create(*context_, "prologue.arginit", func_);
159
TDYa1274165a832012-04-03 17:47:16 -0700160 // Before alloca, check stack overflow.
161 EmitStackOverflowCheck();
162
Logan Chienc670a8d2011-12-20 21:25:56 +0800163 // Create register array
164 for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
165 regs_.push_back(DalvikReg::CreateLocalVarReg(*this, r));
166 }
167
168 retval_reg_.reset(DalvikReg::CreateRetValReg(*this));
Logan Chiend6ececa2011-12-27 16:20:15 +0800169
Logan Chien8dfcbea2012-02-17 18:50:32 +0800170 // Create Shadow Frame
171 EmitPrologueAllocShadowFrame();
172
Logan Chiend6ececa2011-12-27 16:20:15 +0800173 // Store argument to dalvik register
174 irb_.SetInsertPoint(basic_block_reg_arg_init_);
175 EmitPrologueAssignArgRegister();
176
177 // Branch to start address
178 irb_.CreateBr(GetBasicBlock(0));
Logan Chienc670a8d2011-12-20 21:25:56 +0800179}
180
181
TDYa1274165a832012-04-03 17:47:16 -0700182void MethodCompiler::EmitStackOverflowCheck() {
183 irb_.SetInsertPoint(basic_block_stack_overflow_);
184
185 // Call llvm intrinsic function to get frame address.
186 llvm::Function* frameaddress =
187 llvm::Intrinsic::getDeclaration(module_, llvm::Intrinsic::frameaddress);
188
189 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
190 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
191
192 // Cast i8* to int
193 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
194
195 // Get thread.stack_end_
196 llvm::Value* thread_object_addr =
197 irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
198
199 llvm::Value* stack_end_addr =
200 irb_.CreatePtrDisp(thread_object_addr,
201 irb_.getPtrEquivInt(Thread::StackEndOffset().Int32Value()),
202 irb_.getPtrEquivIntTy()->getPointerTo());
203
204 llvm::Value* stack_end = irb_.CreateLoad(stack_end_addr);
205
206 // Check the frame address < thread.stack_end_ ?
207 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
208
209 llvm::BasicBlock* block_exception =
210 llvm::BasicBlock::Create(*context_, "stack_overflow", func_);
211
212 llvm::BasicBlock* block_continue =
213 llvm::BasicBlock::Create(*context_, "stack_overflow_cont", func_);
214
215 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue);
216
217 // If stack overflow, throw exception.
218 irb_.SetInsertPoint(block_exception);
219 irb_.CreateCall(irb_.GetRuntime(ThrowStackOverflowException));
220
221 // Unwind.
Logan Chiendd361c92012-04-10 23:40:37 +0800222 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
TDYa1274165a832012-04-03 17:47:16 -0700223 if (ret_shorty == 'V') {
224 irb_.CreateRetVoid();
225 } else {
226 irb_.CreateRet(irb_.getJZero(ret_shorty));
227 }
228
229 basic_block_stack_overflow_ = block_continue;
230}
231
232
Logan Chienc670a8d2011-12-20 21:25:56 +0800233void MethodCompiler::EmitPrologueLastBranch() {
TDYa1274165a832012-04-03 17:47:16 -0700234 irb_.SetInsertPoint(basic_block_stack_overflow_);
235 irb_.CreateBr(basic_block_reg_alloca_);
236
Logan Chienc670a8d2011-12-20 21:25:56 +0800237 irb_.SetInsertPoint(basic_block_reg_alloca_);
Logan Chien8dfcbea2012-02-17 18:50:32 +0800238 irb_.CreateBr(basic_block_shadow_frame_alloca_);
239
240 irb_.SetInsertPoint(basic_block_shadow_frame_alloca_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800241 irb_.CreateBr(basic_block_reg_zero_init_);
242
243 irb_.SetInsertPoint(basic_block_reg_zero_init_);
Logan Chiend6ececa2011-12-27 16:20:15 +0800244 irb_.CreateBr(basic_block_reg_arg_init_);
245}
246
247
Logan Chien8dfcbea2012-02-17 18:50:32 +0800248void MethodCompiler::EmitPrologueAllocShadowFrame() {
249 irb_.SetInsertPoint(basic_block_shadow_frame_alloca_);
250
251 // Allocate the shadow frame now!
252 uint32_t sirt_size = code_item_->registers_size_;
253 // TODO: registers_size_ is a bad approximation. Compute a
254 // tighter approximation at Dex verifier while performing data-flow
255 // analysis.
256
257 llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
258 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
259
260 // Zero-initialization of the shadow frame
261 llvm::ConstantAggregateZero* zero_initializer =
262 llvm::ConstantAggregateZero::get(shadow_frame_type);
263
264 irb_.CreateStore(zero_initializer, shadow_frame_);
265
Logan Chien8dfcbea2012-02-17 18:50:32 +0800266 // Store the method pointer
Logan Chien1b0a1b72012-03-15 06:20:17 +0800267 llvm::Value* method_field_addr =
268 irb_.CreatePtrDisp(shadow_frame_,
269 irb_.getPtrEquivInt(ShadowFrame::MethodOffset()),
270 irb_.getJObjectTy()->getPointerTo());
271
Logan Chien8dfcbea2012-02-17 18:50:32 +0800272 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
273 irb_.CreateStore(method_object_addr, method_field_addr);
274
275 // Store the number of the pointer slots
Logan Chien1b0a1b72012-03-15 06:20:17 +0800276 llvm::ConstantInt* num_of_refs_offset =
277 irb_.getPtrEquivInt(ShadowFrame::NumberOfReferencesOffset());
278
279 llvm::Value* num_of_refs_field_addr =
280 irb_.CreatePtrDisp(shadow_frame_, num_of_refs_offset,
281 irb_.getJIntTy()->getPointerTo());
282
283 llvm::ConstantInt* num_of_refs_value = irb_.getJInt(sirt_size);
284 irb_.CreateStore(num_of_refs_value, num_of_refs_field_addr);
Logan Chien8dfcbea2012-02-17 18:50:32 +0800285
286 // Push the shadow frame
287 llvm::Value* shadow_frame_upcast =
288 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
289
290 irb_.CreateCall(irb_.GetRuntime(PushShadowFrame), shadow_frame_upcast);
291}
292
293
Logan Chiend6ececa2011-12-27 16:20:15 +0800294void MethodCompiler::EmitPrologueAssignArgRegister() {
295 uint16_t arg_reg = code_item_->registers_size_ - code_item_->ins_size_;
296
297 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
298 llvm::Function::arg_iterator arg_end(func_->arg_end());
299
Logan Chiendd361c92012-04-10 23:40:37 +0800300 uint32_t shorty_size = 0;
301 char const* shorty = oat_compilation_unit_->GetShorty(&shorty_size);
302 CHECK_GE(shorty_size, 1u);
Logan Chiend6ececa2011-12-27 16:20:15 +0800303
304 ++arg_iter; // skip method object
305
Logan Chiendd361c92012-04-10 23:40:37 +0800306 if (!oat_compilation_unit_->IsStatic()) {
Logan Chiend6ececa2011-12-27 16:20:15 +0800307 EmitStoreDalvikReg(arg_reg, kObject, kAccurate, arg_iter);
308 ++arg_iter;
309 ++arg_reg;
310 }
311
Logan Chiendd361c92012-04-10 23:40:37 +0800312 for (uint32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
Logan Chiend6ececa2011-12-27 16:20:15 +0800313 EmitStoreDalvikReg(arg_reg, shorty[i], kAccurate, arg_iter);
314
315 ++arg_reg;
316 if (shorty[i] == 'J' || shorty[i] == 'D') {
317 // Wide types, such as long and double, are using a pair of registers
318 // to store the value, so we have to increase arg_reg again.
319 ++arg_reg;
320 }
321 }
322
323 DCHECK_EQ(arg_end, arg_iter);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800324}
325
326
Logan Chien83426162011-12-09 09:29:50 +0800327void MethodCompiler::EmitInstructions() {
Logan Chiend6c239a2011-12-23 15:11:45 +0800328 uint32_t dex_pc = 0;
329 while (dex_pc < code_item_->insns_size_in_code_units_) {
330 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
331 EmitInstruction(dex_pc, insn);
332 dex_pc += insn->SizeInCodeUnits();
333 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800334}
335
336
Logan Chien83426162011-12-09 09:29:50 +0800337void MethodCompiler::EmitInstruction(uint32_t dex_pc,
338 Instruction const* insn) {
Logan Chiend6c239a2011-12-23 15:11:45 +0800339
340 // Set the IRBuilder insertion point
341 irb_.SetInsertPoint(GetBasicBlock(dex_pc));
342
Logan Chien70f94b42011-12-27 17:49:11 +0800343#define ARGS dex_pc, insn
344
345 // Dispatch the instruction
346 switch (insn->Opcode()) {
347 case Instruction::NOP:
348 EmitInsn_Nop(ARGS);
349 break;
350
351 case Instruction::MOVE:
352 case Instruction::MOVE_FROM16:
353 case Instruction::MOVE_16:
354 EmitInsn_Move(ARGS, kInt);
355 break;
356
357 case Instruction::MOVE_WIDE:
358 case Instruction::MOVE_WIDE_FROM16:
359 case Instruction::MOVE_WIDE_16:
360 EmitInsn_Move(ARGS, kLong);
361 break;
362
363 case Instruction::MOVE_OBJECT:
364 case Instruction::MOVE_OBJECT_FROM16:
365 case Instruction::MOVE_OBJECT_16:
366 EmitInsn_Move(ARGS, kObject);
367 break;
368
369 case Instruction::MOVE_RESULT:
370 EmitInsn_MoveResult(ARGS, kInt);
371 break;
372
373 case Instruction::MOVE_RESULT_WIDE:
374 EmitInsn_MoveResult(ARGS, kLong);
375 break;
376
377 case Instruction::MOVE_RESULT_OBJECT:
378 EmitInsn_MoveResult(ARGS, kObject);
379 break;
380
381 case Instruction::MOVE_EXCEPTION:
382 EmitInsn_MoveException(ARGS);
383 break;
384
385 case Instruction::RETURN_VOID:
386 EmitInsn_ReturnVoid(ARGS);
387 break;
388
389 case Instruction::RETURN:
390 case Instruction::RETURN_WIDE:
391 case Instruction::RETURN_OBJECT:
392 EmitInsn_Return(ARGS);
393 break;
394
395 case Instruction::CONST_4:
396 case Instruction::CONST_16:
397 case Instruction::CONST:
398 case Instruction::CONST_HIGH16:
399 EmitInsn_LoadConstant(ARGS, kInt);
400 break;
401
402 case Instruction::CONST_WIDE_16:
403 case Instruction::CONST_WIDE_32:
404 case Instruction::CONST_WIDE:
405 case Instruction::CONST_WIDE_HIGH16:
406 EmitInsn_LoadConstant(ARGS, kLong);
407 break;
408
409 case Instruction::CONST_STRING:
410 case Instruction::CONST_STRING_JUMBO:
411 EmitInsn_LoadConstantString(ARGS);
412 break;
413
414 case Instruction::CONST_CLASS:
415 EmitInsn_LoadConstantClass(ARGS);
416 break;
417
418 case Instruction::MONITOR_ENTER:
419 EmitInsn_MonitorEnter(ARGS);
420 break;
421
422 case Instruction::MONITOR_EXIT:
423 EmitInsn_MonitorExit(ARGS);
424 break;
425
426 case Instruction::CHECK_CAST:
427 EmitInsn_CheckCast(ARGS);
428 break;
429
430 case Instruction::INSTANCE_OF:
431 EmitInsn_InstanceOf(ARGS);
432 break;
433
434 case Instruction::ARRAY_LENGTH:
435 EmitInsn_ArrayLength(ARGS);
436 break;
437
438 case Instruction::NEW_INSTANCE:
439 EmitInsn_NewInstance(ARGS);
440 break;
441
442 case Instruction::NEW_ARRAY:
443 EmitInsn_NewArray(ARGS);
444 break;
445
446 case Instruction::FILLED_NEW_ARRAY:
447 EmitInsn_FilledNewArray(ARGS, false);
448 break;
449
450 case Instruction::FILLED_NEW_ARRAY_RANGE:
451 EmitInsn_FilledNewArray(ARGS, true);
452 break;
453
454 case Instruction::FILL_ARRAY_DATA:
455 EmitInsn_FillArrayData(ARGS);
456 break;
457
458 case Instruction::THROW:
459 EmitInsn_ThrowException(ARGS);
460 break;
461
462 case Instruction::GOTO:
463 case Instruction::GOTO_16:
464 case Instruction::GOTO_32:
465 EmitInsn_UnconditionalBranch(ARGS);
466 break;
467
468 case Instruction::PACKED_SWITCH:
469 EmitInsn_PackedSwitch(ARGS);
470 break;
471
472 case Instruction::SPARSE_SWITCH:
473 EmitInsn_SparseSwitch(ARGS);
474 break;
475
476 case Instruction::CMPL_FLOAT:
477 EmitInsn_FPCompare(ARGS, kFloat, false);
478 break;
479
480 case Instruction::CMPG_FLOAT:
481 EmitInsn_FPCompare(ARGS, kFloat, true);
482 break;
483
484 case Instruction::CMPL_DOUBLE:
485 EmitInsn_FPCompare(ARGS, kDouble, false);
486 break;
487
488 case Instruction::CMPG_DOUBLE:
489 EmitInsn_FPCompare(ARGS, kDouble, true);
490 break;
491
492 case Instruction::CMP_LONG:
493 EmitInsn_LongCompare(ARGS);
494 break;
495
496 case Instruction::IF_EQ:
497 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_EQ);
498 break;
499
500 case Instruction::IF_NE:
501 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_NE);
502 break;
503
504 case Instruction::IF_LT:
505 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_LT);
506 break;
507
508 case Instruction::IF_GE:
509 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_GE);
510 break;
511
512 case Instruction::IF_GT:
513 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_GT);
514 break;
515
516 case Instruction::IF_LE:
517 EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_LE);
518 break;
519
520 case Instruction::IF_EQZ:
521 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_EQ);
522 break;
523
524 case Instruction::IF_NEZ:
525 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_NE);
526 break;
527
528 case Instruction::IF_LTZ:
529 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_LT);
530 break;
531
532 case Instruction::IF_GEZ:
533 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_GE);
534 break;
535
536 case Instruction::IF_GTZ:
537 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_GT);
538 break;
539
540 case Instruction::IF_LEZ:
541 EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_LE);
542 break;
543
544 case Instruction::AGET:
545 EmitInsn_AGet(ARGS, kInt);
546 break;
547
548 case Instruction::AGET_WIDE:
549 EmitInsn_AGet(ARGS, kLong);
550 break;
551
552 case Instruction::AGET_OBJECT:
553 EmitInsn_AGet(ARGS, kObject);
554 break;
555
556 case Instruction::AGET_BOOLEAN:
557 EmitInsn_AGet(ARGS, kBoolean);
558 break;
559
560 case Instruction::AGET_BYTE:
561 EmitInsn_AGet(ARGS, kByte);
562 break;
563
564 case Instruction::AGET_CHAR:
565 EmitInsn_AGet(ARGS, kChar);
566 break;
567
568 case Instruction::AGET_SHORT:
569 EmitInsn_AGet(ARGS, kShort);
570 break;
571
572 case Instruction::APUT:
573 EmitInsn_APut(ARGS, kInt);
574 break;
575
576 case Instruction::APUT_WIDE:
577 EmitInsn_APut(ARGS, kLong);
578 break;
579
580 case Instruction::APUT_OBJECT:
581 EmitInsn_APut(ARGS, kObject);
582 break;
583
584 case Instruction::APUT_BOOLEAN:
585 EmitInsn_APut(ARGS, kBoolean);
586 break;
587
588 case Instruction::APUT_BYTE:
589 EmitInsn_APut(ARGS, kByte);
590 break;
591
592 case Instruction::APUT_CHAR:
593 EmitInsn_APut(ARGS, kChar);
594 break;
595
596 case Instruction::APUT_SHORT:
597 EmitInsn_APut(ARGS, kShort);
598 break;
599
600 case Instruction::IGET:
601 EmitInsn_IGet(ARGS, kInt);
602 break;
603
604 case Instruction::IGET_WIDE:
605 EmitInsn_IGet(ARGS, kLong);
606 break;
607
608 case Instruction::IGET_OBJECT:
609 EmitInsn_IGet(ARGS, kObject);
610 break;
611
612 case Instruction::IGET_BOOLEAN:
613 EmitInsn_IGet(ARGS, kBoolean);
614 break;
615
616 case Instruction::IGET_BYTE:
617 EmitInsn_IGet(ARGS, kByte);
618 break;
619
620 case Instruction::IGET_CHAR:
621 EmitInsn_IGet(ARGS, kChar);
622 break;
623
624 case Instruction::IGET_SHORT:
625 EmitInsn_IGet(ARGS, kShort);
626 break;
627
628 case Instruction::IPUT:
629 EmitInsn_IPut(ARGS, kInt);
630 break;
631
632 case Instruction::IPUT_WIDE:
633 EmitInsn_IPut(ARGS, kLong);
634 break;
635
636 case Instruction::IPUT_OBJECT:
637 EmitInsn_IPut(ARGS, kObject);
638 break;
639
640 case Instruction::IPUT_BOOLEAN:
641 EmitInsn_IPut(ARGS, kBoolean);
642 break;
643
644 case Instruction::IPUT_BYTE:
645 EmitInsn_IPut(ARGS, kByte);
646 break;
647
648 case Instruction::IPUT_CHAR:
649 EmitInsn_IPut(ARGS, kChar);
650 break;
651
652 case Instruction::IPUT_SHORT:
653 EmitInsn_IPut(ARGS, kShort);
654 break;
655
656 case Instruction::SGET:
657 EmitInsn_SGet(ARGS, kInt);
658 break;
659
660 case Instruction::SGET_WIDE:
661 EmitInsn_SGet(ARGS, kLong);
662 break;
663
664 case Instruction::SGET_OBJECT:
665 EmitInsn_SGet(ARGS, kObject);
666 break;
667
668 case Instruction::SGET_BOOLEAN:
669 EmitInsn_SGet(ARGS, kBoolean);
670 break;
671
672 case Instruction::SGET_BYTE:
673 EmitInsn_SGet(ARGS, kByte);
674 break;
675
676 case Instruction::SGET_CHAR:
677 EmitInsn_SGet(ARGS, kChar);
678 break;
679
680 case Instruction::SGET_SHORT:
681 EmitInsn_SGet(ARGS, kShort);
682 break;
683
684 case Instruction::SPUT:
685 EmitInsn_SPut(ARGS, kInt);
686 break;
687
688 case Instruction::SPUT_WIDE:
689 EmitInsn_SPut(ARGS, kLong);
690 break;
691
692 case Instruction::SPUT_OBJECT:
693 EmitInsn_SPut(ARGS, kObject);
694 break;
695
696 case Instruction::SPUT_BOOLEAN:
697 EmitInsn_SPut(ARGS, kBoolean);
698 break;
699
700 case Instruction::SPUT_BYTE:
701 EmitInsn_SPut(ARGS, kByte);
702 break;
703
704 case Instruction::SPUT_CHAR:
705 EmitInsn_SPut(ARGS, kChar);
706 break;
707
708 case Instruction::SPUT_SHORT:
709 EmitInsn_SPut(ARGS, kShort);
710 break;
711
712
713 case Instruction::INVOKE_VIRTUAL:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800714 EmitInsn_Invoke(ARGS, kVirtual, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800715 break;
716
717 case Instruction::INVOKE_SUPER:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800718 EmitInsn_Invoke(ARGS, kSuper, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800719 break;
720
721 case Instruction::INVOKE_DIRECT:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800722 EmitInsn_Invoke(ARGS, kDirect, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800723 break;
724
725 case Instruction::INVOKE_STATIC:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800726 EmitInsn_Invoke(ARGS, kStatic, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800727 break;
728
729 case Instruction::INVOKE_INTERFACE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800730 EmitInsn_Invoke(ARGS, kInterface, kArgReg);
Logan Chien70f94b42011-12-27 17:49:11 +0800731 break;
732
733 case Instruction::INVOKE_VIRTUAL_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800734 EmitInsn_Invoke(ARGS, kVirtual, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800735 break;
736
737 case Instruction::INVOKE_SUPER_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800738 EmitInsn_Invoke(ARGS, kSuper, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800739 break;
740
741 case Instruction::INVOKE_DIRECT_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800742 EmitInsn_Invoke(ARGS, kDirect, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800743 break;
744
745 case Instruction::INVOKE_STATIC_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800746 EmitInsn_Invoke(ARGS, kStatic, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800747 break;
748
749 case Instruction::INVOKE_INTERFACE_RANGE:
Logan Chien7e7fabc2012-04-10 18:59:11 +0800750 EmitInsn_Invoke(ARGS, kInterface, kArgRange);
Logan Chien70f94b42011-12-27 17:49:11 +0800751 break;
752
753 case Instruction::NEG_INT:
754 EmitInsn_Neg(ARGS, kInt);
755 break;
756
757 case Instruction::NOT_INT:
758 EmitInsn_Not(ARGS, kInt);
759 break;
760
761 case Instruction::NEG_LONG:
762 EmitInsn_Neg(ARGS, kLong);
763 break;
764
765 case Instruction::NOT_LONG:
766 EmitInsn_Not(ARGS, kLong);
767 break;
768
769 case Instruction::NEG_FLOAT:
770 EmitInsn_FNeg(ARGS, kFloat);
771 break;
772
773 case Instruction::NEG_DOUBLE:
774 EmitInsn_FNeg(ARGS, kDouble);
775 break;
776
777 case Instruction::INT_TO_LONG:
778 EmitInsn_SExt(ARGS);
779 break;
780
781 case Instruction::INT_TO_FLOAT:
782 EmitInsn_IntToFP(ARGS, kInt, kFloat);
783 break;
784
785 case Instruction::INT_TO_DOUBLE:
786 EmitInsn_IntToFP(ARGS, kInt, kDouble);
787 break;
788
789 case Instruction::LONG_TO_INT:
790 EmitInsn_Trunc(ARGS);
791 break;
792
793 case Instruction::LONG_TO_FLOAT:
794 EmitInsn_IntToFP(ARGS, kLong, kFloat);
795 break;
796
797 case Instruction::LONG_TO_DOUBLE:
798 EmitInsn_IntToFP(ARGS, kLong, kDouble);
799 break;
800
801 case Instruction::FLOAT_TO_INT:
TDYa127a4746872012-04-11 23:48:55 -0700802 EmitInsn_FPToInt(ARGS, kFloat, kInt, F2I);
Logan Chien70f94b42011-12-27 17:49:11 +0800803 break;
804
805 case Instruction::FLOAT_TO_LONG:
TDYa127a4746872012-04-11 23:48:55 -0700806 EmitInsn_FPToInt(ARGS, kFloat, kLong, F2L);
Logan Chien70f94b42011-12-27 17:49:11 +0800807 break;
808
809 case Instruction::FLOAT_TO_DOUBLE:
810 EmitInsn_FExt(ARGS);
811 break;
812
813 case Instruction::DOUBLE_TO_INT:
TDYa127a4746872012-04-11 23:48:55 -0700814 EmitInsn_FPToInt(ARGS, kDouble, kInt, D2I);
Logan Chien70f94b42011-12-27 17:49:11 +0800815 break;
816
817 case Instruction::DOUBLE_TO_LONG:
TDYa127a4746872012-04-11 23:48:55 -0700818 EmitInsn_FPToInt(ARGS, kDouble, kLong, D2L);
Logan Chien70f94b42011-12-27 17:49:11 +0800819 break;
820
821 case Instruction::DOUBLE_TO_FLOAT:
822 EmitInsn_FTrunc(ARGS);
823 break;
824
825 case Instruction::INT_TO_BYTE:
826 EmitInsn_TruncAndSExt(ARGS, 8);
827 break;
828
829 case Instruction::INT_TO_CHAR:
830 EmitInsn_TruncAndZExt(ARGS, 16);
831 break;
832
833 case Instruction::INT_TO_SHORT:
834 EmitInsn_TruncAndSExt(ARGS, 16);
835 break;
836
837 case Instruction::ADD_INT:
838 EmitInsn_IntArithm(ARGS, kIntArithm_Add, kInt, false);
839 break;
840
841 case Instruction::SUB_INT:
842 EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kInt, false);
843 break;
844
845 case Instruction::MUL_INT:
846 EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kInt, false);
847 break;
848
849 case Instruction::DIV_INT:
850 EmitInsn_IntArithm(ARGS, kIntArithm_Div, kInt, false);
851 break;
852
853 case Instruction::REM_INT:
854 EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kInt, false);
855 break;
856
857 case Instruction::AND_INT:
858 EmitInsn_IntArithm(ARGS, kIntArithm_And, kInt, false);
859 break;
860
861 case Instruction::OR_INT:
862 EmitInsn_IntArithm(ARGS, kIntArithm_Or, kInt, false);
863 break;
864
865 case Instruction::XOR_INT:
866 EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kInt, false);
867 break;
868
869 case Instruction::SHL_INT:
Logan Chien5539ad02012-04-02 14:36:55 +0800870 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800871 break;
872
873 case Instruction::SHR_INT:
Logan Chien5539ad02012-04-02 14:36:55 +0800874 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800875 break;
876
877 case Instruction::USHR_INT:
Logan Chien5539ad02012-04-02 14:36:55 +0800878 EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800879 break;
880
881 case Instruction::ADD_LONG:
882 EmitInsn_IntArithm(ARGS, kIntArithm_Add, kLong, false);
883 break;
884
885 case Instruction::SUB_LONG:
886 EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kLong, false);
887 break;
888
889 case Instruction::MUL_LONG:
890 EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kLong, false);
891 break;
892
893 case Instruction::DIV_LONG:
894 EmitInsn_IntArithm(ARGS, kIntArithm_Div, kLong, false);
895 break;
896
897 case Instruction::REM_LONG:
898 EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kLong, false);
899 break;
900
901 case Instruction::AND_LONG:
902 EmitInsn_IntArithm(ARGS, kIntArithm_And, kLong, false);
903 break;
904
905 case Instruction::OR_LONG:
906 EmitInsn_IntArithm(ARGS, kIntArithm_Or, kLong, false);
907 break;
908
909 case Instruction::XOR_LONG:
910 EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kLong, false);
911 break;
912
913 case Instruction::SHL_LONG:
Logan Chien5539ad02012-04-02 14:36:55 +0800914 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800915 break;
916
917 case Instruction::SHR_LONG:
Logan Chien5539ad02012-04-02 14:36:55 +0800918 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800919 break;
920
921 case Instruction::USHR_LONG:
Logan Chien5539ad02012-04-02 14:36:55 +0800922 EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, false);
Logan Chien70f94b42011-12-27 17:49:11 +0800923 break;
924
925 case Instruction::ADD_FLOAT:
926 EmitInsn_FPArithm(ARGS, kFPArithm_Add, kFloat, false);
927 break;
928
929 case Instruction::SUB_FLOAT:
930 EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kFloat, false);
931 break;
932
933 case Instruction::MUL_FLOAT:
934 EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kFloat, false);
935 break;
936
937 case Instruction::DIV_FLOAT:
938 EmitInsn_FPArithm(ARGS, kFPArithm_Div, kFloat, false);
939 break;
940
941 case Instruction::REM_FLOAT:
942 EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kFloat, false);
943 break;
944
945 case Instruction::ADD_DOUBLE:
946 EmitInsn_FPArithm(ARGS, kFPArithm_Add, kDouble, false);
947 break;
948
949 case Instruction::SUB_DOUBLE:
950 EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kDouble, false);
951 break;
952
953 case Instruction::MUL_DOUBLE:
954 EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kDouble, false);
955 break;
956
957 case Instruction::DIV_DOUBLE:
958 EmitInsn_FPArithm(ARGS, kFPArithm_Div, kDouble, false);
959 break;
960
961 case Instruction::REM_DOUBLE:
962 EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kDouble, false);
963 break;
964
965 case Instruction::ADD_INT_2ADDR:
966 EmitInsn_IntArithm(ARGS, kIntArithm_Add, kInt, true);
967 break;
968
969 case Instruction::SUB_INT_2ADDR:
970 EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kInt, true);
971 break;
972
973 case Instruction::MUL_INT_2ADDR:
974 EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kInt, true);
975 break;
976
977 case Instruction::DIV_INT_2ADDR:
978 EmitInsn_IntArithm(ARGS, kIntArithm_Div, kInt, true);
979 break;
980
981 case Instruction::REM_INT_2ADDR:
982 EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kInt, true);
983 break;
984
985 case Instruction::AND_INT_2ADDR:
986 EmitInsn_IntArithm(ARGS, kIntArithm_And, kInt, true);
987 break;
988
989 case Instruction::OR_INT_2ADDR:
990 EmitInsn_IntArithm(ARGS, kIntArithm_Or, kInt, true);
991 break;
992
993 case Instruction::XOR_INT_2ADDR:
994 EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kInt, true);
995 break;
996
997 case Instruction::SHL_INT_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +0800998 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, true);
Logan Chien70f94b42011-12-27 17:49:11 +0800999 break;
1000
1001 case Instruction::SHR_INT_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +08001002 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, true);
Logan Chien70f94b42011-12-27 17:49:11 +08001003 break;
1004
1005 case Instruction::USHR_INT_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +08001006 EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, true);
Logan Chien70f94b42011-12-27 17:49:11 +08001007 break;
1008
1009 case Instruction::ADD_LONG_2ADDR:
1010 EmitInsn_IntArithm(ARGS, kIntArithm_Add, kLong, true);
1011 break;
1012
1013 case Instruction::SUB_LONG_2ADDR:
1014 EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kLong, true);
1015 break;
1016
1017 case Instruction::MUL_LONG_2ADDR:
1018 EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kLong, true);
1019 break;
1020
1021 case Instruction::DIV_LONG_2ADDR:
1022 EmitInsn_IntArithm(ARGS, kIntArithm_Div, kLong, true);
1023 break;
1024
1025 case Instruction::REM_LONG_2ADDR:
1026 EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kLong, true);
1027 break;
1028
1029 case Instruction::AND_LONG_2ADDR:
1030 EmitInsn_IntArithm(ARGS, kIntArithm_And, kLong, true);
1031 break;
1032
1033 case Instruction::OR_LONG_2ADDR:
1034 EmitInsn_IntArithm(ARGS, kIntArithm_Or, kLong, true);
1035 break;
1036
1037 case Instruction::XOR_LONG_2ADDR:
1038 EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kLong, true);
1039 break;
1040
1041 case Instruction::SHL_LONG_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +08001042 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, true);
Logan Chien70f94b42011-12-27 17:49:11 +08001043 break;
1044
1045 case Instruction::SHR_LONG_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +08001046 EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, true);
Logan Chien70f94b42011-12-27 17:49:11 +08001047 break;
1048
1049 case Instruction::USHR_LONG_2ADDR:
Logan Chien5539ad02012-04-02 14:36:55 +08001050 EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, true);
Logan Chien70f94b42011-12-27 17:49:11 +08001051 break;
1052
1053 case Instruction::ADD_FLOAT_2ADDR:
1054 EmitInsn_FPArithm(ARGS, kFPArithm_Add, kFloat, true);
1055 break;
1056
1057 case Instruction::SUB_FLOAT_2ADDR:
1058 EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kFloat, true);
1059 break;
1060
1061 case Instruction::MUL_FLOAT_2ADDR:
1062 EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kFloat, true);
1063 break;
1064
1065 case Instruction::DIV_FLOAT_2ADDR:
1066 EmitInsn_FPArithm(ARGS, kFPArithm_Div, kFloat, true);
1067 break;
1068
1069 case Instruction::REM_FLOAT_2ADDR:
1070 EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kFloat, true);
1071 break;
1072
1073 case Instruction::ADD_DOUBLE_2ADDR:
1074 EmitInsn_FPArithm(ARGS, kFPArithm_Add, kDouble, true);
1075 break;
1076
1077 case Instruction::SUB_DOUBLE_2ADDR:
1078 EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kDouble, true);
1079 break;
1080
1081 case Instruction::MUL_DOUBLE_2ADDR:
1082 EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kDouble, true);
1083 break;
1084
1085 case Instruction::DIV_DOUBLE_2ADDR:
1086 EmitInsn_FPArithm(ARGS, kFPArithm_Div, kDouble, true);
1087 break;
1088
1089 case Instruction::REM_DOUBLE_2ADDR:
1090 EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kDouble, true);
1091 break;
1092
1093 case Instruction::ADD_INT_LIT16:
1094 case Instruction::ADD_INT_LIT8:
1095 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Add);
1096 break;
1097
1098 case Instruction::RSUB_INT:
1099 case Instruction::RSUB_INT_LIT8:
1100 EmitInsn_RSubImmediate(ARGS);
1101 break;
1102
1103 case Instruction::MUL_INT_LIT16:
1104 case Instruction::MUL_INT_LIT8:
1105 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Mul);
1106 break;
1107
1108 case Instruction::DIV_INT_LIT16:
1109 case Instruction::DIV_INT_LIT8:
1110 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Div);
1111 break;
1112
1113 case Instruction::REM_INT_LIT16:
1114 case Instruction::REM_INT_LIT8:
1115 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Rem);
1116 break;
1117
1118 case Instruction::AND_INT_LIT16:
1119 case Instruction::AND_INT_LIT8:
1120 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_And);
1121 break;
1122
1123 case Instruction::OR_INT_LIT16:
1124 case Instruction::OR_INT_LIT8:
1125 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Or);
1126 break;
1127
1128 case Instruction::XOR_INT_LIT16:
1129 case Instruction::XOR_INT_LIT8:
1130 EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Xor);
1131 break;
1132
1133 case Instruction::SHL_INT_LIT8:
Logan Chien5539ad02012-04-02 14:36:55 +08001134 EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shl);
Logan Chien70f94b42011-12-27 17:49:11 +08001135 break;
1136
1137 case Instruction::SHR_INT_LIT8:
Logan Chien5539ad02012-04-02 14:36:55 +08001138 EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shr);
Logan Chien70f94b42011-12-27 17:49:11 +08001139 break;
1140
1141 case Instruction::USHR_INT_LIT8:
Logan Chien5539ad02012-04-02 14:36:55 +08001142 EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_UShr);
Logan Chien70f94b42011-12-27 17:49:11 +08001143 break;
1144
Logan Chien9e5f5c12012-04-10 13:51:45 +08001145 case Instruction::THROW_VERIFICATION_ERROR:
1146 EmitInsn_ThrowVerificationError(ARGS);
1147 break;
1148
Logan Chien70f94b42011-12-27 17:49:11 +08001149 case Instruction::UNUSED_3E:
1150 case Instruction::UNUSED_3F:
1151 case Instruction::UNUSED_40:
1152 case Instruction::UNUSED_41:
1153 case Instruction::UNUSED_42:
1154 case Instruction::UNUSED_43:
1155 case Instruction::UNUSED_73:
1156 case Instruction::UNUSED_79:
1157 case Instruction::UNUSED_7A:
1158 case Instruction::UNUSED_E3:
1159 case Instruction::UNUSED_E4:
1160 case Instruction::UNUSED_E5:
1161 case Instruction::UNUSED_E6:
1162 case Instruction::UNUSED_E7:
1163 case Instruction::UNUSED_E8:
1164 case Instruction::UNUSED_E9:
1165 case Instruction::UNUSED_EA:
1166 case Instruction::UNUSED_EB:
1167 case Instruction::UNUSED_EC:
Logan Chien70f94b42011-12-27 17:49:11 +08001168 case Instruction::UNUSED_EE:
1169 case Instruction::UNUSED_EF:
1170 case Instruction::UNUSED_F0:
1171 case Instruction::UNUSED_F1:
1172 case Instruction::UNUSED_F2:
1173 case Instruction::UNUSED_F3:
1174 case Instruction::UNUSED_F4:
1175 case Instruction::UNUSED_F5:
1176 case Instruction::UNUSED_F6:
1177 case Instruction::UNUSED_F7:
1178 case Instruction::UNUSED_F8:
1179 case Instruction::UNUSED_F9:
1180 case Instruction::UNUSED_FA:
1181 case Instruction::UNUSED_FB:
1182 case Instruction::UNUSED_FC:
1183 case Instruction::UNUSED_FD:
1184 case Instruction::UNUSED_FE:
1185 case Instruction::UNUSED_FF:
1186 LOG(FATAL) << "Dex file contains UNUSED bytecode: " << insn->Opcode();
1187 break;
1188 }
1189
1190#undef ARGS
1191}
1192
1193
1194void MethodCompiler::EmitInsn_Nop(uint32_t dex_pc,
1195 Instruction const* insn) {
Logan Chiene09a6b72011-12-27 17:50:21 +08001196
1197 uint16_t insn_signature = code_item_->insns_[dex_pc];
1198
1199 if (insn_signature == Instruction::kPackedSwitchSignature ||
1200 insn_signature == Instruction::kSparseSwitchSignature ||
1201 insn_signature == Instruction::kArrayDataSignature) {
1202 irb_.CreateUnreachable();
Elliott Hughesb25c3f62012-03-26 16:35:06 -07001203 } else {
Logan Chiene09a6b72011-12-27 17:50:21 +08001204 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1205 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -08001206}
1207
1208
Logan Chien70f94b42011-12-27 17:49:11 +08001209void MethodCompiler::EmitInsn_Move(uint32_t dex_pc,
1210 Instruction const* insn,
1211 JType jty) {
Logan Chien48173132011-12-27 17:51:13 +08001212
Elliott Hughesadb8c672012-03-06 16:49:32 -08001213 DecodedInstruction dec_insn(insn);
Logan Chien48173132011-12-27 17:51:13 +08001214
Elliott Hughesadb8c672012-03-06 16:49:32 -08001215 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, jty, kReg);
1216 EmitStoreDalvikReg(dec_insn.vA, jty, kReg, src_value);
Logan Chien48173132011-12-27 17:51:13 +08001217
Logan Chien70f94b42011-12-27 17:49:11 +08001218 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1219}
1220
1221
1222void MethodCompiler::EmitInsn_MoveResult(uint32_t dex_pc,
1223 Instruction const* insn,
1224 JType jty) {
Logan Chien48173132011-12-27 17:51:13 +08001225
Elliott Hughesadb8c672012-03-06 16:49:32 -08001226 DecodedInstruction dec_insn(insn);
Logan Chien48173132011-12-27 17:51:13 +08001227
1228 llvm::Value* src_value = EmitLoadDalvikRetValReg(jty, kReg);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001229 EmitStoreDalvikReg(dec_insn.vA, jty, kReg, src_value);
Logan Chien48173132011-12-27 17:51:13 +08001230
Logan Chien70f94b42011-12-27 17:49:11 +08001231 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1232}
1233
1234
1235void MethodCompiler::EmitInsn_MoveException(uint32_t dex_pc,
1236 Instruction const* insn) {
Logan Chien3354cec2012-01-13 14:29:03 +08001237
Elliott Hughesadb8c672012-03-06 16:49:32 -08001238 DecodedInstruction dec_insn(insn);
Logan Chien3354cec2012-01-13 14:29:03 +08001239
1240 // Get thread-local exception field address
1241 llvm::Constant* exception_field_offset =
1242 irb_.getPtrEquivInt(Thread::ExceptionOffset().Int32Value());
1243
1244 llvm::Value* thread_object_addr =
1245 irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1246
1247 llvm::Value* exception_field_addr =
1248 irb_.CreatePtrDisp(thread_object_addr, exception_field_offset,
1249 irb_.getJObjectTy()->getPointerTo());
1250
1251 // Get exception object address
1252 llvm::Value* exception_object_addr = irb_.CreateLoad(exception_field_addr);
1253
1254 // Set thread-local exception field address to NULL
1255 irb_.CreateStore(irb_.getJNull(), exception_field_addr);
1256
1257 // Keep the exception object in the Dalvik register
Elliott Hughesadb8c672012-03-06 16:49:32 -08001258 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, exception_object_addr);
Logan Chien3354cec2012-01-13 14:29:03 +08001259
Logan Chien70f94b42011-12-27 17:49:11 +08001260 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1261}
1262
1263
1264void MethodCompiler::EmitInsn_ThrowException(uint32_t dex_pc,
1265 Instruction const* insn) {
Logan Chien6c6f12d2012-01-13 19:26:27 +08001266
Elliott Hughesadb8c672012-03-06 16:49:32 -08001267 DecodedInstruction dec_insn(insn);
Logan Chien6c6f12d2012-01-13 19:26:27 +08001268
1269 llvm::Value* exception_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001270 EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chien6c6f12d2012-01-13 19:26:27 +08001271
TDYa127c8dc1012012-04-19 07:03:33 -07001272 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001273
Logan Chien6c6f12d2012-01-13 19:26:27 +08001274 irb_.CreateCall(irb_.GetRuntime(ThrowException), exception_addr);
1275
1276 EmitBranchExceptionLandingPad(dex_pc);
Logan Chien70f94b42011-12-27 17:49:11 +08001277}
1278
1279
Logan Chien9e5f5c12012-04-10 13:51:45 +08001280void MethodCompiler::EmitInsn_ThrowVerificationError(uint32_t dex_pc,
1281 Instruction const* insn) {
1282
1283 DecodedInstruction dec_insn(insn);
1284
TDYa127c8dc1012012-04-19 07:03:33 -07001285 EmitUpdateDexPC(dex_pc);
Logan Chien9e5f5c12012-04-10 13:51:45 +08001286
1287 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1288 llvm::Value* kind_value = irb_.getInt32(dec_insn.vA);
1289 llvm::Value* ref_value = irb_.getInt32(dec_insn.vB);
1290
1291 irb_.CreateCall3(irb_.GetRuntime(ThrowVerificationError),
1292 method_object_addr, kind_value, ref_value);
1293
1294 EmitBranchExceptionLandingPad(dex_pc);
1295}
1296
1297
Logan Chien70f94b42011-12-27 17:49:11 +08001298void MethodCompiler::EmitInsn_ReturnVoid(uint32_t dex_pc,
1299 Instruction const* insn) {
Logan Chien8898a272011-12-27 17:51:56 +08001300 // Garbage collection safe-point
1301 EmitGuard_GarbageCollectionSuspend(dex_pc);
1302
Logan Chien8dfcbea2012-02-17 18:50:32 +08001303 // Pop the shadow frame
1304 EmitPopShadowFrame();
1305
Logan Chien8898a272011-12-27 17:51:56 +08001306 // Return!
1307 irb_.CreateRetVoid();
Logan Chien70f94b42011-12-27 17:49:11 +08001308}
1309
1310
1311void MethodCompiler::EmitInsn_Return(uint32_t dex_pc,
1312 Instruction const* insn) {
Logan Chien8898a272011-12-27 17:51:56 +08001313
Elliott Hughesadb8c672012-03-06 16:49:32 -08001314 DecodedInstruction dec_insn(insn);
Logan Chien8898a272011-12-27 17:51:56 +08001315
1316 // Garbage collection safe-point
1317 EmitGuard_GarbageCollectionSuspend(dex_pc);
1318
Logan Chien8dfcbea2012-02-17 18:50:32 +08001319 // Pop the shadow frame
1320 EmitPopShadowFrame();
1321 // NOTE: It is important to keep this AFTER the GC safe-point. Otherwise,
1322 // the return value might be collected since the shadow stack is popped.
1323
Logan Chien8898a272011-12-27 17:51:56 +08001324 // Return!
Logan Chiendd361c92012-04-10 23:40:37 +08001325 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
Elliott Hughesadb8c672012-03-06 16:49:32 -08001326 llvm::Value* retval = EmitLoadDalvikReg(dec_insn.vA, ret_shorty, kAccurate);
Logan Chien8898a272011-12-27 17:51:56 +08001327
1328 irb_.CreateRet(retval);
Logan Chien70f94b42011-12-27 17:49:11 +08001329}
1330
1331
1332void MethodCompiler::EmitInsn_LoadConstant(uint32_t dex_pc,
1333 Instruction const* insn,
1334 JType imm_jty) {
Shih-wei Liao798366e2012-02-16 09:25:33 -08001335
Elliott Hughesadb8c672012-03-06 16:49:32 -08001336 DecodedInstruction dec_insn(insn);
Shih-wei Liao798366e2012-02-16 09:25:33 -08001337
1338 DCHECK(imm_jty == kInt || imm_jty == kLong) << imm_jty;
1339
1340 int64_t imm = 0;
1341
1342 switch (insn->Opcode()) {
1343 // 32-bit Immediate
1344 case Instruction::CONST_4:
1345 case Instruction::CONST_16:
1346 case Instruction::CONST:
1347 case Instruction::CONST_WIDE_16:
1348 case Instruction::CONST_WIDE_32:
Elliott Hughesadb8c672012-03-06 16:49:32 -08001349 imm = static_cast<int64_t>(static_cast<int32_t>(dec_insn.vB));
Shih-wei Liao798366e2012-02-16 09:25:33 -08001350 break;
1351
1352 case Instruction::CONST_HIGH16:
1353 imm = static_cast<int64_t>(static_cast<int32_t>(
Elliott Hughesadb8c672012-03-06 16:49:32 -08001354 static_cast<uint32_t>(static_cast<uint16_t>(dec_insn.vB)) << 16));
Shih-wei Liao798366e2012-02-16 09:25:33 -08001355 break;
1356
1357 // 64-bit Immediate
1358 case Instruction::CONST_WIDE:
Elliott Hughesadb8c672012-03-06 16:49:32 -08001359 imm = static_cast<int64_t>(dec_insn.vB_wide);
Shih-wei Liao798366e2012-02-16 09:25:33 -08001360 break;
1361
1362 case Instruction::CONST_WIDE_HIGH16:
1363 imm = static_cast<int64_t>(
Elliott Hughesadb8c672012-03-06 16:49:32 -08001364 static_cast<uint64_t>(static_cast<uint16_t>(dec_insn.vB)) << 48);
Shih-wei Liao798366e2012-02-16 09:25:33 -08001365 break;
1366
1367 // Unknown opcode for load constant (unreachable)
1368 default:
1369 LOG(FATAL) << "Unknown opcode for load constant: " << insn->Opcode();
1370 break;
1371 }
1372
1373 // Store the non-object register
1374 llvm::Type* imm_type = irb_.getJType(imm_jty, kAccurate);
1375 llvm::Constant* imm_value = llvm::ConstantInt::getSigned(imm_type, imm);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001376 EmitStoreDalvikReg(dec_insn.vA, imm_jty, kAccurate, imm_value);
Shih-wei Liao798366e2012-02-16 09:25:33 -08001377
1378 // Store the object register if it is possible to be null.
1379 if (imm_jty == kInt && imm == 0) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08001380 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, irb_.getJNull());
Shih-wei Liao798366e2012-02-16 09:25:33 -08001381 }
1382
Logan Chien70f94b42011-12-27 17:49:11 +08001383 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1384}
1385
1386
1387void MethodCompiler::EmitInsn_LoadConstantString(uint32_t dex_pc,
1388 Instruction const* insn) {
Logan Chienc3b4ba12012-01-16 19:52:53 +08001389
Elliott Hughesadb8c672012-03-06 16:49:32 -08001390 DecodedInstruction dec_insn(insn);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001391
Elliott Hughesadb8c672012-03-06 16:49:32 -08001392 uint32_t string_idx = dec_insn.vB;
Logan Chienc3b4ba12012-01-16 19:52:53 +08001393
1394 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1395
1396 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr);
1397
1398 if (!compiler_->CanAssumeStringIsPresentInDexCache(dex_cache_, string_idx)) {
1399 llvm::BasicBlock* block_str_exist =
1400 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1401
1402 llvm::BasicBlock* block_str_resolve =
1403 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1404
1405 // Test: Is the string resolved and in the dex cache?
1406 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1407
TDYa127a849cb62012-04-01 05:59:34 -07001408 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001409
1410 // String is resolved, go to next basic block.
1411 irb_.SetInsertPoint(block_str_exist);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001412 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, string_addr);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001413 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1414
1415 // String is not resolved yet, resolve it now.
1416 irb_.SetInsertPoint(block_str_resolve);
1417
1418 llvm::Function* runtime_func = irb_.GetRuntime(ResolveString);
1419
1420 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1421
1422 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1423
TDYa127c8dc1012012-04-19 07:03:33 -07001424 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001425
1426 string_addr = irb_.CreateCall2(runtime_func, method_object_addr,
1427 string_idx_value);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001428
1429 EmitGuard_ExceptionLandingPad(dex_pc);
1430 }
1431
1432 // Store the string object to the Dalvik register
Elliott Hughesadb8c672012-03-06 16:49:32 -08001433 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, string_addr);
Logan Chienc3b4ba12012-01-16 19:52:53 +08001434
Logan Chien70f94b42011-12-27 17:49:11 +08001435 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1436}
1437
1438
Logan Chien27b30252012-01-14 03:43:35 +08001439llvm::Value* MethodCompiler::EmitLoadConstantClass(uint32_t dex_pc,
1440 uint32_t type_idx) {
1441 if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
1442 *dex_file_, type_idx)) {
1443 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1444
1445 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1446
TDYa127706e9b62012-04-19 12:24:26 -07001447 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1448
Logan Chien27b30252012-01-14 03:43:35 +08001449 llvm::Function* runtime_func =
1450 irb_.GetRuntime(InitializeTypeAndVerifyAccess);
1451
TDYa127c8dc1012012-04-19 07:03:33 -07001452 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001453
Logan Chien27b30252012-01-14 03:43:35 +08001454 llvm::Value* type_object_addr =
TDYa127706e9b62012-04-19 12:24:26 -07001455 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
Logan Chien27b30252012-01-14 03:43:35 +08001456
1457 EmitGuard_ExceptionLandingPad(dex_pc);
1458
1459 return type_object_addr;
1460
1461 } else {
1462 // Try to load the class (type) object from the test cache.
1463 llvm::Value* type_field_addr =
1464 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1465
1466 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr);
1467
1468 if (compiler_->CanAssumeTypeIsPresentInDexCache(dex_cache_, type_idx)) {
1469 return type_object_addr;
1470 }
1471
1472 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1473
1474 // Test whether class (type) object is in the dex cache or not
1475 llvm::Value* equal_null =
1476 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1477
1478 llvm::BasicBlock* block_cont =
1479 CreateBasicBlockWithDexPC(dex_pc, "cont");
1480
1481 llvm::BasicBlock* block_load_class =
1482 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1483
1484 irb_.CreateCondBr(equal_null, block_load_class, block_cont);
1485
1486 // Failback routine to load the class object
1487 irb_.SetInsertPoint(block_load_class);
1488
1489 llvm::Function* runtime_func = irb_.GetRuntime(InitializeType);
1490
1491 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1492
1493 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1494
TDYa127706e9b62012-04-19 12:24:26 -07001495 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1496
TDYa127c8dc1012012-04-19 07:03:33 -07001497 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001498
Logan Chien27b30252012-01-14 03:43:35 +08001499 llvm::Value* loaded_type_object_addr =
TDYa127706e9b62012-04-19 12:24:26 -07001500 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
Logan Chien27b30252012-01-14 03:43:35 +08001501
1502 EmitGuard_ExceptionLandingPad(dex_pc);
1503
1504 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1505
1506 irb_.CreateBr(block_cont);
1507
1508 // Now the class object must be loaded
1509 irb_.SetInsertPoint(block_cont);
1510
1511 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1512
1513 phi->addIncoming(type_object_addr, block_original);
1514 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1515
1516 return phi;
1517 }
1518}
1519
1520
Logan Chien70f94b42011-12-27 17:49:11 +08001521void MethodCompiler::EmitInsn_LoadConstantClass(uint32_t dex_pc,
1522 Instruction const* insn) {
Logan Chien27b30252012-01-14 03:43:35 +08001523
Elliott Hughesadb8c672012-03-06 16:49:32 -08001524 DecodedInstruction dec_insn(insn);
Logan Chien27b30252012-01-14 03:43:35 +08001525
Elliott Hughesadb8c672012-03-06 16:49:32 -08001526 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB);
1527 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, type_object_addr);
Logan Chien27b30252012-01-14 03:43:35 +08001528
Logan Chien70f94b42011-12-27 17:49:11 +08001529 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1530}
1531
1532
1533void MethodCompiler::EmitInsn_MonitorEnter(uint32_t dex_pc,
1534 Instruction const* insn) {
Logan Chien9e0dbe42012-01-13 12:11:37 +08001535
Elliott Hughesadb8c672012-03-06 16:49:32 -08001536 DecodedInstruction dec_insn(insn);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001537
1538 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001539 EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001540
1541 // TODO: Slow path always. May not need NullPointerException check.
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(LockObject), 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_MonitorExit(uint32_t dex_pc,
1556 Instruction const* insn) {
Logan Chien9e0dbe42012-01-13 12:11:37 +08001557
Elliott Hughesadb8c672012-03-06 16:49:32 -08001558 DecodedInstruction dec_insn(insn);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001559
1560 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001561 EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001562
1563 EmitGuard_NullPointerException(dex_pc, object_addr);
1564
TDYa127c8dc1012012-04-19 07:03:33 -07001565 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001566
TDYa127706e9b62012-04-19 12:24:26 -07001567 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1568
1569 irb_.CreateCall2(irb_.GetRuntime(UnlockObject), object_addr, thread_object_addr);
Logan Chien9e0dbe42012-01-13 12:11:37 +08001570 EmitGuard_ExceptionLandingPad(dex_pc);
1571
Logan Chien70f94b42011-12-27 17:49:11 +08001572 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1573}
1574
1575
1576void MethodCompiler::EmitInsn_CheckCast(uint32_t dex_pc,
1577 Instruction const* insn) {
Logan Chienfc880952012-01-15 23:53:10 +08001578
Elliott Hughesadb8c672012-03-06 16:49:32 -08001579 DecodedInstruction dec_insn(insn);
Logan Chienfc880952012-01-15 23:53:10 +08001580
1581 llvm::BasicBlock* block_test_class =
1582 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1583
1584 llvm::BasicBlock* block_test_sub_class =
1585 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1586
1587 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001588 EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chienfc880952012-01-15 23:53:10 +08001589
1590 // Test: Is the reference equal to null? Act as no-op when it is null.
1591 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1592
1593 irb_.CreateCondBr(equal_null,
1594 GetNextBasicBlock(dex_pc),
1595 block_test_class);
1596
1597 // Test: Is the object instantiated from the given class?
1598 irb_.SetInsertPoint(block_test_class);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001599 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB);
Logan Chienfc880952012-01-15 23:53:10 +08001600 DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
1601
1602 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1603
1604 llvm::Value* object_type_field_addr =
1605 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1606
1607 llvm::Value* object_type_object_addr =
1608 irb_.CreateLoad(object_type_field_addr);
1609
1610 llvm::Value* equal_class =
1611 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1612
1613 irb_.CreateCondBr(equal_class,
1614 GetNextBasicBlock(dex_pc),
1615 block_test_sub_class);
1616
1617 // Test: Is the object instantiated from the subclass of the given class?
1618 irb_.SetInsertPoint(block_test_sub_class);
1619
TDYa127c8dc1012012-04-19 07:03:33 -07001620 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001621
Logan Chienfc880952012-01-15 23:53:10 +08001622 irb_.CreateCall2(irb_.GetRuntime(CheckCast),
1623 type_object_addr, object_type_object_addr);
1624
1625 EmitGuard_ExceptionLandingPad(dex_pc);
1626
Logan Chien70f94b42011-12-27 17:49:11 +08001627 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1628}
1629
1630
1631void MethodCompiler::EmitInsn_InstanceOf(uint32_t dex_pc,
1632 Instruction const* insn) {
Logan Chien68725e22012-01-15 22:25:34 +08001633
Elliott Hughesadb8c672012-03-06 16:49:32 -08001634 DecodedInstruction dec_insn(insn);
Logan Chien68725e22012-01-15 22:25:34 +08001635
1636 llvm::Constant* zero = irb_.getJInt(0);
1637 llvm::Constant* one = irb_.getJInt(1);
1638
1639 llvm::BasicBlock* block_nullp = CreateBasicBlockWithDexPC(dex_pc, "nullp");
1640
1641 llvm::BasicBlock* block_test_class =
1642 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1643
1644 llvm::BasicBlock* block_class_equals =
1645 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
1646
1647 llvm::BasicBlock* block_test_sub_class =
1648 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1649
1650 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001651 EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
Logan Chien68725e22012-01-15 22:25:34 +08001652
1653 // Overview of the following code :
1654 // We check for null, if so, then false, otherwise check for class == . If so
1655 // then true, otherwise do callout slowpath.
1656 //
1657 // Test: Is the reference equal to null? Set 0 when it is null.
1658 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1659
1660 irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
1661
1662 irb_.SetInsertPoint(block_nullp);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001663 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, zero);
Logan Chien68725e22012-01-15 22:25:34 +08001664 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1665
1666 // Test: Is the object instantiated from the given class?
1667 irb_.SetInsertPoint(block_test_class);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001668 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vC);
Logan Chien68725e22012-01-15 22:25:34 +08001669 DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
1670
1671 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1672
1673 llvm::Value* object_type_field_addr =
1674 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1675
1676 llvm::Value* object_type_object_addr =
1677 irb_.CreateLoad(object_type_field_addr);
1678
1679 llvm::Value* equal_class =
1680 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1681
1682 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
1683
1684 irb_.SetInsertPoint(block_class_equals);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001685 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, one);
Logan Chien68725e22012-01-15 22:25:34 +08001686 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1687
1688 // Test: Is the object instantiated from the subclass of the given class?
1689 irb_.SetInsertPoint(block_test_sub_class);
1690
1691 llvm::Value* result =
1692 irb_.CreateCall2(irb_.GetRuntime(IsAssignable),
1693 type_object_addr, object_type_object_addr);
1694
Elliott Hughesadb8c672012-03-06 16:49:32 -08001695 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
Logan Chien68725e22012-01-15 22:25:34 +08001696
Logan Chien70f94b42011-12-27 17:49:11 +08001697 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1698}
1699
1700
Logan Chien61bb6142012-02-03 15:34:53 +08001701llvm::Value* MethodCompiler::EmitLoadArrayLength(llvm::Value* array) {
1702 // Load array length field address
1703 llvm::Constant* array_len_field_offset =
1704 irb_.getPtrEquivInt(Array::LengthOffset().Int32Value());
1705
1706 llvm::Value* array_len_field_addr =
1707 irb_.CreatePtrDisp(array, array_len_field_offset,
1708 irb_.getJIntTy()->getPointerTo());
1709
1710 // Load array length
1711 return irb_.CreateLoad(array_len_field_addr);
1712}
1713
1714
Logan Chien70f94b42011-12-27 17:49:11 +08001715void MethodCompiler::EmitInsn_ArrayLength(uint32_t dex_pc,
1716 Instruction const* insn) {
Logan Chien61bb6142012-02-03 15:34:53 +08001717
Elliott Hughesadb8c672012-03-06 16:49:32 -08001718 DecodedInstruction dec_insn(insn);
Logan Chien61bb6142012-02-03 15:34:53 +08001719
1720 // Get the array object address
Elliott Hughesadb8c672012-03-06 16:49:32 -08001721 llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
Logan Chien61bb6142012-02-03 15:34:53 +08001722 EmitGuard_NullPointerException(dex_pc, array_addr);
1723
1724 // Get the array length and store it to the register
1725 llvm::Value* array_len = EmitLoadArrayLength(array_addr);
Elliott Hughesadb8c672012-03-06 16:49:32 -08001726 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, array_len);
Logan Chien61bb6142012-02-03 15:34:53 +08001727
Logan Chien70f94b42011-12-27 17:49:11 +08001728 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1729}
1730
1731
1732void MethodCompiler::EmitInsn_NewInstance(uint32_t dex_pc,
1733 Instruction const* insn) {
Logan Chien032bdad2012-01-16 09:59:23 +08001734
Elliott Hughesadb8c672012-03-06 16:49:32 -08001735 DecodedInstruction dec_insn(insn);
Logan Chien032bdad2012-01-16 09:59:23 +08001736
1737 llvm::Function* runtime_func;
Logan Chien1a032b12012-04-11 11:43:04 +08001738 if (compiler_->CanAccessInstantiableTypeWithoutChecks(
1739 method_idx_, dex_cache_, *dex_file_, dec_insn.vB)) {
Logan Chien032bdad2012-01-16 09:59:23 +08001740 runtime_func = irb_.GetRuntime(AllocObject);
1741 } else {
1742 runtime_func = irb_.GetRuntime(AllocObjectWithAccessCheck);
1743 }
1744
Elliott Hughesadb8c672012-03-06 16:49:32 -08001745 llvm::Constant* type_index_value = irb_.getInt32(dec_insn.vB);
Logan Chien032bdad2012-01-16 09:59:23 +08001746
1747 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1748
TDYa127da83d972012-04-18 00:21:49 -07001749 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1750
TDYa127c8dc1012012-04-19 07:03:33 -07001751 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001752
Logan Chien032bdad2012-01-16 09:59:23 +08001753 llvm::Value* object_addr =
TDYa127da83d972012-04-18 00:21:49 -07001754 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
Logan Chien032bdad2012-01-16 09:59:23 +08001755
1756 EmitGuard_ExceptionLandingPad(dex_pc);
1757
Elliott Hughesadb8c672012-03-06 16:49:32 -08001758 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, object_addr);
Logan Chien032bdad2012-01-16 09:59:23 +08001759
Logan Chien70f94b42011-12-27 17:49:11 +08001760 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1761}
1762
1763
Logan Chiena2cc6a32012-01-16 10:38:41 +08001764llvm::Value* MethodCompiler::EmitAllocNewArray(uint32_t dex_pc,
1765 int32_t length,
1766 uint32_t type_idx,
1767 bool is_filled_new_array) {
1768 llvm::Function* runtime_func;
1769
1770 bool skip_access_check =
1771 compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
1772 *dex_file_, type_idx);
1773
TDYa127a849cb62012-04-01 05:59:34 -07001774 llvm::Value* array_length_value;
1775
Logan Chiena2cc6a32012-01-16 10:38:41 +08001776 if (is_filled_new_array) {
1777 runtime_func = skip_access_check ?
1778 irb_.GetRuntime(CheckAndAllocArray) :
1779 irb_.GetRuntime(CheckAndAllocArrayWithAccessCheck);
TDYa127a849cb62012-04-01 05:59:34 -07001780 array_length_value = irb_.getInt32(length);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001781 } else {
1782 runtime_func = skip_access_check ?
1783 irb_.GetRuntime(AllocArray) :
1784 irb_.GetRuntime(AllocArrayWithAccessCheck);
TDYa127a849cb62012-04-01 05:59:34 -07001785 array_length_value = EmitLoadDalvikReg(length, kInt, kAccurate);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001786 }
1787
1788 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
1789
1790 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1791
TDYa127da83d972012-04-18 00:21:49 -07001792 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
1793
TDYa127c8dc1012012-04-19 07:03:33 -07001794 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08001795
Logan Chiena2cc6a32012-01-16 10:38:41 +08001796 llvm::Value* object_addr =
TDYa127da83d972012-04-18 00:21:49 -07001797 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
1798 array_length_value, thread_object_addr);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001799
1800 EmitGuard_ExceptionLandingPad(dex_pc);
1801
1802 return object_addr;
1803}
1804
1805
Logan Chien70f94b42011-12-27 17:49:11 +08001806void MethodCompiler::EmitInsn_NewArray(uint32_t dex_pc,
1807 Instruction const* insn) {
Logan Chiena2cc6a32012-01-16 10:38:41 +08001808
Elliott Hughesadb8c672012-03-06 16:49:32 -08001809 DecodedInstruction dec_insn(insn);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001810
1811 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001812 EmitAllocNewArray(dex_pc, dec_insn.vB, dec_insn.vC, false);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001813
Elliott Hughesadb8c672012-03-06 16:49:32 -08001814 EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, object_addr);
Logan Chiena2cc6a32012-01-16 10:38:41 +08001815
Logan Chien70f94b42011-12-27 17:49:11 +08001816 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1817}
1818
1819
1820void MethodCompiler::EmitInsn_FilledNewArray(uint32_t dex_pc,
1821 Instruction const* insn,
1822 bool is_range) {
Logan Chiena85fb2f2012-01-16 12:52:56 +08001823
Elliott Hughesadb8c672012-03-06 16:49:32 -08001824 DecodedInstruction dec_insn(insn);
Logan Chiena85fb2f2012-01-16 12:52:56 +08001825
1826 llvm::Value* object_addr =
Elliott Hughesadb8c672012-03-06 16:49:32 -08001827 EmitAllocNewArray(dex_pc, dec_insn.vA, dec_insn.vB, true);
Logan Chiena85fb2f2012-01-16 12:52:56 +08001828
Elliott Hughesadb8c672012-03-06 16:49:32 -08001829 if (dec_insn.vA > 0) {
Logan Chiendd361c92012-04-10 23:40:37 +08001830 // Resolve the element type
TDYa127183cf262012-04-11 07:53:21 -07001831 Class* klass = dex_cache_->GetResolvedType(dec_insn.vB)->GetComponentType();
Logan Chiendd361c92012-04-10 23:40:37 +08001832 // TODO: Avoid the usage of the dex_cache_. Try to figure out a better
1833 // way to distinguish [I and [L.
Logan Chiena85fb2f2012-01-16 12:52:56 +08001834 CHECK_NE(klass, static_cast<Class*>(NULL));
Logan Chiena85fb2f2012-01-16 12:52:56 +08001835
Logan Chiendd361c92012-04-10 23:40:37 +08001836 uint32_t alignment;
1837 llvm::Constant* elem_size;
1838 llvm::PointerType* field_type;
Logan Chiena85fb2f2012-01-16 12:52:56 +08001839
Logan Chiendd361c92012-04-10 23:40:37 +08001840 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
1841 // as the element, thus we are only checking 2 cases: primitive int and
1842 // non-primitive type.
Logan Chiena85fb2f2012-01-16 12:52:56 +08001843 if (klass->IsPrimitiveInt()) {
Logan Chiendd361c92012-04-10 23:40:37 +08001844 alignment = sizeof(int32_t);
1845 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
Logan Chiena85fb2f2012-01-16 12:52:56 +08001846 field_type = irb_.getJIntTy()->getPointerTo();
1847 } else {
1848 CHECK(!klass->IsPrimitive());
Logan Chiendd361c92012-04-10 23:40:37 +08001849 alignment = irb_.getSizeOfPtrEquivInt();
1850 elem_size = irb_.getSizeOfPtrEquivIntValue();
Logan Chiena85fb2f2012-01-16 12:52:56 +08001851 field_type = irb_.getJObjectTy()->getPointerTo();
1852 }
1853
Logan Chiendd361c92012-04-10 23:40:37 +08001854 llvm::Value* data_field_offset =
1855 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
1856
1857 llvm::Value* data_field_addr =
1858 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
1859
Logan Chiena85fb2f2012-01-16 12:52:56 +08001860 // TODO: Tune this code. Currently we are generating one instruction for
1861 // one element which may be very space consuming. Maybe changing to use
1862 // memcpy may help; however, since we can't guarantee that the alloca of
1863 // dalvik register are continuous, we can't perform such optimization yet.
Elliott Hughesadb8c672012-03-06 16:49:32 -08001864 for (uint32_t i = 0; i < dec_insn.vA; ++i) {
Logan Chiena85fb2f2012-01-16 12:52:56 +08001865 int reg_index;
1866 if (is_range) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08001867 reg_index = dec_insn.vC + i;
Logan Chiena85fb2f2012-01-16 12:52:56 +08001868 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08001869 reg_index = dec_insn.arg[i];
Logan Chiena85fb2f2012-01-16 12:52:56 +08001870 }
1871
1872 llvm::Value* reg_value;
1873 if (klass->IsPrimitiveInt()) {
1874 reg_value = EmitLoadDalvikReg(reg_index, kInt, kAccurate);
1875 } else {
1876 reg_value = EmitLoadDalvikReg(reg_index, kObject, kAccurate);
1877 }
1878
1879 irb_.CreateStore(reg_value, data_field_addr);
1880
Logan Chiendd361c92012-04-10 23:40:37 +08001881 data_field_addr =
1882 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
Logan Chiena85fb2f2012-01-16 12:52:56 +08001883 }
1884 }
1885
1886 EmitStoreDalvikRetValReg(kObject, kAccurate, object_addr);
1887
Logan Chien70f94b42011-12-27 17:49:11 +08001888 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1889}
1890
1891
1892void MethodCompiler::EmitInsn_FillArrayData(uint32_t dex_pc,
1893 Instruction const* insn) {
Logan Chiene58b6582012-01-16 17:13:13 +08001894
Elliott Hughesadb8c672012-03-06 16:49:32 -08001895 DecodedInstruction dec_insn(insn);
Logan Chiene58b6582012-01-16 17:13:13 +08001896
1897 // Read the payload
1898 struct PACKED Payload {
1899 uint16_t ident_;
1900 uint16_t elem_width_;
1901 uint32_t num_elems_;
1902 uint8_t data_[];
1903 };
1904
1905 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
Elliott Hughesadb8c672012-03-06 16:49:32 -08001906 static_cast<int32_t>(dec_insn.vB);
Logan Chiene58b6582012-01-16 17:13:13 +08001907
1908 Payload const* payload =
1909 reinterpret_cast<Payload const*>(code_item_->insns_ + payload_offset);
1910
1911 uint32_t size_in_bytes = payload->elem_width_ * payload->num_elems_;
1912
1913 // Load and check the array
Elliott Hughesadb8c672012-03-06 16:49:32 -08001914 llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chiene58b6582012-01-16 17:13:13 +08001915
1916 EmitGuard_NullPointerException(dex_pc, array_addr);
1917
1918 if (payload->num_elems_ > 0) {
1919 // Test: Is array length big enough?
1920 llvm::Constant* last_index = irb_.getJInt(payload->num_elems_ - 1);
1921
1922 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, last_index);
1923
1924 // Get array data field
1925 llvm::Value* data_field_offset_value =
TDYa127b77799d2012-04-06 22:16:31 -07001926 irb_.getPtrEquivInt(Array::DataOffset(payload->elem_width_).Int32Value());
Logan Chiene58b6582012-01-16 17:13:13 +08001927
1928 llvm::Value* data_field_addr =
1929 irb_.CreatePtrDisp(array_addr, data_field_offset_value,
1930 irb_.getInt8Ty()->getPointerTo());
1931
1932 // Emit payload to bitcode constant pool
1933 std::vector<llvm::Constant*> const_pool_data;
1934 for (uint32_t i = 0; i < size_in_bytes; ++i) {
1935 const_pool_data.push_back(irb_.getInt8(payload->data_[i]));
1936 }
1937
1938 llvm::Constant* const_pool_data_array_value = llvm::ConstantArray::get(
1939 llvm::ArrayType::get(irb_.getInt8Ty(), size_in_bytes), const_pool_data);
1940
1941 llvm::Value* const_pool_data_array_addr =
1942 new llvm::GlobalVariable(*module_,
1943 const_pool_data_array_value->getType(),
1944 false, llvm::GlobalVariable::InternalLinkage,
1945 const_pool_data_array_value,
1946 "array_data_payload");
1947
1948 // Find the memcpy intrinsic
1949 llvm::Type* memcpy_arg_types[] = {
1950 llvm::Type::getInt8Ty(*context_)->getPointerTo(),
1951 llvm::Type::getInt8Ty(*context_)->getPointerTo(),
1952 llvm::Type::getInt32Ty(*context_)
1953 };
1954
1955 llvm::Function* memcpy_intrinsic =
1956 llvm::Intrinsic::getDeclaration(module_,
1957 llvm::Intrinsic::memcpy,
1958 memcpy_arg_types);
1959
1960 // Copy now!
1961 llvm::Value *args[] = {
1962 data_field_addr,
1963 irb_.CreateConstGEP2_32(const_pool_data_array_addr, 0, 0),
1964 irb_.getInt32(size_in_bytes),
1965 irb_.getInt32(0), // alignment: no guarantee
1966 irb_.getFalse() // is_volatile: false
1967 };
1968
1969 irb_.CreateCall(memcpy_intrinsic, args);
1970 }
1971
Logan Chien70f94b42011-12-27 17:49:11 +08001972 irb_.CreateBr(GetNextBasicBlock(dex_pc));
1973}
1974
1975
1976void MethodCompiler::EmitInsn_UnconditionalBranch(uint32_t dex_pc,
1977 Instruction const* insn) {
Logan Chiena466c162011-12-27 17:55:46 +08001978
Elliott Hughesadb8c672012-03-06 16:49:32 -08001979 DecodedInstruction dec_insn(insn);
Logan Chiena466c162011-12-27 17:55:46 +08001980
Elliott Hughesadb8c672012-03-06 16:49:32 -08001981 int32_t branch_offset = dec_insn.vA;
Logan Chiena466c162011-12-27 17:55:46 +08001982
1983 if (branch_offset <= 0) {
1984 // Garbage collection safe-point on backward branch
1985 EmitGuard_GarbageCollectionSuspend(dex_pc);
1986 }
1987
1988 irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
Logan Chien70f94b42011-12-27 17:49:11 +08001989}
1990
1991
1992void MethodCompiler::EmitInsn_PackedSwitch(uint32_t dex_pc,
1993 Instruction const* insn) {
Logan Chien7a89b6d2011-12-27 17:56:56 +08001994
Elliott Hughesadb8c672012-03-06 16:49:32 -08001995 DecodedInstruction dec_insn(insn);
Logan Chien7a89b6d2011-12-27 17:56:56 +08001996
1997 struct PACKED Payload {
1998 uint16_t ident_;
1999 uint16_t num_cases_;
2000 int32_t first_key_;
2001 int32_t targets_[];
2002 };
2003
2004 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
Elliott Hughesadb8c672012-03-06 16:49:32 -08002005 static_cast<int32_t>(dec_insn.vB);
Logan Chien7a89b6d2011-12-27 17:56:56 +08002006
2007 Payload const* payload =
2008 reinterpret_cast<Payload const*>(code_item_->insns_ + payload_offset);
2009
Elliott Hughesadb8c672012-03-06 16:49:32 -08002010 llvm::Value* value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chien7a89b6d2011-12-27 17:56:56 +08002011
2012 llvm::SwitchInst* sw =
2013 irb_.CreateSwitch(value, GetNextBasicBlock(dex_pc), payload->num_cases_);
2014
2015 for (uint16_t i = 0; i < payload->num_cases_; ++i) {
2016 sw->addCase(irb_.getInt32(payload->first_key_ + i),
2017 GetBasicBlock(dex_pc + payload->targets_[i]));
2018 }
Logan Chien70f94b42011-12-27 17:49:11 +08002019}
2020
2021
2022void MethodCompiler::EmitInsn_SparseSwitch(uint32_t dex_pc,
2023 Instruction const* insn) {
Logan Chien7a89b6d2011-12-27 17:56:56 +08002024
Elliott Hughesadb8c672012-03-06 16:49:32 -08002025 DecodedInstruction dec_insn(insn);
Logan Chien7a89b6d2011-12-27 17:56:56 +08002026
2027 struct PACKED Payload {
2028 uint16_t ident_;
2029 uint16_t num_cases_;
2030 int32_t keys_and_targets_[];
2031 };
2032
2033 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
Elliott Hughesadb8c672012-03-06 16:49:32 -08002034 static_cast<int32_t>(dec_insn.vB);
Logan Chien7a89b6d2011-12-27 17:56:56 +08002035
2036 Payload const* payload =
2037 reinterpret_cast<Payload const*>(code_item_->insns_ + payload_offset);
2038
2039 int32_t const* keys = payload->keys_and_targets_;
2040 int32_t const* targets = payload->keys_and_targets_ + payload->num_cases_;
2041
Elliott Hughesadb8c672012-03-06 16:49:32 -08002042 llvm::Value* value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chien7a89b6d2011-12-27 17:56:56 +08002043
2044 llvm::SwitchInst* sw =
2045 irb_.CreateSwitch(value, GetNextBasicBlock(dex_pc), payload->num_cases_);
2046
2047 for (size_t i = 0; i < payload->num_cases_; ++i) {
2048 sw->addCase(irb_.getInt32(keys[i]), GetBasicBlock(dex_pc + targets[i]));
2049 }
Logan Chien70f94b42011-12-27 17:49:11 +08002050}
2051
2052
2053void MethodCompiler::EmitInsn_FPCompare(uint32_t dex_pc,
2054 Instruction const* insn,
2055 JType fp_jty,
2056 bool gt_bias) {
Logan Chien2c37e8e2011-12-27 17:58:46 +08002057
Elliott Hughesadb8c672012-03-06 16:49:32 -08002058 DecodedInstruction dec_insn(insn);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002059
2060 DCHECK(fp_jty == kFloat || fp_jty == kDouble) << "JType: " << fp_jty;
2061
Elliott Hughesadb8c672012-03-06 16:49:32 -08002062 llvm::Value* src1_value = EmitLoadDalvikReg(dec_insn.vB, fp_jty, kAccurate);
2063 llvm::Value* src2_value = EmitLoadDalvikReg(dec_insn.vC, fp_jty, kAccurate);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002064
2065 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
2066 llvm::Value* cmp_lt;
2067
2068 if (gt_bias) {
2069 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
2070 } else {
2071 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
2072 }
2073
2074 llvm::Value* result = EmitCompareResultSelection(cmp_eq, cmp_lt);
Elliott Hughesadb8c672012-03-06 16:49:32 -08002075 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002076
Logan Chien70f94b42011-12-27 17:49:11 +08002077 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2078}
2079
2080
2081void MethodCompiler::EmitInsn_LongCompare(uint32_t dex_pc,
2082 Instruction const* insn) {
Logan Chien2c37e8e2011-12-27 17:58:46 +08002083
Elliott Hughesadb8c672012-03-06 16:49:32 -08002084 DecodedInstruction dec_insn(insn);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002085
Elliott Hughesadb8c672012-03-06 16:49:32 -08002086 llvm::Value* src1_value = EmitLoadDalvikReg(dec_insn.vB, kLong, kAccurate);
2087 llvm::Value* src2_value = EmitLoadDalvikReg(dec_insn.vC, kLong, kAccurate);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002088
2089 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
2090 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
2091
2092 llvm::Value* result = EmitCompareResultSelection(cmp_eq, cmp_lt);
Elliott Hughesadb8c672012-03-06 16:49:32 -08002093 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
Logan Chien2c37e8e2011-12-27 17:58:46 +08002094
Logan Chien70f94b42011-12-27 17:49:11 +08002095 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2096}
2097
2098
Logan Chien2c37e8e2011-12-27 17:58:46 +08002099llvm::Value* MethodCompiler::EmitCompareResultSelection(llvm::Value* cmp_eq,
2100 llvm::Value* cmp_lt) {
2101
2102 llvm::Constant* zero = irb_.getJInt(0);
2103 llvm::Constant* pos1 = irb_.getJInt(1);
2104 llvm::Constant* neg1 = irb_.getJInt(-1);
2105
2106 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
2107 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
2108
2109 return result_eq;
2110}
2111
2112
Logan Chien70f94b42011-12-27 17:49:11 +08002113void MethodCompiler::EmitInsn_BinaryConditionalBranch(uint32_t dex_pc,
2114 Instruction const* insn,
2115 CondBranchKind cond) {
Logan Chiena78e3c82011-12-27 17:59:35 +08002116
Elliott Hughesadb8c672012-03-06 16:49:32 -08002117 DecodedInstruction dec_insn(insn);
Logan Chiena78e3c82011-12-27 17:59:35 +08002118
Elliott Hughesadb8c672012-03-06 16:49:32 -08002119 int8_t src1_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vA);
2120 int8_t src2_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vB);
Logan Chiena78e3c82011-12-27 17:59:35 +08002121
2122 DCHECK_NE(kRegUnknown, src1_reg_cat);
2123 DCHECK_NE(kRegUnknown, src2_reg_cat);
2124 DCHECK_NE(kRegCat2, src1_reg_cat);
2125 DCHECK_NE(kRegCat2, src2_reg_cat);
2126
Elliott Hughesadb8c672012-03-06 16:49:32 -08002127 int32_t branch_offset = dec_insn.vC;
Logan Chiena78e3c82011-12-27 17:59:35 +08002128
2129 if (branch_offset <= 0) {
2130 // Garbage collection safe-point on backward branch
2131 EmitGuard_GarbageCollectionSuspend(dex_pc);
2132 }
2133
2134 if (src1_reg_cat == kRegZero && src2_reg_cat == kRegZero) {
2135 irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
2136 return;
2137 }
2138
2139 llvm::Value* src1_value;
2140 llvm::Value* src2_value;
2141
2142 if (src1_reg_cat != kRegZero && src2_reg_cat != kRegZero) {
2143 CHECK_EQ(src1_reg_cat, src2_reg_cat);
2144
2145 if (src1_reg_cat == kRegCat1nr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002146 src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
2147 src2_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002148 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002149 src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
2150 src2_value = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002151 }
2152 } else {
2153 DCHECK(src1_reg_cat == kRegZero ||
2154 src2_reg_cat == kRegZero);
2155
2156 if (src1_reg_cat == kRegZero) {
2157 if (src2_reg_cat == kRegCat1nr) {
2158 src1_value = irb_.getJInt(0);
Elliott Hughesadb8c672012-03-06 16:49:32 -08002159 src2_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002160 } else {
2161 src1_value = irb_.getJNull();
Elliott Hughesadb8c672012-03-06 16:49:32 -08002162 src2_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002163 }
2164 } else { // src2_reg_cat == kRegZero
2165 if (src2_reg_cat == kRegCat1nr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002166 src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002167 src2_value = irb_.getJInt(0);
2168 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002169 src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002170 src2_value = irb_.getJNull();
2171 }
2172 }
2173 }
2174
2175 llvm::Value* cond_value =
2176 EmitConditionResult(src1_value, src2_value, cond);
2177
2178 irb_.CreateCondBr(cond_value,
2179 GetBasicBlock(dex_pc + branch_offset),
2180 GetNextBasicBlock(dex_pc));
Logan Chien70f94b42011-12-27 17:49:11 +08002181}
2182
2183
2184void MethodCompiler::EmitInsn_UnaryConditionalBranch(uint32_t dex_pc,
2185 Instruction const* insn,
2186 CondBranchKind cond) {
Logan Chiena78e3c82011-12-27 17:59:35 +08002187
Elliott Hughesadb8c672012-03-06 16:49:32 -08002188 DecodedInstruction dec_insn(insn);
Logan Chiena78e3c82011-12-27 17:59:35 +08002189
Elliott Hughesadb8c672012-03-06 16:49:32 -08002190 int8_t src_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vA);
Logan Chiena78e3c82011-12-27 17:59:35 +08002191
2192 DCHECK_NE(kRegUnknown, src_reg_cat);
2193 DCHECK_NE(kRegCat2, src_reg_cat);
2194
Elliott Hughesadb8c672012-03-06 16:49:32 -08002195 int32_t branch_offset = dec_insn.vB;
Logan Chiena78e3c82011-12-27 17:59:35 +08002196
2197 if (branch_offset <= 0) {
2198 // Garbage collection safe-point on backward branch
2199 EmitGuard_GarbageCollectionSuspend(dex_pc);
2200 }
2201
2202 if (src_reg_cat == kRegZero) {
2203 irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
2204 return;
2205 }
2206
2207 llvm::Value* src1_value;
2208 llvm::Value* src2_value;
2209
2210 if (src_reg_cat == kRegCat1nr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002211 src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002212 src2_value = irb_.getInt32(0);
2213 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002214 src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
Logan Chiena78e3c82011-12-27 17:59:35 +08002215 src2_value = irb_.getJNull();
2216 }
2217
2218 llvm::Value* cond_value =
2219 EmitConditionResult(src1_value, src2_value, cond);
2220
2221 irb_.CreateCondBr(cond_value,
2222 GetBasicBlock(dex_pc + branch_offset),
2223 GetNextBasicBlock(dex_pc));
2224}
2225
2226
2227RegCategory MethodCompiler::GetInferredRegCategory(uint32_t dex_pc,
2228 uint16_t reg_idx) {
Logan Chiendd361c92012-04-10 23:40:37 +08002229
2230 Compiler::MethodReference mref(dex_file_, method_idx_);
2231
2232 InferredRegCategoryMap const* map =
Ian Rogers776ac1f2012-04-13 23:36:36 -07002233 verifier::MethodVerifier::GetInferredRegCategoryMap(mref);
Logan Chiendd361c92012-04-10 23:40:37 +08002234
Logan Chiena78e3c82011-12-27 17:59:35 +08002235 CHECK_NE(map, static_cast<InferredRegCategoryMap*>(NULL));
2236
2237 return map->GetRegCategory(dex_pc, reg_idx);
2238}
2239
2240
2241llvm::Value* MethodCompiler::EmitConditionResult(llvm::Value* lhs,
2242 llvm::Value* rhs,
2243 CondBranchKind cond) {
2244 switch (cond) {
2245 case kCondBranch_EQ:
2246 return irb_.CreateICmpEQ(lhs, rhs);
2247
2248 case kCondBranch_NE:
2249 return irb_.CreateICmpNE(lhs, rhs);
2250
2251 case kCondBranch_LT:
2252 return irb_.CreateICmpSLT(lhs, rhs);
2253
2254 case kCondBranch_GE:
2255 return irb_.CreateICmpSGE(lhs, rhs);
2256
2257 case kCondBranch_GT:
2258 return irb_.CreateICmpSGT(lhs, rhs);
2259
2260 case kCondBranch_LE:
2261 return irb_.CreateICmpSLE(lhs, rhs);
2262
2263 default: // Unreachable
2264 LOG(FATAL) << "Unknown conditional branch kind: " << cond;
2265 return NULL;
2266 }
Logan Chien70f94b42011-12-27 17:49:11 +08002267}
2268
TDYa12783bb6622012-04-17 02:20:34 -07002269void MethodCompiler::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2270 // Using runtime support, let the target can override by InlineAssembly.
2271 llvm::Function* runtime_func = irb_.GetRuntime(MarkGCCard);
2272
2273 irb_.CreateCall2(runtime_func, value, target_addr);
2274}
Logan Chien70f94b42011-12-27 17:49:11 +08002275
Logan Chiene27fdbb2012-01-02 23:27:26 +08002276void
2277MethodCompiler::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2278 llvm::Value* array,
2279 llvm::Value* index) {
2280 llvm::Value* array_len = EmitLoadArrayLength(array);
2281
2282 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
2283
2284 llvm::BasicBlock* block_exception =
2285 CreateBasicBlockWithDexPC(dex_pc, "overflow");
2286
2287 llvm::BasicBlock* block_continue =
2288 CreateBasicBlockWithDexPC(dex_pc, "cont");
2289
2290 irb_.CreateCondBr(cmp, block_exception, block_continue);
2291
2292 irb_.SetInsertPoint(block_exception);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002293
TDYa127c8dc1012012-04-19 07:03:33 -07002294 EmitUpdateDexPC(dex_pc);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002295 irb_.CreateCall2(irb_.GetRuntime(ThrowIndexOutOfBounds), index, array_len);
2296 EmitBranchExceptionLandingPad(dex_pc);
2297
2298 irb_.SetInsertPoint(block_continue);
2299}
2300
2301
2302void MethodCompiler::EmitGuard_ArrayException(uint32_t dex_pc,
2303 llvm::Value* array,
2304 llvm::Value* index) {
2305 EmitGuard_NullPointerException(dex_pc, array);
2306 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
2307}
2308
2309
2310// Emit Array GetElementPtr
2311llvm::Value* MethodCompiler::EmitArrayGEP(llvm::Value* array_addr,
2312 llvm::Value* index_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08002313 llvm::Type* elem_type,
2314 JType elem_jty) {
2315
2316 int data_offset;
2317 if (elem_jty == kLong || elem_jty == kDouble ||
2318 (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
2319 data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
2320 } else {
2321 data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
2322 }
Logan Chiene27fdbb2012-01-02 23:27:26 +08002323
2324 llvm::Constant* data_offset_value =
Ian Rogers04ec04e2012-02-28 16:15:33 -08002325 irb_.getPtrEquivInt(data_offset);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002326
2327 llvm::Value* array_data_addr =
2328 irb_.CreatePtrDisp(array_addr, data_offset_value,
2329 elem_type->getPointerTo());
2330
2331 return irb_.CreateGEP(array_data_addr, index_value);
2332}
2333
2334
Logan Chien70f94b42011-12-27 17:49:11 +08002335void MethodCompiler::EmitInsn_AGet(uint32_t dex_pc,
2336 Instruction const* insn,
2337 JType elem_jty) {
Logan Chiene27fdbb2012-01-02 23:27:26 +08002338
Elliott Hughesadb8c672012-03-06 16:49:32 -08002339 DecodedInstruction dec_insn(insn);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002340
Elliott Hughesadb8c672012-03-06 16:49:32 -08002341 llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
2342 llvm::Value* index_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002343
2344 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
2345
2346 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
2347
2348 llvm::Value* array_elem_addr =
Ian Rogers04ec04e2012-02-28 16:15:33 -08002349 EmitArrayGEP(array_addr, index_value, elem_type, elem_jty);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002350
2351 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr);
2352
Elliott Hughesadb8c672012-03-06 16:49:32 -08002353 EmitStoreDalvikReg(dec_insn.vA, elem_jty, kArray, array_elem_value);
Logan Chiene27fdbb2012-01-02 23:27:26 +08002354
Logan Chien70f94b42011-12-27 17:49:11 +08002355 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2356}
2357
2358
2359void MethodCompiler::EmitInsn_APut(uint32_t dex_pc,
2360 Instruction const* insn,
2361 JType elem_jty) {
Logan Chien8dabb432012-01-02 23:29:32 +08002362
Elliott Hughesadb8c672012-03-06 16:49:32 -08002363 DecodedInstruction dec_insn(insn);
Logan Chien8dabb432012-01-02 23:29:32 +08002364
Elliott Hughesadb8c672012-03-06 16:49:32 -08002365 llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
2366 llvm::Value* index_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
Logan Chien8dabb432012-01-02 23:29:32 +08002367
2368 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
2369
2370 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
2371
2372 llvm::Value* array_elem_addr =
Ian Rogers04ec04e2012-02-28 16:15:33 -08002373 EmitArrayGEP(array_addr, index_value, elem_type, elem_jty);
Logan Chien8dabb432012-01-02 23:29:32 +08002374
Elliott Hughesadb8c672012-03-06 16:49:32 -08002375 llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, elem_jty, kArray);
Logan Chien8dabb432012-01-02 23:29:32 +08002376
TDYa12783bb6622012-04-17 02:20:34 -07002377 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
TDYa1271b86d072012-04-05 17:38:56 -07002378 llvm::Function* runtime_func = irb_.GetRuntime(CheckPutArrayElement);
2379
2380 irb_.CreateCall2(runtime_func, new_value, array_addr);
2381
2382 EmitGuard_ExceptionLandingPad(dex_pc);
TDYa12783bb6622012-04-17 02:20:34 -07002383
2384 EmitMarkGCCard(new_value, array_addr);
TDYa1271b86d072012-04-05 17:38:56 -07002385 }
2386
Logan Chien8dabb432012-01-02 23:29:32 +08002387 irb_.CreateStore(new_value, array_elem_addr);
2388
Logan Chien70f94b42011-12-27 17:49:11 +08002389 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2390}
2391
2392
2393void MethodCompiler::EmitInsn_IGet(uint32_t dex_pc,
2394 Instruction const* insn,
2395 JType field_jty) {
Logan Chien48f1d2a2012-01-02 22:49:53 +08002396
Elliott Hughesadb8c672012-03-06 16:49:32 -08002397 DecodedInstruction dec_insn(insn);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002398
Elliott Hughesadb8c672012-03-06 16:49:32 -08002399 uint32_t reg_idx = dec_insn.vB;
2400 uint32_t field_idx = dec_insn.vC;
Logan Chien48f1d2a2012-01-02 22:49:53 +08002401
Logan Chien48f1d2a2012-01-02 22:49:53 +08002402 llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
2403
2404 EmitGuard_NullPointerException(dex_pc, object_addr);
2405
2406 llvm::Value* field_value;
2407
Logan Chien933abf82012-04-11 12:24:31 +08002408 int field_offset;
2409 bool is_volatile;
2410 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
2411 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002412
Logan Chien933abf82012-04-11 12:24:31 +08002413 if (!is_fast_path) {
Logan Chien48f1d2a2012-01-02 22:49:53 +08002414 llvm::Function* runtime_func;
2415
2416 if (field_jty == kObject) {
Logan Chien3b2b2e72012-03-06 16:11:45 +08002417 runtime_func = irb_.GetRuntime(GetObjectInstance);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002418 } else if (field_jty == kLong || field_jty == kDouble) {
Logan Chien3b2b2e72012-03-06 16:11:45 +08002419 runtime_func = irb_.GetRuntime(Get64Instance);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002420 } else {
Logan Chien3b2b2e72012-03-06 16:11:45 +08002421 runtime_func = irb_.GetRuntime(Get32Instance);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002422 }
2423
2424 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
2425
2426 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2427
TDYa127c8dc1012012-04-19 07:03:33 -07002428 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002429
Logan Chien3b2b2e72012-03-06 16:11:45 +08002430 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
2431 method_object_addr, object_addr);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002432
2433 EmitGuard_ExceptionLandingPad(dex_pc);
2434
2435 } else {
Logan Chien933abf82012-04-11 12:24:31 +08002436 DCHECK_GE(field_offset, 0);
2437
Logan Chien48f1d2a2012-01-02 22:49:53 +08002438 llvm::PointerType* field_type =
2439 irb_.getJType(field_jty, kField)->getPointerTo();
2440
Logan Chien933abf82012-04-11 12:24:31 +08002441 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002442
2443 llvm::Value* field_addr =
Logan Chien933abf82012-04-11 12:24:31 +08002444 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002445
Logan Chien933abf82012-04-11 12:24:31 +08002446 // TODO: Check is_volatile. We need to generate atomic load instruction
2447 // when is_volatile is true.
Logan Chien48f1d2a2012-01-02 22:49:53 +08002448 field_value = irb_.CreateLoad(field_addr);
2449 }
2450
Elliott Hughesadb8c672012-03-06 16:49:32 -08002451 EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, field_value);
Logan Chien48f1d2a2012-01-02 22:49:53 +08002452
Logan Chien70f94b42011-12-27 17:49:11 +08002453 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2454}
2455
2456
2457void MethodCompiler::EmitInsn_IPut(uint32_t dex_pc,
2458 Instruction const* insn,
2459 JType field_jty) {
Logan Chiendd6aa872012-01-03 16:06:32 +08002460
Elliott Hughesadb8c672012-03-06 16:49:32 -08002461 DecodedInstruction dec_insn(insn);
Logan Chiendd6aa872012-01-03 16:06:32 +08002462
Elliott Hughesadb8c672012-03-06 16:49:32 -08002463 uint32_t reg_idx = dec_insn.vB;
2464 uint32_t field_idx = dec_insn.vC;
Logan Chiendd6aa872012-01-03 16:06:32 +08002465
Logan Chiendd6aa872012-01-03 16:06:32 +08002466 llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
2467
2468 EmitGuard_NullPointerException(dex_pc, object_addr);
2469
Elliott Hughesadb8c672012-03-06 16:49:32 -08002470 llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
Logan Chiendd6aa872012-01-03 16:06:32 +08002471
Logan Chien933abf82012-04-11 12:24:31 +08002472 int field_offset;
2473 bool is_volatile;
2474 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
2475 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
Logan Chiendd6aa872012-01-03 16:06:32 +08002476
Logan Chien933abf82012-04-11 12:24:31 +08002477 if (!is_fast_path) {
Logan Chiendd6aa872012-01-03 16:06:32 +08002478 llvm::Function* runtime_func;
2479
2480 if (field_jty == kObject) {
2481 runtime_func = irb_.GetRuntime(SetObjectInstance);
2482 } else if (field_jty == kLong || field_jty == kDouble) {
2483 runtime_func = irb_.GetRuntime(Set64Instance);
2484 } else {
2485 runtime_func = irb_.GetRuntime(Set32Instance);
2486 }
2487
2488 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
2489
2490 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2491
TDYa127c8dc1012012-04-19 07:03:33 -07002492 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002493
Logan Chien3b2b2e72012-03-06 16:11:45 +08002494 irb_.CreateCall4(runtime_func, field_idx_value,
2495 method_object_addr, object_addr, new_value);
Logan Chiendd6aa872012-01-03 16:06:32 +08002496
2497 EmitGuard_ExceptionLandingPad(dex_pc);
2498
2499 } else {
Logan Chien933abf82012-04-11 12:24:31 +08002500 DCHECK_GE(field_offset, 0);
2501
Logan Chiendd6aa872012-01-03 16:06:32 +08002502 llvm::PointerType* field_type =
2503 irb_.getJType(field_jty, kField)->getPointerTo();
2504
Logan Chien933abf82012-04-11 12:24:31 +08002505 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
Logan Chiendd6aa872012-01-03 16:06:32 +08002506
2507 llvm::Value* field_addr =
Logan Chien933abf82012-04-11 12:24:31 +08002508 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
Logan Chiendd6aa872012-01-03 16:06:32 +08002509
Logan Chien933abf82012-04-11 12:24:31 +08002510 // TODO: Check is_volatile. We need to generate atomic store instruction
2511 // when is_volatile is true.
Logan Chiendd6aa872012-01-03 16:06:32 +08002512 irb_.CreateStore(new_value, field_addr);
TDYa12783bb6622012-04-17 02:20:34 -07002513
2514 if (field_jty == kObject) { // If put an object, mark the GC card table.
2515 EmitMarkGCCard(new_value, object_addr);
2516 }
Logan Chiendd6aa872012-01-03 16:06:32 +08002517 }
2518
Logan Chien70f94b42011-12-27 17:49:11 +08002519 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2520}
2521
2522
Logan Chien438c4b62012-01-17 16:06:00 +08002523llvm::Value* MethodCompiler::EmitLoadStaticStorage(uint32_t dex_pc,
2524 uint32_t type_idx) {
2525 llvm::BasicBlock* block_load_static =
2526 CreateBasicBlockWithDexPC(dex_pc, "load_static");
2527
2528 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2529
2530 // Load static storage from dex cache
2531 llvm::Value* storage_field_addr =
2532 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
2533
2534 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr);
2535
2536 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
2537
2538 // Test: Is the static storage of this class initialized?
2539 llvm::Value* equal_null =
2540 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
2541
2542 irb_.CreateCondBr(equal_null, block_load_static, block_cont);
2543
2544 // Failback routine to load the class object
2545 irb_.SetInsertPoint(block_load_static);
2546
2547 llvm::Function* runtime_func =
2548 irb_.GetRuntime(InitializeStaticStorage);
2549
2550 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
2551
2552 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2553
TDYa127706e9b62012-04-19 12:24:26 -07002554 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
2555
TDYa127c8dc1012012-04-19 07:03:33 -07002556 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002557
Logan Chien438c4b62012-01-17 16:06:00 +08002558 llvm::Value* loaded_storage_object_addr =
TDYa127706e9b62012-04-19 12:24:26 -07002559 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
Logan Chien438c4b62012-01-17 16:06:00 +08002560
2561 EmitGuard_ExceptionLandingPad(dex_pc);
2562
2563 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
2564
2565 irb_.CreateBr(block_cont);
2566
2567 // Now the class object must be loaded
2568 irb_.SetInsertPoint(block_cont);
2569
2570 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
2571
2572 phi->addIncoming(storage_object_addr, block_original);
2573 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
2574
2575 return phi;
2576}
2577
2578
Logan Chien70f94b42011-12-27 17:49:11 +08002579void MethodCompiler::EmitInsn_SGet(uint32_t dex_pc,
2580 Instruction const* insn,
2581 JType field_jty) {
Logan Chien438c4b62012-01-17 16:06:00 +08002582
Elliott Hughesadb8c672012-03-06 16:49:32 -08002583 DecodedInstruction dec_insn(insn);
Logan Chien438c4b62012-01-17 16:06:00 +08002584
Logan Chien933abf82012-04-11 12:24:31 +08002585 uint32_t field_idx = dec_insn.vB;
Logan Chien438c4b62012-01-17 16:06:00 +08002586
Logan Chien933abf82012-04-11 12:24:31 +08002587 int field_offset;
2588 int ssb_index;
2589 bool is_referrers_class;
2590 bool is_volatile;
2591
2592 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
2593 field_idx, oat_compilation_unit_, field_offset, ssb_index,
2594 is_referrers_class, is_volatile, false);
Logan Chien438c4b62012-01-17 16:06:00 +08002595
2596 llvm::Value* static_field_value;
2597
Logan Chien933abf82012-04-11 12:24:31 +08002598 if (!is_fast_path) {
Logan Chien438c4b62012-01-17 16:06:00 +08002599 llvm::Function* runtime_func;
2600
2601 if (field_jty == kObject) {
2602 runtime_func = irb_.GetRuntime(GetObjectStatic);
2603 } else if (field_jty == kLong || field_jty == kDouble) {
2604 runtime_func = irb_.GetRuntime(Get64Static);
2605 } else {
2606 runtime_func = irb_.GetRuntime(Get32Static);
2607 }
2608
Elliott Hughesadb8c672012-03-06 16:49:32 -08002609 llvm::Constant* field_idx_value = irb_.getInt32(dec_insn.vB);
Logan Chien438c4b62012-01-17 16:06:00 +08002610
2611 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2612
TDYa127c8dc1012012-04-19 07:03:33 -07002613 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002614
Logan Chien438c4b62012-01-17 16:06:00 +08002615 static_field_value =
2616 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
2617
2618 EmitGuard_ExceptionLandingPad(dex_pc);
2619
2620 } else {
Logan Chien933abf82012-04-11 12:24:31 +08002621 DCHECK_GE(field_offset, 0);
Logan Chien438c4b62012-01-17 16:06:00 +08002622
Logan Chien933abf82012-04-11 12:24:31 +08002623 llvm::Value* static_storage_addr = NULL;
2624
2625 if (is_referrers_class) {
2626 // Fast path, static storage base is this method's class
2627 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2628
2629 llvm::Constant* declaring_class_offset_value =
2630 irb_.getPtrEquivInt(Method::DeclaringClassOffset().Int32Value());
2631
2632 llvm::Value* static_storage_field_addr =
2633 irb_.CreatePtrDisp(method_object_addr, declaring_class_offset_value,
2634 irb_.getJObjectTy()->getPointerTo());
2635
2636 static_storage_addr = irb_.CreateLoad(static_storage_field_addr);
2637 } else {
2638 // Medium path, static storage base in a different class which
2639 // requires checks that the other class is initialized
2640 DCHECK_GE(ssb_index, 0);
2641 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
2642 }
2643
2644 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
Logan Chien438c4b62012-01-17 16:06:00 +08002645
2646 llvm::Value* static_field_addr =
2647 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
2648 irb_.getJType(field_jty, kField)->getPointerTo());
2649
Logan Chien933abf82012-04-11 12:24:31 +08002650 // TODO: Check is_volatile. We need to generate atomic load instruction
2651 // when is_volatile is true.
Logan Chien438c4b62012-01-17 16:06:00 +08002652 static_field_value = irb_.CreateLoad(static_field_addr);
2653 }
2654
Elliott Hughesadb8c672012-03-06 16:49:32 -08002655 EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, static_field_value);
Logan Chien438c4b62012-01-17 16:06:00 +08002656
Logan Chien70f94b42011-12-27 17:49:11 +08002657 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2658}
2659
2660
2661void MethodCompiler::EmitInsn_SPut(uint32_t dex_pc,
2662 Instruction const* insn,
2663 JType field_jty) {
Logan Chien14179c82012-01-17 17:06:34 +08002664
Elliott Hughesadb8c672012-03-06 16:49:32 -08002665 DecodedInstruction dec_insn(insn);
Logan Chien14179c82012-01-17 17:06:34 +08002666
Logan Chien933abf82012-04-11 12:24:31 +08002667 uint32_t field_idx = dec_insn.vB;
Logan Chien14179c82012-01-17 17:06:34 +08002668
Elliott Hughesadb8c672012-03-06 16:49:32 -08002669 llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
Logan Chien14179c82012-01-17 17:06:34 +08002670
Logan Chien933abf82012-04-11 12:24:31 +08002671 int field_offset;
2672 int ssb_index;
2673 bool is_referrers_class;
2674 bool is_volatile;
2675
2676 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
2677 field_idx, oat_compilation_unit_, field_offset, ssb_index,
2678 is_referrers_class, is_volatile, true);
2679
2680 if (!is_fast_path) {
Logan Chien14179c82012-01-17 17:06:34 +08002681 llvm::Function* runtime_func;
2682
2683 if (field_jty == kObject) {
2684 runtime_func = irb_.GetRuntime(SetObjectStatic);
2685 } else if (field_jty == kLong || field_jty == kDouble) {
2686 runtime_func = irb_.GetRuntime(Set64Static);
2687 } else {
2688 runtime_func = irb_.GetRuntime(Set32Static);
2689 }
2690
Elliott Hughesadb8c672012-03-06 16:49:32 -08002691 llvm::Constant* field_idx_value = irb_.getInt32(dec_insn.vB);
Logan Chien14179c82012-01-17 17:06:34 +08002692
2693 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2694
TDYa127c8dc1012012-04-19 07:03:33 -07002695 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08002696
Logan Chien14179c82012-01-17 17:06:34 +08002697 irb_.CreateCall3(runtime_func, field_idx_value,
2698 method_object_addr, new_value);
2699
2700 EmitGuard_ExceptionLandingPad(dex_pc);
2701
2702 } else {
Logan Chien933abf82012-04-11 12:24:31 +08002703 DCHECK_GE(field_offset, 0);
Logan Chien14179c82012-01-17 17:06:34 +08002704
Logan Chien933abf82012-04-11 12:24:31 +08002705 llvm::Value* static_storage_addr = NULL;
2706
2707 if (is_referrers_class) {
2708 // Fast path, static storage base is this method's class
2709 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2710
2711 llvm::Constant* declaring_class_offset_value =
2712 irb_.getPtrEquivInt(Method::DeclaringClassOffset().Int32Value());
2713
2714 llvm::Value* static_storage_field_addr =
2715 irb_.CreatePtrDisp(method_object_addr, declaring_class_offset_value,
2716 irb_.getJObjectTy()->getPointerTo());
2717
2718 static_storage_addr = irb_.CreateLoad(static_storage_field_addr);
2719 } else {
2720 // Medium path, static storage base in a different class which
2721 // requires checks that the other class is initialized
2722 DCHECK_GE(ssb_index, 0);
2723 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
2724 }
2725
2726 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
Logan Chien14179c82012-01-17 17:06:34 +08002727
2728 llvm::Value* static_field_addr =
2729 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
2730 irb_.getJType(field_jty, kField)->getPointerTo());
2731
Logan Chien933abf82012-04-11 12:24:31 +08002732 // TODO: Check is_volatile. We need to generate atomic store instruction
2733 // when is_volatile is true.
Logan Chien14179c82012-01-17 17:06:34 +08002734 irb_.CreateStore(new_value, static_field_addr);
TDYa12783bb6622012-04-17 02:20:34 -07002735
2736 if (field_jty == kObject) { // If put an object, mark the GC card table.
2737 EmitMarkGCCard(new_value, static_storage_addr);
2738 }
Logan Chien14179c82012-01-17 17:06:34 +08002739 }
2740
Logan Chien70f94b42011-12-27 17:49:11 +08002741 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2742}
2743
2744
Logan Chien1a121b92012-02-15 22:23:42 +08002745void MethodCompiler::
2746EmitLoadActualParameters(std::vector<llvm::Value*>& args,
2747 uint32_t callee_method_idx,
Elliott Hughesadb8c672012-03-06 16:49:32 -08002748 DecodedInstruction const& dec_insn,
Logan Chien7e7fabc2012-04-10 18:59:11 +08002749 InvokeArgFmt arg_fmt,
Logan Chien1a121b92012-02-15 22:23:42 +08002750 bool is_static) {
2751
2752 // Get method signature
2753 DexFile::MethodId const& method_id =
2754 dex_file_->GetMethodId(callee_method_idx);
2755
Logan Chien8faf8022012-02-24 12:25:29 +08002756 uint32_t shorty_size;
Logan Chien1a121b92012-02-15 22:23:42 +08002757 char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
Logan Chien8faf8022012-02-24 12:25:29 +08002758 CHECK_GE(shorty_size, 1u);
Logan Chien1a121b92012-02-15 22:23:42 +08002759
2760 // Load argument values according to the shorty (without "this")
2761 uint16_t reg_count = 0;
2762
2763 if (!is_static) {
2764 ++reg_count; // skip the "this" pointer
2765 }
2766
Logan Chien7e7fabc2012-04-10 18:59:11 +08002767 bool is_range = (arg_fmt == kArgRange);
2768
Logan Chien8faf8022012-02-24 12:25:29 +08002769 for (uint32_t i = 1; i < shorty_size; ++i) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002770 uint32_t reg_idx = (is_range) ? (dec_insn.vC + reg_count)
2771 : (dec_insn.arg[reg_count]);
Logan Chien1a121b92012-02-15 22:23:42 +08002772
2773 args.push_back(EmitLoadDalvikReg(reg_idx, shorty[i], kAccurate));
2774
2775 ++reg_count;
2776 if (shorty[i] == 'J' || shorty[i] == 'D') {
2777 // Wide types, such as long and double, are using a pair of registers
2778 // to store the value, so we have to increase arg_reg again.
2779 ++reg_count;
2780 }
2781 }
2782
Elliott Hughesadb8c672012-03-06 16:49:32 -08002783 DCHECK_EQ(reg_count, dec_insn.vA)
Logan Chien1a121b92012-02-15 22:23:42 +08002784 << "Actual argument mismatch for callee: "
2785 << PrettyMethod(callee_method_idx, *dex_file_);
2786}
2787
TDYa1270b686e52012-04-09 22:43:35 -07002788llvm::Value* MethodCompiler::EmitFixStub(llvm::Value* callee_method_object_addr,
2789 uint32_t method_idx,
2790 bool is_static) {
2791 // TODO: Remove this after we solve the link and trampoline related problems.
2792 llvm::Value* code_addr = irb_.CreateCall(irb_.GetRuntime(FixStub), callee_method_object_addr);
2793
2794 llvm::FunctionType* method_type = GetFunctionType(method_idx, is_static);
2795
2796 return irb_.CreatePointerCast(code_addr, method_type->getPointerTo());
TDYa12785321912012-04-01 15:24:56 -07002797}
Logan Chien1a121b92012-02-15 22:23:42 +08002798
Shih-wei Liao399ed3f2012-03-08 01:27:04 -08002799
Logan Chien7e7fabc2012-04-10 18:59:11 +08002800void MethodCompiler::EmitInsn_Invoke(uint32_t dex_pc,
2801 Instruction const* insn,
2802 InvokeType invoke_type,
2803 InvokeArgFmt arg_fmt) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08002804 DecodedInstruction dec_insn(insn);
Logan Chien46fbb412012-02-15 22:29:08 +08002805
Logan Chien61c65dc2012-02-29 03:22:30 +08002806 bool is_static = (invoke_type == kStatic);
Logan Chien7e7fabc2012-04-10 18:59:11 +08002807 uint32_t callee_method_idx = dec_insn.vB;
Logan Chien61c65dc2012-02-29 03:22:30 +08002808
Logan Chien7e7fabc2012-04-10 18:59:11 +08002809 // Compute invoke related information for compiler decision
2810 int vtable_idx = -1;
Logan Chien92ad16d2012-03-18 05:48:55 +08002811 uintptr_t direct_code = 0; // Currently unused
Logan Chienfca64372012-04-23 14:57:01 +08002812 uintptr_t direct_method = 0;
Logan Chien61c65dc2012-02-29 03:22:30 +08002813 bool is_fast_path = compiler_->
Logan Chien7e7fabc2012-04-10 18:59:11 +08002814 ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
Logan Chien92ad16d2012-03-18 05:48:55 +08002815 invoke_type, vtable_idx, direct_code, direct_method);
Logan Chien61c65dc2012-02-29 03:22:30 +08002816
Logan Chien7e7fabc2012-04-10 18:59:11 +08002817 // Load *this* actual parameter
Logan Chien1a121b92012-02-15 22:23:42 +08002818 llvm::Value* this_addr = NULL;
2819
2820 if (!is_static) {
2821 // Test: Is *this* parameter equal to null?
Logan Chien7e7fabc2012-04-10 18:59:11 +08002822 this_addr = (arg_fmt == kArgReg) ?
2823 EmitLoadDalvikReg(dec_insn.arg[0], kObject, kAccurate):
2824 EmitLoadDalvikReg(dec_insn.vC + 0, kObject, kAccurate);
2825
Logan Chien1a121b92012-02-15 22:23:42 +08002826 EmitGuard_NullPointerException(dex_pc, this_addr);
2827 }
2828
Logan Chien7e7fabc2012-04-10 18:59:11 +08002829 // Load the method object
TDYa1274e42a592012-04-10 20:13:54 -07002830 llvm::Value* callee_method_object_addr = NULL;
Logan Chien7e7fabc2012-04-10 18:59:11 +08002831
2832 if (!is_fast_path) {
TDYa1274e42a592012-04-10 20:13:54 -07002833 callee_method_object_addr =
Logan Chien7e7fabc2012-04-10 18:59:11 +08002834 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
2835 this_addr, dex_pc, is_fast_path);
2836 } else {
2837 switch (invoke_type) {
2838 case kStatic:
2839 case kDirect:
Logan Chienfca64372012-04-23 14:57:01 +08002840 if (direct_method != 0u &&
2841 direct_method != static_cast<uintptr_t>(-1)) {
2842 callee_method_object_addr =
2843 EmitLoadSDCalleeDirectMethodObjectAddr(callee_method_idx,
2844 direct_method);
2845 } else {
2846 callee_method_object_addr =
2847 EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
2848 }
Logan Chien7e7fabc2012-04-10 18:59:11 +08002849 break;
2850
2851 case kVirtual:
2852 DCHECK(vtable_idx != -1);
TDYa1274e42a592012-04-10 20:13:54 -07002853 callee_method_object_addr =
Logan Chien7e7fabc2012-04-10 18:59:11 +08002854 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
2855 break;
2856
2857 case kSuper:
2858 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
2859 "the fast path.";
2860 break;
2861
2862 case kInterface:
TDYa1274e42a592012-04-10 20:13:54 -07002863 callee_method_object_addr =
Logan Chien7e7fabc2012-04-10 18:59:11 +08002864 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
2865 invoke_type, this_addr,
2866 dex_pc, is_fast_path);
2867 break;
2868 }
2869 }
2870
Logan Chien7e7fabc2012-04-10 18:59:11 +08002871 llvm::Value* code_addr =
TDYa127ce154722012-04-21 16:43:29 -07002872 irb_.LoadFromObjectOffset(callee_method_object_addr,
2873 Method::GetCodeOffset().Int32Value(),
2874 GetFunctionType(callee_method_idx, is_static)->getPointerTo());
TDYa12785321912012-04-01 15:24:56 -07002875
Logan Chien1a121b92012-02-15 22:23:42 +08002876 // Load the actual parameter
2877 std::vector<llvm::Value*> args;
2878
2879 args.push_back(callee_method_object_addr); // method object for callee
2880
2881 if (!is_static) {
Logan Chien7e7fabc2012-04-10 18:59:11 +08002882 DCHECK(this_addr != NULL);
Logan Chien1a121b92012-02-15 22:23:42 +08002883 args.push_back(this_addr); // "this" object for callee
2884 }
2885
2886 EmitLoadActualParameters(args, callee_method_idx, dec_insn,
Logan Chien7e7fabc2012-04-10 18:59:11 +08002887 arg_fmt, is_static);
Logan Chien1a121b92012-02-15 22:23:42 +08002888
TDYa1275bb86012012-04-11 05:57:28 -07002889#if 0
Logan Chien8dfcbea2012-02-17 18:50:32 +08002890 // Invoke callee
TDYa127c8dc1012012-04-19 07:03:33 -07002891 EmitUpdateDexPC(dex_pc);
Logan Chien1a121b92012-02-15 22:23:42 +08002892 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2893 EmitGuard_ExceptionLandingPad(dex_pc);
2894
Logan Chien7e7fabc2012-04-10 18:59:11 +08002895 uint32_t callee_access_flags = is_static ? kAccStatic : 0;
2896 UniquePtr<OatCompilationUnit> callee_oat_compilation_unit(
2897 oat_compilation_unit_->GetCallee(callee_method_idx, callee_access_flags));
2898
2899 char ret_shorty = callee_oat_compilation_unit->GetShorty()[0];
Shih-wei Liao90d50992012-02-19 03:32:05 -08002900 if (ret_shorty != 'V') {
Logan Chien1a121b92012-02-15 22:23:42 +08002901 EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
2902 }
TDYa1275bb86012012-04-11 05:57:28 -07002903#else
2904 uint32_t callee_access_flags = is_static ? kAccStatic : 0;
2905 UniquePtr<OatCompilationUnit> callee_oat_compilation_unit(
2906 oat_compilation_unit_->GetCallee(callee_method_idx, callee_access_flags));
2907
2908 char ret_shorty = callee_oat_compilation_unit->GetShorty()[0];
2909
2910
TDYa127c8dc1012012-04-19 07:03:33 -07002911 EmitUpdateDexPC(dex_pc);
TDYa1275bb86012012-04-11 05:57:28 -07002912
2913
2914 llvm::BasicBlock* block_normal = CreateBasicBlockWithDexPC(dex_pc, "normal");
TDYa127ce154722012-04-21 16:43:29 -07002915 llvm::BasicBlock* block_stub = CreateBasicBlockWithDexPC(dex_pc, "stub");
TDYa1275bb86012012-04-11 05:57:28 -07002916 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2917
2918 llvm::Type* accurate_ret_type = irb_.getJType(ret_shorty, kAccurate);
2919 llvm::Value* retval_addr = NULL;
2920 if (ret_shorty != 'V') {
2921 retval_addr = irb_.CreateAlloca(accurate_ret_type);
2922 }
2923
2924
TDYa1275bb86012012-04-11 05:57:28 -07002925 llvm::Value* code_addr_int = irb_.CreatePtrToInt(code_addr, irb_.getPtrEquivIntTy());
TDYa127ce154722012-04-21 16:43:29 -07002926 llvm::Value* max_stub_int = irb_.getPtrEquivInt(special_stub::kMaxSpecialStub);
2927 llvm::Value* is_stub = irb_.CreateICmpULT(code_addr_int, max_stub_int);
2928 irb_.CreateCondBr(is_stub, block_stub, block_normal);
TDYa1275bb86012012-04-11 05:57:28 -07002929
2930
2931 irb_.SetInsertPoint(block_normal);
2932 {
2933 // Invoke callee
TDYa127ce154722012-04-21 16:43:29 -07002934 llvm::Value* retval = irb_.CreateCall(code_addr, args);
TDYa1275bb86012012-04-11 05:57:28 -07002935 if (ret_shorty != 'V') {
TDYa127ce154722012-04-21 16:43:29 -07002936 EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
TDYa1275bb86012012-04-11 05:57:28 -07002937 }
2938 }
2939 irb_.CreateBr(block_continue);
2940
2941
TDYa127ce154722012-04-21 16:43:29 -07002942 irb_.SetInsertPoint(block_stub);
TDYa1275bb86012012-04-11 05:57:28 -07002943 {
TDYa127ce154722012-04-21 16:43:29 -07002944 { // lazy link
2945 // TODO: Remove this after we solve the link problem.
2946 llvm::BasicBlock* block_proxy_stub = CreateBasicBlockWithDexPC(dex_pc, "proxy");
2947 llvm::BasicBlock* block_link = CreateBasicBlockWithDexPC(dex_pc, "link");
2948
2949 irb_.CreateCondBr(irb_.CreateIsNull(code_addr), block_link, block_proxy_stub);
2950
2951
2952 irb_.SetInsertPoint(block_link);
2953 code_addr = EmitFixStub(callee_method_object_addr, callee_method_idx, is_static);
2954
2955 EmitGuard_ExceptionLandingPad(dex_pc);
2956
2957 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2958 if (ret_shorty != 'V') {
2959 EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
2960 }
2961 irb_.CreateBr(block_continue);
2962
2963
2964 irb_.SetInsertPoint(block_proxy_stub);
TDYa1275bb86012012-04-11 05:57:28 -07002965 }
TDYa127ce154722012-04-21 16:43:29 -07002966 { // proxy stub
2967 llvm::Value* temp_space_addr;
2968 if (ret_shorty != 'V') {
2969 temp_space_addr = irb_.CreateAlloca(irb_.getJValueTy());
2970 args.push_back(temp_space_addr);
2971 }
2972 // TODO: Remove this after we solve the proxy trampoline calling convention problem.
2973 irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
2974 if (ret_shorty != 'V') {
2975 llvm::Value* result_addr =
2976 irb_.CreateBitCast(temp_space_addr, accurate_ret_type->getPointerTo());
2977 llvm::Value* retval = irb_.CreateLoad(result_addr);
2978 EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
2979 }
TDYa1275bb86012012-04-11 05:57:28 -07002980 }
2981 }
2982 irb_.CreateBr(block_continue);
2983
2984
2985 irb_.SetInsertPoint(block_continue);
2986
TDYa1275bb86012012-04-11 05:57:28 -07002987 EmitGuard_ExceptionLandingPad(dex_pc);
2988#endif
Logan Chien1a121b92012-02-15 22:23:42 +08002989
Logan Chien70f94b42011-12-27 17:49:11 +08002990 irb_.CreateBr(GetNextBasicBlock(dex_pc));
2991}
2992
2993
Logan Chien7e7fabc2012-04-10 18:59:11 +08002994llvm::Value* MethodCompiler::
Logan Chienfca64372012-04-23 14:57:01 +08002995EmitLoadSDCalleeDirectMethodObjectAddr(uint32_t callee_method_idx,
2996 uintptr_t direct_method) {
2997 std::string direct_method_name(
2998 StringPrintf("ArtMethodObject_%08lx",
2999 static_cast<unsigned long>(direct_method)));
3000
3001 llvm::GlobalVariable* direct_method_addr =
3002 module_->getGlobalVariable(direct_method_name);
3003
3004 if (direct_method_addr == NULL) {
3005 direct_method_addr =
3006 new llvm::GlobalVariable(*module_, irb_.getJObjectTy()->getElementType(),
3007 false, llvm::GlobalVariable::ExternalLinkage,
3008 NULL, direct_method_name);
3009 }
3010
3011 return direct_method_addr;
3012}
3013
3014
3015llvm::Value* MethodCompiler::
Logan Chien7e7fabc2012-04-10 18:59:11 +08003016EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
3017 llvm::Value* callee_method_object_field_addr =
3018 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
Logan Chien7caf37e2012-02-03 22:56:04 +08003019
Logan Chien7e7fabc2012-04-10 18:59:11 +08003020 return irb_.CreateLoad(callee_method_object_field_addr);
3021}
Logan Chien7caf37e2012-02-03 22:56:04 +08003022
Logan Chien7caf37e2012-02-03 22:56:04 +08003023
Logan Chien7e7fabc2012-04-10 18:59:11 +08003024llvm::Value* MethodCompiler::
3025EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
3026 llvm::Value* this_addr) {
3027 // Load class object of *this* pointer
3028 llvm::Constant* class_field_offset_value =
3029 irb_.getPtrEquivInt(Object::ClassOffset().Int32Value());
Logan Chien7caf37e2012-02-03 22:56:04 +08003030
Logan Chien7e7fabc2012-04-10 18:59:11 +08003031 llvm::Value* class_field_addr =
3032 irb_.CreatePtrDisp(this_addr, class_field_offset_value,
3033 irb_.getJObjectTy()->getPointerTo());
Logan Chien7caf37e2012-02-03 22:56:04 +08003034
Logan Chien7e7fabc2012-04-10 18:59:11 +08003035 llvm::Value* class_object_addr = irb_.CreateLoad(class_field_addr);
Logan Chien7caf37e2012-02-03 22:56:04 +08003036
Logan Chien7e7fabc2012-04-10 18:59:11 +08003037 // Load vtable address
3038 llvm::Constant* vtable_offset_value =
3039 irb_.getPtrEquivInt(Class::VTableOffset().Int32Value());
3040
3041 llvm::Value* vtable_field_addr =
3042 irb_.CreatePtrDisp(class_object_addr, vtable_offset_value,
3043 irb_.getJObjectTy()->getPointerTo());
3044
3045 llvm::Value* vtable_addr = irb_.CreateLoad(vtable_field_addr);
3046
3047 // Load callee method object
3048 llvm::Value* vtable_idx_value =
3049 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
3050
3051 llvm::Value* method_field_addr =
3052 EmitArrayGEP(vtable_addr, vtable_idx_value, irb_.getJObjectTy(), kObject);
3053
3054 return irb_.CreateLoad(method_field_addr);
3055}
3056
3057
3058llvm::Value* MethodCompiler::
3059EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
3060 InvokeType invoke_type,
3061 llvm::Value* this_addr,
3062 uint32_t dex_pc,
3063 bool is_fast_path) {
3064
3065 llvm::Function* runtime_func = NULL;
3066
3067 switch (invoke_type) {
3068 case kStatic:
3069 runtime_func = irb_.GetRuntime(FindStaticMethodWithAccessCheck);
3070 break;
3071
3072 case kDirect:
3073 runtime_func = irb_.GetRuntime(FindDirectMethodWithAccessCheck);
3074 break;
3075
3076 case kVirtual:
3077 runtime_func = irb_.GetRuntime(FindVirtualMethodWithAccessCheck);
3078 break;
3079
3080 case kSuper:
3081 runtime_func = irb_.GetRuntime(FindSuperMethodWithAccessCheck);
3082 break;
3083
3084 case kInterface:
3085 if (is_fast_path) {
3086 runtime_func = irb_.GetRuntime(FindInterfaceMethod);
3087 } else {
3088 runtime_func = irb_.GetRuntime(FindInterfaceMethodWithAccessCheck);
3089 }
3090 break;
3091 }
Logan Chien7caf37e2012-02-03 22:56:04 +08003092
3093 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
3094
Logan Chien7e7fabc2012-04-10 18:59:11 +08003095 if (this_addr == NULL) {
3096 DCHECK_EQ(invoke_type, kStatic);
3097 this_addr = irb_.getJNull();
3098 }
3099
3100 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
3101
TDYa127da83d972012-04-18 00:21:49 -07003102 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
3103
TDYa127c8dc1012012-04-19 07:03:33 -07003104 EmitUpdateDexPC(dex_pc);
Logan Chien8dfcbea2012-02-17 18:50:32 +08003105
TDYa1270b686e52012-04-09 22:43:35 -07003106 llvm::Value* callee_method_object_addr =
TDYa127da83d972012-04-18 00:21:49 -07003107 irb_.CreateCall4(runtime_func,
Logan Chien7e7fabc2012-04-10 18:59:11 +08003108 callee_method_idx_value,
3109 this_addr,
TDYa127da83d972012-04-18 00:21:49 -07003110 caller_method_object_addr,
3111 thread_object_addr);
Logan Chien7caf37e2012-02-03 22:56:04 +08003112
3113 EmitGuard_ExceptionLandingPad(dex_pc);
3114
Logan Chien7e7fabc2012-04-10 18:59:11 +08003115 return callee_method_object_addr;
Logan Chien70f94b42011-12-27 17:49:11 +08003116}
3117
3118
3119void MethodCompiler::EmitInsn_Neg(uint32_t dex_pc,
3120 Instruction const* insn,
3121 JType op_jty) {
Logan Chien1b5685f2011-12-27 18:01:14 +08003122
Elliott Hughesadb8c672012-03-06 16:49:32 -08003123 DecodedInstruction dec_insn(insn);
Logan Chien1b5685f2011-12-27 18:01:14 +08003124
3125 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3126
Elliott Hughesadb8c672012-03-06 16:49:32 -08003127 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chien1b5685f2011-12-27 18:01:14 +08003128 llvm::Value* result_value = irb_.CreateNeg(src_value);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003129 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chien1b5685f2011-12-27 18:01:14 +08003130
Logan Chien70f94b42011-12-27 17:49:11 +08003131 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3132}
3133
3134
3135void MethodCompiler::EmitInsn_Not(uint32_t dex_pc,
3136 Instruction const* insn,
3137 JType op_jty) {
Logan Chiene53750d2011-12-27 18:02:27 +08003138
Elliott Hughesadb8c672012-03-06 16:49:32 -08003139 DecodedInstruction dec_insn(insn);
Logan Chiene53750d2011-12-27 18:02:27 +08003140
3141 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3142
Elliott Hughesadb8c672012-03-06 16:49:32 -08003143 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chiene53750d2011-12-27 18:02:27 +08003144 llvm::Value* result_value =
3145 irb_.CreateXor(src_value, static_cast<uint64_t>(-1));
3146
Elliott Hughesadb8c672012-03-06 16:49:32 -08003147 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chiene53750d2011-12-27 18:02:27 +08003148
Logan Chien70f94b42011-12-27 17:49:11 +08003149 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3150}
3151
3152
3153void MethodCompiler::EmitInsn_SExt(uint32_t dex_pc,
3154 Instruction const* insn) {
Logan Chien61752ad2011-12-27 18:03:51 +08003155
Elliott Hughesadb8c672012-03-06 16:49:32 -08003156 DecodedInstruction dec_insn(insn);
Logan Chien61752ad2011-12-27 18:03:51 +08003157
Elliott Hughesadb8c672012-03-06 16:49:32 -08003158 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chien61752ad2011-12-27 18:03:51 +08003159 llvm::Value* result_value = irb_.CreateSExt(src_value, irb_.getJLongTy());
Elliott Hughesadb8c672012-03-06 16:49:32 -08003160 EmitStoreDalvikReg(dec_insn.vA, kLong, kAccurate, result_value);
Logan Chien61752ad2011-12-27 18:03:51 +08003161
Logan Chien70f94b42011-12-27 17:49:11 +08003162 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3163}
3164
3165
3166void MethodCompiler::EmitInsn_Trunc(uint32_t dex_pc,
3167 Instruction const* insn) {
Logan Chien17a57662011-12-27 18:05:14 +08003168
Elliott Hughesadb8c672012-03-06 16:49:32 -08003169 DecodedInstruction dec_insn(insn);
Logan Chien17a57662011-12-27 18:05:14 +08003170
Elliott Hughesadb8c672012-03-06 16:49:32 -08003171 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kLong, kAccurate);
Logan Chien17a57662011-12-27 18:05:14 +08003172 llvm::Value* result_value = irb_.CreateTrunc(src_value, irb_.getJIntTy());
Elliott Hughesadb8c672012-03-06 16:49:32 -08003173 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chien17a57662011-12-27 18:05:14 +08003174
Logan Chien70f94b42011-12-27 17:49:11 +08003175 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3176}
3177
3178
3179void MethodCompiler::EmitInsn_TruncAndSExt(uint32_t dex_pc,
3180 Instruction const* insn,
3181 unsigned N) {
Logan Chienb6744c52011-12-27 18:06:26 +08003182
Elliott Hughesadb8c672012-03-06 16:49:32 -08003183 DecodedInstruction dec_insn(insn);
Logan Chienb6744c52011-12-27 18:06:26 +08003184
Elliott Hughesadb8c672012-03-06 16:49:32 -08003185 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chienb6744c52011-12-27 18:06:26 +08003186
3187 llvm::Value* trunc_value =
3188 irb_.CreateTrunc(src_value, llvm::Type::getIntNTy(*context_, N));
3189
3190 llvm::Value* result_value = irb_.CreateSExt(trunc_value, irb_.getJIntTy());
3191
Elliott Hughesadb8c672012-03-06 16:49:32 -08003192 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chienb6744c52011-12-27 18:06:26 +08003193
Logan Chien70f94b42011-12-27 17:49:11 +08003194 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3195}
3196
3197
3198void MethodCompiler::EmitInsn_TruncAndZExt(uint32_t dex_pc,
3199 Instruction const* insn,
3200 unsigned N) {
Logan Chienb6744c52011-12-27 18:06:26 +08003201
Elliott Hughesadb8c672012-03-06 16:49:32 -08003202 DecodedInstruction dec_insn(insn);
Logan Chienb6744c52011-12-27 18:06:26 +08003203
Elliott Hughesadb8c672012-03-06 16:49:32 -08003204 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chienb6744c52011-12-27 18:06:26 +08003205
3206 llvm::Value* trunc_value =
3207 irb_.CreateTrunc(src_value, llvm::Type::getIntNTy(*context_, N));
3208
3209 llvm::Value* result_value = irb_.CreateZExt(trunc_value, irb_.getJIntTy());
3210
Elliott Hughesadb8c672012-03-06 16:49:32 -08003211 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chienb6744c52011-12-27 18:06:26 +08003212
Logan Chien70f94b42011-12-27 17:49:11 +08003213 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3214}
3215
3216
3217void MethodCompiler::EmitInsn_FNeg(uint32_t dex_pc,
3218 Instruction const* insn,
3219 JType op_jty) {
Logan Chien7a48b092011-12-27 18:07:45 +08003220
Elliott Hughesadb8c672012-03-06 16:49:32 -08003221 DecodedInstruction dec_insn(insn);
Logan Chien7a48b092011-12-27 18:07:45 +08003222
3223 DCHECK(op_jty == kFloat || op_jty == kDouble) << op_jty;
3224
Elliott Hughesadb8c672012-03-06 16:49:32 -08003225 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chien7a48b092011-12-27 18:07:45 +08003226 llvm::Value* result_value = irb_.CreateFNeg(src_value);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003227 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chien7a48b092011-12-27 18:07:45 +08003228
Logan Chien70f94b42011-12-27 17:49:11 +08003229 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3230}
3231
3232
3233void MethodCompiler::EmitInsn_IntToFP(uint32_t dex_pc,
3234 Instruction const* insn,
3235 JType src_jty,
3236 JType dest_jty) {
Logan Chien62dd4532011-12-27 18:09:00 +08003237
Elliott Hughesadb8c672012-03-06 16:49:32 -08003238 DecodedInstruction dec_insn(insn);
Logan Chien62dd4532011-12-27 18:09:00 +08003239
3240 DCHECK(src_jty == kInt || src_jty == kLong) << src_jty;
3241 DCHECK(dest_jty == kFloat || dest_jty == kDouble) << dest_jty;
3242
Elliott Hughesadb8c672012-03-06 16:49:32 -08003243 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
Logan Chien62dd4532011-12-27 18:09:00 +08003244 llvm::Type* dest_type = irb_.getJType(dest_jty, kAccurate);
3245 llvm::Value* dest_value = irb_.CreateSIToFP(src_value, dest_type);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003246 EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
Logan Chien62dd4532011-12-27 18:09:00 +08003247
Logan Chien70f94b42011-12-27 17:49:11 +08003248 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3249}
3250
3251
3252void MethodCompiler::EmitInsn_FPToInt(uint32_t dex_pc,
3253 Instruction const* insn,
3254 JType src_jty,
TDYa127a4746872012-04-11 23:48:55 -07003255 JType dest_jty,
3256 runtime_support::RuntimeId runtime_func_id) {
Logan Chien12dc1752011-12-27 18:10:15 +08003257
Elliott Hughesadb8c672012-03-06 16:49:32 -08003258 DecodedInstruction dec_insn(insn);
Logan Chien12dc1752011-12-27 18:10:15 +08003259
3260 DCHECK(src_jty == kFloat || src_jty == kDouble) << src_jty;
3261 DCHECK(dest_jty == kInt || dest_jty == kLong) << dest_jty;
3262
Elliott Hughesadb8c672012-03-06 16:49:32 -08003263 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
TDYa127a4746872012-04-11 23:48:55 -07003264 llvm::Value* dest_value = irb_.CreateCall(irb_.GetRuntime(runtime_func_id), src_value);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003265 EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
Logan Chien12dc1752011-12-27 18:10:15 +08003266
Logan Chien70f94b42011-12-27 17:49:11 +08003267 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3268}
3269
3270
3271void MethodCompiler::EmitInsn_FExt(uint32_t dex_pc,
3272 Instruction const* insn) {
Logan Chienc56ded92011-12-27 18:10:57 +08003273
Elliott Hughesadb8c672012-03-06 16:49:32 -08003274 DecodedInstruction dec_insn(insn);
Logan Chienc56ded92011-12-27 18:10:57 +08003275
Elliott Hughesadb8c672012-03-06 16:49:32 -08003276 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kFloat, kAccurate);
Logan Chienc56ded92011-12-27 18:10:57 +08003277 llvm::Value* result_value = irb_.CreateFPExt(src_value, irb_.getJDoubleTy());
Elliott Hughesadb8c672012-03-06 16:49:32 -08003278 EmitStoreDalvikReg(dec_insn.vA, kDouble, kAccurate, result_value);
Logan Chienc56ded92011-12-27 18:10:57 +08003279
Logan Chien70f94b42011-12-27 17:49:11 +08003280 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3281}
3282
3283
3284void MethodCompiler::EmitInsn_FTrunc(uint32_t dex_pc,
3285 Instruction const* insn) {
Logan Chien927744f2011-12-27 18:11:52 +08003286
Elliott Hughesadb8c672012-03-06 16:49:32 -08003287 DecodedInstruction dec_insn(insn);
Logan Chien927744f2011-12-27 18:11:52 +08003288
Elliott Hughesadb8c672012-03-06 16:49:32 -08003289 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kDouble, kAccurate);
Logan Chien927744f2011-12-27 18:11:52 +08003290 llvm::Value* result_value = irb_.CreateFPTrunc(src_value, irb_.getJFloatTy());
Elliott Hughesadb8c672012-03-06 16:49:32 -08003291 EmitStoreDalvikReg(dec_insn.vA, kFloat, kAccurate, result_value);
Logan Chien927744f2011-12-27 18:11:52 +08003292
Logan Chien70f94b42011-12-27 17:49:11 +08003293 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3294}
3295
3296
3297void MethodCompiler::EmitInsn_IntArithm(uint32_t dex_pc,
3298 Instruction const* insn,
3299 IntArithmKind arithm,
3300 JType op_jty,
3301 bool is_2addr) {
Logan Chienc3f7d962011-12-27 18:13:18 +08003302
Elliott Hughesadb8c672012-03-06 16:49:32 -08003303 DecodedInstruction dec_insn(insn);
Logan Chienc3f7d962011-12-27 18:13:18 +08003304
3305 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3306
3307 llvm::Value* src1_value;
3308 llvm::Value* src2_value;
3309
3310 if (is_2addr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08003311 src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
3312 src2_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chienc3f7d962011-12-27 18:13:18 +08003313 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08003314 src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
3315 src2_value = EmitLoadDalvikReg(dec_insn.vC, op_jty, kAccurate);
Logan Chienc3f7d962011-12-27 18:13:18 +08003316 }
3317
3318 llvm::Value* result_value =
3319 EmitIntArithmResultComputation(dex_pc, src1_value, src2_value,
3320 arithm, op_jty);
3321
Elliott Hughesadb8c672012-03-06 16:49:32 -08003322 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chienc3f7d962011-12-27 18:13:18 +08003323
Logan Chien70f94b42011-12-27 17:49:11 +08003324 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3325}
3326
3327
3328void MethodCompiler::EmitInsn_IntArithmImmediate(uint32_t dex_pc,
3329 Instruction const* insn,
3330 IntArithmKind arithm) {
Logan Chienc3f7d962011-12-27 18:13:18 +08003331
Elliott Hughesadb8c672012-03-06 16:49:32 -08003332 DecodedInstruction dec_insn(insn);
Logan Chienc3f7d962011-12-27 18:13:18 +08003333
Elliott Hughesadb8c672012-03-06 16:49:32 -08003334 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
Logan Chienc3f7d962011-12-27 18:13:18 +08003335
Elliott Hughesadb8c672012-03-06 16:49:32 -08003336 llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
Logan Chienc3f7d962011-12-27 18:13:18 +08003337
3338 llvm::Value* result_value =
3339 EmitIntArithmResultComputation(dex_pc, src_value, imm_value, arithm, kInt);
3340
Elliott Hughesadb8c672012-03-06 16:49:32 -08003341 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chienc3f7d962011-12-27 18:13:18 +08003342
Logan Chien70f94b42011-12-27 17:49:11 +08003343 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3344}
3345
3346
Logan Chienc3f7d962011-12-27 18:13:18 +08003347llvm::Value*
3348MethodCompiler::EmitIntArithmResultComputation(uint32_t dex_pc,
3349 llvm::Value* lhs,
3350 llvm::Value* rhs,
3351 IntArithmKind arithm,
3352 JType op_jty) {
3353 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3354
3355 switch (arithm) {
3356 case kIntArithm_Add:
3357 return irb_.CreateAdd(lhs, rhs);
3358
3359 case kIntArithm_Sub:
3360 return irb_.CreateSub(lhs, rhs);
3361
3362 case kIntArithm_Mul:
3363 return irb_.CreateMul(lhs, rhs);
3364
3365 case kIntArithm_Div:
Logan Chienc3f7d962011-12-27 18:13:18 +08003366 case kIntArithm_Rem:
TDYa127f8641ce2012-04-02 06:40:40 -07003367 return EmitIntDivRemResultComputation(dex_pc, lhs, rhs, arithm, op_jty);
Logan Chienc3f7d962011-12-27 18:13:18 +08003368
3369 case kIntArithm_And:
3370 return irb_.CreateAnd(lhs, rhs);
3371
3372 case kIntArithm_Or:
3373 return irb_.CreateOr(lhs, rhs);
3374
3375 case kIntArithm_Xor:
3376 return irb_.CreateXor(lhs, rhs);
3377
Logan Chienc3f7d962011-12-27 18:13:18 +08003378 default:
3379 LOG(FATAL) << "Unknown integer arithmetic kind: " << arithm;
3380 return NULL;
3381 }
3382}
3383
3384
TDYa127f8641ce2012-04-02 06:40:40 -07003385llvm::Value*
3386MethodCompiler::EmitIntDivRemResultComputation(uint32_t dex_pc,
3387 llvm::Value* dividend,
3388 llvm::Value* divisor,
3389 IntArithmKind arithm,
3390 JType op_jty) {
3391 // Throw exception if the divisor is 0.
3392 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
3393
3394 // Check the special case: MININT / -1 = MININT
3395 // That case will cause overflow, which is undefined behavior in llvm.
3396 // So we check the divisor is -1 or not, if the divisor is -1, we do
3397 // the special path to avoid undefined behavior.
3398 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
3399 llvm::Value* zero = irb_.getJZero(op_jty);
3400 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
3401 llvm::Value* result = irb_.CreateAlloca(op_type);
3402
3403 llvm::BasicBlock* eq_neg_one = CreateBasicBlockWithDexPC(dex_pc, "eq_neg_one");
3404 llvm::BasicBlock* ne_neg_one = CreateBasicBlockWithDexPC(dex_pc, "ne_neg_one");
3405 llvm::BasicBlock* neg_one_cont = CreateBasicBlockWithDexPC(dex_pc, "neg_one_cont");
3406
3407 llvm::Value* is_equal_neg_one = EmitConditionResult(divisor, neg_one, kCondBranch_EQ);
3408 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one);
3409
3410 // If divisor == -1
3411 irb_.SetInsertPoint(eq_neg_one);
3412 llvm::Value* eq_result;
3413 if (arithm == kIntArithm_Div) {
3414 // We can just change from "dividend div -1" to "neg dividend".
3415 // The sub don't care the sign/unsigned because of two's complement representation.
3416 // And the behavior is what we want:
3417 // -(2^n) (2^n)-1
3418 // MININT < k <= MAXINT -> mul k -1 = -k
3419 // MININT == k -> mul k -1 = k
3420 //
3421 // LLVM use sub to represent 'neg'
3422 eq_result = irb_.CreateSub(zero, dividend);
3423 } else {
3424 // Everything modulo -1 will be 0.
3425 eq_result = zero;
3426 }
3427 irb_.CreateStore(eq_result, result);
3428 irb_.CreateBr(neg_one_cont);
3429
3430 // If divisor != -1, just do the division.
3431 irb_.SetInsertPoint(ne_neg_one);
3432 llvm::Value* ne_result;
3433 if (arithm == kIntArithm_Div) {
3434 ne_result = irb_.CreateSDiv(dividend, divisor);
3435 } else {
3436 ne_result = irb_.CreateSRem(dividend, divisor);
3437 }
3438 irb_.CreateStore(ne_result, result);
3439 irb_.CreateBr(neg_one_cont);
3440
3441 irb_.SetInsertPoint(neg_one_cont);
3442 return irb_.CreateLoad(result);
3443}
3444
3445
Logan Chien5539ad02012-04-02 14:36:55 +08003446void MethodCompiler::EmitInsn_IntShiftArithm(uint32_t dex_pc,
3447 Instruction const* insn,
3448 IntShiftArithmKind arithm,
3449 JType op_jty,
3450 bool is_2addr) {
3451
3452 DecodedInstruction dec_insn(insn);
3453
3454 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3455
3456 llvm::Value* src1_value;
3457 llvm::Value* src2_value;
3458
3459 // NOTE: The 2nd operand of the shift arithmetic instruction is
3460 // 32-bit integer regardless of the 1st operand.
3461 if (is_2addr) {
3462 src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
3463 src2_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
3464 } else {
3465 src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
3466 src2_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
3467 }
3468
3469 llvm::Value* result_value =
3470 EmitIntShiftArithmResultComputation(dex_pc, src1_value, src2_value,
3471 arithm, op_jty);
3472
3473 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
3474
3475 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3476}
3477
3478
3479void MethodCompiler::
3480EmitInsn_IntShiftArithmImmediate(uint32_t dex_pc,
3481 Instruction const* insn,
3482 IntShiftArithmKind arithm) {
3483
3484 DecodedInstruction dec_insn(insn);
3485
3486 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
3487
3488 llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
3489
3490 llvm::Value* result_value =
3491 EmitIntShiftArithmResultComputation(dex_pc, src_value, imm_value,
3492 arithm, kInt);
3493
3494 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
3495
3496 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3497}
3498
3499
3500llvm::Value*
3501MethodCompiler::EmitIntShiftArithmResultComputation(uint32_t dex_pc,
3502 llvm::Value* lhs,
3503 llvm::Value* rhs,
3504 IntShiftArithmKind arithm,
3505 JType op_jty) {
3506 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3507
3508 if (op_jty == kInt) {
3509 rhs = irb_.CreateAnd(rhs, 0x1f);
3510 } else {
3511 llvm::Value* masked_rhs = irb_.CreateAnd(rhs, 0x3f);
3512 rhs = irb_.CreateZExt(masked_rhs, irb_.getJLongTy());
3513 }
3514
3515 switch (arithm) {
3516 case kIntArithm_Shl:
3517 return irb_.CreateShl(lhs, rhs);
3518
3519 case kIntArithm_Shr:
3520 return irb_.CreateAShr(lhs, rhs);
3521
3522 case kIntArithm_UShr:
3523 return irb_.CreateLShr(lhs, rhs);
3524
3525 default:
3526 LOG(FATAL) << "Unknown integer shift arithmetic kind: " << arithm;
3527 return NULL;
3528 }
3529}
3530
3531
Logan Chien70f94b42011-12-27 17:49:11 +08003532void MethodCompiler::EmitInsn_RSubImmediate(uint32_t dex_pc,
3533 Instruction const* insn) {
Logan Chien65c62d42011-12-27 18:14:18 +08003534
Elliott Hughesadb8c672012-03-06 16:49:32 -08003535 DecodedInstruction dec_insn(insn);
Logan Chien65c62d42011-12-27 18:14:18 +08003536
Elliott Hughesadb8c672012-03-06 16:49:32 -08003537 llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
3538 llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
Logan Chien65c62d42011-12-27 18:14:18 +08003539 llvm::Value* result_value = irb_.CreateSub(imm_value, src_value);
Elliott Hughesadb8c672012-03-06 16:49:32 -08003540 EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
Logan Chien65c62d42011-12-27 18:14:18 +08003541
Logan Chien70f94b42011-12-27 17:49:11 +08003542 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3543}
3544
3545
3546void MethodCompiler::EmitInsn_FPArithm(uint32_t dex_pc,
3547 Instruction const* insn,
3548 FPArithmKind arithm,
3549 JType op_jty,
3550 bool is_2addr) {
Logan Chien76e1c792011-12-27 18:15:01 +08003551
Elliott Hughesadb8c672012-03-06 16:49:32 -08003552 DecodedInstruction dec_insn(insn);
Logan Chien76e1c792011-12-27 18:15:01 +08003553
3554 DCHECK(op_jty == kFloat || op_jty == kDouble) << op_jty;
3555
3556 llvm::Value* src1_value;
3557 llvm::Value* src2_value;
3558
3559 if (is_2addr) {
Elliott Hughesadb8c672012-03-06 16:49:32 -08003560 src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
3561 src2_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
Logan Chien76e1c792011-12-27 18:15:01 +08003562 } else {
Elliott Hughesadb8c672012-03-06 16:49:32 -08003563 src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
3564 src2_value = EmitLoadDalvikReg(dec_insn.vC, op_jty, kAccurate);
Logan Chien76e1c792011-12-27 18:15:01 +08003565 }
3566
3567 llvm::Value* result_value =
3568 EmitFPArithmResultComputation(dex_pc, src1_value, src2_value, arithm);
3569
Elliott Hughesadb8c672012-03-06 16:49:32 -08003570 EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
Logan Chien76e1c792011-12-27 18:15:01 +08003571
Logan Chien70f94b42011-12-27 17:49:11 +08003572 irb_.CreateBr(GetNextBasicBlock(dex_pc));
3573}
3574
3575
Logan Chien76e1c792011-12-27 18:15:01 +08003576llvm::Value*
3577MethodCompiler::EmitFPArithmResultComputation(uint32_t dex_pc,
3578 llvm::Value *lhs,
3579 llvm::Value *rhs,
3580 FPArithmKind arithm) {
3581 switch (arithm) {
3582 case kFPArithm_Add:
3583 return irb_.CreateFAdd(lhs, rhs);
3584
3585 case kFPArithm_Sub:
3586 return irb_.CreateFSub(lhs, rhs);
3587
3588 case kFPArithm_Mul:
3589 return irb_.CreateFMul(lhs, rhs);
3590
3591 case kFPArithm_Div:
3592 return irb_.CreateFDiv(lhs, rhs);
3593
3594 case kFPArithm_Rem:
3595 return irb_.CreateFRem(lhs, rhs);
3596
3597 default:
3598 LOG(FATAL) << "Unknown floating-point arithmetic kind: " << arithm;
3599 return NULL;
3600 }
3601}
3602
3603
Logan Chienc3f7d962011-12-27 18:13:18 +08003604void MethodCompiler::EmitGuard_DivZeroException(uint32_t dex_pc,
3605 llvm::Value* denominator,
3606 JType op_jty) {
3607 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
3608
3609 llvm::Constant* zero = irb_.getJZero(op_jty);
3610
3611 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
3612
3613 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
3614
3615 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
3616
3617 irb_.CreateCondBr(equal_zero, block_exception, block_continue);
3618
3619 irb_.SetInsertPoint(block_exception);
TDYa127c8dc1012012-04-19 07:03:33 -07003620 EmitUpdateDexPC(dex_pc);
Logan Chienc3f7d962011-12-27 18:13:18 +08003621 irb_.CreateCall(irb_.GetRuntime(ThrowDivZeroException));
3622 EmitBranchExceptionLandingPad(dex_pc);
3623
3624 irb_.SetInsertPoint(block_continue);
3625}
3626
3627
Logan Chien61bb6142012-02-03 15:34:53 +08003628void MethodCompiler::EmitGuard_NullPointerException(uint32_t dex_pc,
3629 llvm::Value* object) {
3630 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
3631
3632 llvm::BasicBlock* block_exception =
3633 CreateBasicBlockWithDexPC(dex_pc, "nullp");
3634
3635 llvm::BasicBlock* block_continue =
3636 CreateBasicBlockWithDexPC(dex_pc, "cont");
3637
3638 irb_.CreateCondBr(equal_null, block_exception, block_continue);
3639
3640 irb_.SetInsertPoint(block_exception);
TDYa127c8dc1012012-04-19 07:03:33 -07003641 EmitUpdateDexPC(dex_pc);
TDYa1273f9137d2012-04-08 15:59:19 -07003642 irb_.CreateCall(irb_.GetRuntime(ThrowNullPointerException), irb_.getInt32(dex_pc));
Logan Chien61bb6142012-02-03 15:34:53 +08003643 EmitBranchExceptionLandingPad(dex_pc);
3644
3645 irb_.SetInsertPoint(block_continue);
3646}
3647
3648
Logan Chienbb4d12a2012-02-17 14:10:01 +08003649llvm::Value* MethodCompiler::EmitLoadDexCacheAddr(MemberOffset offset) {
3650 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
3651
3652 llvm::Value* dex_cache_offset_value =
3653 irb_.getPtrEquivInt(offset.Int32Value());
3654
3655 llvm::Value* dex_cache_field_addr =
3656 irb_.CreatePtrDisp(method_object_addr, dex_cache_offset_value,
3657 irb_.getJObjectTy()->getPointerTo());
3658
3659 return irb_.CreateLoad(dex_cache_field_addr);
3660}
3661
3662
Logan Chienbb4d12a2012-02-17 14:10:01 +08003663llvm::Value* MethodCompiler::
3664EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
3665 llvm::Value* static_storage_dex_cache_addr =
3666 EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
3667
3668 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
3669
3670 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08003671 irb_.getJObjectTy(), kObject);
Logan Chienbb4d12a2012-02-17 14:10:01 +08003672}
3673
3674
3675llvm::Value* MethodCompiler::
3676EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
3677 llvm::Value* resolved_type_dex_cache_addr =
3678 EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
3679
3680 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
3681
3682 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08003683 irb_.getJObjectTy(), kObject);
Logan Chienbb4d12a2012-02-17 14:10:01 +08003684}
3685
3686
3687llvm::Value* MethodCompiler::
Logan Chien61c65dc2012-02-29 03:22:30 +08003688EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
3689 llvm::Value* resolved_method_dex_cache_addr =
3690 EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
3691
3692 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
3693
3694 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08003695 irb_.getJObjectTy(), kObject);
Logan Chien61c65dc2012-02-29 03:22:30 +08003696}
3697
3698
3699llvm::Value* MethodCompiler::
Logan Chienbb4d12a2012-02-17 14:10:01 +08003700EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
3701 llvm::Value* string_dex_cache_addr =
3702 EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
3703
3704 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
3705
3706 return EmitArrayGEP(string_dex_cache_addr, string_idx_value,
Ian Rogers04ec04e2012-02-28 16:15:33 -08003707 irb_.getJObjectTy(), kObject);
Logan Chienbb4d12a2012-02-17 14:10:01 +08003708}
3709
3710
Logan Chien83426162011-12-09 09:29:50 +08003711CompiledMethod *MethodCompiler::Compile() {
Logan Chien0b827102011-12-20 19:46:14 +08003712 // Code generation
3713 CreateFunction();
3714
3715 EmitPrologue();
3716 EmitInstructions();
Logan Chienc670a8d2011-12-20 21:25:56 +08003717 EmitPrologueLastBranch();
Logan Chien0b827102011-12-20 19:46:14 +08003718
Logan Chiend6c239a2011-12-23 15:11:45 +08003719 // Verify the generated bitcode
TDYa127853cd092012-04-21 22:15:31 -07003720 VERIFY_LLVM_FUNCTION(*func_);
Logan Chiend6c239a2011-12-23 15:11:45 +08003721
Logan Chien8b977d32012-02-21 19:14:55 +08003722 // Add the memory usage approximation of the compilation unit
3723 cunit_->AddMemUsageApproximation(code_item_->insns_size_in_code_units_ * 900);
3724 // NOTE: From statistic, the bitcode size is 4.5 times bigger than the
3725 // Dex file. Besides, we have to convert the code unit into bytes.
3726 // Thus, we got our magic number 9.
3727
Logan Chien110bcba2012-04-16 19:11:28 +08003728 CompiledMethod* compiled_method =
3729 new CompiledMethod(cunit_->GetInstructionSet(),
3730 cunit_->GetElfIndex(),
3731 elf_func_idx_);
3732
3733 cunit_->RegisterCompiledMethod(func_, compiled_method);
3734
3735 return compiled_method;
Logan Chien0b827102011-12-20 19:46:14 +08003736}
3737
3738
3739llvm::Value* MethodCompiler::EmitLoadMethodObjectAddr() {
3740 return func_->arg_begin();
Shih-wei Liaod1fec812012-02-13 09:51:10 -08003741}
Logan Chien83426162011-12-09 09:29:50 +08003742
3743
Logan Chien5bcc04e2012-01-30 14:15:12 +08003744void MethodCompiler::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
3745 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
3746 irb_.CreateBr(lpad);
3747 } else {
3748 irb_.CreateBr(GetUnwindBasicBlock());
3749 }
3750}
3751
3752
3753void MethodCompiler::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
3754 llvm::Value* exception_pending =
3755 irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));
3756
3757 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
3758
3759 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
3760 irb_.CreateCondBr(exception_pending, lpad, block_cont);
3761 } else {
3762 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont);
3763 }
3764
3765 irb_.SetInsertPoint(block_cont);
3766}
3767
3768
Logan Chien924072f2012-01-30 15:07:24 +08003769void MethodCompiler::EmitGuard_GarbageCollectionSuspend(uint32_t dex_pc) {
3770 llvm::Value* runtime_func = irb_.GetRuntime(TestSuspend);
TDYa127853cd092012-04-21 22:15:31 -07003771
3772 llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
3773
TDYa127c8dc1012012-04-19 07:03:33 -07003774 EmitUpdateDexPC(dex_pc);
TDYa127853cd092012-04-21 22:15:31 -07003775
3776 irb_.CreateCall(runtime_func, thread_object_addr);
Logan Chien924072f2012-01-30 15:07:24 +08003777
3778 EmitGuard_ExceptionLandingPad(dex_pc);
3779}
3780
3781
Logan Chiend6c239a2011-12-23 15:11:45 +08003782llvm::BasicBlock* MethodCompiler::
3783CreateBasicBlockWithDexPC(uint32_t dex_pc, char const* postfix) {
3784 std::string name;
3785
3786 if (postfix) {
3787 StringAppendF(&name, "B%u.%s", dex_pc, postfix);
3788 } else {
3789 StringAppendF(&name, "B%u", dex_pc);
3790 }
3791
3792 return llvm::BasicBlock::Create(*context_, name, func_);
3793}
3794
3795
3796llvm::BasicBlock* MethodCompiler::GetBasicBlock(uint32_t dex_pc) {
3797 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
3798
3799 llvm::BasicBlock* basic_block = basic_blocks_[dex_pc];
3800
3801 if (!basic_block) {
3802 basic_block = CreateBasicBlockWithDexPC(dex_pc);
3803 basic_blocks_[dex_pc] = basic_block;
3804 }
3805
3806 return basic_block;
3807}
3808
3809
3810llvm::BasicBlock*
3811MethodCompiler::GetNextBasicBlock(uint32_t dex_pc) {
3812 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
3813 return GetBasicBlock(dex_pc + insn->SizeInCodeUnits());
3814}
3815
3816
Logan Chien5bcc04e2012-01-30 14:15:12 +08003817int32_t MethodCompiler::GetTryItemOffset(uint32_t dex_pc) {
3818 // TODO: Since we are emitting the dex instructions in ascending order
3819 // w.r.t. address, we can cache the lastest try item offset so that we
3820 // don't have to do binary search for every query.
3821
3822 int32_t min = 0;
3823 int32_t max = code_item_->tries_size_ - 1;
3824
3825 while (min <= max) {
3826 int32_t mid = min + (max - min) / 2;
3827
3828 DexFile::TryItem const* ti = DexFile::GetTryItems(*code_item_, mid);
3829 uint32_t start = ti->start_addr_;
3830 uint32_t end = start + ti->insn_count_;
3831
3832 if (dex_pc < start) {
3833 max = mid - 1;
3834 } else if (dex_pc >= end) {
3835 min = mid + 1;
3836 } else {
3837 return mid; // found
3838 }
3839 }
3840
3841 return -1; // not found
3842}
3843
3844
3845llvm::BasicBlock* MethodCompiler::GetLandingPadBasicBlock(uint32_t dex_pc) {
3846 // Find the try item for this address in this method
3847 int32_t ti_offset = GetTryItemOffset(dex_pc);
3848
3849 if (ti_offset == -1) {
3850 return NULL; // No landing pad is available for this address.
3851 }
3852
3853 // Check for the existing landing pad basic block
3854 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
3855 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
3856
3857 if (block_lpad) {
3858 // We have generated landing pad for this try item already. Return the
3859 // same basic block.
3860 return block_lpad;
3861 }
3862
3863 // Get try item from code item
3864 DexFile::TryItem const* ti = DexFile::GetTryItems(*code_item_, ti_offset);
3865
3866 // Create landing pad basic block
3867 block_lpad = llvm::BasicBlock::Create(*context_,
3868 StringPrintf("lpad%d", ti_offset),
3869 func_);
3870
3871 // Change IRBuilder insert point
3872 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
3873 irb_.SetInsertPoint(block_lpad);
3874
3875 // Find catch block with matching type
3876 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
3877
3878 // TODO: Maybe passing try item offset will be a better idea? For now,
3879 // we are passing dex_pc, so that we can use existing runtime support
3880 // function directly. However, in the runtime supporting function we
3881 // have to search for try item with binary search which can be
3882 // eliminated.
3883 llvm::Value* dex_pc_value = irb_.getInt32(ti->start_addr_);
3884
3885 llvm::Value* catch_handler_index_value =
3886 irb_.CreateCall2(irb_.GetRuntime(FindCatchBlock),
3887 method_object_addr, dex_pc_value);
3888
3889 // Switch instruction (Go to unwind basic block by default)
3890 llvm::SwitchInst* sw =
3891 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
3892
3893 // Cases with matched catch block
3894 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
3895
3896 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
3897 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
3898 }
3899
3900 // Restore the orignal insert point for IRBuilder
3901 irb_.restoreIP(irb_ip_original);
3902
3903 // Cache this landing pad
3904 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
3905 basic_block_landing_pads_[ti_offset] = block_lpad;
3906
3907 return block_lpad;
3908}
3909
3910
3911llvm::BasicBlock* MethodCompiler::GetUnwindBasicBlock() {
3912 // Check the existing unwinding baisc block block
3913 if (basic_block_unwind_ != NULL) {
3914 return basic_block_unwind_;
3915 }
3916
3917 // Create new basic block for unwinding
3918 basic_block_unwind_ =
3919 llvm::BasicBlock::Create(*context_, "exception_unwind", func_);
3920
3921 // Change IRBuilder insert point
3922 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
3923 irb_.SetInsertPoint(basic_block_unwind_);
3924
Logan Chien8dfcbea2012-02-17 18:50:32 +08003925 // Pop the shadow frame
3926 EmitPopShadowFrame();
3927
Logan Chien5bcc04e2012-01-30 14:15:12 +08003928 // Emit the code to return default value (zero) for the given return type.
Logan Chiendd361c92012-04-10 23:40:37 +08003929 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
Logan Chien5bcc04e2012-01-30 14:15:12 +08003930 if (ret_shorty == 'V') {
3931 irb_.CreateRetVoid();
3932 } else {
3933 irb_.CreateRet(irb_.getJZero(ret_shorty));
3934 }
3935
3936 // Restore the orignal insert point for IRBuilder
3937 irb_.restoreIP(irb_ip_original);
3938
3939 return basic_block_unwind_;
3940}
3941
3942
Logan Chienc670a8d2011-12-20 21:25:56 +08003943llvm::Value* MethodCompiler::AllocDalvikLocalVarReg(RegCategory cat,
3944 uint32_t reg_idx) {
3945
3946 // Save current IR builder insert point
3947 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
3948
3949 // Alloca
3950 llvm::Value* reg_addr = NULL;
3951
3952 switch (cat) {
3953 case kRegCat1nr:
3954 irb_.SetInsertPoint(basic_block_reg_alloca_);
3955 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0,
3956 StringPrintf("r%u", reg_idx));
3957
3958 irb_.SetInsertPoint(basic_block_reg_zero_init_);
3959 irb_.CreateStore(irb_.getJInt(0), reg_addr);
3960 break;
3961
3962 case kRegCat2:
3963 irb_.SetInsertPoint(basic_block_reg_alloca_);
3964 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0,
3965 StringPrintf("w%u", reg_idx));
3966
3967 irb_.SetInsertPoint(basic_block_reg_zero_init_);
3968 irb_.CreateStore(irb_.getJLong(0), reg_addr);
3969 break;
3970
3971 case kRegObject:
Logan Chien8dfcbea2012-02-17 18:50:32 +08003972 {
3973 irb_.SetInsertPoint(basic_block_shadow_frame_alloca_);
Logan Chienc670a8d2011-12-20 21:25:56 +08003974
Logan Chien8dfcbea2012-02-17 18:50:32 +08003975 llvm::Value* gep_index[] = {
3976 irb_.getInt32(0), // No pointer displacement
3977 irb_.getInt32(1), // SIRT
3978 irb_.getInt32(reg_idx) // Pointer field
3979 };
3980
3981 reg_addr = irb_.CreateGEP(shadow_frame_, gep_index,
3982 StringPrintf("p%u", reg_idx));
3983
3984 irb_.SetInsertPoint(basic_block_reg_zero_init_);
3985 irb_.CreateStore(irb_.getJNull(), reg_addr);
3986 }
Logan Chienc670a8d2011-12-20 21:25:56 +08003987 break;
3988
3989 default:
3990 LOG(FATAL) << "Unknown register category for allocation: " << cat;
3991 }
3992
3993 // Restore IRBuilder insert point
3994 irb_.restoreIP(irb_ip_original);
3995
3996 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
3997 return reg_addr;
3998}
3999
4000
4001llvm::Value* MethodCompiler::AllocDalvikRetValReg(RegCategory cat) {
4002 // Save current IR builder insert point
4003 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
4004
4005 // Alloca
4006 llvm::Value* reg_addr = NULL;
4007
4008 switch (cat) {
4009 case kRegCat1nr:
4010 irb_.SetInsertPoint(basic_block_reg_alloca_);
4011 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0, "r_res");
4012 break;
4013
4014 case kRegCat2:
4015 irb_.SetInsertPoint(basic_block_reg_alloca_);
4016 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0, "w_res");
4017 break;
4018
4019 case kRegObject:
4020 irb_.SetInsertPoint(basic_block_reg_alloca_);
4021 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0, "p_res");
4022 break;
4023
4024 default:
4025 LOG(FATAL) << "Unknown register category for allocation: " << cat;
4026 }
4027
4028 // Restore IRBuilder insert point
4029 irb_.restoreIP(irb_ip_original);
4030
4031 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
4032 return reg_addr;
4033}
4034
4035
Logan Chien8dfcbea2012-02-17 18:50:32 +08004036void MethodCompiler::EmitPopShadowFrame() {
4037 irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
4038}
4039
4040
TDYa127c8dc1012012-04-19 07:03:33 -07004041void MethodCompiler::EmitUpdateDexPC(uint32_t dex_pc) {
4042 irb_.StoreToObjectOffset(shadow_frame_,
4043 ShadowFrame::DexPCOffset(),
4044 irb_.getInt32(dex_pc));
Logan Chien8dfcbea2012-02-17 18:50:32 +08004045}
4046
4047
Logan Chien83426162011-12-09 09:29:50 +08004048} // namespace compiler_llvm
4049} // namespace art