blob: a7793aec26932a92df45dbbb6e46c2a17b9460a1 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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 "dex_file-inl.h"
18#include "driver/compiler_driver.h"
19#include "driver/dex_compilation_unit.h"
20#include "intrinsic_helper.h"
21#include "ir_builder.h"
22#include "method_reference.h"
23#include "mirror/abstract_method.h"
24#include "mirror/array.h"
25#include "mirror/string.h"
26#include "thread.h"
27#include "utils_llvm.h"
28#include "verifier/method_verifier.h"
29
30#include "dex/compiler_ir.h"
31#include "dex/mir_graph.h"
32#include "dex/quick/mir_to_lir.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070033
34#include <llvm/ADT/STLExtras.h>
35#include <llvm/IR/Intrinsics.h>
36#include <llvm/IR/Metadata.h>
37#include <llvm/Pass.h>
38#include <llvm/Support/CFG.h>
39#include <llvm/Support/InstIterator.h>
40
41#include <vector>
42#include <map>
43#include <utility>
44
Brian Carlstrom3e3d5912013-07-18 00:19:45 -070045using ::art::kMIRIgnoreNullCheck;
46using ::art::kMIRIgnoreRangeCheck;
47using ::art::llvm::IRBuilder;
48using ::art::llvm::IntrinsicHelper;
49using ::art::llvm::JType;
50using ::art::llvm::RuntimeSupportBuilder;
51using ::art::llvm::kBoolean;
52using ::art::llvm::kByte;
53using ::art::llvm::kChar;
54using ::art::llvm::kDouble;
55using ::art::llvm::kFloat;
56using ::art::llvm::kInt;
57using ::art::llvm::kLikely;
58using ::art::llvm::kLong;
59using ::art::llvm::kObject;
60using ::art::llvm::kShort;
61using ::art::llvm::kTBAAConstJObject;
62using ::art::llvm::kTBAAHeapArray;
63using ::art::llvm::kTBAAHeapInstance;
64using ::art::llvm::kTBAAHeapStatic;
65using ::art::llvm::kTBAARegister;
66using ::art::llvm::kTBAARuntimeInfo;
67using ::art::llvm::kTBAAShadowFrame;
68using ::art::llvm::kUnlikely;
69using ::art::llvm::kVoid;
70using ::art::llvm::runtime_support::AllocArray;
71using ::art::llvm::runtime_support::AllocArrayWithAccessCheck;
72using ::art::llvm::runtime_support::AllocObject;
73using ::art::llvm::runtime_support::AllocObjectWithAccessCheck;
74using ::art::llvm::runtime_support::CheckAndAllocArray;
75using ::art::llvm::runtime_support::CheckAndAllocArrayWithAccessCheck;
76using ::art::llvm::runtime_support::CheckCast;
77using ::art::llvm::runtime_support::CheckPutArrayElement;
78using ::art::llvm::runtime_support::FillArrayData;
79using ::art::llvm::runtime_support::FindCatchBlock;
80using ::art::llvm::runtime_support::FindDirectMethodWithAccessCheck;
81using ::art::llvm::runtime_support::FindInterfaceMethod;
82using ::art::llvm::runtime_support::FindInterfaceMethodWithAccessCheck;
83using ::art::llvm::runtime_support::FindStaticMethodWithAccessCheck;
84using ::art::llvm::runtime_support::FindSuperMethodWithAccessCheck;
85using ::art::llvm::runtime_support::FindVirtualMethodWithAccessCheck;
86using ::art::llvm::runtime_support::Get32Instance;
87using ::art::llvm::runtime_support::Get32Static;
88using ::art::llvm::runtime_support::Get64Instance;
89using ::art::llvm::runtime_support::Get64Static;
90using ::art::llvm::runtime_support::GetObjectInstance;
91using ::art::llvm::runtime_support::GetObjectStatic;
92using ::art::llvm::runtime_support::InitializeStaticStorage;
93using ::art::llvm::runtime_support::InitializeType;
94using ::art::llvm::runtime_support::InitializeTypeAndVerifyAccess;
95using ::art::llvm::runtime_support::IsAssignable;
96using ::art::llvm::runtime_support::ResolveString;
97using ::art::llvm::runtime_support::RuntimeId;
98using ::art::llvm::runtime_support::Set32Instance;
99using ::art::llvm::runtime_support::Set32Static;
100using ::art::llvm::runtime_support::Set64Instance;
101using ::art::llvm::runtime_support::Set64Static;
102using ::art::llvm::runtime_support::SetObjectInstance;
103using ::art::llvm::runtime_support::SetObjectStatic;
104using ::art::llvm::runtime_support::ThrowDivZeroException;
105using ::art::llvm::runtime_support::ThrowException;
106using ::art::llvm::runtime_support::ThrowIndexOutOfBounds;
107using ::art::llvm::runtime_support::ThrowNullPointerException;
108using ::art::llvm::runtime_support::ThrowStackOverflowException;
109using ::art::llvm::runtime_support::art_d2i;
110using ::art::llvm::runtime_support::art_d2l;
111using ::art::llvm::runtime_support::art_f2i;
112using ::art::llvm::runtime_support::art_f2l;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700113
114namespace art {
115extern char RemapShorty(char shortyType);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700116} // namespace art
Brian Carlstrom7940e442013-07-12 13:46:57 -0700117
118namespace {
119
120class GBCExpanderPass : public llvm::FunctionPass {
121 private:
122 const IntrinsicHelper& intrinsic_helper_;
123 IRBuilder& irb_;
124
125 llvm::LLVMContext& context_;
126 RuntimeSupportBuilder& rtb_;
127
128 private:
129 llvm::AllocaInst* shadow_frame_;
130 llvm::Value* old_shadow_frame_;
131
132 private:
133 art::CompilerDriver* const driver_;
134
135 const art::DexCompilationUnit* const dex_compilation_unit_;
136
137 llvm::Function* func_;
138
139 std::vector<llvm::BasicBlock*> basic_blocks_;
140
141 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
142 llvm::BasicBlock* current_bb_;
143 std::map<llvm::BasicBlock*, std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> > >
144 landing_pad_phi_mapping_;
145 llvm::BasicBlock* basic_block_unwind_;
146
147 // Maps each vreg to its shadow frame address.
148 std::vector<llvm::Value*> shadow_frame_vreg_addresses_;
149
150 bool changed_;
151
152 private:
153 //----------------------------------------------------------------------------
154 // Constant for GBC expansion
155 //----------------------------------------------------------------------------
156 enum IntegerShiftKind {
157 kIntegerSHL,
158 kIntegerSHR,
159 kIntegerUSHR,
160 };
161
162 private:
163 //----------------------------------------------------------------------------
164 // Helper function for GBC expansion
165 //----------------------------------------------------------------------------
166
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700167 llvm::Value* ExpandToRuntime(RuntimeId rt, llvm::CallInst& inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700168
169 uint64_t LV2UInt(llvm::Value* lv) {
170 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
171 }
172
173 int64_t LV2SInt(llvm::Value* lv) {
174 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
175 }
176
177 private:
178 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
179 // Refactor these utility functions from MethodCompiler to avoid forking.
180
181 void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
182
183 void RewriteFunction();
184
185 void RewriteBasicBlock(llvm::BasicBlock* original_block);
186
187 void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
188 llvm::BasicBlock* new_basic_block);
189
190
191 // Sign or zero extend category 1 types < 32bits in size to 32bits.
192 llvm::Value* SignOrZeroExtendCat1Types(llvm::Value* value, JType jty);
193
194 // Truncate category 1 types from 32bits to the given JType size.
195 llvm::Value* TruncateCat1Types(llvm::Value* value, JType jty);
196
197 //----------------------------------------------------------------------------
198 // Dex cache code generation helper function
199 //----------------------------------------------------------------------------
200 llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
201
202 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
203
204 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
205
206 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
207
208 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
209
210 //----------------------------------------------------------------------------
211 // Code generation helper function
212 //----------------------------------------------------------------------------
213 llvm::Value* EmitLoadMethodObjectAddr();
214
215 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
216
217 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
218
219 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
220 llvm::Value* this_addr);
221
222 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
223 llvm::Value* index_value,
224 JType elem_jty);
225
226 //----------------------------------------------------------------------------
227 // Invoke helper function
228 //----------------------------------------------------------------------------
229 llvm::Value* EmitInvoke(llvm::CallInst& call_inst);
230
231 //----------------------------------------------------------------------------
232 // Inlining helper functions
233 //----------------------------------------------------------------------------
234 bool EmitIntrinsic(llvm::CallInst& call_inst, llvm::Value** result);
235
236 bool EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
237 llvm::Value** result, bool is_empty);
238
239 private:
240 //----------------------------------------------------------------------------
241 // Expand Greenland intrinsics
242 //----------------------------------------------------------------------------
243 void Expand_TestSuspend(llvm::CallInst& call_inst);
244
245 void Expand_MarkGCCard(llvm::CallInst& call_inst);
246
247 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
248
249 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
250
251 void Expand_LockObject(llvm::Value* obj);
252
253 void Expand_UnlockObject(llvm::Value* obj);
254
255 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
256 llvm::Value* index_value,
257 JType elem_jty);
258
259 void Expand_ArrayPut(llvm::Value* new_value,
260 llvm::Value* array_addr,
261 llvm::Value* index_value,
262 JType elem_jty);
263
264 void Expand_FilledNewArray(llvm::CallInst& call_inst);
265
266 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
267 llvm::Value* is_volatile_value,
268 llvm::Value* object_addr,
269 JType field_jty);
270
271 void Expand_IPutFast(llvm::Value* field_offset_value,
272 llvm::Value* is_volatile_value,
273 llvm::Value* object_addr,
274 llvm::Value* new_value,
275 JType field_jty);
276
277 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
278 llvm::Value* field_offset_value,
279 llvm::Value* is_volatile_value,
280 JType field_jty);
281
282 void Expand_SPutFast(llvm::Value* static_storage_addr,
283 llvm::Value* field_offset_value,
284 llvm::Value* is_volatile_value,
285 llvm::Value* new_value,
286 JType field_jty);
287
288 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
289
290 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
291
292 llvm::Value*
293 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
294
295 llvm::Value*
296 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
297 llvm::Value* this_addr);
298
299 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
300
301 llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
302
303 void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
304
305 void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
306
307 void Expand_PopShadowFrame();
308
309 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
310
311 //----------------------------------------------------------------------------
312 // Quick
313 //----------------------------------------------------------------------------
314
315 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
316 llvm::Value* src2_value,
317 bool gt_bias);
318
319 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
320
321 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
322 llvm::Value* cmp_lt);
323
324 llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
325 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
326
327 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
328 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
329
330 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
331 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
332
333 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
334 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
335
336 llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
337 llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
338
339 void Expand_MonitorEnter(llvm::CallInst& call_inst);
340 void Expand_MonitorExit(llvm::CallInst& call_inst);
341
342 void Expand_HLCheckCast(llvm::CallInst& call_inst);
343 llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
344
345 llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
346
347 llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
348
349 llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
350 llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
351 llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
352 void Expand_HLFillArrayData(llvm::CallInst& call_inst);
353
354 llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
355 llvm::Value* array_length_value,
356 uint32_t type_idx,
357 bool is_filled_new_array);
358
359 llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
360 art::InvokeType invoke_type,
361 llvm::Value* this_addr,
362 uint32_t dex_pc,
363 bool is_fast_path);
364
365 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
366
367 void EmitUpdateDexPC(uint32_t dex_pc);
368
369 void EmitGuard_DivZeroException(uint32_t dex_pc,
370 llvm::Value* denominator,
371 JType op_jty);
372
373 void EmitGuard_NullPointerException(uint32_t dex_pc, llvm::Value* object,
374 int opt_flags);
375
376 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
377 llvm::Value* array,
378 llvm::Value* index,
379 int opt_flags);
380
381 llvm::FunctionType* GetFunctionType(llvm::Type* ret_type, uint32_t method_idx, bool is_static);
382
383 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
384
385 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
386 const char* postfix);
387
388 int32_t GetTryItemOffset(uint32_t dex_pc);
389
390 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
391
392 llvm::BasicBlock* GetUnwindBasicBlock();
393
394 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
395
396 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
397
398 //----------------------------------------------------------------------------
399 // Expand Arithmetic Helper Intrinsics
400 //----------------------------------------------------------------------------
401
402 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
403 llvm::Value* src2_value,
404 IntegerShiftKind kind,
405 JType op_jty);
406
407 public:
408 static char ID;
409
410 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
411 art::CompilerDriver* driver, const art::DexCompilationUnit* dex_compilation_unit)
412 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
413 context_(irb.getContext()), rtb_(irb.Runtime()),
414 shadow_frame_(NULL), old_shadow_frame_(NULL),
415 driver_(driver),
416 dex_compilation_unit_(dex_compilation_unit),
417 func_(NULL), current_bb_(NULL), basic_block_unwind_(NULL), changed_(false) {}
418
419 bool runOnFunction(llvm::Function& func);
420
421 private:
422 void InsertStackOverflowCheck(llvm::Function& func);
423
424 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
425 llvm::CallInst& call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426};
427
428char GBCExpanderPass::ID = 0;
429
430bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
431 VLOG(compiler) << "GBC expansion on " << func.getName().str();
432
433 // Runtime support or stub
434 if (dex_compilation_unit_ == NULL) {
435 return false;
436 }
437
438 // Setup rewrite context
439 shadow_frame_ = NULL;
440 old_shadow_frame_ = NULL;
441 func_ = &func;
442 changed_ = false; // Assume unchanged
443
444 shadow_frame_vreg_addresses_.resize(dex_compilation_unit_->GetCodeItem()->registers_size_, NULL);
445 basic_blocks_.resize(dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
446 basic_block_landing_pads_.resize(dex_compilation_unit_->GetCodeItem()->tries_size_, NULL);
447 basic_block_unwind_ = NULL;
448 for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
449 bb_iter != bb_end;
450 ++bb_iter) {
451 if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
452 continue;
453 }
454 uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
455 basic_blocks_[dex_pc] = bb_iter;
456 }
457
458 // Insert stack overflow check
459 InsertStackOverflowCheck(func); // TODO: Use intrinsic.
460
461 // Rewrite the intrinsics
462 RewriteFunction();
463
464 VERIFY_LLVM_FUNCTION(func);
465
466 return changed_;
467}
468
469void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
470 llvm::BasicBlock* curr_basic_block = original_block;
471
472 llvm::BasicBlock::iterator inst_iter = original_block->begin();
473 llvm::BasicBlock::iterator inst_end = original_block->end();
474
475 while (inst_iter != inst_end) {
476 llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
477 IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
478
479 if (call_inst) {
480 llvm::Function* callee_func = call_inst->getCalledFunction();
481 intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
482 }
483
484 if (intr_id == IntrinsicHelper::UnknownId) {
485 // This is not intrinsic call. Skip this instruction.
486 ++inst_iter;
487 continue;
488 }
489
490 // Rewrite the intrinsic and change the function
491 changed_ = true;
492 irb_.SetInsertPoint(inst_iter);
493
494 // Expand the intrinsic
495 if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
496 inst_iter->replaceAllUsesWith(new_value);
497 }
498
499 // Remove the old intrinsic call instruction
500 llvm::BasicBlock::iterator old_inst = inst_iter++;
501 old_inst->eraseFromParent();
502
503 // Splice the instruction to the new basic block
504 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
505 if (next_basic_block != curr_basic_block) {
506 next_basic_block->getInstList().splice(
507 irb_.GetInsertPoint(), curr_basic_block->getInstList(),
508 inst_iter, inst_end);
509 curr_basic_block = next_basic_block;
510 inst_end = curr_basic_block->end();
511 }
512 }
513}
514
515
516void GBCExpanderPass::RewriteFunction() {
517 size_t num_basic_blocks = func_->getBasicBlockList().size();
518 // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
519 // because we will create new basic block while expanding the intrinsics.
520 // We only want to iterate through the input basic blocks.
521
522 landing_pad_phi_mapping_.clear();
523
524 for (llvm::Function::iterator bb_iter = func_->begin();
525 num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
526 // Set insert point to current basic block.
527 irb_.SetInsertPoint(bb_iter);
528
529 current_bb_ = bb_iter;
530
531 // Rewrite the basic block
532 RewriteBasicBlock(bb_iter);
533
534 // Update the phi-instructions in the successor basic block
535 llvm::BasicBlock* last_block = irb_.GetInsertBlock();
536 if (last_block != bb_iter) {
537 UpdatePhiInstruction(bb_iter, last_block);
538 }
539 }
540
541 typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
542 HandlerPHIMap handler_phi;
543 // Iterate every used landing pad basic block
544 for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
545 llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
546 if (lbb == NULL) {
547 continue;
548 }
549
550 llvm::TerminatorInst* term_inst = lbb->getTerminator();
551 std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> >& rewrite_pair
552 = landing_pad_phi_mapping_[lbb];
553 irb_.SetInsertPoint(lbb->begin());
554
555 // Iterate every succeeding basic block (catch block)
556 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
557 succ_iter != succ_end; ++succ_iter) {
558 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
559
560 // Iterate every phi instructions in the succeeding basic block
561 for (llvm::BasicBlock::iterator
562 inst_iter = succ_basic_block->begin(),
563 inst_end = succ_basic_block->end();
564 inst_iter != inst_end; ++inst_iter) {
565 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
566
567 if (!phi) {
568 break; // Meet non-phi instruction. Done.
569 }
570
571 if (handler_phi[phi] == NULL) {
572 handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
573 }
574
575 // Create new_phi in landing pad
576 llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
577 // Insert all incoming value into new_phi by rewrite_pair
578 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
579 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
580 llvm::BasicBlock* new_bb = rewrite_pair[j].second;
581 new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
582 }
583 // Delete all incoming value from phi by rewrite_pair
584 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
585 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
586 int old_bb_idx = phi->getBasicBlockIndex(old_bb);
587 if (old_bb_idx >= 0) {
588 phi->removeIncomingValue(old_bb_idx, false);
589 }
590 }
591 // Insert new_phi into new handler phi
592 handler_phi[phi]->addIncoming(new_phi, lbb);
593 }
594 }
595 }
596
597 // Replace all handler phi
598 // We can't just use the old handler phi, because some exception edges will disappear after we
599 // compute fast-path.
600 for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
601 llvm::PHINode* old_phi = it->first;
602 llvm::PHINode* new_phi = it->second;
603 new_phi->insertBefore(old_phi);
604 old_phi->replaceAllUsesWith(new_phi);
605 old_phi->eraseFromParent();
606 }
607}
608
609void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
610 llvm::BasicBlock* new_basic_block) {
611 llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
612
613 if (!term_inst) {
614 return; // No terminating instruction in new_basic_block. Nothing to do.
615 }
616
617 // Iterate every succeeding basic block
618 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
619 succ_iter != succ_end; ++succ_iter) {
620 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
621
622 // Iterate every phi instructions in the succeeding basic block
623 for (llvm::BasicBlock::iterator
624 inst_iter = succ_basic_block->begin(),
625 inst_end = succ_basic_block->end();
626 inst_iter != inst_end; ++inst_iter) {
627 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
628
629 if (!phi) {
630 break; // Meet non-phi instruction. Done.
631 }
632
633 // Update the incoming block of this phi instruction
634 for (llvm::PHINode::block_iterator
635 ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
636 ibb_iter != ibb_end; ++ibb_iter) {
637 if (*ibb_iter == old_basic_block) {
638 *ibb_iter = new_basic_block;
639 }
640 }
641 }
642 }
643}
644
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700645llvm::Value* GBCExpanderPass::ExpandToRuntime(RuntimeId rt, llvm::CallInst& inst) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700646 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
647 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
648 // function, therefore only called function is needed to change.
649 unsigned num_args = inst.getNumArgOperands();
650
651 if (num_args <= 0) {
652 return irb_.CreateCall(irb_.GetRuntime(rt));
653 } else {
654 std::vector<llvm::Value*> args;
655 for (unsigned i = 0; i < num_args; i++) {
656 args.push_back(inst.getArgOperand(i));
657 }
658
659 return irb_.CreateCall(irb_.GetRuntime(rt), args);
660 }
661}
662
663void
664GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
665 llvm::Function* func = first_non_alloca->getParent()->getParent();
666 llvm::Module* module = func->getParent();
667
668 // Call llvm intrinsic function to get frame address.
669 llvm::Function* frameaddress =
670 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
671
672 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
673 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
674
675 // Cast i8* to int
676 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
677
678 // Get thread.stack_end_
679 llvm::Value* stack_end =
680 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
681 irb_.getPtrEquivIntTy(),
682 kTBAARuntimeInfo);
683
684 // Check the frame address < thread.stack_end_ ?
685 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
686
687 llvm::BasicBlock* block_exception =
688 llvm::BasicBlock::Create(context_, "stack_overflow", func);
689
690 llvm::BasicBlock* block_continue =
691 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
692
693 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
694
695 // If stack overflow, throw exception.
696 irb_.SetInsertPoint(block_exception);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700697 irb_.CreateCall(irb_.GetRuntime(ThrowStackOverflowException));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700698
699 // Unwind.
700 llvm::Type* ret_type = func->getReturnType();
701 if (ret_type->isVoidTy()) {
702 irb_.CreateRetVoid();
703 } else {
704 // The return value is ignored when there's an exception. MethodCompiler
705 // returns zero value under the the corresponding return type in this case.
706 // GBCExpander returns LLVM undef value here for brevity
707 irb_.CreateRet(llvm::UndefValue::get(ret_type));
708 }
709
710 irb_.SetInsertPoint(block_continue);
711}
712
713llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
714 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
715
716 return irb_.LoadFromObjectOffset(method_object_addr,
717 offset.Int32Value(),
718 irb_.getJObjectTy(),
719 kTBAAConstJObject);
720}
721
722llvm::Value*
723GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
724 llvm::Value* static_storage_dex_cache_addr =
725 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset());
726
727 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
728
729 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
730}
731
732llvm::Value*
733GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
734 llvm::Value* resolved_type_dex_cache_addr =
735 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedTypesOffset());
736
737 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
738
739 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
740}
741
742llvm::Value* GBCExpanderPass::
743EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
744 llvm::Value* resolved_method_dex_cache_addr =
745 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedMethodsOffset());
746
747 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
748
749 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
750}
751
752llvm::Value* GBCExpanderPass::
753EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
754 llvm::Value* string_dex_cache_addr =
755 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheStringsOffset());
756
757 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
758
759 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
760}
761
762llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
763 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
764 return parent_func->arg_begin();
765}
766
767llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
768 // Load array length
769 return irb_.LoadFromObjectOffset(array,
770 art::mirror::Array::LengthOffset().Int32Value(),
771 irb_.getJIntTy(),
772 kTBAAConstJObject);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700773}
774
775llvm::Value*
776GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
777 llvm::Value* callee_method_object_field_addr =
778 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
779
780 return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
781}
782
783llvm::Value* GBCExpanderPass::
784EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
785 // Load class object of *this* pointer
786 llvm::Value* class_object_addr =
787 irb_.LoadFromObjectOffset(this_addr,
788 art::mirror::Object::ClassOffset().Int32Value(),
789 irb_.getJObjectTy(),
790 kTBAAConstJObject);
791
792 // Load vtable address
793 llvm::Value* vtable_addr =
794 irb_.LoadFromObjectOffset(class_object_addr,
795 art::mirror::Class::VTableOffset().Int32Value(),
796 irb_.getJObjectTy(),
797 kTBAAConstJObject);
798
799 // Load callee method object
800 llvm::Value* vtable_idx_value =
801 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
802
803 llvm::Value* method_field_addr =
804 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
805
806 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
807}
808
809// Emit Array GetElementPtr
810llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
811 llvm::Value* index_value,
812 JType elem_jty) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700813 int data_offset;
814 if (elem_jty == kLong || elem_jty == kDouble ||
815 (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::mirror::Object*))) {
816 data_offset = art::mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
817 } else {
818 data_offset = art::mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
819 }
820
821 llvm::Constant* data_offset_value =
822 irb_.getPtrEquivInt(data_offset);
823
824 llvm::Type* elem_type = irb_.getJType(elem_jty);
825
826 llvm::Value* array_data_addr =
827 irb_.CreatePtrDisp(array_addr, data_offset_value,
828 elem_type->getPointerTo());
829
830 return irb_.CreateGEP(array_data_addr, index_value);
831}
832
833llvm::Value* GBCExpanderPass::EmitInvoke(llvm::CallInst& call_inst) {
834 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
835 art::InvokeType invoke_type =
836 static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
837 bool is_static = (invoke_type == art::kStatic);
838 art::MethodReference target_method(dex_compilation_unit_->GetDexFile(),
839 LV2UInt(call_inst.getArgOperand(1)));
840
841 // Load *this* actual parameter
842 llvm::Value* this_addr = (!is_static) ? call_inst.getArgOperand(3) : NULL;
843
844 // Compute invoke related information for compiler decision
845 int vtable_idx = -1;
846 uintptr_t direct_code = 0;
847 uintptr_t direct_method = 0;
848 bool is_fast_path = driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc,
849 invoke_type, target_method,
850 vtable_idx,
851 direct_code, direct_method,
852 true);
853 // Load the method object
854 llvm::Value* callee_method_object_addr = NULL;
855
856 if (!is_fast_path) {
857 callee_method_object_addr =
858 EmitCallRuntimeForCalleeMethodObjectAddr(target_method.dex_method_index, invoke_type,
859 this_addr, dex_pc, is_fast_path);
860 } else {
861 switch (invoke_type) {
862 case art::kStatic:
863 case art::kDirect:
864 if (direct_method != 0u &&
865 direct_method != static_cast<uintptr_t>(-1)) {
866 callee_method_object_addr =
867 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
868 irb_.getJObjectTy());
869 } else {
870 callee_method_object_addr =
871 EmitLoadSDCalleeMethodObjectAddr(target_method.dex_method_index);
872 }
873 break;
874
875 case art::kVirtual:
876 DCHECK(vtable_idx != -1);
877 callee_method_object_addr =
878 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
879 break;
880
881 case art::kSuper:
882 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
883 "the fast path.";
884 break;
885
886 case art::kInterface:
887 callee_method_object_addr =
888 EmitCallRuntimeForCalleeMethodObjectAddr(target_method.dex_method_index,
889 invoke_type, this_addr,
890 dex_pc, is_fast_path);
891 break;
892 }
893 }
894
895 // Load the actual parameter
896 std::vector<llvm::Value*> args;
897
898 args.push_back(callee_method_object_addr); // method object for callee
899
900 for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
901 args.push_back(call_inst.getArgOperand(i));
902 }
903
904 llvm::Value* code_addr;
905 llvm::Type* func_type = GetFunctionType(call_inst.getType(),
906 target_method.dex_method_index, is_static);
907 if (direct_code != 0u && direct_code != static_cast<uintptr_t>(-1)) {
908 code_addr =
909 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
910 func_type->getPointerTo());
911 } else {
912 code_addr =
913 irb_.LoadFromObjectOffset(callee_method_object_addr,
914 art::mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
915 func_type->getPointerTo(), kTBAARuntimeInfo);
916 }
917
918 // Invoke callee
919 EmitUpdateDexPC(dex_pc);
920 llvm::Value* retval = irb_.CreateCall(code_addr, args);
921 EmitGuard_ExceptionLandingPad(dex_pc);
922
923 return retval;
924}
925
926bool GBCExpanderPass::EmitIntrinsic(llvm::CallInst& call_inst,
927 llvm::Value** result) {
928 DCHECK(result != NULL);
929
930 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
931 std::string callee_method_name(
932 PrettyMethod(callee_method_idx, *dex_compilation_unit_->GetDexFile()));
933
934 if (callee_method_name == "int java.lang.String.length()") {
935 return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
936 false /* is_empty */);
937 }
938 if (callee_method_name == "boolean java.lang.String.isEmpty()") {
939 return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
940 true /* is_empty */);
941 }
942
943 *result = NULL;
944 return false;
945}
946
947bool GBCExpanderPass::EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
948 llvm::Value** result,
949 bool is_empty) {
950 art::InvokeType invoke_type =
951 static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
952 DCHECK_NE(invoke_type, art::kStatic);
953 DCHECK_EQ(call_inst.getNumArgOperands(), 4U);
954
955 llvm::Value* this_object = call_inst.getArgOperand(3);
956 llvm::Value* string_count =
957 irb_.LoadFromObjectOffset(this_object,
958 art::mirror::String::CountOffset().Int32Value(),
959 irb_.getJIntTy(),
960 kTBAAConstJObject);
961 if (is_empty) {
962 llvm::Value* count_equals_zero = irb_.CreateICmpEQ(string_count,
963 irb_.getJInt(0));
964 llvm::Value* is_empty = irb_.CreateSelect(count_equals_zero,
965 irb_.getJBoolean(true),
966 irb_.getJBoolean(false));
967 is_empty = SignOrZeroExtendCat1Types(is_empty, kBoolean);
968 *result = is_empty;
969 } else {
970 *result = string_count;
971 }
972 return true;
973}
974
975void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
976 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
977
978 llvm::Value* suspend_count =
979 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
980 irb_.getInt16Ty(),
981 kTBAARuntimeInfo);
982 llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
983
984 llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
985 llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
986
987 irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
988
989 irb_.SetInsertPoint(basic_block_suspend);
990 if (dex_pc != art::DexFile::kDexNoIndex) {
991 EmitUpdateDexPC(dex_pc);
992 }
993 irb_.Runtime().EmitTestSuspend();
994
995 llvm::BasicBlock* basic_block_exception = CreateBasicBlockWithDexPC(dex_pc, "exception");
996 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
997 irb_.CreateCondBr(exception_pending, basic_block_exception, basic_block_cont, kUnlikely);
998
999 irb_.SetInsertPoint(basic_block_exception);
1000 llvm::Type* ret_type = call_inst.getParent()->getParent()->getReturnType();
1001 if (ret_type->isVoidTy()) {
1002 irb_.CreateRetVoid();
1003 } else {
1004 // The return value is ignored when there's an exception.
1005 irb_.CreateRet(llvm::UndefValue::get(ret_type));
1006 }
1007
1008 irb_.SetInsertPoint(basic_block_cont);
1009 return;
1010}
1011
1012void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
1013 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
1014 return;
1015}
1016
1017llvm::Value*
1018GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
1019 uint32_t string_idx =
1020 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
1021
1022 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1023
1024 return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
1025}
1026
1027llvm::Value*
1028GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
1029 uint32_t type_idx =
1030 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
1031
1032 llvm::Value* type_field_addr =
1033 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1034
1035 return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
1036}
1037
1038void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
1039 rtb_.EmitLockObject(obj);
1040 return;
1041}
1042
1043void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
1044 rtb_.EmitUnlockObject(obj);
1045 return;
1046}
1047
1048llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
1049 llvm::Value* index_value,
1050 JType elem_jty) {
1051 llvm::Value* array_elem_addr =
1052 EmitArrayGEP(array_addr, index_value, elem_jty);
1053
1054 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1055}
1056
1057void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
1058 llvm::Value* array_addr,
1059 llvm::Value* index_value,
1060 JType elem_jty) {
1061 llvm::Value* array_elem_addr =
1062 EmitArrayGEP(array_addr, index_value, elem_jty);
1063
1064 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1065
1066 return;
1067}
1068
1069void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
1070 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
1071 llvm::Value* array = call_inst.getArgOperand(0);
1072
1073 uint32_t element_jty =
1074 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
1075
1076 DCHECK(call_inst.getNumArgOperands() > 2);
1077 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
1078
1079 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
1080
1081 uint32_t alignment;
1082 llvm::Constant* elem_size;
1083 llvm::PointerType* field_type;
1084
1085 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
1086 // as the element, thus we are only checking 2 cases: primitive int and
1087 // non-primitive type.
1088 if (is_elem_int_ty) {
1089 alignment = sizeof(int32_t);
1090 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
1091 field_type = irb_.getJIntTy()->getPointerTo();
1092 } else {
1093 alignment = irb_.getSizeOfPtrEquivInt();
1094 elem_size = irb_.getSizeOfPtrEquivIntValue();
1095 field_type = irb_.getJObjectTy()->getPointerTo();
1096 }
1097
1098 llvm::Value* data_field_offset =
1099 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
1100
1101 llvm::Value* data_field_addr =
1102 irb_.CreatePtrDisp(array, data_field_offset, field_type);
1103
1104 for (unsigned i = 0; i < num_elements; ++i) {
1105 // Values to fill the array begin at the 3rd argument
1106 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
1107
1108 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
1109
1110 data_field_addr =
1111 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
1112 }
1113
1114 return;
1115}
1116
1117llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
1118 llvm::Value* /*is_volatile_value*/,
1119 llvm::Value* object_addr,
1120 JType field_jty) {
1121 int field_offset =
1122 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1123
1124 DCHECK_GE(field_offset, 0);
1125
1126 llvm::PointerType* field_type =
1127 irb_.getJType(field_jty)->getPointerTo();
1128
1129 field_offset_value = irb_.getPtrEquivInt(field_offset);
1130
1131 llvm::Value* field_addr =
1132 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1133
1134 // TODO: Check is_volatile. We need to generate atomic load instruction
1135 // when is_volatile is true.
1136 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1137}
1138
1139void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
1140 llvm::Value* /* is_volatile_value */,
1141 llvm::Value* object_addr,
1142 llvm::Value* new_value,
1143 JType field_jty) {
1144 int field_offset =
1145 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1146
1147 DCHECK_GE(field_offset, 0);
1148
1149 llvm::PointerType* field_type =
1150 irb_.getJType(field_jty)->getPointerTo();
1151
1152 field_offset_value = irb_.getPtrEquivInt(field_offset);
1153
1154 llvm::Value* field_addr =
1155 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1156
1157 // TODO: Check is_volatile. We need to generate atomic store instruction
1158 // when is_volatile is true.
1159 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1160
1161 return;
1162}
1163
1164llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
1165 llvm::Value* field_offset_value,
1166 llvm::Value* /*is_volatile_value*/,
1167 JType field_jty) {
1168 int field_offset =
1169 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1170
1171 DCHECK_GE(field_offset, 0);
1172
1173 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1174
1175 llvm::Value* static_field_addr =
1176 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1177 irb_.getJType(field_jty)->getPointerTo());
1178
1179 // TODO: Check is_volatile. We need to generate atomic store instruction
1180 // when is_volatile is true.
1181 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1182}
1183
1184void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
1185 llvm::Value* field_offset_value,
1186 llvm::Value* /* is_volatile_value */,
1187 llvm::Value* new_value,
1188 JType field_jty) {
1189 int field_offset =
1190 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1191
1192 DCHECK_GE(field_offset, 0);
1193
1194 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1195
1196 llvm::Value* static_field_addr =
1197 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1198 irb_.getJType(field_jty)->getPointerTo());
1199
1200 // TODO: Check is_volatile. We need to generate atomic store instruction
1201 // when is_volatile is true.
1202 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1203
1204 return;
1205}
1206
1207llvm::Value*
1208GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
1209 return irb_.LoadFromObjectOffset(method_object_addr,
1210 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
1211 irb_.getJObjectTy(),
1212 kTBAAConstJObject);
1213}
1214
1215llvm::Value*
1216GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
1217 uint32_t type_idx =
1218 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
1219
1220 llvm::Value* storage_field_addr =
1221 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1222
1223 return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
1224}
1225
1226llvm::Value*
1227GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
1228 uint32_t callee_method_idx =
1229 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
1230
1231 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
1232}
1233
1234llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
1235 llvm::Value* vtable_idx_value,
1236 llvm::Value* this_addr) {
1237 int vtable_idx =
1238 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
1239
1240 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
1241}
1242
1243llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
1244 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
1245 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
1246 unsigned num_args = call_inst.getNumArgOperands();
1247 llvm::Type* ret_type = call_inst.getType();
1248
1249 // Determine the function type of the callee method
1250 std::vector<llvm::Type*> args_type;
1251 std::vector<llvm::Value*> args;
1252 for (unsigned i = 0; i < num_args; i++) {
1253 args.push_back(call_inst.getArgOperand(i));
1254 args_type.push_back(args[i]->getType());
1255 }
1256
1257 llvm::FunctionType* callee_method_type =
1258 llvm::FunctionType::get(ret_type, args_type, false);
1259
1260 llvm::Value* code_addr =
1261 irb_.LoadFromObjectOffset(callee_method_object_addr,
1262 art::mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
1263 callee_method_type->getPointerTo(),
1264 kTBAARuntimeInfo);
1265
1266 // Invoke callee
1267 llvm::Value* retval = irb_.CreateCall(code_addr, args);
1268
1269 return retval;
1270}
1271
1272llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
1273 bool is_div, JType op_jty) {
1274 llvm::Value* dividend = call_inst.getArgOperand(0);
1275 llvm::Value* divisor = call_inst.getArgOperand(1);
1276 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1277 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
1278 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
1279
1280 // Check the special case: MININT / -1 = MININT
1281 // That case will cause overflow, which is undefined behavior in llvm.
1282 // So we check the divisor is -1 or not, if the divisor is -1, we do
1283 // the special path to avoid undefined behavior.
1284 llvm::Type* op_type = irb_.getJType(op_jty);
1285 llvm::Value* zero = irb_.getJZero(op_jty);
1286 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
1287
1288 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
1289 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1290 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1291 llvm::BasicBlock* neg_one_cont =
1292 llvm::BasicBlock::Create(context_, "", parent);
1293
1294 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
1295 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
1296
1297 // If divisor == -1
1298 irb_.SetInsertPoint(eq_neg_one);
1299 llvm::Value* eq_result;
1300 if (is_div) {
1301 // We can just change from "dividend div -1" to "neg dividend". The sub
1302 // don't care the sign/unsigned because of two's complement representation.
1303 // And the behavior is what we want:
1304 // -(2^n) (2^n)-1
1305 // MININT < k <= MAXINT -> mul k -1 = -k
1306 // MININT == k -> mul k -1 = k
1307 //
1308 // LLVM use sub to represent 'neg'
1309 eq_result = irb_.CreateSub(zero, dividend);
1310 } else {
1311 // Everything modulo -1 will be 0.
1312 eq_result = zero;
1313 }
1314 irb_.CreateBr(neg_one_cont);
1315
1316 // If divisor != -1, just do the division.
1317 irb_.SetInsertPoint(ne_neg_one);
1318 llvm::Value* ne_result;
1319 if (is_div) {
1320 ne_result = irb_.CreateSDiv(dividend, divisor);
1321 } else {
1322 ne_result = irb_.CreateSRem(dividend, divisor);
1323 }
1324 irb_.CreateBr(neg_one_cont);
1325
1326 irb_.SetInsertPoint(neg_one_cont);
1327 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
1328 result->addIncoming(eq_result, eq_neg_one);
1329 result->addIncoming(ne_result, ne_neg_one);
1330
1331 return result;
1332}
1333
1334void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
1335 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
1336 // MethodCompiler::EmitPushShadowFrame
1337 uint16_t num_vregs =
1338 llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
1339
1340 llvm::StructType* shadow_frame_type =
1341 irb_.getShadowFrameTy(num_vregs);
1342
1343 // Create allocas at the start of entry block.
1344 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1345 llvm::BasicBlock* entry_block = &func_->front();
1346 irb_.SetInsertPoint(&entry_block->front());
1347
1348 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
1349
1350 // Alloca a pointer to old shadow frame
1351 old_shadow_frame_ =
1352 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
1353
1354 irb_.restoreIP(irb_ip_original);
1355
1356 // Push the shadow frame
1357 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1358
1359 llvm::Value* shadow_frame_upcast =
1360 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1361
1362 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1363 method_object_addr,
1364 num_vregs);
1365
1366 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1367
1368 return;
1369}
1370
1371void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
1372 llvm::Value* value) {
1373 unsigned vreg_idx = LV2UInt(entry_idx);
1374 DCHECK_LT(vreg_idx, dex_compilation_unit_->GetCodeItem()->registers_size_);
1375
1376 llvm::Value* vreg_addr = shadow_frame_vreg_addresses_[vreg_idx];
1377 if (UNLIKELY(vreg_addr == NULL)) {
1378 DCHECK(shadow_frame_ != NULL);
1379
1380 llvm::Value* gep_index[] = {
1381 irb_.getInt32(0), // No pointer displacement
1382 irb_.getInt32(1), // VRegs
1383 entry_idx // Pointer field
1384 };
1385
1386 // A shadow frame address must dominate every use in the function so we
1387 // place it in the entry block right after the allocas.
1388 llvm::BasicBlock::iterator first_non_alloca = func_->getEntryBlock().begin();
1389 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1390 ++first_non_alloca;
1391 }
1392
1393 llvm::IRBuilderBase::InsertPoint ip = irb_.saveIP();
1394 irb_.SetInsertPoint(static_cast<llvm::Instruction*>(first_non_alloca));
1395 vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1396 shadow_frame_vreg_addresses_[vreg_idx] = vreg_addr;
1397 irb_.restoreIP(ip);
1398 }
1399
1400 irb_.CreateStore(value,
1401 irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
1402 kTBAAShadowFrame);
1403 return;
1404}
1405
1406void GBCExpanderPass::Expand_PopShadowFrame() {
1407 if (old_shadow_frame_ == NULL) {
1408 return;
1409 }
1410 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1411 return;
1412}
1413
1414void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1415 irb_.StoreToObjectOffset(shadow_frame_,
1416 art::ShadowFrame::DexPCOffset(),
1417 dex_pc_value,
1418 kTBAAShadowFrame);
1419 return;
1420}
1421
1422void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
1423 // All alloca instructions are generated in the first basic block of the
1424 // function, and there are no alloca instructions after the first non-alloca
1425 // instruction.
1426
1427 llvm::BasicBlock* first_basic_block = &func.front();
1428
1429 // Look for first non-alloca instruction
1430 llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
1431 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1432 ++first_non_alloca;
1433 }
1434
1435 irb_.SetInsertPoint(first_non_alloca);
1436
1437 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1438 // alloca instructions)
1439 EmitStackOverflowCheck(&*first_non_alloca);
1440
1441 irb_.Runtime().EmitTestSuspend();
1442
1443 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
1444 if (next_basic_block != first_basic_block) {
1445 // Splice the rest of the instruction to the continuing basic block
1446 next_basic_block->getInstList().splice(
1447 irb_.GetInsertPoint(), first_basic_block->getInstList(),
1448 first_non_alloca, first_basic_block->end());
1449
1450 // Rewrite the basic block
1451 RewriteBasicBlock(next_basic_block);
1452
1453 // Update the phi-instructions in the successor basic block
1454 UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
1455 }
1456
1457 // We have changed the basic block
1458 changed_ = true;
1459}
1460
1461// ==== High-level intrinsic expander ==========================================
1462
1463llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1464 llvm::Value* src2_value,
1465 bool gt_bias) {
1466 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1467 llvm::Value* cmp_lt;
1468
1469 if (gt_bias) {
1470 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1471 } else {
1472 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1473 }
1474
1475 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1476}
1477
1478llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1479 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1480 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1481
1482 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1483}
1484
1485llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1486 llvm::Value* cmp_lt) {
Brian Carlstrom7940e442013-07-12 13:46:57 -07001487 llvm::Constant* zero = irb_.getJInt(0);
1488 llvm::Constant* pos1 = irb_.getJInt(1);
1489 llvm::Constant* neg1 = irb_.getJInt(-1);
1490
1491 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1492 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1493
1494 return result_eq;
1495}
1496
1497llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1498 llvm::Value* src2_value,
1499 IntegerShiftKind kind,
1500 JType op_jty) {
1501 DCHECK(op_jty == kInt || op_jty == kLong);
1502
1503 // Mask and zero-extend RHS properly
1504 if (op_jty == kInt) {
1505 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1506 } else {
1507 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1508 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1509 }
1510
1511 // Create integer shift llvm instruction
1512 switch (kind) {
1513 case kIntegerSHL:
1514 return irb_.CreateShl(src1_value, src2_value);
1515
1516 case kIntegerSHR:
1517 return irb_.CreateAShr(src1_value, src2_value);
1518
1519 case kIntegerUSHR:
1520 return irb_.CreateLShr(src1_value, src2_value);
1521
1522 default:
1523 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1524 return NULL;
1525 }
1526}
1527
1528llvm::Value* GBCExpanderPass::SignOrZeroExtendCat1Types(llvm::Value* value, JType jty) {
1529 switch (jty) {
1530 case kBoolean:
1531 case kChar:
1532 return irb_.CreateZExt(value, irb_.getJType(kInt));
1533 case kByte:
1534 case kShort:
1535 return irb_.CreateSExt(value, irb_.getJType(kInt));
1536 case kVoid:
1537 case kInt:
1538 case kLong:
1539 case kFloat:
1540 case kDouble:
1541 case kObject:
1542 return value; // Nothing to do.
1543 default:
1544 LOG(FATAL) << "Unknown java type: " << jty;
1545 return NULL;
1546 }
1547}
1548
1549llvm::Value* GBCExpanderPass::TruncateCat1Types(llvm::Value* value, JType jty) {
1550 switch (jty) {
1551 case kBoolean:
1552 case kChar:
1553 case kByte:
1554 case kShort:
1555 return irb_.CreateTrunc(value, irb_.getJType(jty));
1556 case kVoid:
1557 case kInt:
1558 case kLong:
1559 case kFloat:
1560 case kDouble:
1561 case kObject:
1562 return value; // Nothing to do.
1563 default:
1564 LOG(FATAL) << "Unknown java type: " << jty;
1565 return NULL;
1566 }
1567}
1568
1569llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1570 JType elem_jty) {
1571 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1572 llvm::Value* array_addr = call_inst.getArgOperand(1);
1573 llvm::Value* index_value = call_inst.getArgOperand(2);
1574 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1575
1576 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
1577 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
1578 opt_flags);
1579
1580 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1581
1582 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1583
1584 return SignOrZeroExtendCat1Types(array_elem_value, elem_jty);
1585}
1586
1587
1588void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1589 JType elem_jty) {
1590 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1591 llvm::Value* new_value = call_inst.getArgOperand(1);
1592 llvm::Value* array_addr = call_inst.getArgOperand(2);
1593 llvm::Value* index_value = call_inst.getArgOperand(3);
1594 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1595
1596 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
1597 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
1598 opt_flags);
1599
1600 new_value = TruncateCat1Types(new_value, elem_jty);
1601
1602 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1603
1604 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001605 llvm::Function* runtime_func = irb_.GetRuntime(CheckPutArrayElement);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001606
1607 irb_.CreateCall2(runtime_func, new_value, array_addr);
1608
1609 EmitGuard_ExceptionLandingPad(dex_pc);
1610
1611 EmitMarkGCCard(new_value, array_addr);
1612 }
1613
1614 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1615
1616 return;
1617}
1618
1619llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1620 JType field_jty) {
1621 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1622 llvm::Value* object_addr = call_inst.getArgOperand(1);
1623 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
1624 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1625
1626 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
1627
1628 llvm::Value* field_value;
1629
1630 int field_offset;
1631 bool is_volatile;
1632 bool is_fast_path = driver_->ComputeInstanceFieldInfo(
1633 field_idx, dex_compilation_unit_, field_offset, is_volatile, false);
1634
1635 if (!is_fast_path) {
1636 llvm::Function* runtime_func;
1637
1638 if (field_jty == kObject) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001639 runtime_func = irb_.GetRuntime(GetObjectInstance);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001640 } else if (field_jty == kLong || field_jty == kDouble) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001641 runtime_func = irb_.GetRuntime(Get64Instance);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001642 } else {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001643 runtime_func = irb_.GetRuntime(Get32Instance);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001644 }
1645
1646 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1647
1648 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1649
1650 EmitUpdateDexPC(dex_pc);
1651
1652 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1653 method_object_addr, object_addr);
1654
1655 EmitGuard_ExceptionLandingPad(dex_pc);
1656
1657 if (field_jty == kFloat || field_jty == kDouble) {
1658 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty));
1659 }
1660 } else {
1661 DCHECK_GE(field_offset, 0);
1662
1663 llvm::PointerType* field_type =
1664 irb_.getJType(field_jty)->getPointerTo();
1665
1666 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1667
1668 llvm::Value* field_addr =
1669 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1670
1671 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1672 field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
1673
1674 if (is_volatile) {
1675 irb_.CreateMemoryBarrier(art::kLoadLoad);
1676 }
1677 }
1678
1679 return field_value;
1680}
1681
1682void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1683 JType field_jty) {
1684 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1685 llvm::Value* new_value = call_inst.getArgOperand(1);
1686 llvm::Value* object_addr = call_inst.getArgOperand(2);
1687 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
1688 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1689
1690 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
1691
1692 int field_offset;
1693 bool is_volatile;
1694 bool is_fast_path = driver_->ComputeInstanceFieldInfo(
1695 field_idx, dex_compilation_unit_, field_offset, is_volatile, true);
1696
1697 if (!is_fast_path) {
1698 llvm::Function* runtime_func;
1699
1700 if (field_jty == kFloat) {
1701 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
1702 } else if (field_jty == kDouble) {
1703 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
1704 }
1705
1706 if (field_jty == kObject) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001707 runtime_func = irb_.GetRuntime(SetObjectInstance);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001708 } else if (field_jty == kLong || field_jty == kDouble) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001709 runtime_func = irb_.GetRuntime(Set64Instance);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001710 } else {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001711 runtime_func = irb_.GetRuntime(Set32Instance);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001712 }
1713
1714 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1715
1716 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1717
1718 EmitUpdateDexPC(dex_pc);
1719
1720 irb_.CreateCall4(runtime_func, field_idx_value,
1721 method_object_addr, object_addr, new_value);
1722
1723 EmitGuard_ExceptionLandingPad(dex_pc);
1724
1725 } else {
1726 DCHECK_GE(field_offset, 0);
1727
1728 if (is_volatile) {
1729 irb_.CreateMemoryBarrier(art::kStoreStore);
1730 }
1731
1732 llvm::PointerType* field_type =
1733 irb_.getJType(field_jty)->getPointerTo();
1734
1735 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1736
1737 llvm::Value* field_addr =
1738 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1739
1740 new_value = TruncateCat1Types(new_value, field_jty);
1741 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1742
1743 if (is_volatile) {
1744 irb_.CreateMemoryBarrier(art::kLoadLoad);
1745 }
1746
1747 if (field_jty == kObject) { // If put an object, mark the GC card table.
1748 EmitMarkGCCard(new_value, object_addr);
1749 }
1750 }
1751
1752 return;
1753}
1754
1755llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1756 uint32_t type_idx) {
1757 if (!driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
1758 *dex_compilation_unit_->GetDexFile(), type_idx)) {
1759 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1760
1761 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1762
1763 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1764
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001765 llvm::Function* runtime_func = irb_.GetRuntime(InitializeTypeAndVerifyAccess);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001766
1767 EmitUpdateDexPC(dex_pc);
1768
1769 llvm::Value* type_object_addr =
1770 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1771
1772 EmitGuard_ExceptionLandingPad(dex_pc);
1773
1774 return type_object_addr;
1775
1776 } else {
1777 // Try to load the class (type) object from the test cache.
1778 llvm::Value* type_field_addr =
1779 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1780
1781 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
1782
1783 if (driver_->CanAssumeTypeIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(), type_idx)) {
1784 return type_object_addr;
1785 }
1786
1787 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1788
1789 // Test whether class (type) object is in the dex cache or not
1790 llvm::Value* equal_null =
1791 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1792
1793 llvm::BasicBlock* block_cont =
1794 CreateBasicBlockWithDexPC(dex_pc, "cont");
1795
1796 llvm::BasicBlock* block_load_class =
1797 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1798
1799 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1800
1801 // Failback routine to load the class object
1802 irb_.SetInsertPoint(block_load_class);
1803
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001804 llvm::Function* runtime_func = irb_.GetRuntime(InitializeType);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001805
1806 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1807
1808 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1809
1810 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1811
1812 EmitUpdateDexPC(dex_pc);
1813
1814 llvm::Value* loaded_type_object_addr =
1815 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1816
1817 EmitGuard_ExceptionLandingPad(dex_pc);
1818
1819 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1820
1821 irb_.CreateBr(block_cont);
1822
1823 // Now the class object must be loaded
1824 irb_.SetInsertPoint(block_cont);
1825
1826 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1827
1828 phi->addIncoming(type_object_addr, block_original);
1829 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1830
1831 return phi;
1832 }
1833}
1834
1835llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1836 uint32_t type_idx) {
1837 llvm::BasicBlock* block_load_static =
1838 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1839
1840 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1841
1842 // Load static storage from dex cache
1843 llvm::Value* storage_field_addr =
1844 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1845
1846 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
1847
1848 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1849
1850 // Test: Is the static storage of this class initialized?
1851 llvm::Value* equal_null =
1852 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1853
1854 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1855
1856 // Failback routine to load the class object
1857 irb_.SetInsertPoint(block_load_static);
1858
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001859 llvm::Function* runtime_func = irb_.GetRuntime(InitializeStaticStorage);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001860
1861 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1862
1863 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1864
1865 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1866
1867 EmitUpdateDexPC(dex_pc);
1868
1869 llvm::Value* loaded_storage_object_addr =
1870 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1871
1872 EmitGuard_ExceptionLandingPad(dex_pc);
1873
1874 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1875
1876 irb_.CreateBr(block_cont);
1877
1878 // Now the class object must be loaded
1879 irb_.SetInsertPoint(block_cont);
1880
1881 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1882
1883 phi->addIncoming(storage_object_addr, block_original);
1884 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1885
1886 return phi;
1887}
1888
1889llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1890 JType field_jty) {
1891 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1892 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1893
1894 int field_offset;
1895 int ssb_index;
1896 bool is_referrers_class;
1897 bool is_volatile;
1898
1899 bool is_fast_path = driver_->ComputeStaticFieldInfo(
1900 field_idx, dex_compilation_unit_, field_offset, ssb_index,
1901 is_referrers_class, is_volatile, false);
1902
1903 llvm::Value* static_field_value;
1904
1905 if (!is_fast_path) {
1906 llvm::Function* runtime_func;
1907
1908 if (field_jty == kObject) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001909 runtime_func = irb_.GetRuntime(GetObjectStatic);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001910 } else if (field_jty == kLong || field_jty == kDouble) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001911 runtime_func = irb_.GetRuntime(Get64Static);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001912 } else {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001913 runtime_func = irb_.GetRuntime(Get32Static);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001914 }
1915
1916 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1917
1918 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1919
1920 EmitUpdateDexPC(dex_pc);
1921
1922 static_field_value =
1923 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1924
1925 EmitGuard_ExceptionLandingPad(dex_pc);
1926
1927 if (field_jty == kFloat || field_jty == kDouble) {
1928 static_field_value = irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty));
1929 }
1930 } else {
1931 DCHECK_GE(field_offset, 0);
1932
1933 llvm::Value* static_storage_addr = NULL;
1934
1935 if (is_referrers_class) {
1936 // Fast path, static storage base is this method's class
1937 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1938
1939 static_storage_addr =
1940 irb_.LoadFromObjectOffset(method_object_addr,
1941 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
1942 irb_.getJObjectTy(),
1943 kTBAAConstJObject);
1944 } else {
1945 // Medium path, static storage base in a different class which
1946 // requires checks that the other class is initialized
1947 DCHECK_GE(ssb_index, 0);
1948 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1949 }
1950
1951 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1952
1953 llvm::Value* static_field_addr =
1954 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1955 irb_.getJType(field_jty)->getPointerTo());
1956
1957 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1958 static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
1959
1960 if (is_volatile) {
1961 irb_.CreateMemoryBarrier(art::kLoadLoad);
1962 }
1963 }
1964
1965 return static_field_value;
1966}
1967
1968void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1969 JType field_jty) {
1970 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1971 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1972 llvm::Value* new_value = call_inst.getArgOperand(1);
1973
1974 if (field_jty == kFloat || field_jty == kDouble) {
1975 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
1976 }
1977
1978 int field_offset;
1979 int ssb_index;
1980 bool is_referrers_class;
1981 bool is_volatile;
1982
1983 bool is_fast_path = driver_->ComputeStaticFieldInfo(
1984 field_idx, dex_compilation_unit_, field_offset, ssb_index,
1985 is_referrers_class, is_volatile, true);
1986
1987 if (!is_fast_path) {
1988 llvm::Function* runtime_func;
1989
1990 if (field_jty == kObject) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001991 runtime_func = irb_.GetRuntime(SetObjectStatic);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001992 } else if (field_jty == kLong || field_jty == kDouble) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001993 runtime_func = irb_.GetRuntime(Set64Static);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001994 } else {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07001995 runtime_func = irb_.GetRuntime(Set32Static);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001996 }
1997
1998 if (field_jty == kFloat) {
1999 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
2000 } else if (field_jty == kDouble) {
2001 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
2002 }
2003
2004 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
2005
2006 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2007
2008 EmitUpdateDexPC(dex_pc);
2009
2010 irb_.CreateCall3(runtime_func, field_idx_value,
2011 method_object_addr, new_value);
2012
2013 EmitGuard_ExceptionLandingPad(dex_pc);
2014
2015 } else {
2016 DCHECK_GE(field_offset, 0);
2017
2018 llvm::Value* static_storage_addr = NULL;
2019
2020 if (is_referrers_class) {
2021 // Fast path, static storage base is this method's class
2022 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2023
2024 static_storage_addr =
2025 irb_.LoadFromObjectOffset(method_object_addr,
2026 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
2027 irb_.getJObjectTy(),
2028 kTBAAConstJObject);
2029 } else {
2030 // Medium path, static storage base in a different class which
2031 // requires checks that the other class is initialized
2032 DCHECK_GE(ssb_index, 0);
2033 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
2034 }
2035
2036 if (is_volatile) {
2037 irb_.CreateMemoryBarrier(art::kStoreStore);
2038 }
2039
2040 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
2041
2042 llvm::Value* static_field_addr =
2043 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
2044 irb_.getJType(field_jty)->getPointerTo());
2045
2046 new_value = TruncateCat1Types(new_value, field_jty);
2047 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
2048
2049 if (is_volatile) {
2050 irb_.CreateMemoryBarrier(art::kStoreLoad);
2051 }
2052
2053 if (field_jty == kObject) { // If put an object, mark the GC card table.
2054 EmitMarkGCCard(new_value, static_storage_addr);
2055 }
2056 }
2057
2058 return;
2059}
2060
2061llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
2062 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2063 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
2064
2065 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
2066
2067 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
2068
2069 if (!driver_->CanAssumeStringIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(),
2070 string_idx)) {
2071 llvm::BasicBlock* block_str_exist =
2072 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
2073
2074 llvm::BasicBlock* block_str_resolve =
2075 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
2076
2077 llvm::BasicBlock* block_cont =
2078 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
2079
2080 // Test: Is the string resolved and in the dex cache?
2081 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
2082
2083 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
2084
2085 // String is resolved, go to next basic block.
2086 irb_.SetInsertPoint(block_str_exist);
2087 irb_.CreateBr(block_cont);
2088
2089 // String is not resolved yet, resolve it now.
2090 irb_.SetInsertPoint(block_str_resolve);
2091
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002092 llvm::Function* runtime_func = irb_.GetRuntime(ResolveString);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002093
2094 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2095
2096 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
2097
2098 EmitUpdateDexPC(dex_pc);
2099
2100 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
2101 string_idx_value);
2102
2103 EmitGuard_ExceptionLandingPad(dex_pc);
2104
2105 irb_.CreateBr(block_cont);
2106
2107
2108 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
2109
2110 irb_.SetInsertPoint(block_cont);
2111
2112 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
2113
2114 phi->addIncoming(string_addr, block_str_exist);
2115 phi->addIncoming(result, block_pre_cont);
2116
2117 string_addr = phi;
2118 }
2119
2120 return string_addr;
2121}
2122
2123llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
2124 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2125 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2126
2127 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2128
2129 return type_object_addr;
2130}
2131
2132void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
2133 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2134 llvm::Value* object_addr = call_inst.getArgOperand(1);
2135 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
2136
2137 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
2138
2139 EmitUpdateDexPC(dex_pc);
2140
2141 irb_.Runtime().EmitLockObject(object_addr);
2142
2143 return;
2144}
2145
2146void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
2147 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2148 llvm::Value* object_addr = call_inst.getArgOperand(1);
2149 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
2150
2151 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
2152
2153 EmitUpdateDexPC(dex_pc);
2154
2155 irb_.Runtime().EmitUnlockObject(object_addr);
2156
2157 EmitGuard_ExceptionLandingPad(dex_pc);
2158
2159 return;
2160}
2161
2162void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
2163 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2164 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2165 llvm::Value* object_addr = call_inst.getArgOperand(1);
2166
2167 llvm::BasicBlock* block_test_class =
2168 CreateBasicBlockWithDexPC(dex_pc, "test_class");
2169
2170 llvm::BasicBlock* block_test_sub_class =
2171 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2172
2173 llvm::BasicBlock* block_cont =
2174 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
2175
2176 // Test: Is the reference equal to null? Act as no-op when it is null.
2177 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2178
2179 irb_.CreateCondBr(equal_null, block_cont, block_test_class, kUnlikely);
2180
2181 // Test: Is the object instantiated from the given class?
2182 irb_.SetInsertPoint(block_test_class);
2183 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2184 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
2185
2186 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2187
2188 llvm::Value* object_type_field_addr =
2189 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2190
2191 llvm::Value* object_type_object_addr =
2192 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2193
2194 llvm::Value* equal_class =
2195 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2196
2197 irb_.CreateCondBr(equal_class, block_cont, block_test_sub_class, kLikely);
2198
2199 // Test: Is the object instantiated from the subclass of the given class?
2200 irb_.SetInsertPoint(block_test_sub_class);
2201
2202 EmitUpdateDexPC(dex_pc);
2203
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002204 irb_.CreateCall2(irb_.GetRuntime(CheckCast),
Brian Carlstrom7940e442013-07-12 13:46:57 -07002205 type_object_addr, object_type_object_addr);
2206
2207 EmitGuard_ExceptionLandingPad(dex_pc);
2208
2209 irb_.CreateBr(block_cont);
2210
2211 irb_.SetInsertPoint(block_cont);
2212
2213 return;
2214}
2215
2216llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
2217 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2218 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2219 llvm::Value* object_addr = call_inst.getArgOperand(1);
2220
2221 llvm::BasicBlock* block_nullp =
2222 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2223
2224 llvm::BasicBlock* block_test_class =
2225 CreateBasicBlockWithDexPC(dex_pc, "test_class");
2226
2227 llvm::BasicBlock* block_class_equals =
2228 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
2229
2230 llvm::BasicBlock* block_test_sub_class =
2231 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2232
2233 llvm::BasicBlock* block_cont =
2234 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
2235
2236 // Overview of the following code :
2237 // We check for null, if so, then false, otherwise check for class == . If so
2238 // then true, otherwise do callout slowpath.
2239 //
2240 // Test: Is the reference equal to null? Set 0 when it is null.
2241 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2242
2243 irb_.CreateCondBr(equal_null, block_nullp, block_test_class, kUnlikely);
2244
2245 irb_.SetInsertPoint(block_nullp);
2246 irb_.CreateBr(block_cont);
2247
2248 // Test: Is the object instantiated from the given class?
2249 irb_.SetInsertPoint(block_test_class);
2250 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2251 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
2252
2253 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2254
2255 llvm::Value* object_type_field_addr =
2256 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2257
2258 llvm::Value* object_type_object_addr =
2259 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2260
2261 llvm::Value* equal_class =
2262 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2263
2264 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class, kLikely);
2265
2266 irb_.SetInsertPoint(block_class_equals);
2267 irb_.CreateBr(block_cont);
2268
2269 // Test: Is the object instantiated from the subclass of the given class?
2270 irb_.SetInsertPoint(block_test_sub_class);
2271 llvm::Value* result =
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002272 irb_.CreateCall2(irb_.GetRuntime(IsAssignable),
Brian Carlstrom7940e442013-07-12 13:46:57 -07002273 type_object_addr, object_type_object_addr);
2274 irb_.CreateBr(block_cont);
2275
2276 irb_.SetInsertPoint(block_cont);
2277
2278 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
2279
2280 phi->addIncoming(irb_.getJInt(0), block_nullp);
2281 phi->addIncoming(irb_.getJInt(1), block_class_equals);
2282 phi->addIncoming(result, block_test_sub_class);
2283
2284 return phi;
2285}
2286
2287llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
2288 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2289 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2290
2291 llvm::Function* runtime_func;
2292 if (driver_->CanAccessInstantiableTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
2293 *dex_compilation_unit_->GetDexFile(),
2294 type_idx)) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002295 runtime_func = irb_.GetRuntime(AllocObject);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002296 } else {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002297 runtime_func = irb_.GetRuntime(AllocObjectWithAccessCheck);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002298 }
2299
2300 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2301
2302 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2303
2304 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2305
2306 EmitUpdateDexPC(dex_pc);
2307
2308 llvm::Value* object_addr =
2309 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
2310
2311 EmitGuard_ExceptionLandingPad(dex_pc);
2312
2313 return object_addr;
2314}
2315
2316llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
2317 art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
2318 bool is_static = (invoke_type == art::kStatic);
2319
2320 if (!is_static) {
2321 // Test: Is *this* parameter equal to null?
2322 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2323 llvm::Value* this_addr = call_inst.getArgOperand(3);
2324 int opt_flags = LV2UInt(call_inst.getArgOperand(2));
2325
2326 EmitGuard_NullPointerException(dex_pc, this_addr, opt_flags);
2327 }
2328
2329 llvm::Value* result = NULL;
2330 if (EmitIntrinsic(call_inst, &result)) {
2331 return result;
2332 }
2333
2334 return EmitInvoke(call_inst);
2335}
2336
2337llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
2338 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2339 // Get the array object address
2340 llvm::Value* array_addr = call_inst.getArgOperand(1);
2341 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
2342
2343 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
2344
2345 // Get the array length and store it to the register
2346 return EmitLoadArrayLength(array_addr);
2347}
2348
2349llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
2350 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2351 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2352 llvm::Value* length = call_inst.getArgOperand(1);
2353
2354 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2355}
2356
2357llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
2358 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2359 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2360 uint32_t length = call_inst.getNumArgOperands() - 3;
2361
2362 llvm::Value* object_addr =
2363 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2364
2365 if (length > 0) {
2366 // Check for the element type
2367 uint32_t type_desc_len = 0;
2368 const char* type_desc =
2369 dex_compilation_unit_->GetDexFile()->StringByTypeIdx(type_idx, &type_desc_len);
2370
2371 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2372 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2373 bool is_elem_int_ty = (type_desc[1] == 'I');
2374
2375 uint32_t alignment;
2376 llvm::Constant* elem_size;
2377 llvm::PointerType* field_type;
2378
2379 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2380 // as the element, thus we are only checking 2 cases: primitive int and
2381 // non-primitive type.
2382 if (is_elem_int_ty) {
2383 alignment = sizeof(int32_t);
2384 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2385 field_type = irb_.getJIntTy()->getPointerTo();
2386 } else {
2387 alignment = irb_.getSizeOfPtrEquivInt();
2388 elem_size = irb_.getSizeOfPtrEquivIntValue();
2389 field_type = irb_.getJObjectTy()->getPointerTo();
2390 }
2391
2392 llvm::Value* data_field_offset =
2393 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
2394
2395 llvm::Value* data_field_addr =
2396 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2397
2398 // TODO: Tune this code. Currently we are generating one instruction for
2399 // one element which may be very space consuming. Maybe changing to use
2400 // memcpy may help; however, since we can't guarantee that the alloca of
2401 // dalvik register are continuous, we can't perform such optimization yet.
2402 for (uint32_t i = 0; i < length; ++i) {
2403 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2404
2405 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2406
2407 data_field_addr =
2408 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2409 }
2410 }
2411
2412 return object_addr;
2413}
2414
2415void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
2416 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2417 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2418 LV2SInt(call_inst.getArgOperand(0));
2419 llvm::Value* array_addr = call_inst.getArgOperand(1);
2420
2421 const art::Instruction::ArrayDataPayload* payload =
2422 reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
2423 dex_compilation_unit_->GetCodeItem()->insns_ + payload_offset);
2424
2425 if (payload->element_count == 0) {
2426 // When the number of the elements in the payload is zero, we don't have
2427 // to copy any numbers. However, we should check whether the array object
2428 // address is equal to null or not.
2429 EmitGuard_NullPointerException(dex_pc, array_addr, 0);
2430 } else {
2431 // To save the code size, we are going to call the runtime function to
2432 // copy the content from DexFile.
2433
2434 // NOTE: We will check for the NullPointerException in the runtime.
2435
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002436 llvm::Function* runtime_func = irb_.GetRuntime(FillArrayData);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002437
2438 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2439
2440 EmitUpdateDexPC(dex_pc);
2441
2442 irb_.CreateCall4(runtime_func,
2443 method_object_addr, irb_.getInt32(dex_pc),
2444 array_addr, irb_.getInt32(payload_offset));
2445
2446 EmitGuard_ExceptionLandingPad(dex_pc);
2447 }
2448
2449 return;
2450}
2451
2452llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2453 llvm::Value* array_length_value,
2454 uint32_t type_idx,
2455 bool is_filled_new_array) {
2456 llvm::Function* runtime_func;
2457
2458 bool skip_access_check =
2459 driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
2460 *dex_compilation_unit_->GetDexFile(), type_idx);
2461
2462
2463 if (is_filled_new_array) {
2464 runtime_func = skip_access_check ?
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002465 irb_.GetRuntime(CheckAndAllocArray) :
2466 irb_.GetRuntime(CheckAndAllocArrayWithAccessCheck);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002467 } else {
2468 runtime_func = skip_access_check ?
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002469 irb_.GetRuntime(AllocArray) :
2470 irb_.GetRuntime(AllocArrayWithAccessCheck);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002471 }
2472
2473 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2474
2475 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2476
2477 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2478
2479 EmitUpdateDexPC(dex_pc);
2480
2481 llvm::Value* object_addr =
2482 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2483 array_length_value, thread_object_addr);
2484
2485 EmitGuard_ExceptionLandingPad(dex_pc);
2486
2487 return object_addr;
2488}
2489
2490llvm::Value* GBCExpanderPass::
2491EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
2492 art::InvokeType invoke_type,
2493 llvm::Value* this_addr,
2494 uint32_t dex_pc,
2495 bool is_fast_path) {
Brian Carlstrom7940e442013-07-12 13:46:57 -07002496 llvm::Function* runtime_func = NULL;
2497
2498 switch (invoke_type) {
2499 case art::kStatic:
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002500 runtime_func = irb_.GetRuntime(FindStaticMethodWithAccessCheck);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002501 break;
2502
2503 case art::kDirect:
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002504 runtime_func = irb_.GetRuntime(FindDirectMethodWithAccessCheck);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002505 break;
2506
2507 case art::kVirtual:
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002508 runtime_func = irb_.GetRuntime(FindVirtualMethodWithAccessCheck);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002509 break;
2510
2511 case art::kSuper:
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002512 runtime_func = irb_.GetRuntime(FindSuperMethodWithAccessCheck);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002513 break;
2514
2515 case art::kInterface:
2516 if (is_fast_path) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002517 runtime_func = irb_.GetRuntime(FindInterfaceMethod);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002518 } else {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002519 runtime_func = irb_.GetRuntime(FindInterfaceMethodWithAccessCheck);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002520 }
2521 break;
2522 }
2523
2524 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2525
2526 if (this_addr == NULL) {
2527 DCHECK_EQ(invoke_type, art::kStatic);
2528 this_addr = irb_.getJNull();
2529 }
2530
2531 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2532
2533 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2534
2535 EmitUpdateDexPC(dex_pc);
2536
2537 llvm::Value* callee_method_object_addr =
2538 irb_.CreateCall4(runtime_func,
2539 callee_method_idx_value,
2540 this_addr,
2541 caller_method_object_addr,
2542 thread_object_addr);
2543
2544 EmitGuard_ExceptionLandingPad(dex_pc);
2545
2546 return callee_method_object_addr;
2547}
2548
2549void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2550 // Using runtime support, let the target can override by InlineAssembly.
2551 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2552}
2553
2554void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
2555 if (shadow_frame_ == NULL) {
2556 return;
2557 }
2558 irb_.StoreToObjectOffset(shadow_frame_,
2559 art::ShadowFrame::DexPCOffset(),
2560 irb_.getInt32(dex_pc),
2561 kTBAAShadowFrame);
2562}
2563
2564void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2565 llvm::Value* denominator,
2566 JType op_jty) {
2567 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2568
2569 llvm::Constant* zero = irb_.getJZero(op_jty);
2570
2571 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2572
2573 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2574
2575 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2576
2577 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2578
2579 irb_.SetInsertPoint(block_exception);
2580 EmitUpdateDexPC(dex_pc);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002581 irb_.CreateCall(irb_.GetRuntime(ThrowDivZeroException));
Brian Carlstrom7940e442013-07-12 13:46:57 -07002582 EmitBranchExceptionLandingPad(dex_pc);
2583
2584 irb_.SetInsertPoint(block_continue);
2585}
2586
2587void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
2588 llvm::Value* object,
2589 int opt_flags) {
2590 bool ignore_null_check = ((opt_flags & MIR_IGNORE_NULL_CHECK) != 0);
2591 if (ignore_null_check) {
2592 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2593 if (lpad) {
2594 // There is at least one catch: create a "fake" conditional branch to
2595 // keep the exception edge to the catch block.
2596 landing_pad_phi_mapping_[lpad].push_back(
2597 std::make_pair(current_bb_->getUniquePredecessor(),
2598 irb_.GetInsertBlock()));
2599
2600 llvm::BasicBlock* block_continue =
2601 CreateBasicBlockWithDexPC(dex_pc, "cont");
2602
2603 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
2604
2605 irb_.SetInsertPoint(block_continue);
2606 }
2607 } else {
2608 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
2609
2610 llvm::BasicBlock* block_exception =
2611 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2612
2613 llvm::BasicBlock* block_continue =
2614 CreateBasicBlockWithDexPC(dex_pc, "cont");
2615
2616 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2617
2618 irb_.SetInsertPoint(block_exception);
2619 EmitUpdateDexPC(dex_pc);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002620 irb_.CreateCall(irb_.GetRuntime(ThrowNullPointerException),
Brian Carlstrom7940e442013-07-12 13:46:57 -07002621 irb_.getInt32(dex_pc));
2622 EmitBranchExceptionLandingPad(dex_pc);
2623
2624 irb_.SetInsertPoint(block_continue);
2625 }
2626}
2627
2628void
2629GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2630 llvm::Value* array,
2631 llvm::Value* index,
2632 int opt_flags) {
2633 bool ignore_range_check = ((opt_flags & MIR_IGNORE_RANGE_CHECK) != 0);
2634 if (ignore_range_check) {
2635 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2636 if (lpad) {
2637 // There is at least one catch: create a "fake" conditional branch to
2638 // keep the exception edge to the catch block.
2639 landing_pad_phi_mapping_[lpad].push_back(
2640 std::make_pair(current_bb_->getUniquePredecessor(),
2641 irb_.GetInsertBlock()));
2642
2643 llvm::BasicBlock* block_continue =
2644 CreateBasicBlockWithDexPC(dex_pc, "cont");
2645
2646 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
2647
2648 irb_.SetInsertPoint(block_continue);
2649 }
2650 } else {
2651 llvm::Value* array_len = EmitLoadArrayLength(array);
2652
2653 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
2654
2655 llvm::BasicBlock* block_exception =
2656 CreateBasicBlockWithDexPC(dex_pc, "overflow");
2657
2658 llvm::BasicBlock* block_continue =
2659 CreateBasicBlockWithDexPC(dex_pc, "cont");
2660
2661 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2662
2663 irb_.SetInsertPoint(block_exception);
2664
2665 EmitUpdateDexPC(dex_pc);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002666 irb_.CreateCall2(irb_.GetRuntime(ThrowIndexOutOfBounds), index, array_len);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002667 EmitBranchExceptionLandingPad(dex_pc);
2668
2669 irb_.SetInsertPoint(block_continue);
2670 }
2671}
2672
2673llvm::FunctionType* GBCExpanderPass::GetFunctionType(llvm::Type* ret_type, uint32_t method_idx,
2674 bool is_static) {
2675 // Get method signature
2676 art::DexFile::MethodId const& method_id =
2677 dex_compilation_unit_->GetDexFile()->GetMethodId(method_idx);
2678
2679 uint32_t shorty_size;
2680 const char* shorty = dex_compilation_unit_->GetDexFile()->GetMethodShorty(method_id, &shorty_size);
2681 CHECK_GE(shorty_size, 1u);
2682
2683 // Get argument type
2684 std::vector<llvm::Type*> args_type;
2685
2686 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2687
2688 if (!is_static) {
2689 args_type.push_back(irb_.getJType('L')); // "this" object pointer
2690 }
2691
2692 for (uint32_t i = 1; i < shorty_size; ++i) {
2693 char shorty_type = art::RemapShorty(shorty[i]);
2694 args_type.push_back(irb_.getJType(shorty_type));
2695 }
2696
2697 return llvm::FunctionType::get(ret_type, args_type, false);
2698}
2699
2700
2701llvm::BasicBlock* GBCExpanderPass::
2702CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2703 std::string name;
2704
2705#if !defined(NDEBUG)
2706 art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
2707#endif
2708
2709 return llvm::BasicBlock::Create(context_, name, func_);
2710}
2711
2712llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
2713 DCHECK(dex_pc < dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
2714 CHECK(basic_blocks_[dex_pc] != NULL);
2715 return basic_blocks_[dex_pc];
2716}
2717
2718int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2719 int32_t min = 0;
2720 int32_t max = dex_compilation_unit_->GetCodeItem()->tries_size_ - 1;
2721
2722 while (min <= max) {
2723 int32_t mid = min + (max - min) / 2;
2724
2725 const art::DexFile::TryItem* ti =
2726 art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(), mid);
2727 uint32_t start = ti->start_addr_;
2728 uint32_t end = start + ti->insn_count_;
2729
2730 if (dex_pc < start) {
2731 max = mid - 1;
2732 } else if (dex_pc >= end) {
2733 min = mid + 1;
2734 } else {
2735 return mid; // found
2736 }
2737 }
2738
2739 return -1; // not found
2740}
2741
2742llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2743 // Find the try item for this address in this method
2744 int32_t ti_offset = GetTryItemOffset(dex_pc);
2745
2746 if (ti_offset == -1) {
2747 return NULL; // No landing pad is available for this address.
2748 }
2749
2750 // Check for the existing landing pad basic block
2751 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2752 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2753
2754 if (block_lpad) {
2755 // We have generated landing pad for this try item already. Return the
2756 // same basic block.
2757 return block_lpad;
2758 }
2759
2760 // Get try item from code item
2761 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(),
2762 ti_offset);
2763
2764 std::string lpadname;
2765
2766#if !defined(NDEBUG)
2767 art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
2768#endif
2769
2770 // Create landing pad basic block
2771 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2772
2773 // Change IRBuilder insert point
2774 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2775 irb_.SetInsertPoint(block_lpad);
2776
2777 // Find catch block with matching type
2778 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2779
2780 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2781
2782 llvm::Value* catch_handler_index_value =
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002783 irb_.CreateCall2(irb_.GetRuntime(FindCatchBlock),
Brian Carlstrom7940e442013-07-12 13:46:57 -07002784 method_object_addr, ti_offset_value);
2785
2786 // Switch instruction (Go to unwind basic block by default)
2787 llvm::SwitchInst* sw =
2788 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2789
2790 // Cases with matched catch block
2791 art::CatchHandlerIterator iter(*dex_compilation_unit_->GetCodeItem(), ti->start_addr_);
2792
2793 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2794 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2795 }
2796
2797 // Restore the orignal insert point for IRBuilder
2798 irb_.restoreIP(irb_ip_original);
2799
2800 // Cache this landing pad
2801 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2802 basic_block_landing_pads_[ti_offset] = block_lpad;
2803
2804 return block_lpad;
2805}
2806
2807llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2808 // Check the existing unwinding baisc block block
2809 if (basic_block_unwind_ != NULL) {
2810 return basic_block_unwind_;
2811 }
2812
2813 // Create new basic block for unwinding
2814 basic_block_unwind_ =
2815 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2816
2817 // Change IRBuilder insert point
2818 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2819 irb_.SetInsertPoint(basic_block_unwind_);
2820
2821 // Pop the shadow frame
2822 Expand_PopShadowFrame();
2823
2824 // Emit the code to return default value (zero) for the given return type.
2825 char ret_shorty = dex_compilation_unit_->GetShorty()[0];
2826 ret_shorty = art::RemapShorty(ret_shorty);
2827 if (ret_shorty == 'V') {
2828 irb_.CreateRetVoid();
2829 } else {
2830 irb_.CreateRet(irb_.getJZero(ret_shorty));
2831 }
2832
2833 // Restore the orignal insert point for IRBuilder
2834 irb_.restoreIP(irb_ip_original);
2835
2836 return basic_block_unwind_;
2837}
2838
2839void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2840 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
2841 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
2842 irb_.GetInsertBlock()));
2843 irb_.CreateBr(lpad);
2844 } else {
2845 irb_.CreateBr(GetUnwindBasicBlock());
2846 }
2847}
2848
2849void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
2850 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2851
2852 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2853
2854 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
2855 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
2856 irb_.GetInsertBlock()));
2857 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
2858 } else {
2859 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
2860 }
2861
2862 irb_.SetInsertPoint(block_cont);
2863}
2864
2865llvm::Value*
2866GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2867 llvm::CallInst& call_inst) {
2868 switch (intr_id) {
2869 //==- Thread -----------------------------------------------------------==//
2870 case IntrinsicHelper::GetCurrentThread: {
2871 return irb_.Runtime().EmitGetCurrentThread();
2872 }
2873 case IntrinsicHelper::CheckSuspend: {
2874 Expand_TestSuspend(call_inst);
2875 return NULL;
2876 }
2877 case IntrinsicHelper::TestSuspend: {
2878 Expand_TestSuspend(call_inst);
2879 return NULL;
2880 }
2881 case IntrinsicHelper::MarkGCCard: {
2882 Expand_MarkGCCard(call_inst);
2883 return NULL;
2884 }
2885
2886 //==- Exception --------------------------------------------------------==//
2887 case IntrinsicHelper::ThrowException: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002888 return ExpandToRuntime(ThrowException, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002889 }
2890 case IntrinsicHelper::HLThrowException: {
2891 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2892
2893 EmitUpdateDexPC(dex_pc);
2894
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002895 irb_.CreateCall(irb_.GetRuntime(ThrowException),
Brian Carlstrom7940e442013-07-12 13:46:57 -07002896 call_inst.getArgOperand(0));
2897
2898 EmitGuard_ExceptionLandingPad(dex_pc);
2899 return NULL;
2900 }
2901 case IntrinsicHelper::GetException: {
2902 return irb_.Runtime().EmitGetAndClearException();
2903 }
2904 case IntrinsicHelper::IsExceptionPending: {
2905 return irb_.Runtime().EmitIsExceptionPending();
2906 }
2907 case IntrinsicHelper::FindCatchBlock: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002908 return ExpandToRuntime(FindCatchBlock, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002909 }
2910 case IntrinsicHelper::ThrowDivZeroException: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002911 return ExpandToRuntime(ThrowDivZeroException, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002912 }
2913 case IntrinsicHelper::ThrowNullPointerException: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002914 return ExpandToRuntime(ThrowNullPointerException, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002915 }
2916 case IntrinsicHelper::ThrowIndexOutOfBounds: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002917 return ExpandToRuntime(ThrowIndexOutOfBounds, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002918 }
2919
2920 //==- Const String -----------------------------------------------------==//
2921 case IntrinsicHelper::ConstString: {
2922 return Expand_ConstString(call_inst);
2923 }
2924 case IntrinsicHelper::LoadStringFromDexCache: {
2925 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2926 }
2927 case IntrinsicHelper::ResolveString: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002928 return ExpandToRuntime(ResolveString, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002929 }
2930
2931 //==- Const Class ------------------------------------------------------==//
2932 case IntrinsicHelper::ConstClass: {
2933 return Expand_ConstClass(call_inst);
2934 }
2935 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002936 return ExpandToRuntime(InitializeTypeAndVerifyAccess, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002937 }
2938 case IntrinsicHelper::LoadTypeFromDexCache: {
2939 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2940 }
2941 case IntrinsicHelper::InitializeType: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002942 return ExpandToRuntime(InitializeType, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002943 }
2944
2945 //==- Lock -------------------------------------------------------------==//
2946 case IntrinsicHelper::LockObject: {
2947 Expand_LockObject(call_inst.getArgOperand(0));
2948 return NULL;
2949 }
2950 case IntrinsicHelper::UnlockObject: {
2951 Expand_UnlockObject(call_inst.getArgOperand(0));
2952 return NULL;
2953 }
2954
2955 //==- Cast -------------------------------------------------------------==//
2956 case IntrinsicHelper::CheckCast: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002957 return ExpandToRuntime(CheckCast, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002958 }
2959 case IntrinsicHelper::HLCheckCast: {
2960 Expand_HLCheckCast(call_inst);
2961 return NULL;
2962 }
2963 case IntrinsicHelper::IsAssignable: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002964 return ExpandToRuntime(IsAssignable, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002965 }
2966
2967 //==- Alloc ------------------------------------------------------------==//
2968 case IntrinsicHelper::AllocObject: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002969 return ExpandToRuntime(AllocObject, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002970 }
2971 case IntrinsicHelper::AllocObjectWithAccessCheck: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002972 return ExpandToRuntime(AllocObjectWithAccessCheck, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002973 }
2974
2975 //==- Instance ---------------------------------------------------------==//
2976 case IntrinsicHelper::NewInstance: {
2977 return Expand_NewInstance(call_inst);
2978 }
2979 case IntrinsicHelper::InstanceOf: {
2980 return Expand_InstanceOf(call_inst);
2981 }
2982
2983 //==- Array ------------------------------------------------------------==//
2984 case IntrinsicHelper::NewArray: {
2985 return Expand_NewArray(call_inst);
2986 }
2987 case IntrinsicHelper::OptArrayLength: {
2988 return Expand_OptArrayLength(call_inst);
2989 }
2990 case IntrinsicHelper::ArrayLength: {
2991 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2992 }
2993 case IntrinsicHelper::AllocArray: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002994 return ExpandToRuntime(AllocArray, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07002995 }
2996 case IntrinsicHelper::AllocArrayWithAccessCheck: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07002997 return ExpandToRuntime(AllocArrayWithAccessCheck,
Brian Carlstrom7940e442013-07-12 13:46:57 -07002998 call_inst);
2999 }
3000 case IntrinsicHelper::CheckAndAllocArray: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003001 return ExpandToRuntime(CheckAndAllocArray, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003002 }
3003 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003004 return ExpandToRuntime(CheckAndAllocArrayWithAccessCheck,
Brian Carlstrom7940e442013-07-12 13:46:57 -07003005 call_inst);
3006 }
3007 case IntrinsicHelper::ArrayGet: {
3008 return Expand_ArrayGet(call_inst.getArgOperand(0),
3009 call_inst.getArgOperand(1),
3010 kInt);
3011 }
3012 case IntrinsicHelper::ArrayGetWide: {
3013 return Expand_ArrayGet(call_inst.getArgOperand(0),
3014 call_inst.getArgOperand(1),
3015 kLong);
3016 }
3017 case IntrinsicHelper::ArrayGetObject: {
3018 return Expand_ArrayGet(call_inst.getArgOperand(0),
3019 call_inst.getArgOperand(1),
3020 kObject);
3021 }
3022 case IntrinsicHelper::ArrayGetBoolean: {
3023 return Expand_ArrayGet(call_inst.getArgOperand(0),
3024 call_inst.getArgOperand(1),
3025 kBoolean);
3026 }
3027 case IntrinsicHelper::ArrayGetByte: {
3028 return Expand_ArrayGet(call_inst.getArgOperand(0),
3029 call_inst.getArgOperand(1),
3030 kByte);
3031 }
3032 case IntrinsicHelper::ArrayGetChar: {
3033 return Expand_ArrayGet(call_inst.getArgOperand(0),
3034 call_inst.getArgOperand(1),
3035 kChar);
3036 }
3037 case IntrinsicHelper::ArrayGetShort: {
3038 return Expand_ArrayGet(call_inst.getArgOperand(0),
3039 call_inst.getArgOperand(1),
3040 kShort);
3041 }
3042 case IntrinsicHelper::ArrayPut: {
3043 Expand_ArrayPut(call_inst.getArgOperand(0),
3044 call_inst.getArgOperand(1),
3045 call_inst.getArgOperand(2),
3046 kInt);
3047 return NULL;
3048 }
3049 case IntrinsicHelper::ArrayPutWide: {
3050 Expand_ArrayPut(call_inst.getArgOperand(0),
3051 call_inst.getArgOperand(1),
3052 call_inst.getArgOperand(2),
3053 kLong);
3054 return NULL;
3055 }
3056 case IntrinsicHelper::ArrayPutObject: {
3057 Expand_ArrayPut(call_inst.getArgOperand(0),
3058 call_inst.getArgOperand(1),
3059 call_inst.getArgOperand(2),
3060 kObject);
3061 return NULL;
3062 }
3063 case IntrinsicHelper::ArrayPutBoolean: {
3064 Expand_ArrayPut(call_inst.getArgOperand(0),
3065 call_inst.getArgOperand(1),
3066 call_inst.getArgOperand(2),
3067 kBoolean);
3068 return NULL;
3069 }
3070 case IntrinsicHelper::ArrayPutByte: {
3071 Expand_ArrayPut(call_inst.getArgOperand(0),
3072 call_inst.getArgOperand(1),
3073 call_inst.getArgOperand(2),
3074 kByte);
3075 return NULL;
3076 }
3077 case IntrinsicHelper::ArrayPutChar: {
3078 Expand_ArrayPut(call_inst.getArgOperand(0),
3079 call_inst.getArgOperand(1),
3080 call_inst.getArgOperand(2),
3081 kChar);
3082 return NULL;
3083 }
3084 case IntrinsicHelper::ArrayPutShort: {
3085 Expand_ArrayPut(call_inst.getArgOperand(0),
3086 call_inst.getArgOperand(1),
3087 call_inst.getArgOperand(2),
3088 kShort);
3089 return NULL;
3090 }
3091 case IntrinsicHelper::CheckPutArrayElement: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003092 return ExpandToRuntime(CheckPutArrayElement, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003093 }
3094 case IntrinsicHelper::FilledNewArray: {
3095 Expand_FilledNewArray(call_inst);
3096 return NULL;
3097 }
3098 case IntrinsicHelper::FillArrayData: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003099 return ExpandToRuntime(FillArrayData, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003100 }
3101 case IntrinsicHelper::HLFillArrayData: {
3102 Expand_HLFillArrayData(call_inst);
3103 return NULL;
3104 }
3105 case IntrinsicHelper::HLFilledNewArray: {
3106 return Expand_HLFilledNewArray(call_inst);
3107 }
3108
3109 //==- Instance Field ---------------------------------------------------==//
3110 case IntrinsicHelper::InstanceFieldGet:
3111 case IntrinsicHelper::InstanceFieldGetBoolean:
3112 case IntrinsicHelper::InstanceFieldGetByte:
3113 case IntrinsicHelper::InstanceFieldGetChar:
3114 case IntrinsicHelper::InstanceFieldGetShort: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003115 return ExpandToRuntime(Get32Instance, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003116 }
3117 case IntrinsicHelper::InstanceFieldGetWide: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003118 return ExpandToRuntime(Get64Instance, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003119 }
3120 case IntrinsicHelper::InstanceFieldGetObject: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003121 return ExpandToRuntime(GetObjectInstance, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003122 }
3123 case IntrinsicHelper::InstanceFieldGetFast: {
3124 return Expand_IGetFast(call_inst.getArgOperand(0),
3125 call_inst.getArgOperand(1),
3126 call_inst.getArgOperand(2),
3127 kInt);
3128 }
3129 case IntrinsicHelper::InstanceFieldGetWideFast: {
3130 return Expand_IGetFast(call_inst.getArgOperand(0),
3131 call_inst.getArgOperand(1),
3132 call_inst.getArgOperand(2),
3133 kLong);
3134 }
3135 case IntrinsicHelper::InstanceFieldGetObjectFast: {
3136 return Expand_IGetFast(call_inst.getArgOperand(0),
3137 call_inst.getArgOperand(1),
3138 call_inst.getArgOperand(2),
3139 kObject);
3140 }
3141 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
3142 return Expand_IGetFast(call_inst.getArgOperand(0),
3143 call_inst.getArgOperand(1),
3144 call_inst.getArgOperand(2),
3145 kBoolean);
3146 }
3147 case IntrinsicHelper::InstanceFieldGetByteFast: {
3148 return Expand_IGetFast(call_inst.getArgOperand(0),
3149 call_inst.getArgOperand(1),
3150 call_inst.getArgOperand(2),
3151 kByte);
3152 }
3153 case IntrinsicHelper::InstanceFieldGetCharFast: {
3154 return Expand_IGetFast(call_inst.getArgOperand(0),
3155 call_inst.getArgOperand(1),
3156 call_inst.getArgOperand(2),
3157 kChar);
3158 }
3159 case IntrinsicHelper::InstanceFieldGetShortFast: {
3160 return Expand_IGetFast(call_inst.getArgOperand(0),
3161 call_inst.getArgOperand(1),
3162 call_inst.getArgOperand(2),
3163 kShort);
3164 }
3165 case IntrinsicHelper::InstanceFieldPut:
3166 case IntrinsicHelper::InstanceFieldPutBoolean:
3167 case IntrinsicHelper::InstanceFieldPutByte:
3168 case IntrinsicHelper::InstanceFieldPutChar:
3169 case IntrinsicHelper::InstanceFieldPutShort: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003170 return ExpandToRuntime(Set32Instance, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003171 }
3172 case IntrinsicHelper::InstanceFieldPutWide: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003173 return ExpandToRuntime(Set64Instance, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003174 }
3175 case IntrinsicHelper::InstanceFieldPutObject: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003176 return ExpandToRuntime(SetObjectInstance, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003177 }
3178 case IntrinsicHelper::InstanceFieldPutFast: {
3179 Expand_IPutFast(call_inst.getArgOperand(0),
3180 call_inst.getArgOperand(1),
3181 call_inst.getArgOperand(2),
3182 call_inst.getArgOperand(3),
3183 kInt);
3184 return NULL;
3185 }
3186 case IntrinsicHelper::InstanceFieldPutWideFast: {
3187 Expand_IPutFast(call_inst.getArgOperand(0),
3188 call_inst.getArgOperand(1),
3189 call_inst.getArgOperand(2),
3190 call_inst.getArgOperand(3),
3191 kLong);
3192 return NULL;
3193 }
3194 case IntrinsicHelper::InstanceFieldPutObjectFast: {
3195 Expand_IPutFast(call_inst.getArgOperand(0),
3196 call_inst.getArgOperand(1),
3197 call_inst.getArgOperand(2),
3198 call_inst.getArgOperand(3),
3199 kObject);
3200 return NULL;
3201 }
3202 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
3203 Expand_IPutFast(call_inst.getArgOperand(0),
3204 call_inst.getArgOperand(1),
3205 call_inst.getArgOperand(2),
3206 call_inst.getArgOperand(3),
3207 kBoolean);
3208 return NULL;
3209 }
3210 case IntrinsicHelper::InstanceFieldPutByteFast: {
3211 Expand_IPutFast(call_inst.getArgOperand(0),
3212 call_inst.getArgOperand(1),
3213 call_inst.getArgOperand(2),
3214 call_inst.getArgOperand(3),
3215 kByte);
3216 return NULL;
3217 }
3218 case IntrinsicHelper::InstanceFieldPutCharFast: {
3219 Expand_IPutFast(call_inst.getArgOperand(0),
3220 call_inst.getArgOperand(1),
3221 call_inst.getArgOperand(2),
3222 call_inst.getArgOperand(3),
3223 kChar);
3224 return NULL;
3225 }
3226 case IntrinsicHelper::InstanceFieldPutShortFast: {
3227 Expand_IPutFast(call_inst.getArgOperand(0),
3228 call_inst.getArgOperand(1),
3229 call_inst.getArgOperand(2),
3230 call_inst.getArgOperand(3),
3231 kShort);
3232 return NULL;
3233 }
3234
3235 //==- Static Field -----------------------------------------------------==//
3236 case IntrinsicHelper::StaticFieldGet:
3237 case IntrinsicHelper::StaticFieldGetBoolean:
3238 case IntrinsicHelper::StaticFieldGetByte:
3239 case IntrinsicHelper::StaticFieldGetChar:
3240 case IntrinsicHelper::StaticFieldGetShort: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003241 return ExpandToRuntime(Get32Static, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003242 }
3243 case IntrinsicHelper::StaticFieldGetWide: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003244 return ExpandToRuntime(Get64Static, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003245 }
3246 case IntrinsicHelper::StaticFieldGetObject: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003247 return ExpandToRuntime(GetObjectStatic, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003248 }
3249 case IntrinsicHelper::StaticFieldGetFast: {
3250 return Expand_SGetFast(call_inst.getArgOperand(0),
3251 call_inst.getArgOperand(1),
3252 call_inst.getArgOperand(2),
3253 kInt);
3254 }
3255 case IntrinsicHelper::StaticFieldGetWideFast: {
3256 return Expand_SGetFast(call_inst.getArgOperand(0),
3257 call_inst.getArgOperand(1),
3258 call_inst.getArgOperand(2),
3259 kLong);
3260 }
3261 case IntrinsicHelper::StaticFieldGetObjectFast: {
3262 return Expand_SGetFast(call_inst.getArgOperand(0),
3263 call_inst.getArgOperand(1),
3264 call_inst.getArgOperand(2),
3265 kObject);
3266 }
3267 case IntrinsicHelper::StaticFieldGetBooleanFast: {
3268 return Expand_SGetFast(call_inst.getArgOperand(0),
3269 call_inst.getArgOperand(1),
3270 call_inst.getArgOperand(2),
3271 kBoolean);
3272 }
3273 case IntrinsicHelper::StaticFieldGetByteFast: {
3274 return Expand_SGetFast(call_inst.getArgOperand(0),
3275 call_inst.getArgOperand(1),
3276 call_inst.getArgOperand(2),
3277 kByte);
3278 }
3279 case IntrinsicHelper::StaticFieldGetCharFast: {
3280 return Expand_SGetFast(call_inst.getArgOperand(0),
3281 call_inst.getArgOperand(1),
3282 call_inst.getArgOperand(2),
3283 kChar);
3284 }
3285 case IntrinsicHelper::StaticFieldGetShortFast: {
3286 return Expand_SGetFast(call_inst.getArgOperand(0),
3287 call_inst.getArgOperand(1),
3288 call_inst.getArgOperand(2),
3289 kShort);
3290 }
3291 case IntrinsicHelper::StaticFieldPut:
3292 case IntrinsicHelper::StaticFieldPutBoolean:
3293 case IntrinsicHelper::StaticFieldPutByte:
3294 case IntrinsicHelper::StaticFieldPutChar:
3295 case IntrinsicHelper::StaticFieldPutShort: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003296 return ExpandToRuntime(Set32Static, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003297 }
3298 case IntrinsicHelper::StaticFieldPutWide: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003299 return ExpandToRuntime(Set64Static, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003300 }
3301 case IntrinsicHelper::StaticFieldPutObject: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003302 return ExpandToRuntime(SetObjectStatic, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003303 }
3304 case IntrinsicHelper::StaticFieldPutFast: {
3305 Expand_SPutFast(call_inst.getArgOperand(0),
3306 call_inst.getArgOperand(1),
3307 call_inst.getArgOperand(2),
3308 call_inst.getArgOperand(3),
3309 kInt);
3310 return NULL;
3311 }
3312 case IntrinsicHelper::StaticFieldPutWideFast: {
3313 Expand_SPutFast(call_inst.getArgOperand(0),
3314 call_inst.getArgOperand(1),
3315 call_inst.getArgOperand(2),
3316 call_inst.getArgOperand(3),
3317 kLong);
3318 return NULL;
3319 }
3320 case IntrinsicHelper::StaticFieldPutObjectFast: {
3321 Expand_SPutFast(call_inst.getArgOperand(0),
3322 call_inst.getArgOperand(1),
3323 call_inst.getArgOperand(2),
3324 call_inst.getArgOperand(3),
3325 kObject);
3326 return NULL;
3327 }
3328 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3329 Expand_SPutFast(call_inst.getArgOperand(0),
3330 call_inst.getArgOperand(1),
3331 call_inst.getArgOperand(2),
3332 call_inst.getArgOperand(3),
3333 kBoolean);
3334 return NULL;
3335 }
3336 case IntrinsicHelper::StaticFieldPutByteFast: {
3337 Expand_SPutFast(call_inst.getArgOperand(0),
3338 call_inst.getArgOperand(1),
3339 call_inst.getArgOperand(2),
3340 call_inst.getArgOperand(3),
3341 kByte);
3342 return NULL;
3343 }
3344 case IntrinsicHelper::StaticFieldPutCharFast: {
3345 Expand_SPutFast(call_inst.getArgOperand(0),
3346 call_inst.getArgOperand(1),
3347 call_inst.getArgOperand(2),
3348 call_inst.getArgOperand(3),
3349 kChar);
3350 return NULL;
3351 }
3352 case IntrinsicHelper::StaticFieldPutShortFast: {
3353 Expand_SPutFast(call_inst.getArgOperand(0),
3354 call_inst.getArgOperand(1),
3355 call_inst.getArgOperand(2),
3356 call_inst.getArgOperand(3),
3357 kShort);
3358 return NULL;
3359 }
3360 case IntrinsicHelper::LoadDeclaringClassSSB: {
3361 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3362 }
3363 case IntrinsicHelper::LoadClassSSBFromDexCache: {
3364 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
3365 }
3366 case IntrinsicHelper::InitializeAndLoadClassSSB: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003367 return ExpandToRuntime(InitializeStaticStorage, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003368 }
3369
3370 //==- High-level Array -------------------------------------------------==//
3371 case IntrinsicHelper::HLArrayGet: {
3372 return Expand_HLArrayGet(call_inst, kInt);
3373 }
3374 case IntrinsicHelper::HLArrayGetBoolean: {
3375 return Expand_HLArrayGet(call_inst, kBoolean);
3376 }
3377 case IntrinsicHelper::HLArrayGetByte: {
3378 return Expand_HLArrayGet(call_inst, kByte);
3379 }
3380 case IntrinsicHelper::HLArrayGetChar: {
3381 return Expand_HLArrayGet(call_inst, kChar);
3382 }
3383 case IntrinsicHelper::HLArrayGetShort: {
3384 return Expand_HLArrayGet(call_inst, kShort);
3385 }
3386 case IntrinsicHelper::HLArrayGetFloat: {
3387 return Expand_HLArrayGet(call_inst, kFloat);
3388 }
3389 case IntrinsicHelper::HLArrayGetWide: {
3390 return Expand_HLArrayGet(call_inst, kLong);
3391 }
3392 case IntrinsicHelper::HLArrayGetDouble: {
3393 return Expand_HLArrayGet(call_inst, kDouble);
3394 }
3395 case IntrinsicHelper::HLArrayGetObject: {
3396 return Expand_HLArrayGet(call_inst, kObject);
3397 }
3398 case IntrinsicHelper::HLArrayPut: {
3399 Expand_HLArrayPut(call_inst, kInt);
3400 return NULL;
3401 }
3402 case IntrinsicHelper::HLArrayPutBoolean: {
3403 Expand_HLArrayPut(call_inst, kBoolean);
3404 return NULL;
3405 }
3406 case IntrinsicHelper::HLArrayPutByte: {
3407 Expand_HLArrayPut(call_inst, kByte);
3408 return NULL;
3409 }
3410 case IntrinsicHelper::HLArrayPutChar: {
3411 Expand_HLArrayPut(call_inst, kChar);
3412 return NULL;
3413 }
3414 case IntrinsicHelper::HLArrayPutShort: {
3415 Expand_HLArrayPut(call_inst, kShort);
3416 return NULL;
3417 }
3418 case IntrinsicHelper::HLArrayPutFloat: {
3419 Expand_HLArrayPut(call_inst, kFloat);
3420 return NULL;
3421 }
3422 case IntrinsicHelper::HLArrayPutWide: {
3423 Expand_HLArrayPut(call_inst, kLong);
3424 return NULL;
3425 }
3426 case IntrinsicHelper::HLArrayPutDouble: {
3427 Expand_HLArrayPut(call_inst, kDouble);
3428 return NULL;
3429 }
3430 case IntrinsicHelper::HLArrayPutObject: {
3431 Expand_HLArrayPut(call_inst, kObject);
3432 return NULL;
3433 }
3434
3435 //==- High-level Instance ----------------------------------------------==//
3436 case IntrinsicHelper::HLIGet: {
3437 return Expand_HLIGet(call_inst, kInt);
3438 }
3439 case IntrinsicHelper::HLIGetBoolean: {
3440 return Expand_HLIGet(call_inst, kBoolean);
3441 }
3442 case IntrinsicHelper::HLIGetByte: {
3443 return Expand_HLIGet(call_inst, kByte);
3444 }
3445 case IntrinsicHelper::HLIGetChar: {
3446 return Expand_HLIGet(call_inst, kChar);
3447 }
3448 case IntrinsicHelper::HLIGetShort: {
3449 return Expand_HLIGet(call_inst, kShort);
3450 }
3451 case IntrinsicHelper::HLIGetFloat: {
3452 return Expand_HLIGet(call_inst, kFloat);
3453 }
3454 case IntrinsicHelper::HLIGetWide: {
3455 return Expand_HLIGet(call_inst, kLong);
3456 }
3457 case IntrinsicHelper::HLIGetDouble: {
3458 return Expand_HLIGet(call_inst, kDouble);
3459 }
3460 case IntrinsicHelper::HLIGetObject: {
3461 return Expand_HLIGet(call_inst, kObject);
3462 }
3463 case IntrinsicHelper::HLIPut: {
3464 Expand_HLIPut(call_inst, kInt);
3465 return NULL;
3466 }
3467 case IntrinsicHelper::HLIPutBoolean: {
3468 Expand_HLIPut(call_inst, kBoolean);
3469 return NULL;
3470 }
3471 case IntrinsicHelper::HLIPutByte: {
3472 Expand_HLIPut(call_inst, kByte);
3473 return NULL;
3474 }
3475 case IntrinsicHelper::HLIPutChar: {
3476 Expand_HLIPut(call_inst, kChar);
3477 return NULL;
3478 }
3479 case IntrinsicHelper::HLIPutShort: {
3480 Expand_HLIPut(call_inst, kShort);
3481 return NULL;
3482 }
3483 case IntrinsicHelper::HLIPutFloat: {
3484 Expand_HLIPut(call_inst, kFloat);
3485 return NULL;
3486 }
3487 case IntrinsicHelper::HLIPutWide: {
3488 Expand_HLIPut(call_inst, kLong);
3489 return NULL;
3490 }
3491 case IntrinsicHelper::HLIPutDouble: {
3492 Expand_HLIPut(call_inst, kDouble);
3493 return NULL;
3494 }
3495 case IntrinsicHelper::HLIPutObject: {
3496 Expand_HLIPut(call_inst, kObject);
3497 return NULL;
3498 }
3499
3500 //==- High-level Invoke ------------------------------------------------==//
3501 case IntrinsicHelper::HLInvokeVoid:
3502 case IntrinsicHelper::HLInvokeObj:
3503 case IntrinsicHelper::HLInvokeInt:
3504 case IntrinsicHelper::HLInvokeFloat:
3505 case IntrinsicHelper::HLInvokeLong:
3506 case IntrinsicHelper::HLInvokeDouble: {
3507 return Expand_HLInvoke(call_inst);
3508 }
3509
3510 //==- Invoke -----------------------------------------------------------==//
3511 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003512 return ExpandToRuntime(FindStaticMethodWithAccessCheck, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003513 }
3514 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003515 return ExpandToRuntime(FindDirectMethodWithAccessCheck, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003516 }
3517 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003518 return ExpandToRuntime(FindVirtualMethodWithAccessCheck, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003519 }
3520 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003521 return ExpandToRuntime(FindSuperMethodWithAccessCheck, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003522 }
3523 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003524 return ExpandToRuntime(FindInterfaceMethodWithAccessCheck, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003525 }
3526 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3527 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3528 }
3529 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3530 return Expand_GetVirtualCalleeMethodObjAddrFast(
3531 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3532 }
3533 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003534 return ExpandToRuntime(FindInterfaceMethod, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003535 }
3536 case IntrinsicHelper::InvokeRetVoid:
3537 case IntrinsicHelper::InvokeRetBoolean:
3538 case IntrinsicHelper::InvokeRetByte:
3539 case IntrinsicHelper::InvokeRetChar:
3540 case IntrinsicHelper::InvokeRetShort:
3541 case IntrinsicHelper::InvokeRetInt:
3542 case IntrinsicHelper::InvokeRetLong:
3543 case IntrinsicHelper::InvokeRetFloat:
3544 case IntrinsicHelper::InvokeRetDouble:
3545 case IntrinsicHelper::InvokeRetObject: {
3546 return Expand_Invoke(call_inst);
3547 }
3548
3549 //==- Math -------------------------------------------------------------==//
3550 case IntrinsicHelper::DivInt: {
3551 return Expand_DivRem(call_inst, /* is_div */true, kInt);
3552 }
3553 case IntrinsicHelper::RemInt: {
3554 return Expand_DivRem(call_inst, /* is_div */false, kInt);
3555 }
3556 case IntrinsicHelper::DivLong: {
3557 return Expand_DivRem(call_inst, /* is_div */true, kLong);
3558 }
3559 case IntrinsicHelper::RemLong: {
3560 return Expand_DivRem(call_inst, /* is_div */false, kLong);
3561 }
3562 case IntrinsicHelper::D2L: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003563 return ExpandToRuntime(art_d2l, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003564 }
3565 case IntrinsicHelper::D2I: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003566 return ExpandToRuntime(art_d2i, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003567 }
3568 case IntrinsicHelper::F2L: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003569 return ExpandToRuntime(art_f2l, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003570 }
3571 case IntrinsicHelper::F2I: {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -07003572 return ExpandToRuntime(art_f2i, call_inst);
Brian Carlstrom7940e442013-07-12 13:46:57 -07003573 }
3574
3575 //==- High-level Static ------------------------------------------------==//
3576 case IntrinsicHelper::HLSget: {
3577 return Expand_HLSget(call_inst, kInt);
3578 }
3579 case IntrinsicHelper::HLSgetBoolean: {
3580 return Expand_HLSget(call_inst, kBoolean);
3581 }
3582 case IntrinsicHelper::HLSgetByte: {
3583 return Expand_HLSget(call_inst, kByte);
3584 }
3585 case IntrinsicHelper::HLSgetChar: {
3586 return Expand_HLSget(call_inst, kChar);
3587 }
3588 case IntrinsicHelper::HLSgetShort: {
3589 return Expand_HLSget(call_inst, kShort);
3590 }
3591 case IntrinsicHelper::HLSgetFloat: {
3592 return Expand_HLSget(call_inst, kFloat);
3593 }
3594 case IntrinsicHelper::HLSgetWide: {
3595 return Expand_HLSget(call_inst, kLong);
3596 }
3597 case IntrinsicHelper::HLSgetDouble: {
3598 return Expand_HLSget(call_inst, kDouble);
3599 }
3600 case IntrinsicHelper::HLSgetObject: {
3601 return Expand_HLSget(call_inst, kObject);
3602 }
3603 case IntrinsicHelper::HLSput: {
3604 Expand_HLSput(call_inst, kInt);
3605 return NULL;
3606 }
3607 case IntrinsicHelper::HLSputBoolean: {
3608 Expand_HLSput(call_inst, kBoolean);
3609 return NULL;
3610 }
3611 case IntrinsicHelper::HLSputByte: {
3612 Expand_HLSput(call_inst, kByte);
3613 return NULL;
3614 }
3615 case IntrinsicHelper::HLSputChar: {
3616 Expand_HLSput(call_inst, kChar);
3617 return NULL;
3618 }
3619 case IntrinsicHelper::HLSputShort: {
3620 Expand_HLSput(call_inst, kShort);
3621 return NULL;
3622 }
3623 case IntrinsicHelper::HLSputFloat: {
3624 Expand_HLSput(call_inst, kFloat);
3625 return NULL;
3626 }
3627 case IntrinsicHelper::HLSputWide: {
3628 Expand_HLSput(call_inst, kLong);
3629 return NULL;
3630 }
3631 case IntrinsicHelper::HLSputDouble: {
3632 Expand_HLSput(call_inst, kDouble);
3633 return NULL;
3634 }
3635 case IntrinsicHelper::HLSputObject: {
3636 Expand_HLSput(call_inst, kObject);
3637 return NULL;
3638 }
3639
3640 //==- High-level Monitor -----------------------------------------------==//
3641 case IntrinsicHelper::MonitorEnter: {
3642 Expand_MonitorEnter(call_inst);
3643 return NULL;
3644 }
3645 case IntrinsicHelper::MonitorExit: {
3646 Expand_MonitorExit(call_inst);
3647 return NULL;
3648 }
3649
3650 //==- Shadow Frame -----------------------------------------------------==//
3651 case IntrinsicHelper::AllocaShadowFrame: {
3652 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
3653 return NULL;
3654 }
3655 case IntrinsicHelper::SetVReg: {
3656 Expand_SetVReg(call_inst.getArgOperand(0),
3657 call_inst.getArgOperand(1));
3658 return NULL;
3659 }
3660 case IntrinsicHelper::PopShadowFrame: {
3661 Expand_PopShadowFrame();
3662 return NULL;
3663 }
3664 case IntrinsicHelper::UpdateDexPC: {
3665 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3666 return NULL;
3667 }
3668
3669 //==- Comparison -------------------------------------------------------==//
3670 case IntrinsicHelper::CmplFloat:
3671 case IntrinsicHelper::CmplDouble: {
3672 return Expand_FPCompare(call_inst.getArgOperand(0),
3673 call_inst.getArgOperand(1),
3674 false);
3675 }
3676 case IntrinsicHelper::CmpgFloat:
3677 case IntrinsicHelper::CmpgDouble: {
3678 return Expand_FPCompare(call_inst.getArgOperand(0),
3679 call_inst.getArgOperand(1),
3680 true);
3681 }
3682 case IntrinsicHelper::CmpLong: {
3683 return Expand_LongCompare(call_inst.getArgOperand(0),
3684 call_inst.getArgOperand(1));
3685 }
3686
3687 //==- Const ------------------------------------------------------------==//
3688 case IntrinsicHelper::ConstInt:
3689 case IntrinsicHelper::ConstLong: {
3690 return call_inst.getArgOperand(0);
3691 }
3692 case IntrinsicHelper::ConstFloat: {
3693 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3694 irb_.getJFloatTy());
3695 }
3696 case IntrinsicHelper::ConstDouble: {
3697 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3698 irb_.getJDoubleTy());
3699 }
3700 case IntrinsicHelper::ConstObj: {
3701 CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
3702 return irb_.getJNull();
3703 }
3704
3705 //==- Method Info ------------------------------------------------------==//
3706 case IntrinsicHelper::MethodInfo: {
3707 // Nothing to be done, because MethodInfo carries optional hints that are
3708 // not needed by the portable path.
3709 return NULL;
3710 }
3711
3712 //==- Copy -------------------------------------------------------------==//
3713 case IntrinsicHelper::CopyInt:
3714 case IntrinsicHelper::CopyFloat:
3715 case IntrinsicHelper::CopyLong:
3716 case IntrinsicHelper::CopyDouble:
3717 case IntrinsicHelper::CopyObj: {
3718 return call_inst.getArgOperand(0);
3719 }
3720
3721 //==- Shift ------------------------------------------------------------==//
3722 case IntrinsicHelper::SHLLong: {
3723 return Expand_IntegerShift(call_inst.getArgOperand(0),
3724 call_inst.getArgOperand(1),
3725 kIntegerSHL, kLong);
3726 }
3727 case IntrinsicHelper::SHRLong: {
3728 return Expand_IntegerShift(call_inst.getArgOperand(0),
3729 call_inst.getArgOperand(1),
3730 kIntegerSHR, kLong);
3731 }
3732 case IntrinsicHelper::USHRLong: {
3733 return Expand_IntegerShift(call_inst.getArgOperand(0),
3734 call_inst.getArgOperand(1),
3735 kIntegerUSHR, kLong);
3736 }
3737 case IntrinsicHelper::SHLInt: {
3738 return Expand_IntegerShift(call_inst.getArgOperand(0),
3739 call_inst.getArgOperand(1),
3740 kIntegerSHL, kInt);
3741 }
3742 case IntrinsicHelper::SHRInt: {
3743 return Expand_IntegerShift(call_inst.getArgOperand(0),
3744 call_inst.getArgOperand(1),
3745 kIntegerSHR, kInt);
3746 }
3747 case IntrinsicHelper::USHRInt: {
3748 return Expand_IntegerShift(call_inst.getArgOperand(0),
3749 call_inst.getArgOperand(1),
3750 kIntegerUSHR, kInt);
3751 }
3752
3753 //==- Conversion -------------------------------------------------------==//
3754 case IntrinsicHelper::IntToChar: {
3755 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3756 irb_.getJIntTy());
3757 }
3758 case IntrinsicHelper::IntToShort: {
3759 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3760 irb_.getJIntTy());
3761 }
3762 case IntrinsicHelper::IntToByte: {
3763 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3764 irb_.getJIntTy());
3765 }
3766
3767 //==- Exception --------------------------------------------------------==//
3768 case IntrinsicHelper::CatchTargets: {
3769 UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
3770 llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
3771 CHECK(si != NULL);
3772 irb_.CreateBr(si->getDefaultDest());
3773 si->eraseFromParent();
3774 return call_inst.getArgOperand(0);
3775 }
3776
3777 //==- Constructor barrier-----------------------------------------------==//
3778 case IntrinsicHelper::ConstructorBarrier: {
3779 irb_.CreateMemoryBarrier(art::kStoreStore);
3780 return NULL;
3781 }
3782
3783 //==- Unknown Cases ----------------------------------------------------==//
3784 case IntrinsicHelper::MaxIntrinsicId:
3785 case IntrinsicHelper::UnknownId:
3786 //default:
3787 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3788 // give some warning on unmatched cases.
3789 // NOTE: We should not implement these cases.
3790 break;
3791 }
3792 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
3793 return NULL;
Brian Carlstrom1895ea32013-07-18 13:28:37 -07003794} // NOLINT(readability/fn_size)
Brian Carlstrom7940e442013-07-12 13:46:57 -07003795
3796} // anonymous namespace
3797
3798namespace art {
3799namespace llvm {
3800
3801::llvm::FunctionPass*
3802CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
3803 CompilerDriver* driver, const DexCompilationUnit* dex_compilation_unit) {
3804 return new GBCExpanderPass(intrinsic_helper, irb, driver, dex_compilation_unit);
3805}
3806
3807} // namespace llvm
3808} // namespace art