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