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