blob: 6e8ce12e08f4b73e1a7d63858db45c2e3ba0855f [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>
35
36using namespace art;
37using namespace compiler_llvm;
38
39using art::greenland::IntrinsicHelper;
40
41namespace {
42
43class GBCExpanderPass : public llvm::FunctionPass {
44 private:
45 const IntrinsicHelper& intrinsic_helper_;
46 IRBuilder& irb_;
47
48 llvm::LLVMContext& context_;
49 RuntimeSupportBuilder& rtb_;
50
51 private:
52 llvm::AllocaInst* shadow_frame_;
53 llvm::Value* old_shadow_frame_;
54 uint32_t shadow_frame_size_;
55
56 private:
TDYa1275e869b62012-07-25 00:45:39 -070057 // TODO: Init these fields
58 Compiler* compiler_;
59
60 const DexFile* dex_file_;
61 DexCache* dex_cache_;
62 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_;
73 llvm::BasicBlock* basic_block_unwind_;
74
75 private:
Shih-wei Liao21d28f52012-06-12 05:55:00 -070076 //----------------------------------------------------------------------------
Logan Chien75e4b602012-07-23 14:24:12 -070077 // Constant for GBC expansion
78 //----------------------------------------------------------------------------
79 enum IntegerShiftKind {
80 kIntegerSHL,
81 kIntegerSHR,
82 kIntegerUSHR,
83 };
84
85 private:
86 //----------------------------------------------------------------------------
Shih-wei Liao21d28f52012-06-12 05:55:00 -070087 // Helper function for GBC expansion
88 //----------------------------------------------------------------------------
89
Shih-wei Liao21d28f52012-06-12 05:55:00 -070090 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
91 llvm::CallInst& inst);
92
TDYa1275e869b62012-07-25 00:45:39 -070093 uint64_t LV2UInt(llvm::Value* lv) {
94 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
95 }
96
97 int64_t LV2SInt(llvm::Value* lv) {
98 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
99 }
100
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700101 private:
102 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
103 // Refactor these utility functions from MethodCompiler to avoid forking.
104
105 bool EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
106
107 //----------------------------------------------------------------------------
108 // Dex cache code generation helper function
109 //----------------------------------------------------------------------------
110 llvm::Value* EmitLoadDexCacheAddr(MemberOffset dex_cache_offset);
111
112 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
113
114 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
115
116 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
117
118 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
119
120 //----------------------------------------------------------------------------
121 // Code generation helper function
122 //----------------------------------------------------------------------------
123 llvm::Value* EmitLoadMethodObjectAddr();
124
125 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
126
127 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
128
129 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
130 llvm::Value* this_addr);
131
132 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
133 llvm::Value* index_value,
134 JType elem_jty);
135
136 private:
137 //----------------------------------------------------------------------------
138 // Expand Greenland intrinsics
139 //----------------------------------------------------------------------------
140 void Expand_TestSuspend(llvm::CallInst& call_inst);
141
TDYa1279a129452012-07-19 03:10:08 -0700142 void Expand_MarkGCCard(llvm::CallInst& call_inst);
143
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700144 llvm::Value* Expand_GetException();
145
146 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
147
148 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
149
150 void Expand_LockObject(llvm::Value* obj);
151
152 void Expand_UnlockObject(llvm::Value* obj);
153
154 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
155 llvm::Value* index_value,
156 JType elem_jty);
157
158 void Expand_ArrayPut(llvm::Value* new_value,
159 llvm::Value* array_addr,
160 llvm::Value* index_value,
161 JType elem_jty);
162
163 void Expand_FilledNewArray(llvm::CallInst& call_inst);
164
165 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
166 llvm::Value* is_volatile_value,
167 llvm::Value* object_addr,
168 JType field_jty);
169
170 void Expand_IPutFast(llvm::Value* field_offset_value,
171 llvm::Value* is_volatile_value,
172 llvm::Value* object_addr,
173 llvm::Value* new_value,
174 JType field_jty);
175
176 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
177 llvm::Value* field_offset_value,
178 llvm::Value* is_volatile_value,
179 JType field_jty);
180
181 void Expand_SPutFast(llvm::Value* static_storage_addr,
182 llvm::Value* field_offset_value,
183 llvm::Value* is_volatile_value,
184 llvm::Value* new_value,
185 JType field_jty);
186
187 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
188
189 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
190
191 llvm::Value*
192 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
193
194 llvm::Value*
195 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
196 llvm::Value* this_addr);
197
198 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
199
200 llvm::Value* Expand_DivRem(llvm::Value* dividend, llvm::Value* divisor,
201 bool is_div, JType op_jty);
202
203 void Expand_AllocaShadowFrame(llvm::Value* num_entry_value);
204
205 void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
206
207 void Expand_PopShadowFrame();
208
209 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
210
TDYa127a1b21852012-07-23 03:20:39 -0700211 //----------------------------------------------------------------------------
212 // Quick
213 //----------------------------------------------------------------------------
214
215 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
216 llvm::Value* src2_value,
217 bool gt_bias);
218
219 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
220
221 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
222 llvm::Value* cmp_lt);
223
TDYa1275e869b62012-07-25 00:45:39 -0700224 class ScopedExpandToBasicBlock {
225 public:
226 ScopedExpandToBasicBlock(IRBuilder& irb, llvm::Instruction* expand_inst)
227 : irb_(irb), expand_inst_(expand_inst) {
228 llvm::Function* func = expand_inst_->getParent()->getParent();
229 begin_bb_ = llvm::BasicBlock::Create(irb_.getContext(),
230 "",
231 func);
232 irb_.SetInsertPoint(begin_bb_);
233 }
234
235 ~ScopedExpandToBasicBlock() {
236 llvm::BasicBlock* end_bb = irb_.GetInsertBlock();
237 SplitAndInsertBasicBlocksAfter(*expand_inst_, begin_bb_, end_bb);
238 }
239
240 private:
241 // Split the basic block containing INST at INST and insert a sequence of
242 // basic blocks with a single entry at BEGIN_BB and a single exit at END_BB
243 // before INST.
244 llvm::BasicBlock*
245 SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
246 llvm::BasicBlock* begin_bb,
247 llvm::BasicBlock* end_bb);
248 private:
249 IRBuilder& irb_;
250 llvm::Instruction* expand_inst_;
251 llvm::BasicBlock* begin_bb_;
252 };
253
254 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
255 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
256
257 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
258
259 void EmitUpdateDexPC(uint32_t dex_pc);
260
261 void EmitGuard_DivZeroException(uint32_t dex_pc,
262 llvm::Value* denominator,
263 JType op_jty);
264
265 void EmitGuard_NullPointerException(uint32_t dex_pc,
266 llvm::Value* object);
267
268 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
269 llvm::Value* array,
270 llvm::Value* index);
271
272 void EmitGuard_ArrayException(uint32_t dex_pc,
273 llvm::Value* array,
274 llvm::Value* index);
275
276 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
277
278 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
279
280 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
281 const char* postfix);
282
283 int32_t GetTryItemOffset(uint32_t dex_pc);
284
285 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
286
287 llvm::BasicBlock* GetUnwindBasicBlock();
288
289 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
290
291 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
292
Logan Chien75e4b602012-07-23 14:24:12 -0700293 //----------------------------------------------------------------------------
294 // Expand Arithmetic Helper Intrinsics
295 //----------------------------------------------------------------------------
296
297 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
298 llvm::Value* src2_value,
299 IntegerShiftKind kind,
300 JType op_jty);
301
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700302 public:
303 static char ID;
304
305 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
306 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
307 context_(irb.getContext()), rtb_(irb.Runtime())
308 { }
309
310 bool runOnFunction(llvm::Function& func);
311
312 private:
313 bool InsertStackOverflowCheck(llvm::Function& func);
314
315 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
316 llvm::CallInst& call_inst);
317
318};
319
320char GBCExpanderPass::ID = 0;
321
322bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700323 // Runtime support or stub
324 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
325 return false;
326 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700327 bool changed;
328
TDYa127b672d1e2012-06-28 21:21:45 -0700329 // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700330 changed = InsertStackOverflowCheck(func);
331
332 std::list<std::pair<llvm::CallInst*,
333 IntrinsicHelper::IntrinsicId> > work_list;
334
335 for (llvm::inst_iterator inst_iter = llvm::inst_begin(func),
336 inst_end = llvm::inst_end(func); inst_iter != inst_end; inst_iter++) {
337 // Only CallInst with its called function is dexlang intrinsic need to
338 // process
339 llvm::Instruction* inst = &*inst_iter;
340 if (llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst)) {
341 const llvm::Function* callee = call_inst->getCalledFunction();
342
343 if (callee != NULL) {
344 IntrinsicHelper::IntrinsicId intr_id =
345 intrinsic_helper_.GetIntrinsicId(callee);
346
347 if (intr_id != IntrinsicHelper::UnknownId) {
348 work_list.push_back(std::make_pair(call_inst, intr_id));
349 }
350 }
351 }
352 }
353
354 changed |= !work_list.empty();
355
356 shadow_frame_ = NULL;
357 old_shadow_frame_ = NULL;
358 shadow_frame_size_ = 0;
TDYa1275e869b62012-07-25 00:45:39 -0700359 func_ = &func;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700360
361 // Remove the instruction containing in the work_list
362 while (!work_list.empty()) {
363 llvm::CallInst* intr_inst = work_list.front().first;
364 IntrinsicHelper::IntrinsicId intr_id = work_list.front().second;
365
366 // Remove the instruction from work list
367 work_list.pop_front();
368
369 // Move the IRBuilder insert pointer
370 irb_.SetInsertPoint(intr_inst);
371
372 // Process the expansion
373 llvm::Value* new_value = ExpandIntrinsic(intr_id, *intr_inst);
374
375 // Use the new value from the expansion
376 if (new_value != NULL) {
377 intr_inst->replaceAllUsesWith(new_value);
378 }
379
380 // Remove the intrinsic instruction
381 intr_inst->eraseFromParent();
382 }
383
384 VERIFY_LLVM_FUNCTION(func);
385
386 return changed;
387}
388
389llvm::BasicBlock*
TDYa1275e869b62012-07-25 00:45:39 -0700390GBCExpanderPass::ScopedExpandToBasicBlock::
391SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
392 llvm::BasicBlock* begin_bb,
393 llvm::BasicBlock* end_bb) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700394 llvm::BasicBlock* original = inst->getParent();
395 llvm::Function* parent = original->getParent();
396
397 // 1. Create a new basic block A after ORIGINAL
398 llvm::BasicBlock *insert_before =
399 llvm::next(llvm::Function::iterator(original)).getNodePtrUnchecked();
400 llvm::BasicBlock* a =
TDYa1275e869b62012-07-25 00:45:39 -0700401 llvm::BasicBlock::Create(irb_.getContext(), "", parent, insert_before);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700402
403 // 2. Move all instructions in ORIGINAL after INST (included) to A
404 a->getInstList().splice(a->end(), original->getInstList(),
405 inst, original->end());
406
407 // 3. Add an unconditional branch in ORIGINAL to begin_bb
408 llvm::BranchInst::Create(begin_bb, original);
409
410 // 4. Add an unconditional branch in END_BB to A
411 llvm::BranchInst::Create(a, end_bb);
412
413 // 5. Update the PHI nodes in the successors of A. Update the PHI node entry
414 // with incoming basic block from ORIGINAL to A
415 for (llvm::succ_iterator succ_iter = llvm::succ_begin(a),
416 succ_end = llvm::succ_end(a); succ_iter != succ_end; succ_iter++) {
417 llvm::BasicBlock* succ = *succ_iter;
418 llvm::PHINode* phi;
419 for (llvm::BasicBlock::iterator inst_iter = succ->begin();
420 (phi = llvm::dyn_cast<llvm::PHINode>(inst_iter)); ++inst_iter) {
421 int idx;
422 while ((idx = phi->getBasicBlockIndex(original)) != -1) {
423 phi->setIncomingBlock(static_cast<unsigned>(idx), a);
424 }
425 }
426 }
427
428 return a;
429}
430
431llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
432 llvm::CallInst& inst) {
433 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
434 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
435 // function, therefore only called function is needed to change.
436 unsigned num_args = inst.getNumArgOperands();
437
438 if (num_args <= 0) {
439 return irb_.CreateCall(irb_.GetRuntime(rt));
440 } else {
441 std::vector<llvm::Value*> args;
442 for (unsigned i = 0; i < num_args; i++) {
443 args.push_back(inst.getArgOperand(i));
444 }
445
446 return irb_.CreateCall(irb_.GetRuntime(rt), args);
447 }
448}
449
450bool
451GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
TDYa1275e869b62012-07-25 00:45:39 -0700452 ScopedExpandToBasicBlock eb(irb_, first_non_alloca);
453
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700454 llvm::Function* func = first_non_alloca->getParent()->getParent();
455 llvm::Module* module = func->getParent();
456
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700457 // Call llvm intrinsic function to get frame address.
458 llvm::Function* frameaddress =
459 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
460
461 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
462 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
463
464 // Cast i8* to int
465 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
466
467 // Get thread.stack_end_
468 llvm::Value* stack_end =
469 irb_.Runtime().EmitLoadFromThreadOffset(Thread::StackEndOffset().Int32Value(),
470 irb_.getPtrEquivIntTy(),
471 kTBAARuntimeInfo);
472
473 // Check the frame address < thread.stack_end_ ?
474 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
475
476 llvm::BasicBlock* block_exception =
477 llvm::BasicBlock::Create(context_, "stack_overflow", func);
478
479 llvm::BasicBlock* block_continue =
480 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
481
482 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
483
484 // If stack overflow, throw exception.
485 irb_.SetInsertPoint(block_exception);
486 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
487
488 // Unwind.
489 llvm::Type* ret_type = func->getReturnType();
490 if (ret_type->isVoidTy()) {
491 irb_.CreateRetVoid();
492 } else {
493 // The return value is ignored when there's an exception. MethodCompiler
494 // returns zero value under the the corresponding return type in this case.
495 // GBCExpander returns LLVM undef value here for brevity
496 irb_.CreateRet(llvm::UndefValue::get(ret_type));
497 }
498
499 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700500 return true;
501}
502
503llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(MemberOffset offset) {
504 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
505
506 return irb_.LoadFromObjectOffset(method_object_addr,
507 offset.Int32Value(),
508 irb_.getJObjectTy(),
509 kTBAAConstJObject);
510}
511
512llvm::Value*
513GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
514 llvm::Value* static_storage_dex_cache_addr =
515 EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
516
517 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
518
519 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
520}
521
522llvm::Value*
523GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
524 llvm::Value* resolved_type_dex_cache_addr =
525 EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
526
527 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
528
529 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
530}
531
532llvm::Value* GBCExpanderPass::
533EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
534 llvm::Value* resolved_method_dex_cache_addr =
535 EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
536
537 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
538
539 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
540}
541
542llvm::Value* GBCExpanderPass::
543EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
544 llvm::Value* string_dex_cache_addr =
545 EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
546
547 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
548
549 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
550}
551
552llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
553 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
554 return parent_func->arg_begin();
555}
556
557llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
558 // Load array length
559 return irb_.LoadFromObjectOffset(array,
560 Array::LengthOffset().Int32Value(),
561 irb_.getJIntTy(),
562 kTBAAConstJObject);
563
564}
565
566llvm::Value*
567GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
568 llvm::Value* callee_method_object_field_addr =
569 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
570
571 return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
572}
573
574llvm::Value* GBCExpanderPass::
575EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
576 // Load class object of *this* pointer
577 llvm::Value* class_object_addr =
578 irb_.LoadFromObjectOffset(this_addr,
579 Object::ClassOffset().Int32Value(),
580 irb_.getJObjectTy(),
581 kTBAAConstJObject);
582
583 // Load vtable address
584 llvm::Value* vtable_addr =
585 irb_.LoadFromObjectOffset(class_object_addr,
586 Class::VTableOffset().Int32Value(),
587 irb_.getJObjectTy(),
588 kTBAAConstJObject);
589
590 // Load callee method object
591 llvm::Value* vtable_idx_value =
592 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
593
594 llvm::Value* method_field_addr =
595 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
596
597 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
598}
599
600// Emit Array GetElementPtr
601llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
602 llvm::Value* index_value,
603 JType elem_jty) {
604
605 int data_offset;
606 if (elem_jty == kLong || elem_jty == kDouble ||
607 (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
608 data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
609 } else {
610 data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
611 }
612
613 llvm::Constant* data_offset_value =
614 irb_.getPtrEquivInt(data_offset);
615
616 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
617
618 llvm::Value* array_data_addr =
619 irb_.CreatePtrDisp(array_addr, data_offset_value,
620 elem_type->getPointerTo());
621
622 return irb_.CreateGEP(array_data_addr, index_value);
623}
624
625void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
TDYa1275e869b62012-07-25 00:45:39 -0700626 ScopedExpandToBasicBlock eb(irb_, &call_inst);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700627 irb_.Runtime().EmitTestSuspend();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700628 return;
629}
630
TDYa1279a129452012-07-19 03:10:08 -0700631void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1275e869b62012-07-25 00:45:39 -0700632 ScopedExpandToBasicBlock eb(irb_, &call_inst);
TDYa1279a129452012-07-19 03:10:08 -0700633 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700634 return;
635}
636
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700637llvm::Value* GBCExpanderPass::Expand_GetException() {
638 // Get thread-local exception field address
639 llvm::Value* exception_object_addr =
640 irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
641 irb_.getJObjectTy(),
642 kTBAAJRuntime);
643
644 // Set thread-local exception field address to NULL
645 irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
646 irb_.getJNull(),
647 kTBAAJRuntime);
648
649 return exception_object_addr;
650}
651
652llvm::Value*
653GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
654 uint32_t string_idx =
655 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
656
657 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
658
659 return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
660}
661
662llvm::Value*
663GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
664 uint32_t type_idx =
665 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
666
667 llvm::Value* type_field_addr =
668 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
669
670 return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
671}
672
673void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
TDYa1275e869b62012-07-25 00:45:39 -0700674 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700675 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700676 return;
677}
678
679void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
TDYa1275e869b62012-07-25 00:45:39 -0700680 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700681 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700682 return;
683}
684
685llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
686 llvm::Value* index_value,
687 JType elem_jty) {
688 llvm::Value* array_elem_addr =
689 EmitArrayGEP(array_addr, index_value, elem_jty);
690
691 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
692}
693
694void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
695 llvm::Value* array_addr,
696 llvm::Value* index_value,
697 JType elem_jty) {
698 llvm::Value* array_elem_addr =
699 EmitArrayGEP(array_addr, index_value, elem_jty);
700
701 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
702
703 return;
704}
705
706void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
707 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
708 llvm::Value* array = call_inst.getArgOperand(0);
709
710 uint32_t element_jty =
711 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
712
713 DCHECK(call_inst.getNumArgOperands() > 2);
714 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
715
716 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
717
718 uint32_t alignment;
719 llvm::Constant* elem_size;
720 llvm::PointerType* field_type;
721
722 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
723 // as the element, thus we are only checking 2 cases: primitive int and
724 // non-primitive type.
725 if (is_elem_int_ty) {
726 alignment = sizeof(int32_t);
727 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
728 field_type = irb_.getJIntTy()->getPointerTo();
729 } else {
730 alignment = irb_.getSizeOfPtrEquivInt();
731 elem_size = irb_.getSizeOfPtrEquivIntValue();
732 field_type = irb_.getJObjectTy()->getPointerTo();
733 }
734
735 llvm::Value* data_field_offset =
736 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
737
738 llvm::Value* data_field_addr =
739 irb_.CreatePtrDisp(array, data_field_offset, field_type);
740
741 for (unsigned i = 0; i < num_elements; ++i) {
742 // Values to fill the array begin at the 3rd argument
743 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
744
745 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
746
747 data_field_addr =
748 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
749 }
750
751 return;
752}
753
754llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
755 llvm::Value* /*is_volatile_value*/,
756 llvm::Value* object_addr,
757 JType field_jty) {
758 int field_offset =
759 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
760
761 DCHECK_GE(field_offset, 0);
762
763 llvm::PointerType* field_type =
764 irb_.getJType(field_jty, kField)->getPointerTo();
765
766 field_offset_value = irb_.getPtrEquivInt(field_offset);
767
768 llvm::Value* field_addr =
769 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
770
771 // TODO: Check is_volatile. We need to generate atomic load instruction
772 // when is_volatile is true.
773 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
774}
775
776void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
777 llvm::Value* /* is_volatile_value */,
778 llvm::Value* object_addr,
779 llvm::Value* new_value,
780 JType field_jty) {
781 int field_offset =
782 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
783
784 DCHECK_GE(field_offset, 0);
785
786 llvm::PointerType* field_type =
787 irb_.getJType(field_jty, kField)->getPointerTo();
788
789 field_offset_value = irb_.getPtrEquivInt(field_offset);
790
791 llvm::Value* field_addr =
792 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
793
794 // TODO: Check is_volatile. We need to generate atomic store instruction
795 // when is_volatile is true.
796 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
797
798 return;
799}
800
801llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
802 llvm::Value* field_offset_value,
803 llvm::Value* /*is_volatile_value*/,
804 JType field_jty) {
805 int field_offset =
806 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
807
808 DCHECK_GE(field_offset, 0);
809
810 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
811
812 llvm::Value* static_field_addr =
813 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
814 irb_.getJType(field_jty, kField)->getPointerTo());
815
816 // TODO: Check is_volatile. We need to generate atomic store instruction
817 // when is_volatile is true.
818 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
819}
820
821void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
822 llvm::Value* field_offset_value,
823 llvm::Value* /* is_volatile_value */,
824 llvm::Value* new_value,
825 JType field_jty) {
826 int field_offset =
827 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
828
829 DCHECK_GE(field_offset, 0);
830
831 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
832
833 llvm::Value* static_field_addr =
834 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
835 irb_.getJType(field_jty, kField)->getPointerTo());
836
837 // TODO: Check is_volatile. We need to generate atomic store instruction
838 // when is_volatile is true.
839 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
840
841 return;
842}
843
844llvm::Value*
845GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
846 return irb_.LoadFromObjectOffset(method_object_addr,
847 Method::DeclaringClassOffset().Int32Value(),
848 irb_.getJObjectTy(),
849 kTBAAConstJObject);
850}
851
852llvm::Value*
853GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
854 uint32_t type_idx =
855 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
856
857 llvm::Value* storage_field_addr =
858 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
859
860 return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
861}
862
863llvm::Value*
864GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
865 uint32_t callee_method_idx =
866 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
867
868 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
869}
870
871llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
872 llvm::Value* vtable_idx_value,
873 llvm::Value* this_addr) {
874 int vtable_idx =
875 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
876
877 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
878}
879
880llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
881 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
882 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
883 unsigned num_args = call_inst.getNumArgOperands();
884 llvm::Type* ret_type = call_inst.getType();
885
886 // Determine the function type of the callee method
887 std::vector<llvm::Type*> args_type;
888 std::vector<llvm::Value*> args;
889 for (unsigned i = 0; i < num_args; i++) {
890 args.push_back(call_inst.getArgOperand(i));
891 args_type.push_back(args[i]->getType());
892 }
893
894 llvm::FunctionType* callee_method_type =
895 llvm::FunctionType::get(ret_type, args_type, false);
896
897 llvm::Value* code_addr =
898 irb_.LoadFromObjectOffset(callee_method_object_addr,
899 Method::GetCodeOffset().Int32Value(),
900 callee_method_type->getPointerTo(),
901 kTBAAJRuntime);
902
903 // Invoke callee
904 llvm::Value* retval = irb_.CreateCall(code_addr, args);
905
906 return retval;
907}
908
909llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::Value* dividend,
910 llvm::Value* divisor,
911 bool is_div, JType op_jty) {
912 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
913
914 // Check the special case: MININT / -1 = MININT
915 // That case will cause overflow, which is undefined behavior in llvm.
916 // So we check the divisor is -1 or not, if the divisor is -1, we do
917 // the special path to avoid undefined behavior.
918 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
919 llvm::Value* zero = irb_.getJZero(op_jty);
920 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
921
TDYa1275e869b62012-07-25 00:45:39 -0700922 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700923
TDYa1275e869b62012-07-25 00:45:39 -0700924 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700925 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
926 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
927 llvm::BasicBlock* neg_one_cont =
928 llvm::BasicBlock::Create(context_, "", parent);
929
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700930 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
931 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
932
933 // If divisor == -1
934 irb_.SetInsertPoint(eq_neg_one);
935 llvm::Value* eq_result;
936 if (is_div) {
937 // We can just change from "dividend div -1" to "neg dividend". The sub
938 // don't care the sign/unsigned because of two's complement representation.
939 // And the behavior is what we want:
940 // -(2^n) (2^n)-1
941 // MININT < k <= MAXINT -> mul k -1 = -k
942 // MININT == k -> mul k -1 = k
943 //
944 // LLVM use sub to represent 'neg'
945 eq_result = irb_.CreateSub(zero, dividend);
946 } else {
947 // Everything modulo -1 will be 0.
948 eq_result = zero;
949 }
950 irb_.CreateBr(neg_one_cont);
951
952 // If divisor != -1, just do the division.
953 irb_.SetInsertPoint(ne_neg_one);
954 llvm::Value* ne_result;
955 if (is_div) {
956 ne_result = irb_.CreateSDiv(dividend, divisor);
957 } else {
958 ne_result = irb_.CreateSRem(dividend, divisor);
959 }
960 irb_.CreateBr(neg_one_cont);
961
962 irb_.SetInsertPoint(neg_one_cont);
963 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
964 result->addIncoming(eq_result, eq_neg_one);
965 result->addIncoming(ne_result, ne_neg_one);
966
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700967 return result;
968}
969
970void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
971 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
972 // MethodCompiler::EmitPushShadowFrame
973 shadow_frame_size_ =
974 llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
975
976 llvm::StructType* shadow_frame_type =
977 irb_.getShadowFrameTy(shadow_frame_size_);
978
979 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
980
981 // Alloca a pointer to old shadow frame
982 old_shadow_frame_ =
983 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
984
985 // Zero-initialization of the shadow frame table
986 llvm::Value* shadow_frame_table =
987 irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
988 llvm::Type* table_type = shadow_frame_type->getElementType(1);
989
990 llvm::ConstantAggregateZero* zero_initializer =
991 llvm::ConstantAggregateZero::get(table_type);
992
993 irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
994
995 // Push the shadow frame
996 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
997
998 // Push the shadow frame
999 llvm::Value* shadow_frame_upcast =
1000 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1001
1002 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1003 method_object_addr,
1004 shadow_frame_size_);
1005
1006 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1007
1008 return;
1009}
1010
1011void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
1012 llvm::Value* entry_idx) {
1013 DCHECK(shadow_frame_ != NULL);
1014
1015 llvm::Value* gep_index[] = {
1016 irb_.getInt32(0), // No pointer displacement
1017 irb_.getInt32(1), // SIRT
1018 entry_idx // Pointer field
1019 };
1020
1021 llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1022 irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
1023 return;
1024}
1025
1026void GBCExpanderPass::Expand_PopShadowFrame() {
1027 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1028 return;
1029}
1030
1031void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1032 irb_.StoreToObjectOffset(shadow_frame_,
1033 ShadowFrame::DexPCOffset(),
1034 dex_pc_value,
1035 kTBAAShadowFrame);
1036 return;
1037}
1038
1039bool GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
1040 // DexLang generates all alloca instruction in the first basic block of the
1041 // FUNC and also there's no any alloca instructions after the first non-alloca
1042 // instruction
1043
1044 llvm::BasicBlock::iterator first_non_alloca = func.front().begin();
1045 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1046 ++first_non_alloca;
1047 }
1048
1049 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1050 // alloca instructions)
1051 return EmitStackOverflowCheck(&*first_non_alloca);
1052}
1053
TDYa1275e869b62012-07-25 00:45:39 -07001054// ==== High-level intrinsic expander ==========================================
1055
TDYa127a1b21852012-07-23 03:20:39 -07001056llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1057 llvm::Value* src2_value,
1058 bool gt_bias) {
1059 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1060 llvm::Value* cmp_lt;
1061
1062 if (gt_bias) {
1063 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1064 } else {
1065 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1066 }
1067
1068 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1069}
1070
1071llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1072 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1073 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1074
1075 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1076}
1077
1078llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1079 llvm::Value* cmp_lt) {
1080
1081 llvm::Constant* zero = irb_.getJInt(0);
1082 llvm::Constant* pos1 = irb_.getJInt(1);
1083 llvm::Constant* neg1 = irb_.getJInt(-1);
1084
1085 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1086 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1087
1088 return result_eq;
1089}
1090
Logan Chien75e4b602012-07-23 14:24:12 -07001091llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1092 llvm::Value* src2_value,
1093 IntegerShiftKind kind,
1094 JType op_jty) {
1095 DCHECK(op_jty == kInt || op_jty == kLong);
1096
1097 // Mask and zero-extend RHS properly
1098 if (op_jty == kInt) {
1099 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1100 } else {
1101 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1102 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1103 }
1104
1105 // Create integer shift llvm instruction
1106 switch (kind) {
1107 case kIntegerSHL:
1108 return irb_.CreateShl(src1_value, src2_value);
1109
1110 case kIntegerSHR:
1111 return irb_.CreateAShr(src1_value, src2_value);
1112
1113 case kIntegerUSHR:
1114 return irb_.CreateLShr(src1_value, src2_value);
1115
1116 default:
1117 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1118 return NULL;
1119 }
1120}
1121
TDYa1275e869b62012-07-25 00:45:39 -07001122llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1123 JType field_jty) {
1124 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1125
1126 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1127 llvm::Value* object_addr = call_inst.getArgOperand(1);
1128 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
1129
1130 // TODO: opt_flags
1131 EmitGuard_NullPointerException(dex_pc, object_addr);
1132
1133 llvm::Value* field_value;
1134
1135 int field_offset;
1136 bool is_volatile;
1137 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1138 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
1139
1140 if (!is_fast_path) {
1141 llvm::Function* runtime_func;
1142
1143 if (field_jty == kObject) {
1144 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1145 } else if (field_jty == kLong || field_jty == kDouble) {
1146 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1147 } else {
1148 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1149 }
1150
1151 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1152
1153 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1154
1155 EmitUpdateDexPC(dex_pc);
1156
1157 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1158 method_object_addr, object_addr);
1159
1160 EmitGuard_ExceptionLandingPad(dex_pc);
1161
1162 } else {
1163 DCHECK_GE(field_offset, 0);
1164
1165 llvm::PointerType* field_type =
1166 irb_.getJType(field_jty, kField)->getPointerTo();
1167
1168 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1169
1170 llvm::Value* field_addr =
1171 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1172
1173 // TODO: Check is_volatile. We need to generate atomic load instruction
1174 // when is_volatile is true.
1175 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1176 }
1177
1178 if (field_jty == kFloat || field_jty == kDouble) {
1179 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty, kReg));
1180 }
1181
1182 return field_value;
1183}
1184
1185void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1186 JType field_jty) {
1187 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1188
1189 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1190 llvm::Value* object_addr = call_inst.getArgOperand(1);
1191 llvm::Value* new_value = call_inst.getArgOperand(2);
1192 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
1193
1194 if (field_jty == kFloat || field_jty == kDouble) {
1195 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kReg));
1196 }
1197
1198 // TODO: opt_flags
1199 EmitGuard_NullPointerException(dex_pc, object_addr);
1200
1201 int field_offset;
1202 bool is_volatile;
1203 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1204 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
1205
1206 if (!is_fast_path) {
1207 llvm::Function* runtime_func;
1208
1209 if (field_jty == kObject) {
1210 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1211 } else if (field_jty == kLong || field_jty == kDouble) {
1212 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1213 } else {
1214 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1215 }
1216
1217 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1218
1219 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1220
1221 EmitUpdateDexPC(dex_pc);
1222
1223 irb_.CreateCall4(runtime_func, field_idx_value,
1224 method_object_addr, object_addr, new_value);
1225
1226 EmitGuard_ExceptionLandingPad(dex_pc);
1227
1228 } else {
1229 DCHECK_GE(field_offset, 0);
1230
1231 llvm::PointerType* field_type =
1232 irb_.getJType(field_jty, kField)->getPointerTo();
1233
1234 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1235
1236 llvm::Value* field_addr =
1237 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1238
1239 // TODO: Check is_volatile. We need to generate atomic store instruction
1240 // when is_volatile is true.
1241 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1242
1243 if (field_jty == kObject) { // If put an object, mark the GC card table.
1244 EmitMarkGCCard(new_value, object_addr);
1245 }
1246 }
1247
1248 return;
1249}
1250
1251void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
1252 // Using runtime support, let the target can override by InlineAssembly.
1253 irb_.Runtime().EmitMarkGCCard(value, target_addr);
1254}
1255
1256void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
1257 irb_.StoreToObjectOffset(shadow_frame_,
1258 ShadowFrame::DexPCOffset(),
1259 irb_.getInt32(dex_pc),
1260 kTBAAShadowFrame);
1261}
1262
1263void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
1264 llvm::Value* denominator,
1265 JType op_jty) {
1266 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
1267
1268 llvm::Constant* zero = irb_.getJZero(op_jty);
1269
1270 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
1271
1272 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
1273
1274 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
1275
1276 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
1277
1278 irb_.SetInsertPoint(block_exception);
1279 EmitUpdateDexPC(dex_pc);
1280 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
1281 EmitBranchExceptionLandingPad(dex_pc);
1282
1283 irb_.SetInsertPoint(block_continue);
1284}
1285
1286void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
1287 llvm::Value* object) {
1288 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
1289
1290 llvm::BasicBlock* block_exception =
1291 CreateBasicBlockWithDexPC(dex_pc, "nullp");
1292
1293 llvm::BasicBlock* block_continue =
1294 CreateBasicBlockWithDexPC(dex_pc, "cont");
1295
1296 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
1297
1298 irb_.SetInsertPoint(block_exception);
1299 EmitUpdateDexPC(dex_pc);
1300 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
1301 irb_.getInt32(dex_pc));
1302 EmitBranchExceptionLandingPad(dex_pc);
1303
1304 irb_.SetInsertPoint(block_continue);
1305}
1306
1307void
1308GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
1309 llvm::Value* array,
1310 llvm::Value* index) {
1311 llvm::Value* array_len = EmitLoadArrayLength(array);
1312
1313 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
1314
1315 llvm::BasicBlock* block_exception =
1316 CreateBasicBlockWithDexPC(dex_pc, "overflow");
1317
1318 llvm::BasicBlock* block_continue =
1319 CreateBasicBlockWithDexPC(dex_pc, "cont");
1320
1321 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
1322
1323 irb_.SetInsertPoint(block_exception);
1324
1325 EmitUpdateDexPC(dex_pc);
1326 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
1327 EmitBranchExceptionLandingPad(dex_pc);
1328
1329 irb_.SetInsertPoint(block_continue);
1330}
1331
1332void GBCExpanderPass::EmitGuard_ArrayException(uint32_t dex_pc,
1333 llvm::Value* array,
1334 llvm::Value* index) {
1335 EmitGuard_NullPointerException(dex_pc, array);
1336 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
1337}
1338
1339llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
1340 bool is_static) {
1341 // Get method signature
1342 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
1343
1344 uint32_t shorty_size;
1345 const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
1346 CHECK_GE(shorty_size, 1u);
1347
1348 // Get return type
1349 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
1350
1351 // Get argument type
1352 std::vector<llvm::Type*> args_type;
1353
1354 args_type.push_back(irb_.getJObjectTy()); // method object pointer
1355
1356 if (!is_static) {
1357 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
1358 }
1359
1360 for (uint32_t i = 1; i < shorty_size; ++i) {
1361 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
1362 }
1363
1364 return llvm::FunctionType::get(ret_type, args_type, false);
1365}
1366
1367
1368llvm::BasicBlock* GBCExpanderPass::
1369CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
1370 std::string name;
1371
1372#if !defined(NDEBUG)
1373 StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
1374#endif
1375
1376 return llvm::BasicBlock::Create(context_, name, func_);
1377}
1378
1379llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
1380 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
1381
1382 return basic_blocks_[dex_pc];
1383}
1384
1385int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
1386 int32_t min = 0;
1387 int32_t max = code_item_->tries_size_ - 1;
1388
1389 while (min <= max) {
1390 int32_t mid = min + (max - min) / 2;
1391
1392 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, mid);
1393 uint32_t start = ti->start_addr_;
1394 uint32_t end = start + ti->insn_count_;
1395
1396 if (dex_pc < start) {
1397 max = mid - 1;
1398 } else if (dex_pc >= end) {
1399 min = mid + 1;
1400 } else {
1401 return mid; // found
1402 }
1403 }
1404
1405 return -1; // not found
1406}
1407
1408llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
1409 // Find the try item for this address in this method
1410 int32_t ti_offset = GetTryItemOffset(dex_pc);
1411
1412 if (ti_offset == -1) {
1413 return NULL; // No landing pad is available for this address.
1414 }
1415
1416 // Check for the existing landing pad basic block
1417 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
1418 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
1419
1420 if (block_lpad) {
1421 // We have generated landing pad for this try item already. Return the
1422 // same basic block.
1423 return block_lpad;
1424 }
1425
1426 // Get try item from code item
1427 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, ti_offset);
1428
1429 std::string lpadname;
1430
1431#if !defined(NDEBUG)
1432 StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
1433#endif
1434
1435 // Create landing pad basic block
1436 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
1437
1438 // Change IRBuilder insert point
1439 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1440 irb_.SetInsertPoint(block_lpad);
1441
1442 // Find catch block with matching type
1443 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1444
1445 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
1446
1447 llvm::Value* catch_handler_index_value =
1448 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
1449 method_object_addr, ti_offset_value);
1450
1451 // Switch instruction (Go to unwind basic block by default)
1452 llvm::SwitchInst* sw =
1453 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
1454
1455 // Cases with matched catch block
1456 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
1457
1458 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
1459 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
1460 }
1461
1462 // Restore the orignal insert point for IRBuilder
1463 irb_.restoreIP(irb_ip_original);
1464
1465 // Cache this landing pad
1466 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
1467 basic_block_landing_pads_[ti_offset] = block_lpad;
1468
1469 return block_lpad;
1470}
1471
1472llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
1473 // Check the existing unwinding baisc block block
1474 if (basic_block_unwind_ != NULL) {
1475 return basic_block_unwind_;
1476 }
1477
1478 // Create new basic block for unwinding
1479 basic_block_unwind_ =
1480 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
1481
1482 // Change IRBuilder insert point
1483 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1484 irb_.SetInsertPoint(basic_block_unwind_);
1485
1486 // Pop the shadow frame
1487 Expand_PopShadowFrame();
1488
1489 // Emit the code to return default value (zero) for the given return type.
1490 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
1491 if (ret_shorty == 'V') {
1492 irb_.CreateRetVoid();
1493 } else {
1494 irb_.CreateRet(irb_.getJZero(ret_shorty));
1495 }
1496
1497 // Restore the orignal insert point for IRBuilder
1498 irb_.restoreIP(irb_ip_original);
1499
1500 return basic_block_unwind_;
1501}
1502
1503void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
1504 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
1505 irb_.CreateBr(lpad);
1506 } else {
1507 irb_.CreateBr(GetUnwindBasicBlock());
1508 }
1509}
1510
1511void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
1512 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
1513
1514 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1515
1516 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
1517 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
1518 } else {
1519 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
1520 }
1521
1522 irb_.SetInsertPoint(block_cont);
1523}
1524
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001525llvm::Value*
1526GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
1527 llvm::CallInst& call_inst) {
1528 switch (intr_id) {
1529 //==- Thread -----------------------------------------------------------==//
1530 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07001531 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001532 }
Logan Chiend54a23d2012-07-24 11:19:23 -07001533 case IntrinsicHelper::TestSuspend:
Logan Chien75e4b602012-07-23 14:24:12 -07001534 case IntrinsicHelper::CheckSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07001535 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07001536 return NULL;
1537 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001538 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07001539 Expand_MarkGCCard(call_inst);
1540 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001541 }
Logan Chien75e4b602012-07-23 14:24:12 -07001542
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001543 //==- Exception --------------------------------------------------------==//
1544 case IntrinsicHelper::ThrowException: {
1545 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
1546 }
1547 case IntrinsicHelper::GetException: {
1548 return Expand_GetException();
1549 }
1550 case IntrinsicHelper::IsExceptionPending: {
1551 return irb_.Runtime().EmitIsExceptionPending();
1552 }
1553 case IntrinsicHelper::FindCatchBlock: {
1554 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
1555 }
1556 case IntrinsicHelper::ThrowDivZeroException: {
1557 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
1558 }
1559 case IntrinsicHelper::ThrowNullPointerException: {
1560 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
1561 }
1562 case IntrinsicHelper::ThrowIndexOutOfBounds: {
1563 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
1564 }
Logan Chien75e4b602012-07-23 14:24:12 -07001565
1566 //==- Const String -----------------------------------------------------==//
1567 case IntrinsicHelper::ConstString: {
1568 UNIMPLEMENTED(FATAL);
1569 return NULL;
1570 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001571 case IntrinsicHelper::LoadStringFromDexCache: {
1572 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
1573 }
1574 case IntrinsicHelper::ResolveString: {
1575 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
1576 }
Logan Chien75e4b602012-07-23 14:24:12 -07001577
1578 //==- Const Class ------------------------------------------------------==//
1579 case IntrinsicHelper::ConstClass: {
1580 UNIMPLEMENTED(FATAL);
1581 return NULL;
1582 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001583 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
1584 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
1585 }
1586 case IntrinsicHelper::LoadTypeFromDexCache: {
1587 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
1588 }
1589 case IntrinsicHelper::InitializeType: {
1590 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
1591 }
Logan Chien75e4b602012-07-23 14:24:12 -07001592
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001593 //==- Lock -------------------------------------------------------------==//
1594 case IntrinsicHelper::LockObject: {
1595 Expand_LockObject(call_inst.getArgOperand(0));
1596 return NULL;
1597 }
1598 case IntrinsicHelper::UnlockObject: {
1599 Expand_UnlockObject(call_inst.getArgOperand(0));
1600 return NULL;
1601 }
Logan Chien75e4b602012-07-23 14:24:12 -07001602
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001603 //==- Cast -------------------------------------------------------------==//
1604 case IntrinsicHelper::CheckCast: {
1605 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
1606 }
Logan Chien75e4b602012-07-23 14:24:12 -07001607 case IntrinsicHelper::HLCheckCast: {
1608 UNIMPLEMENTED(FATAL);
1609 return NULL;
1610 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001611 case IntrinsicHelper::IsAssignable: {
1612 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
1613 }
Logan Chien75e4b602012-07-23 14:24:12 -07001614
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001615 //==- Alloc ------------------------------------------------------------==//
1616 case IntrinsicHelper::AllocObject: {
1617 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
1618 }
1619 case IntrinsicHelper::AllocObjectWithAccessCheck: {
1620 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
1621 }
Logan Chien75e4b602012-07-23 14:24:12 -07001622
1623 //==- Instance ---------------------------------------------------------==//
1624 case IntrinsicHelper::NewInstance: {
1625 UNIMPLEMENTED(FATAL);
1626 return NULL;
1627 }
1628 case IntrinsicHelper::InstanceOf: {
1629 UNIMPLEMENTED(FATAL);
1630 return NULL;
1631 }
1632
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001633 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07001634 case IntrinsicHelper::NewArray: {
1635 UNIMPLEMENTED(FATAL);
1636 return NULL;
1637 }
1638 case IntrinsicHelper::OptArrayLength: {
1639 UNIMPLEMENTED(FATAL);
1640 return NULL;
1641 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001642 case IntrinsicHelper::ArrayLength: {
1643 return EmitLoadArrayLength(call_inst.getArgOperand(0));
1644 }
1645 case IntrinsicHelper::AllocArray: {
1646 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
1647 }
1648 case IntrinsicHelper::AllocArrayWithAccessCheck: {
1649 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
1650 call_inst);
1651 }
1652 case IntrinsicHelper::CheckAndAllocArray: {
1653 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
1654 }
1655 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
1656 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
1657 call_inst);
1658 }
1659 case IntrinsicHelper::ArrayGet: {
1660 return Expand_ArrayGet(call_inst.getArgOperand(0),
1661 call_inst.getArgOperand(1),
1662 kInt);
1663 }
1664 case IntrinsicHelper::ArrayGetWide: {
1665 return Expand_ArrayGet(call_inst.getArgOperand(0),
1666 call_inst.getArgOperand(1),
1667 kLong);
1668 }
1669 case IntrinsicHelper::ArrayGetObject: {
1670 return Expand_ArrayGet(call_inst.getArgOperand(0),
1671 call_inst.getArgOperand(1),
1672 kObject);
1673 }
1674 case IntrinsicHelper::ArrayGetBoolean: {
1675 return Expand_ArrayGet(call_inst.getArgOperand(0),
1676 call_inst.getArgOperand(1),
1677 kBoolean);
1678 }
1679 case IntrinsicHelper::ArrayGetByte: {
1680 return Expand_ArrayGet(call_inst.getArgOperand(0),
1681 call_inst.getArgOperand(1),
1682 kByte);
1683 }
1684 case IntrinsicHelper::ArrayGetChar: {
1685 return Expand_ArrayGet(call_inst.getArgOperand(0),
1686 call_inst.getArgOperand(1),
1687 kChar);
1688 }
1689 case IntrinsicHelper::ArrayGetShort: {
1690 return Expand_ArrayGet(call_inst.getArgOperand(0),
1691 call_inst.getArgOperand(1),
1692 kShort);
1693 }
1694 case IntrinsicHelper::ArrayPut: {
1695 Expand_ArrayPut(call_inst.getArgOperand(0),
1696 call_inst.getArgOperand(1),
1697 call_inst.getArgOperand(2),
1698 kInt);
1699 return NULL;
1700 }
1701 case IntrinsicHelper::ArrayPutWide: {
1702 Expand_ArrayPut(call_inst.getArgOperand(0),
1703 call_inst.getArgOperand(1),
1704 call_inst.getArgOperand(2),
1705 kLong);
1706 return NULL;
1707 }
1708 case IntrinsicHelper::ArrayPutObject: {
1709 Expand_ArrayPut(call_inst.getArgOperand(0),
1710 call_inst.getArgOperand(1),
1711 call_inst.getArgOperand(2),
1712 kObject);
1713 return NULL;
1714 }
1715 case IntrinsicHelper::ArrayPutBoolean: {
1716 Expand_ArrayPut(call_inst.getArgOperand(0),
1717 call_inst.getArgOperand(1),
1718 call_inst.getArgOperand(2),
1719 kBoolean);
1720 return NULL;
1721 }
1722 case IntrinsicHelper::ArrayPutByte: {
1723 Expand_ArrayPut(call_inst.getArgOperand(0),
1724 call_inst.getArgOperand(1),
1725 call_inst.getArgOperand(2),
1726 kByte);
1727 return NULL;
1728 }
1729 case IntrinsicHelper::ArrayPutChar: {
1730 Expand_ArrayPut(call_inst.getArgOperand(0),
1731 call_inst.getArgOperand(1),
1732 call_inst.getArgOperand(2),
1733 kChar);
1734 return NULL;
1735 }
1736 case IntrinsicHelper::ArrayPutShort: {
1737 Expand_ArrayPut(call_inst.getArgOperand(0),
1738 call_inst.getArgOperand(1),
1739 call_inst.getArgOperand(2),
1740 kShort);
1741 return NULL;
1742 }
1743 case IntrinsicHelper::CheckPutArrayElement: {
1744 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
1745 }
1746 case IntrinsicHelper::FilledNewArray: {
1747 Expand_FilledNewArray(call_inst);
1748 return NULL;
1749 }
1750 case IntrinsicHelper::FillArrayData: {
1751 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
1752 }
Logan Chien75e4b602012-07-23 14:24:12 -07001753 case IntrinsicHelper::HLFillArrayData: {
1754 UNIMPLEMENTED(FATAL);
1755 return NULL;
1756 }
1757 case IntrinsicHelper::HLFilledNewArray: {
1758 UNIMPLEMENTED(FATAL);
1759 return NULL;
1760 }
1761
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001762 //==- Instance Field ---------------------------------------------------==//
1763 case IntrinsicHelper::InstanceFieldGet:
1764 case IntrinsicHelper::InstanceFieldGetBoolean:
1765 case IntrinsicHelper::InstanceFieldGetByte:
1766 case IntrinsicHelper::InstanceFieldGetChar:
1767 case IntrinsicHelper::InstanceFieldGetShort: {
1768 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
1769 }
1770 case IntrinsicHelper::InstanceFieldGetWide: {
1771 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
1772 }
1773 case IntrinsicHelper::InstanceFieldGetObject: {
1774 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
1775 }
1776 case IntrinsicHelper::InstanceFieldGetFast: {
1777 return Expand_IGetFast(call_inst.getArgOperand(0),
1778 call_inst.getArgOperand(1),
1779 call_inst.getArgOperand(2),
1780 kInt);
1781 }
1782 case IntrinsicHelper::InstanceFieldGetWideFast: {
1783 return Expand_IGetFast(call_inst.getArgOperand(0),
1784 call_inst.getArgOperand(1),
1785 call_inst.getArgOperand(2),
1786 kLong);
1787 }
1788 case IntrinsicHelper::InstanceFieldGetObjectFast: {
1789 return Expand_IGetFast(call_inst.getArgOperand(0),
1790 call_inst.getArgOperand(1),
1791 call_inst.getArgOperand(2),
1792 kObject);
1793 }
1794 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
1795 return Expand_IGetFast(call_inst.getArgOperand(0),
1796 call_inst.getArgOperand(1),
1797 call_inst.getArgOperand(2),
1798 kBoolean);
1799 }
1800 case IntrinsicHelper::InstanceFieldGetByteFast: {
1801 return Expand_IGetFast(call_inst.getArgOperand(0),
1802 call_inst.getArgOperand(1),
1803 call_inst.getArgOperand(2),
1804 kByte);
1805 }
1806 case IntrinsicHelper::InstanceFieldGetCharFast: {
1807 return Expand_IGetFast(call_inst.getArgOperand(0),
1808 call_inst.getArgOperand(1),
1809 call_inst.getArgOperand(2),
1810 kChar);
1811 }
1812 case IntrinsicHelper::InstanceFieldGetShortFast: {
1813 return Expand_IGetFast(call_inst.getArgOperand(0),
1814 call_inst.getArgOperand(1),
1815 call_inst.getArgOperand(2),
1816 kShort);
1817 }
1818 case IntrinsicHelper::InstanceFieldPut:
1819 case IntrinsicHelper::InstanceFieldPutBoolean:
1820 case IntrinsicHelper::InstanceFieldPutByte:
1821 case IntrinsicHelper::InstanceFieldPutChar:
1822 case IntrinsicHelper::InstanceFieldPutShort: {
1823 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
1824 }
1825 case IntrinsicHelper::InstanceFieldPutWide: {
1826 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
1827 }
1828 case IntrinsicHelper::InstanceFieldPutObject: {
1829 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
1830 }
1831 case IntrinsicHelper::InstanceFieldPutFast: {
1832 Expand_IPutFast(call_inst.getArgOperand(0),
1833 call_inst.getArgOperand(1),
1834 call_inst.getArgOperand(2),
1835 call_inst.getArgOperand(3),
1836 kInt);
1837 return NULL;
1838 }
1839 case IntrinsicHelper::InstanceFieldPutWideFast: {
1840 Expand_IPutFast(call_inst.getArgOperand(0),
1841 call_inst.getArgOperand(1),
1842 call_inst.getArgOperand(2),
1843 call_inst.getArgOperand(3),
1844 kLong);
1845 return NULL;
1846 }
1847 case IntrinsicHelper::InstanceFieldPutObjectFast: {
1848 Expand_IPutFast(call_inst.getArgOperand(0),
1849 call_inst.getArgOperand(1),
1850 call_inst.getArgOperand(2),
1851 call_inst.getArgOperand(3),
1852 kObject);
1853 return NULL;
1854 }
1855 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
1856 Expand_IPutFast(call_inst.getArgOperand(0),
1857 call_inst.getArgOperand(1),
1858 call_inst.getArgOperand(2),
1859 call_inst.getArgOperand(3),
1860 kBoolean);
1861 return NULL;
1862 }
1863 case IntrinsicHelper::InstanceFieldPutByteFast: {
1864 Expand_IPutFast(call_inst.getArgOperand(0),
1865 call_inst.getArgOperand(1),
1866 call_inst.getArgOperand(2),
1867 call_inst.getArgOperand(3),
1868 kByte);
1869 return NULL;
1870 }
1871 case IntrinsicHelper::InstanceFieldPutCharFast: {
1872 Expand_IPutFast(call_inst.getArgOperand(0),
1873 call_inst.getArgOperand(1),
1874 call_inst.getArgOperand(2),
1875 call_inst.getArgOperand(3),
1876 kChar);
1877 return NULL;
1878 }
1879 case IntrinsicHelper::InstanceFieldPutShortFast: {
1880 Expand_IPutFast(call_inst.getArgOperand(0),
1881 call_inst.getArgOperand(1),
1882 call_inst.getArgOperand(2),
1883 call_inst.getArgOperand(3),
1884 kShort);
1885 return NULL;
1886 }
Logan Chien75e4b602012-07-23 14:24:12 -07001887
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001888 //==- Static Field -----------------------------------------------------==//
1889 case IntrinsicHelper::StaticFieldGet:
1890 case IntrinsicHelper::StaticFieldGetBoolean:
1891 case IntrinsicHelper::StaticFieldGetByte:
1892 case IntrinsicHelper::StaticFieldGetChar:
1893 case IntrinsicHelper::StaticFieldGetShort: {
1894 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
1895 }
1896 case IntrinsicHelper::StaticFieldGetWide: {
1897 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
1898 }
1899 case IntrinsicHelper::StaticFieldGetObject: {
1900 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
1901 }
1902 case IntrinsicHelper::StaticFieldGetFast: {
1903 return Expand_SGetFast(call_inst.getArgOperand(0),
1904 call_inst.getArgOperand(1),
1905 call_inst.getArgOperand(2),
1906 kInt);
1907 }
1908 case IntrinsicHelper::StaticFieldGetWideFast: {
1909 return Expand_SGetFast(call_inst.getArgOperand(0),
1910 call_inst.getArgOperand(1),
1911 call_inst.getArgOperand(2),
1912 kLong);
1913 }
1914 case IntrinsicHelper::StaticFieldGetObjectFast: {
1915 return Expand_SGetFast(call_inst.getArgOperand(0),
1916 call_inst.getArgOperand(1),
1917 call_inst.getArgOperand(2),
1918 kObject);
1919 }
1920 case IntrinsicHelper::StaticFieldGetBooleanFast: {
1921 return Expand_SGetFast(call_inst.getArgOperand(0),
1922 call_inst.getArgOperand(1),
1923 call_inst.getArgOperand(2),
1924 kBoolean);
1925 }
1926 case IntrinsicHelper::StaticFieldGetByteFast: {
1927 return Expand_SGetFast(call_inst.getArgOperand(0),
1928 call_inst.getArgOperand(1),
1929 call_inst.getArgOperand(2),
1930 kByte);
1931 }
1932 case IntrinsicHelper::StaticFieldGetCharFast: {
1933 return Expand_SGetFast(call_inst.getArgOperand(0),
1934 call_inst.getArgOperand(1),
1935 call_inst.getArgOperand(2),
1936 kChar);
1937 }
1938 case IntrinsicHelper::StaticFieldGetShortFast: {
1939 return Expand_SGetFast(call_inst.getArgOperand(0),
1940 call_inst.getArgOperand(1),
1941 call_inst.getArgOperand(2),
1942 kShort);
1943 }
1944 case IntrinsicHelper::StaticFieldPut:
1945 case IntrinsicHelper::StaticFieldPutBoolean:
1946 case IntrinsicHelper::StaticFieldPutByte:
1947 case IntrinsicHelper::StaticFieldPutChar:
1948 case IntrinsicHelper::StaticFieldPutShort: {
1949 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
1950 }
1951 case IntrinsicHelper::StaticFieldPutWide: {
1952 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
1953 }
1954 case IntrinsicHelper::StaticFieldPutObject: {
1955 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
1956 }
1957 case IntrinsicHelper::StaticFieldPutFast: {
1958 Expand_SPutFast(call_inst.getArgOperand(0),
1959 call_inst.getArgOperand(1),
1960 call_inst.getArgOperand(2),
1961 call_inst.getArgOperand(3),
1962 kInt);
1963 return NULL;
1964 }
1965 case IntrinsicHelper::StaticFieldPutWideFast: {
1966 Expand_SPutFast(call_inst.getArgOperand(0),
1967 call_inst.getArgOperand(1),
1968 call_inst.getArgOperand(2),
1969 call_inst.getArgOperand(3),
1970 kLong);
1971 return NULL;
1972 }
1973 case IntrinsicHelper::StaticFieldPutObjectFast: {
1974 Expand_SPutFast(call_inst.getArgOperand(0),
1975 call_inst.getArgOperand(1),
1976 call_inst.getArgOperand(2),
1977 call_inst.getArgOperand(3),
1978 kObject);
1979 return NULL;
1980 }
1981 case IntrinsicHelper::StaticFieldPutBooleanFast: {
1982 Expand_SPutFast(call_inst.getArgOperand(0),
1983 call_inst.getArgOperand(1),
1984 call_inst.getArgOperand(2),
1985 call_inst.getArgOperand(3),
1986 kBoolean);
1987 return NULL;
1988 }
1989 case IntrinsicHelper::StaticFieldPutByteFast: {
1990 Expand_SPutFast(call_inst.getArgOperand(0),
1991 call_inst.getArgOperand(1),
1992 call_inst.getArgOperand(2),
1993 call_inst.getArgOperand(3),
1994 kByte);
1995 return NULL;
1996 }
1997 case IntrinsicHelper::StaticFieldPutCharFast: {
1998 Expand_SPutFast(call_inst.getArgOperand(0),
1999 call_inst.getArgOperand(1),
2000 call_inst.getArgOperand(2),
2001 call_inst.getArgOperand(3),
2002 kChar);
2003 return NULL;
2004 }
2005 case IntrinsicHelper::StaticFieldPutShortFast: {
2006 Expand_SPutFast(call_inst.getArgOperand(0),
2007 call_inst.getArgOperand(1),
2008 call_inst.getArgOperand(2),
2009 call_inst.getArgOperand(3),
2010 kShort);
2011 return NULL;
2012 }
2013 case IntrinsicHelper::LoadDeclaringClassSSB: {
2014 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
2015 }
2016 case IntrinsicHelper::LoadClassSSBFromDexCache: {
2017 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
2018 }
2019 case IntrinsicHelper::InitializeAndLoadClassSSB: {
2020 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
2021 }
Logan Chien75e4b602012-07-23 14:24:12 -07002022
2023 //==- High-level Array -------------------------------------------------==//
2024 case IntrinsicHelper::HLArrayGet: {
2025 UNIMPLEMENTED(FATAL);
2026 return NULL;
2027 }
2028 case IntrinsicHelper::HLArrayGetBoolean: {
2029 UNIMPLEMENTED(FATAL);
2030 return NULL;
2031 }
2032 case IntrinsicHelper::HLArrayGetByte: {
2033 UNIMPLEMENTED(FATAL);
2034 return NULL;
2035 }
2036 case IntrinsicHelper::HLArrayGetChar: {
2037 UNIMPLEMENTED(FATAL);
2038 return NULL;
2039 }
2040 case IntrinsicHelper::HLArrayGetShort: {
2041 UNIMPLEMENTED(FATAL);
2042 return NULL;
2043 }
2044 case IntrinsicHelper::HLArrayGetFloat: {
2045 UNIMPLEMENTED(FATAL);
2046 return NULL;
2047 }
2048 case IntrinsicHelper::HLArrayGetWide: {
2049 UNIMPLEMENTED(FATAL);
2050 return NULL;
2051 }
2052 case IntrinsicHelper::HLArrayGetDouble: {
2053 UNIMPLEMENTED(FATAL);
2054 return NULL;
2055 }
2056 case IntrinsicHelper::HLArrayGetObject: {
2057 UNIMPLEMENTED(FATAL);
2058 return NULL;
2059 }
2060 case IntrinsicHelper::HLArrayPut: {
2061 UNIMPLEMENTED(FATAL);
2062 return NULL;
2063 }
2064 case IntrinsicHelper::HLArrayPutBoolean: {
2065 UNIMPLEMENTED(FATAL);
2066 return NULL;
2067 }
2068 case IntrinsicHelper::HLArrayPutByte: {
2069 UNIMPLEMENTED(FATAL);
2070 return NULL;
2071 }
2072 case IntrinsicHelper::HLArrayPutChar: {
2073 UNIMPLEMENTED(FATAL);
2074 return NULL;
2075 }
2076 case IntrinsicHelper::HLArrayPutShort: {
2077 UNIMPLEMENTED(FATAL);
2078 return NULL;
2079 }
2080 case IntrinsicHelper::HLArrayPutFloat: {
2081 UNIMPLEMENTED(FATAL);
2082 return NULL;
2083 }
2084 case IntrinsicHelper::HLArrayPutWide: {
2085 UNIMPLEMENTED(FATAL);
2086 return NULL;
2087 }
2088 case IntrinsicHelper::HLArrayPutDouble: {
2089 UNIMPLEMENTED(FATAL);
2090 return NULL;
2091 }
2092 case IntrinsicHelper::HLArrayPutObject: {
2093 UNIMPLEMENTED(FATAL);
2094 return NULL;
2095 }
2096
2097 //==- High-level Instance ----------------------------------------------==//
2098 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07002099 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002100 }
2101 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07002102 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002103 }
2104 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07002105 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002106 }
2107 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07002108 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002109 }
2110 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07002111 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002112 }
2113 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07002114 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002115 }
2116 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07002117 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002118 }
2119 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07002120 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002121 }
2122 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07002123 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002124 }
2125 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07002126 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002127 return NULL;
2128 }
2129 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07002130 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002131 return NULL;
2132 }
2133 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07002134 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002135 return NULL;
2136 }
2137 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07002138 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002139 return NULL;
2140 }
2141 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07002142 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002143 return NULL;
2144 }
2145 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07002146 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002147 return NULL;
2148 }
2149 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07002150 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002151 return NULL;
2152 }
2153 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07002154 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002155 return NULL;
2156 }
2157 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07002158 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002159 return NULL;
2160 }
2161
2162 //==- High-level Invoke ------------------------------------------------==//
2163 case IntrinsicHelper::HLInvokeVoid: {
2164 UNIMPLEMENTED(FATAL);
2165 return NULL;
2166 }
2167 case IntrinsicHelper::HLInvokeObj: {
2168 UNIMPLEMENTED(FATAL);
2169 return NULL;
2170 }
2171 case IntrinsicHelper::HLInvokeInt: {
2172 UNIMPLEMENTED(FATAL);
2173 return NULL;
2174 }
2175 case IntrinsicHelper::HLInvokeFloat: {
2176 UNIMPLEMENTED(FATAL);
2177 return NULL;
2178 }
2179 case IntrinsicHelper::HLInvokeLong: {
2180 UNIMPLEMENTED(FATAL);
2181 return NULL;
2182 }
2183 case IntrinsicHelper::HLInvokeDouble: {
2184 UNIMPLEMENTED(FATAL);
2185 return NULL;
2186 }
2187
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002188 //==- Invoke -----------------------------------------------------------==//
2189 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
2190 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
2191 }
2192 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
2193 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
2194 }
2195 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
2196 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
2197 }
2198 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
2199 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
2200 }
2201 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
2202 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
2203 }
2204 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
2205 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
2206 }
2207 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
2208 return Expand_GetVirtualCalleeMethodObjAddrFast(
2209 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
2210 }
2211 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
2212 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
2213 }
2214 case IntrinsicHelper::InvokeRetVoid:
2215 case IntrinsicHelper::InvokeRetBoolean:
2216 case IntrinsicHelper::InvokeRetByte:
2217 case IntrinsicHelper::InvokeRetChar:
2218 case IntrinsicHelper::InvokeRetShort:
2219 case IntrinsicHelper::InvokeRetInt:
2220 case IntrinsicHelper::InvokeRetLong:
2221 case IntrinsicHelper::InvokeRetFloat:
2222 case IntrinsicHelper::InvokeRetDouble:
2223 case IntrinsicHelper::InvokeRetObject: {
2224 return Expand_Invoke(call_inst);
2225 }
Logan Chien75e4b602012-07-23 14:24:12 -07002226
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002227 //==- Math -------------------------------------------------------------==//
2228 case IntrinsicHelper::DivInt: {
2229 return Expand_DivRem(call_inst.getArgOperand(0),
2230 call_inst.getArgOperand(1),
2231 /* is_div */true, kInt);
2232 }
2233 case IntrinsicHelper::RemInt: {
2234 return Expand_DivRem(call_inst.getArgOperand(0),
2235 call_inst.getArgOperand(1),
2236 /* is_div */false, kInt);
2237 }
2238 case IntrinsicHelper::DivLong: {
2239 return Expand_DivRem(call_inst.getArgOperand(0),
2240 call_inst.getArgOperand(1),
2241 /* is_div */true, kLong);
2242 }
2243 case IntrinsicHelper::RemLong: {
2244 return Expand_DivRem(call_inst.getArgOperand(0),
2245 call_inst.getArgOperand(1),
2246 /* is_div */false, kLong);
2247 }
2248 case IntrinsicHelper::D2L: {
2249 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
2250 }
2251 case IntrinsicHelper::D2I: {
2252 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
2253 }
2254 case IntrinsicHelper::F2L: {
2255 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
2256 }
2257 case IntrinsicHelper::F2I: {
2258 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
2259 }
Logan Chien75e4b602012-07-23 14:24:12 -07002260
2261 //==- High-level Static ------------------------------------------------==//
2262 case IntrinsicHelper::HLSget: {
2263 UNIMPLEMENTED(FATAL);
2264 return NULL;
2265 }
2266 case IntrinsicHelper::HLSgetBoolean: {
2267 UNIMPLEMENTED(FATAL);
2268 return NULL;
2269 }
2270 case IntrinsicHelper::HLSgetByte: {
2271 UNIMPLEMENTED(FATAL);
2272 return NULL;
2273 }
2274 case IntrinsicHelper::HLSgetChar: {
2275 UNIMPLEMENTED(FATAL);
2276 return NULL;
2277 }
2278 case IntrinsicHelper::HLSgetShort: {
2279 UNIMPLEMENTED(FATAL);
2280 return NULL;
2281 }
2282 case IntrinsicHelper::HLSgetFloat: {
2283 UNIMPLEMENTED(FATAL);
2284 return NULL;
2285 }
2286 case IntrinsicHelper::HLSgetWide: {
2287 UNIMPLEMENTED(FATAL);
2288 return NULL;
2289 }
2290 case IntrinsicHelper::HLSgetDouble: {
2291 UNIMPLEMENTED(FATAL);
2292 return NULL;
2293 }
2294 case IntrinsicHelper::HLSgetObject: {
2295 UNIMPLEMENTED(FATAL);
2296 return NULL;
2297 }
2298 case IntrinsicHelper::HLSput: {
2299 UNIMPLEMENTED(FATAL);
2300 return NULL;
2301 }
2302 case IntrinsicHelper::HLSputBoolean: {
2303 UNIMPLEMENTED(FATAL);
2304 return NULL;
2305 }
2306 case IntrinsicHelper::HLSputByte: {
2307 UNIMPLEMENTED(FATAL);
2308 return NULL;
2309 }
2310 case IntrinsicHelper::HLSputChar: {
2311 UNIMPLEMENTED(FATAL);
2312 return NULL;
2313 }
2314 case IntrinsicHelper::HLSputShort: {
2315 UNIMPLEMENTED(FATAL);
2316 return NULL;
2317 }
2318 case IntrinsicHelper::HLSputFloat: {
2319 UNIMPLEMENTED(FATAL);
2320 return NULL;
2321 }
2322 case IntrinsicHelper::HLSputWide: {
2323 UNIMPLEMENTED(FATAL);
2324 return NULL;
2325 }
2326 case IntrinsicHelper::HLSputDouble: {
2327 UNIMPLEMENTED(FATAL);
2328 return NULL;
2329 }
2330 case IntrinsicHelper::HLSputObject: {
2331 UNIMPLEMENTED(FATAL);
2332 return NULL;
2333 }
2334
2335 //==- High-level Monitor -----------------------------------------------==//
2336 case IntrinsicHelper::MonitorEnter: {
2337 UNIMPLEMENTED(FATAL);
2338 return NULL;
2339 }
2340 case IntrinsicHelper::MonitorExit: {
2341 UNIMPLEMENTED(FATAL);
2342 return NULL;
2343 }
2344
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002345 //==- Shadow Frame -----------------------------------------------------==//
2346 case IntrinsicHelper::AllocaShadowFrame: {
2347 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
2348 return NULL;
2349 }
2350 case IntrinsicHelper::SetShadowFrameEntry: {
2351 Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
2352 call_inst.getArgOperand(1));
2353 return NULL;
2354 }
2355 case IntrinsicHelper::PopShadowFrame: {
2356 Expand_PopShadowFrame();
2357 return NULL;
2358 }
2359 case IntrinsicHelper::UpdateDexPC: {
2360 Expand_UpdateDexPC(call_inst.getArgOperand(0));
2361 return NULL;
2362 }
TDYa127a1b21852012-07-23 03:20:39 -07002363
Logan Chien75e4b602012-07-23 14:24:12 -07002364 //==- Comparison -------------------------------------------------------==//
2365 case IntrinsicHelper::CmplFloat:
2366 case IntrinsicHelper::CmplDouble: {
2367 return Expand_FPCompare(call_inst.getArgOperand(0),
2368 call_inst.getArgOperand(1),
2369 false);
2370 }
2371 case IntrinsicHelper::CmpgFloat:
2372 case IntrinsicHelper::CmpgDouble: {
2373 return Expand_FPCompare(call_inst.getArgOperand(0),
2374 call_inst.getArgOperand(1),
2375 true);
2376 }
2377 case IntrinsicHelper::CmpLong: {
2378 return Expand_LongCompare(call_inst.getArgOperand(0),
2379 call_inst.getArgOperand(1));
2380 }
TDYa127a1b21852012-07-23 03:20:39 -07002381
Logan Chien75e4b602012-07-23 14:24:12 -07002382 //==- Switch -----------------------------------------------------------==//
2383 case greenland::IntrinsicHelper::SparseSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07002384 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002385 return NULL;
2386 }
2387 case greenland::IntrinsicHelper::PackedSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07002388 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002389 return NULL;
2390 }
2391
2392 //==- Const ------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07002393 case greenland::IntrinsicHelper::ConstInt:
Logan Chien75e4b602012-07-23 14:24:12 -07002394 case greenland::IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002395 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07002396 }
2397 case greenland::IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002398 return irb_.CreateBitCast(call_inst.getArgOperand(0),
2399 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07002400 }
2401 case greenland::IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002402 return irb_.CreateBitCast(call_inst.getArgOperand(0),
2403 irb_.getJDoubleTy());
2404 }
2405 case greenland::IntrinsicHelper::ConstObj: {
2406 LOG(FATAL) << "ConstObj should not occur at all";
Logan Chien75e4b602012-07-23 14:24:12 -07002407 return NULL;
2408 }
2409
2410 //==- Method Info ------------------------------------------------------==//
2411 case greenland::IntrinsicHelper::MethodInfo: {
TDYa1275e869b62012-07-25 00:45:39 -07002412 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002413 return NULL;
2414 }
2415
2416 //==- Copy -------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07002417 case greenland::IntrinsicHelper::CopyInt:
2418 case greenland::IntrinsicHelper::CopyFloat:
2419 case greenland::IntrinsicHelper::CopyLong:
TDYa1275e869b62012-07-25 00:45:39 -07002420 case greenland::IntrinsicHelper::CopyDouble:
Logan Chien75e4b602012-07-23 14:24:12 -07002421 case greenland::IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002422 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07002423 }
2424
2425 //==- Shift ------------------------------------------------------------==//
2426 case greenland::IntrinsicHelper::SHLLong: {
2427 return Expand_IntegerShift(call_inst.getArgOperand(0),
2428 call_inst.getArgOperand(1),
2429 kIntegerSHL, kLong);
2430 }
2431 case greenland::IntrinsicHelper::SHRLong: {
2432 return Expand_IntegerShift(call_inst.getArgOperand(0),
2433 call_inst.getArgOperand(1),
2434 kIntegerSHR, kLong);
2435 }
2436 case greenland::IntrinsicHelper::USHRLong: {
2437 return Expand_IntegerShift(call_inst.getArgOperand(0),
2438 call_inst.getArgOperand(1),
2439 kIntegerUSHR, kLong);
2440 }
2441 case greenland::IntrinsicHelper::SHLInt: {
2442 return Expand_IntegerShift(call_inst.getArgOperand(0),
2443 call_inst.getArgOperand(1),
2444 kIntegerSHL, kInt);
2445 }
2446 case greenland::IntrinsicHelper::SHRInt: {
2447 return Expand_IntegerShift(call_inst.getArgOperand(0),
2448 call_inst.getArgOperand(1),
2449 kIntegerSHR, kInt);
2450 }
2451 case greenland::IntrinsicHelper::USHRInt: {
2452 return Expand_IntegerShift(call_inst.getArgOperand(0),
2453 call_inst.getArgOperand(1),
2454 kIntegerUSHR, kInt);
2455 }
2456
2457 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07002458 case IntrinsicHelper::IntToChar: {
2459 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
2460 irb_.getJIntTy());
2461 }
2462 case IntrinsicHelper::IntToShort: {
2463 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
2464 irb_.getJIntTy());
2465 }
2466 case IntrinsicHelper::IntToByte: {
2467 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
2468 irb_.getJIntTy());
2469 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002470
Logan Chien75e4b602012-07-23 14:24:12 -07002471 //==- Unknown Cases ----------------------------------------------------==//
2472 case IntrinsicHelper::MaxIntrinsicId:
2473 case IntrinsicHelper::UnknownId:
2474 //default:
2475 // NOTE: "default" is intentionally commented so that C/C++ compiler will
2476 // give some warning on unmatched cases.
2477 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002478 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002479 }
Logan Chien75e4b602012-07-23 14:24:12 -07002480 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002481 return NULL;
2482}
2483
2484} // anonymous namespace
2485
2486namespace art {
2487namespace compiler_llvm {
2488
2489llvm::FunctionPass*
2490CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
2491 return new GBCExpanderPass(intrinsic_helper, irb);
2492}
2493
2494} // namespace compiler_llvm
2495} // namespace art