blob: f7b9cf299ed85fd37af9d08ab8b42037f4ade3a2 [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
TDYa1275a26d442012-07-26 18:58:38 -0700254 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
255
TDYa1275e869b62012-07-25 00:45:39 -0700256 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
257 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
258
TDYa1275a26d442012-07-26 18:58:38 -0700259 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
260 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
261
262 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
263 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
264
TDYa1275e869b62012-07-25 00:45:39 -0700265 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
266
267 void EmitUpdateDexPC(uint32_t dex_pc);
268
269 void EmitGuard_DivZeroException(uint32_t dex_pc,
270 llvm::Value* denominator,
271 JType op_jty);
272
273 void EmitGuard_NullPointerException(uint32_t dex_pc,
274 llvm::Value* object);
275
276 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
277 llvm::Value* array,
278 llvm::Value* index);
279
280 void EmitGuard_ArrayException(uint32_t dex_pc,
281 llvm::Value* array,
282 llvm::Value* index);
283
284 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
285
286 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
287
288 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
289 const char* postfix);
290
291 int32_t GetTryItemOffset(uint32_t dex_pc);
292
293 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
294
295 llvm::BasicBlock* GetUnwindBasicBlock();
296
297 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
298
299 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
300
Logan Chien75e4b602012-07-23 14:24:12 -0700301 //----------------------------------------------------------------------------
302 // Expand Arithmetic Helper Intrinsics
303 //----------------------------------------------------------------------------
304
305 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
306 llvm::Value* src2_value,
307 IntegerShiftKind kind,
308 JType op_jty);
309
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700310 public:
311 static char ID;
312
313 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
314 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
315 context_(irb.getContext()), rtb_(irb.Runtime())
316 { }
317
318 bool runOnFunction(llvm::Function& func);
319
320 private:
321 bool InsertStackOverflowCheck(llvm::Function& func);
322
323 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
324 llvm::CallInst& call_inst);
325
326};
327
328char GBCExpanderPass::ID = 0;
329
330bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700331 // Runtime support or stub
332 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
333 return false;
334 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700335 bool changed;
336
TDYa127b672d1e2012-06-28 21:21:45 -0700337 // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700338 changed = InsertStackOverflowCheck(func);
339
340 std::list<std::pair<llvm::CallInst*,
341 IntrinsicHelper::IntrinsicId> > work_list;
342
343 for (llvm::inst_iterator inst_iter = llvm::inst_begin(func),
344 inst_end = llvm::inst_end(func); inst_iter != inst_end; inst_iter++) {
345 // Only CallInst with its called function is dexlang intrinsic need to
346 // process
347 llvm::Instruction* inst = &*inst_iter;
348 if (llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst)) {
349 const llvm::Function* callee = call_inst->getCalledFunction();
350
351 if (callee != NULL) {
352 IntrinsicHelper::IntrinsicId intr_id =
353 intrinsic_helper_.GetIntrinsicId(callee);
354
355 if (intr_id != IntrinsicHelper::UnknownId) {
356 work_list.push_back(std::make_pair(call_inst, intr_id));
357 }
358 }
359 }
360 }
361
362 changed |= !work_list.empty();
363
364 shadow_frame_ = NULL;
365 old_shadow_frame_ = NULL;
366 shadow_frame_size_ = 0;
TDYa1275e869b62012-07-25 00:45:39 -0700367 func_ = &func;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700368
369 // Remove the instruction containing in the work_list
370 while (!work_list.empty()) {
371 llvm::CallInst* intr_inst = work_list.front().first;
372 IntrinsicHelper::IntrinsicId intr_id = work_list.front().second;
373
374 // Remove the instruction from work list
375 work_list.pop_front();
376
377 // Move the IRBuilder insert pointer
378 irb_.SetInsertPoint(intr_inst);
379
380 // Process the expansion
381 llvm::Value* new_value = ExpandIntrinsic(intr_id, *intr_inst);
382
383 // Use the new value from the expansion
384 if (new_value != NULL) {
385 intr_inst->replaceAllUsesWith(new_value);
386 }
387
388 // Remove the intrinsic instruction
389 intr_inst->eraseFromParent();
390 }
391
392 VERIFY_LLVM_FUNCTION(func);
393
394 return changed;
395}
396
397llvm::BasicBlock*
TDYa1275e869b62012-07-25 00:45:39 -0700398GBCExpanderPass::ScopedExpandToBasicBlock::
399SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
400 llvm::BasicBlock* begin_bb,
401 llvm::BasicBlock* end_bb) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700402 llvm::BasicBlock* original = inst->getParent();
403 llvm::Function* parent = original->getParent();
404
405 // 1. Create a new basic block A after ORIGINAL
406 llvm::BasicBlock *insert_before =
407 llvm::next(llvm::Function::iterator(original)).getNodePtrUnchecked();
408 llvm::BasicBlock* a =
TDYa1275e869b62012-07-25 00:45:39 -0700409 llvm::BasicBlock::Create(irb_.getContext(), "", parent, insert_before);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700410
411 // 2. Move all instructions in ORIGINAL after INST (included) to A
412 a->getInstList().splice(a->end(), original->getInstList(),
413 inst, original->end());
414
415 // 3. Add an unconditional branch in ORIGINAL to begin_bb
416 llvm::BranchInst::Create(begin_bb, original);
417
418 // 4. Add an unconditional branch in END_BB to A
419 llvm::BranchInst::Create(a, end_bb);
420
421 // 5. Update the PHI nodes in the successors of A. Update the PHI node entry
422 // with incoming basic block from ORIGINAL to A
423 for (llvm::succ_iterator succ_iter = llvm::succ_begin(a),
424 succ_end = llvm::succ_end(a); succ_iter != succ_end; succ_iter++) {
425 llvm::BasicBlock* succ = *succ_iter;
426 llvm::PHINode* phi;
427 for (llvm::BasicBlock::iterator inst_iter = succ->begin();
428 (phi = llvm::dyn_cast<llvm::PHINode>(inst_iter)); ++inst_iter) {
429 int idx;
430 while ((idx = phi->getBasicBlockIndex(original)) != -1) {
431 phi->setIncomingBlock(static_cast<unsigned>(idx), a);
432 }
433 }
434 }
435
436 return a;
437}
438
439llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
440 llvm::CallInst& inst) {
441 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
442 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
443 // function, therefore only called function is needed to change.
444 unsigned num_args = inst.getNumArgOperands();
445
446 if (num_args <= 0) {
447 return irb_.CreateCall(irb_.GetRuntime(rt));
448 } else {
449 std::vector<llvm::Value*> args;
450 for (unsigned i = 0; i < num_args; i++) {
451 args.push_back(inst.getArgOperand(i));
452 }
453
454 return irb_.CreateCall(irb_.GetRuntime(rt), args);
455 }
456}
457
458bool
459GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
TDYa1275e869b62012-07-25 00:45:39 -0700460 ScopedExpandToBasicBlock eb(irb_, first_non_alloca);
461
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700462 llvm::Function* func = first_non_alloca->getParent()->getParent();
463 llvm::Module* module = func->getParent();
464
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700465 // Call llvm intrinsic function to get frame address.
466 llvm::Function* frameaddress =
467 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
468
469 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
470 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
471
472 // Cast i8* to int
473 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
474
475 // Get thread.stack_end_
476 llvm::Value* stack_end =
477 irb_.Runtime().EmitLoadFromThreadOffset(Thread::StackEndOffset().Int32Value(),
478 irb_.getPtrEquivIntTy(),
479 kTBAARuntimeInfo);
480
481 // Check the frame address < thread.stack_end_ ?
482 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
483
484 llvm::BasicBlock* block_exception =
485 llvm::BasicBlock::Create(context_, "stack_overflow", func);
486
487 llvm::BasicBlock* block_continue =
488 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
489
490 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
491
492 // If stack overflow, throw exception.
493 irb_.SetInsertPoint(block_exception);
494 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
495
496 // Unwind.
497 llvm::Type* ret_type = func->getReturnType();
498 if (ret_type->isVoidTy()) {
499 irb_.CreateRetVoid();
500 } else {
501 // The return value is ignored when there's an exception. MethodCompiler
502 // returns zero value under the the corresponding return type in this case.
503 // GBCExpander returns LLVM undef value here for brevity
504 irb_.CreateRet(llvm::UndefValue::get(ret_type));
505 }
506
507 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700508 return true;
509}
510
511llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(MemberOffset offset) {
512 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
513
514 return irb_.LoadFromObjectOffset(method_object_addr,
515 offset.Int32Value(),
516 irb_.getJObjectTy(),
517 kTBAAConstJObject);
518}
519
520llvm::Value*
521GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
522 llvm::Value* static_storage_dex_cache_addr =
523 EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
524
525 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
526
527 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
528}
529
530llvm::Value*
531GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
532 llvm::Value* resolved_type_dex_cache_addr =
533 EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
534
535 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
536
537 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
538}
539
540llvm::Value* GBCExpanderPass::
541EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
542 llvm::Value* resolved_method_dex_cache_addr =
543 EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
544
545 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
546
547 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
548}
549
550llvm::Value* GBCExpanderPass::
551EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
552 llvm::Value* string_dex_cache_addr =
553 EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
554
555 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
556
557 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
558}
559
560llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
561 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
562 return parent_func->arg_begin();
563}
564
565llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
566 // Load array length
567 return irb_.LoadFromObjectOffset(array,
568 Array::LengthOffset().Int32Value(),
569 irb_.getJIntTy(),
570 kTBAAConstJObject);
571
572}
573
574llvm::Value*
575GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
576 llvm::Value* callee_method_object_field_addr =
577 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
578
579 return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
580}
581
582llvm::Value* GBCExpanderPass::
583EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
584 // Load class object of *this* pointer
585 llvm::Value* class_object_addr =
586 irb_.LoadFromObjectOffset(this_addr,
587 Object::ClassOffset().Int32Value(),
588 irb_.getJObjectTy(),
589 kTBAAConstJObject);
590
591 // Load vtable address
592 llvm::Value* vtable_addr =
593 irb_.LoadFromObjectOffset(class_object_addr,
594 Class::VTableOffset().Int32Value(),
595 irb_.getJObjectTy(),
596 kTBAAConstJObject);
597
598 // Load callee method object
599 llvm::Value* vtable_idx_value =
600 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
601
602 llvm::Value* method_field_addr =
603 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
604
605 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
606}
607
608// Emit Array GetElementPtr
609llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
610 llvm::Value* index_value,
611 JType elem_jty) {
612
613 int data_offset;
614 if (elem_jty == kLong || elem_jty == kDouble ||
615 (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
616 data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
617 } else {
618 data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
619 }
620
621 llvm::Constant* data_offset_value =
622 irb_.getPtrEquivInt(data_offset);
623
624 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
625
626 llvm::Value* array_data_addr =
627 irb_.CreatePtrDisp(array_addr, data_offset_value,
628 elem_type->getPointerTo());
629
630 return irb_.CreateGEP(array_data_addr, index_value);
631}
632
633void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
TDYa1275e869b62012-07-25 00:45:39 -0700634 ScopedExpandToBasicBlock eb(irb_, &call_inst);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700635 irb_.Runtime().EmitTestSuspend();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700636 return;
637}
638
TDYa1279a129452012-07-19 03:10:08 -0700639void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1275e869b62012-07-25 00:45:39 -0700640 ScopedExpandToBasicBlock eb(irb_, &call_inst);
TDYa1279a129452012-07-19 03:10:08 -0700641 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700642 return;
643}
644
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700645llvm::Value* GBCExpanderPass::Expand_GetException() {
646 // Get thread-local exception field address
647 llvm::Value* exception_object_addr =
648 irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
649 irb_.getJObjectTy(),
650 kTBAAJRuntime);
651
652 // Set thread-local exception field address to NULL
653 irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
654 irb_.getJNull(),
655 kTBAAJRuntime);
656
657 return exception_object_addr;
658}
659
660llvm::Value*
661GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
662 uint32_t string_idx =
663 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
664
665 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
666
667 return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
668}
669
670llvm::Value*
671GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
672 uint32_t type_idx =
673 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
674
675 llvm::Value* type_field_addr =
676 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
677
678 return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
679}
680
681void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
TDYa1275e869b62012-07-25 00:45:39 -0700682 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700683 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700684 return;
685}
686
687void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
TDYa1275e869b62012-07-25 00:45:39 -0700688 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700689 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700690 return;
691}
692
693llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
694 llvm::Value* index_value,
695 JType elem_jty) {
696 llvm::Value* array_elem_addr =
697 EmitArrayGEP(array_addr, index_value, elem_jty);
698
699 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
700}
701
702void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
703 llvm::Value* array_addr,
704 llvm::Value* index_value,
705 JType elem_jty) {
706 llvm::Value* array_elem_addr =
707 EmitArrayGEP(array_addr, index_value, elem_jty);
708
709 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
710
711 return;
712}
713
714void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
715 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
716 llvm::Value* array = call_inst.getArgOperand(0);
717
718 uint32_t element_jty =
719 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
720
721 DCHECK(call_inst.getNumArgOperands() > 2);
722 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
723
724 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
725
726 uint32_t alignment;
727 llvm::Constant* elem_size;
728 llvm::PointerType* field_type;
729
730 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
731 // as the element, thus we are only checking 2 cases: primitive int and
732 // non-primitive type.
733 if (is_elem_int_ty) {
734 alignment = sizeof(int32_t);
735 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
736 field_type = irb_.getJIntTy()->getPointerTo();
737 } else {
738 alignment = irb_.getSizeOfPtrEquivInt();
739 elem_size = irb_.getSizeOfPtrEquivIntValue();
740 field_type = irb_.getJObjectTy()->getPointerTo();
741 }
742
743 llvm::Value* data_field_offset =
744 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
745
746 llvm::Value* data_field_addr =
747 irb_.CreatePtrDisp(array, data_field_offset, field_type);
748
749 for (unsigned i = 0; i < num_elements; ++i) {
750 // Values to fill the array begin at the 3rd argument
751 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
752
753 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
754
755 data_field_addr =
756 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
757 }
758
759 return;
760}
761
762llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
763 llvm::Value* /*is_volatile_value*/,
764 llvm::Value* object_addr,
765 JType field_jty) {
766 int field_offset =
767 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
768
769 DCHECK_GE(field_offset, 0);
770
771 llvm::PointerType* field_type =
772 irb_.getJType(field_jty, kField)->getPointerTo();
773
774 field_offset_value = irb_.getPtrEquivInt(field_offset);
775
776 llvm::Value* field_addr =
777 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
778
779 // TODO: Check is_volatile. We need to generate atomic load instruction
780 // when is_volatile is true.
781 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
782}
783
784void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
785 llvm::Value* /* is_volatile_value */,
786 llvm::Value* object_addr,
787 llvm::Value* new_value,
788 JType field_jty) {
789 int field_offset =
790 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
791
792 DCHECK_GE(field_offset, 0);
793
794 llvm::PointerType* field_type =
795 irb_.getJType(field_jty, kField)->getPointerTo();
796
797 field_offset_value = irb_.getPtrEquivInt(field_offset);
798
799 llvm::Value* field_addr =
800 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
801
802 // TODO: Check is_volatile. We need to generate atomic store instruction
803 // when is_volatile is true.
804 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
805
806 return;
807}
808
809llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
810 llvm::Value* field_offset_value,
811 llvm::Value* /*is_volatile_value*/,
812 JType field_jty) {
813 int field_offset =
814 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
815
816 DCHECK_GE(field_offset, 0);
817
818 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
819
820 llvm::Value* static_field_addr =
821 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
822 irb_.getJType(field_jty, kField)->getPointerTo());
823
824 // TODO: Check is_volatile. We need to generate atomic store instruction
825 // when is_volatile is true.
826 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
827}
828
829void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
830 llvm::Value* field_offset_value,
831 llvm::Value* /* is_volatile_value */,
832 llvm::Value* new_value,
833 JType field_jty) {
834 int field_offset =
835 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
836
837 DCHECK_GE(field_offset, 0);
838
839 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
840
841 llvm::Value* static_field_addr =
842 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
843 irb_.getJType(field_jty, kField)->getPointerTo());
844
845 // TODO: Check is_volatile. We need to generate atomic store instruction
846 // when is_volatile is true.
847 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
848
849 return;
850}
851
852llvm::Value*
853GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
854 return irb_.LoadFromObjectOffset(method_object_addr,
855 Method::DeclaringClassOffset().Int32Value(),
856 irb_.getJObjectTy(),
857 kTBAAConstJObject);
858}
859
860llvm::Value*
861GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
862 uint32_t type_idx =
863 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
864
865 llvm::Value* storage_field_addr =
866 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
867
868 return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
869}
870
871llvm::Value*
872GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
873 uint32_t callee_method_idx =
874 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
875
876 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
877}
878
879llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
880 llvm::Value* vtable_idx_value,
881 llvm::Value* this_addr) {
882 int vtable_idx =
883 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
884
885 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
886}
887
888llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
889 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
890 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
891 unsigned num_args = call_inst.getNumArgOperands();
892 llvm::Type* ret_type = call_inst.getType();
893
894 // Determine the function type of the callee method
895 std::vector<llvm::Type*> args_type;
896 std::vector<llvm::Value*> args;
897 for (unsigned i = 0; i < num_args; i++) {
898 args.push_back(call_inst.getArgOperand(i));
899 args_type.push_back(args[i]->getType());
900 }
901
902 llvm::FunctionType* callee_method_type =
903 llvm::FunctionType::get(ret_type, args_type, false);
904
905 llvm::Value* code_addr =
906 irb_.LoadFromObjectOffset(callee_method_object_addr,
907 Method::GetCodeOffset().Int32Value(),
908 callee_method_type->getPointerTo(),
909 kTBAAJRuntime);
910
911 // Invoke callee
912 llvm::Value* retval = irb_.CreateCall(code_addr, args);
913
914 return retval;
915}
916
917llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::Value* dividend,
918 llvm::Value* divisor,
919 bool is_div, JType op_jty) {
920 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
921
922 // Check the special case: MININT / -1 = MININT
923 // That case will cause overflow, which is undefined behavior in llvm.
924 // So we check the divisor is -1 or not, if the divisor is -1, we do
925 // the special path to avoid undefined behavior.
926 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
927 llvm::Value* zero = irb_.getJZero(op_jty);
928 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
929
TDYa1275e869b62012-07-25 00:45:39 -0700930 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700931
TDYa1275e869b62012-07-25 00:45:39 -0700932 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700933 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
934 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
935 llvm::BasicBlock* neg_one_cont =
936 llvm::BasicBlock::Create(context_, "", parent);
937
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700938 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
939 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
940
941 // If divisor == -1
942 irb_.SetInsertPoint(eq_neg_one);
943 llvm::Value* eq_result;
944 if (is_div) {
945 // We can just change from "dividend div -1" to "neg dividend". The sub
946 // don't care the sign/unsigned because of two's complement representation.
947 // And the behavior is what we want:
948 // -(2^n) (2^n)-1
949 // MININT < k <= MAXINT -> mul k -1 = -k
950 // MININT == k -> mul k -1 = k
951 //
952 // LLVM use sub to represent 'neg'
953 eq_result = irb_.CreateSub(zero, dividend);
954 } else {
955 // Everything modulo -1 will be 0.
956 eq_result = zero;
957 }
958 irb_.CreateBr(neg_one_cont);
959
960 // If divisor != -1, just do the division.
961 irb_.SetInsertPoint(ne_neg_one);
962 llvm::Value* ne_result;
963 if (is_div) {
964 ne_result = irb_.CreateSDiv(dividend, divisor);
965 } else {
966 ne_result = irb_.CreateSRem(dividend, divisor);
967 }
968 irb_.CreateBr(neg_one_cont);
969
970 irb_.SetInsertPoint(neg_one_cont);
971 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
972 result->addIncoming(eq_result, eq_neg_one);
973 result->addIncoming(ne_result, ne_neg_one);
974
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700975 return result;
976}
977
978void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
979 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
980 // MethodCompiler::EmitPushShadowFrame
981 shadow_frame_size_ =
982 llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
983
984 llvm::StructType* shadow_frame_type =
985 irb_.getShadowFrameTy(shadow_frame_size_);
986
987 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
988
989 // Alloca a pointer to old shadow frame
990 old_shadow_frame_ =
991 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
992
993 // Zero-initialization of the shadow frame table
994 llvm::Value* shadow_frame_table =
995 irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
996 llvm::Type* table_type = shadow_frame_type->getElementType(1);
997
998 llvm::ConstantAggregateZero* zero_initializer =
999 llvm::ConstantAggregateZero::get(table_type);
1000
1001 irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
1002
1003 // Push the shadow frame
1004 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1005
1006 // Push the shadow frame
1007 llvm::Value* shadow_frame_upcast =
1008 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1009
1010 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1011 method_object_addr,
1012 shadow_frame_size_);
1013
1014 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1015
1016 return;
1017}
1018
1019void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
1020 llvm::Value* entry_idx) {
1021 DCHECK(shadow_frame_ != NULL);
1022
1023 llvm::Value* gep_index[] = {
1024 irb_.getInt32(0), // No pointer displacement
1025 irb_.getInt32(1), // SIRT
1026 entry_idx // Pointer field
1027 };
1028
1029 llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1030 irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
1031 return;
1032}
1033
1034void GBCExpanderPass::Expand_PopShadowFrame() {
1035 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1036 return;
1037}
1038
1039void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1040 irb_.StoreToObjectOffset(shadow_frame_,
1041 ShadowFrame::DexPCOffset(),
1042 dex_pc_value,
1043 kTBAAShadowFrame);
1044 return;
1045}
1046
1047bool GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
1048 // DexLang generates all alloca instruction in the first basic block of the
1049 // FUNC and also there's no any alloca instructions after the first non-alloca
1050 // instruction
1051
1052 llvm::BasicBlock::iterator first_non_alloca = func.front().begin();
1053 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1054 ++first_non_alloca;
1055 }
1056
1057 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1058 // alloca instructions)
1059 return EmitStackOverflowCheck(&*first_non_alloca);
1060}
1061
TDYa1275e869b62012-07-25 00:45:39 -07001062// ==== High-level intrinsic expander ==========================================
1063
TDYa127a1b21852012-07-23 03:20:39 -07001064llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1065 llvm::Value* src2_value,
1066 bool gt_bias) {
1067 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1068 llvm::Value* cmp_lt;
1069
1070 if (gt_bias) {
1071 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1072 } else {
1073 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1074 }
1075
1076 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1077}
1078
1079llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1080 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1081 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1082
1083 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1084}
1085
1086llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1087 llvm::Value* cmp_lt) {
1088
1089 llvm::Constant* zero = irb_.getJInt(0);
1090 llvm::Constant* pos1 = irb_.getJInt(1);
1091 llvm::Constant* neg1 = irb_.getJInt(-1);
1092
1093 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1094 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1095
1096 return result_eq;
1097}
1098
Logan Chien75e4b602012-07-23 14:24:12 -07001099llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1100 llvm::Value* src2_value,
1101 IntegerShiftKind kind,
1102 JType op_jty) {
1103 DCHECK(op_jty == kInt || op_jty == kLong);
1104
1105 // Mask and zero-extend RHS properly
1106 if (op_jty == kInt) {
1107 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1108 } else {
1109 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1110 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1111 }
1112
1113 // Create integer shift llvm instruction
1114 switch (kind) {
1115 case kIntegerSHL:
1116 return irb_.CreateShl(src1_value, src2_value);
1117
1118 case kIntegerSHR:
1119 return irb_.CreateAShr(src1_value, src2_value);
1120
1121 case kIntegerUSHR:
1122 return irb_.CreateLShr(src1_value, src2_value);
1123
1124 default:
1125 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1126 return NULL;
1127 }
1128}
1129
TDYa1275a26d442012-07-26 18:58:38 -07001130llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1131 JType elem_jty) {
1132 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1133
1134 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1135 llvm::Value* array_addr = call_inst.getArgOperand(1);
1136 llvm::Value* index_value = call_inst.getArgOperand(2);
1137
1138 // TODO: opt_flags
1139 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
1140
1141 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1142
1143 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1144
1145 switch (elem_jty) {
1146 case kVoid:
1147 break;
1148
1149 case kBoolean:
1150 case kChar:
1151 array_elem_value = irb_.CreateZExt(array_elem_value, irb_.getJType(elem_jty, kReg));
1152 break;
1153
1154 case kByte:
1155 case kShort:
1156 array_elem_value = irb_.CreateSExt(array_elem_value, irb_.getJType(elem_jty, kReg));
1157 break;
1158
1159 case kInt:
1160 case kLong:
1161 case kFloat:
1162 case kDouble:
1163 case kObject:
1164 break;
1165
1166 default:
1167 LOG(FATAL) << "Unknown java type: " << elem_jty;
1168 }
1169
1170 return array_elem_value;
1171}
1172
1173
1174void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1175 JType elem_jty) {
1176 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1177
1178 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1179 llvm::Value* new_value = call_inst.getArgOperand(1);
1180 llvm::Value* array_addr = call_inst.getArgOperand(2);
1181 llvm::Value* index_value = call_inst.getArgOperand(3);
1182
1183 // TODO: opt_flags
1184 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
1185
1186 switch (elem_jty) {
1187 case kVoid:
1188 break;
1189
1190 case kBoolean:
1191 case kChar:
1192 new_value = irb_.CreateTrunc(new_value, irb_.getJType(elem_jty, kArray));
1193 break;
1194
1195 case kInt:
1196 case kLong:
1197 case kFloat:
1198 case kDouble:
1199 case kObject:
1200 break;
1201
1202 default:
1203 LOG(FATAL) << "Unknown java type: " << elem_jty;
1204 }
1205
1206 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1207
1208 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
1209 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
1210
1211 irb_.CreateCall2(runtime_func, new_value, array_addr);
1212
1213 EmitGuard_ExceptionLandingPad(dex_pc);
1214
1215 EmitMarkGCCard(new_value, array_addr);
1216 }
1217
1218 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1219
1220 return;
1221}
1222
TDYa1275e869b62012-07-25 00:45:39 -07001223llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1224 JType field_jty) {
1225 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1226
1227 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1228 llvm::Value* object_addr = call_inst.getArgOperand(1);
1229 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
1230
1231 // TODO: opt_flags
1232 EmitGuard_NullPointerException(dex_pc, object_addr);
1233
1234 llvm::Value* field_value;
1235
1236 int field_offset;
1237 bool is_volatile;
1238 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1239 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
1240
1241 if (!is_fast_path) {
1242 llvm::Function* runtime_func;
1243
1244 if (field_jty == kObject) {
1245 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1246 } else if (field_jty == kLong || field_jty == kDouble) {
1247 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1248 } else {
1249 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1250 }
1251
1252 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1253
1254 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1255
1256 EmitUpdateDexPC(dex_pc);
1257
1258 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1259 method_object_addr, object_addr);
1260
1261 EmitGuard_ExceptionLandingPad(dex_pc);
1262
1263 } else {
1264 DCHECK_GE(field_offset, 0);
1265
1266 llvm::PointerType* field_type =
1267 irb_.getJType(field_jty, kField)->getPointerTo();
1268
1269 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1270
1271 llvm::Value* field_addr =
1272 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1273
1274 // TODO: Check is_volatile. We need to generate atomic load instruction
1275 // when is_volatile is true.
1276 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1277 }
1278
1279 if (field_jty == kFloat || field_jty == kDouble) {
TDYa1275a26d442012-07-26 18:58:38 -07001280 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty, kAccurate));
TDYa1275e869b62012-07-25 00:45:39 -07001281 }
1282
1283 return field_value;
1284}
1285
1286void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1287 JType field_jty) {
1288 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1289
1290 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1291 llvm::Value* object_addr = call_inst.getArgOperand(1);
1292 llvm::Value* new_value = call_inst.getArgOperand(2);
1293 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
1294
1295 if (field_jty == kFloat || field_jty == kDouble) {
TDYa1275a26d442012-07-26 18:58:38 -07001296 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
TDYa1275e869b62012-07-25 00:45:39 -07001297 }
1298
1299 // TODO: opt_flags
1300 EmitGuard_NullPointerException(dex_pc, object_addr);
1301
1302 int field_offset;
1303 bool is_volatile;
1304 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1305 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
1306
1307 if (!is_fast_path) {
1308 llvm::Function* runtime_func;
1309
1310 if (field_jty == kObject) {
1311 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1312 } else if (field_jty == kLong || field_jty == kDouble) {
1313 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1314 } else {
1315 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1316 }
1317
1318 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1319
1320 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1321
1322 EmitUpdateDexPC(dex_pc);
1323
1324 irb_.CreateCall4(runtime_func, field_idx_value,
1325 method_object_addr, object_addr, new_value);
1326
1327 EmitGuard_ExceptionLandingPad(dex_pc);
1328
1329 } else {
1330 DCHECK_GE(field_offset, 0);
1331
1332 llvm::PointerType* field_type =
1333 irb_.getJType(field_jty, kField)->getPointerTo();
1334
1335 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1336
1337 llvm::Value* field_addr =
1338 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1339
1340 // TODO: Check is_volatile. We need to generate atomic store instruction
1341 // when is_volatile is true.
1342 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1343
1344 if (field_jty == kObject) { // If put an object, mark the GC card table.
1345 EmitMarkGCCard(new_value, object_addr);
1346 }
1347 }
1348
1349 return;
1350}
1351
TDYa1275a26d442012-07-26 18:58:38 -07001352llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1353 uint32_t type_idx) {
1354 llvm::BasicBlock* block_load_static =
1355 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1356
1357 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1358
1359 // Load static storage from dex cache
1360 llvm::Value* storage_field_addr =
1361 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1362
1363 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
1364
1365 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1366
1367 // Test: Is the static storage of this class initialized?
1368 llvm::Value* equal_null =
1369 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1370
1371 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1372
1373 // Failback routine to load the class object
1374 irb_.SetInsertPoint(block_load_static);
1375
1376 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
1377
1378 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1379
1380 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1381
1382 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1383
1384 EmitUpdateDexPC(dex_pc);
1385
1386 llvm::Value* loaded_storage_object_addr =
1387 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1388
1389 EmitGuard_ExceptionLandingPad(dex_pc);
1390
1391 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1392
1393 irb_.CreateBr(block_cont);
1394
1395 // Now the class object must be loaded
1396 irb_.SetInsertPoint(block_cont);
1397
1398 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1399
1400 phi->addIncoming(storage_object_addr, block_original);
1401 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1402
1403 return phi;
1404}
1405
1406llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1407 JType field_jty) {
1408 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1409
1410 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1411 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1412
1413 int field_offset;
1414 int ssb_index;
1415 bool is_referrers_class;
1416 bool is_volatile;
1417
1418 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1419 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1420 is_referrers_class, is_volatile, false);
1421
1422 llvm::Value* static_field_value;
1423
1424 if (!is_fast_path) {
1425 llvm::Function* runtime_func;
1426
1427 if (field_jty == kObject) {
1428 runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
1429 } else if (field_jty == kLong || field_jty == kDouble) {
1430 runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
1431 } else {
1432 runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
1433 }
1434
1435 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1436
1437 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1438
1439 EmitUpdateDexPC(dex_pc);
1440
1441 static_field_value =
1442 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1443
1444 EmitGuard_ExceptionLandingPad(dex_pc);
1445
1446 } else {
1447 DCHECK_GE(field_offset, 0);
1448
1449 llvm::Value* static_storage_addr = NULL;
1450
1451 if (is_referrers_class) {
1452 // Fast path, static storage base is this method's class
1453 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1454
1455 static_storage_addr =
1456 irb_.LoadFromObjectOffset(method_object_addr,
1457 Method::DeclaringClassOffset().Int32Value(),
1458 irb_.getJObjectTy(),
1459 kTBAAConstJObject);
1460 } else {
1461 // Medium path, static storage base in a different class which
1462 // requires checks that the other class is initialized
1463 DCHECK_GE(ssb_index, 0);
1464 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1465 }
1466
1467 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1468
1469 llvm::Value* static_field_addr =
1470 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1471 irb_.getJType(field_jty, kField)->getPointerTo());
1472
1473 // TODO: Check is_volatile. We need to generate atomic load instruction
1474 // when is_volatile is true.
1475 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1476 }
1477
1478 if (field_jty == kFloat || field_jty == kDouble) {
1479 static_field_value =
1480 irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty, kAccurate));
1481 }
1482
1483 return static_field_value;
1484}
1485
1486void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1487 JType field_jty) {
1488 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1489
1490 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1491 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1492 llvm::Value* new_value = call_inst.getArgOperand(1);
1493
1494 if (field_jty == kFloat || field_jty == kDouble) {
1495 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
1496 }
1497
1498 int field_offset;
1499 int ssb_index;
1500 bool is_referrers_class;
1501 bool is_volatile;
1502
1503 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1504 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1505 is_referrers_class, is_volatile, true);
1506
1507 if (!is_fast_path) {
1508 llvm::Function* runtime_func;
1509
1510 if (field_jty == kObject) {
1511 runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
1512 } else if (field_jty == kLong || field_jty == kDouble) {
1513 runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
1514 } else {
1515 runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
1516 }
1517
1518 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1519
1520 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1521
1522 EmitUpdateDexPC(dex_pc);
1523
1524 irb_.CreateCall3(runtime_func, field_idx_value,
1525 method_object_addr, new_value);
1526
1527 EmitGuard_ExceptionLandingPad(dex_pc);
1528
1529 } else {
1530 DCHECK_GE(field_offset, 0);
1531
1532 llvm::Value* static_storage_addr = NULL;
1533
1534 if (is_referrers_class) {
1535 // Fast path, static storage base is this method's class
1536 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1537
1538 static_storage_addr =
1539 irb_.LoadFromObjectOffset(method_object_addr,
1540 Method::DeclaringClassOffset().Int32Value(),
1541 irb_.getJObjectTy(),
1542 kTBAAConstJObject);
1543 } else {
1544 // Medium path, static storage base in a different class which
1545 // requires checks that the other class is initialized
1546 DCHECK_GE(ssb_index, 0);
1547 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1548 }
1549
1550 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1551
1552 llvm::Value* static_field_addr =
1553 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1554 irb_.getJType(field_jty, kField)->getPointerTo());
1555
1556 // TODO: Check is_volatile. We need to generate atomic store instruction
1557 // when is_volatile is true.
1558 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1559
1560 if (field_jty == kObject) { // If put an object, mark the GC card table.
1561 EmitMarkGCCard(new_value, static_storage_addr);
1562 }
1563 }
1564
1565 return;
1566}
1567
TDYa1275e869b62012-07-25 00:45:39 -07001568void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
1569 // Using runtime support, let the target can override by InlineAssembly.
1570 irb_.Runtime().EmitMarkGCCard(value, target_addr);
1571}
1572
1573void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
1574 irb_.StoreToObjectOffset(shadow_frame_,
1575 ShadowFrame::DexPCOffset(),
1576 irb_.getInt32(dex_pc),
1577 kTBAAShadowFrame);
1578}
1579
1580void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
1581 llvm::Value* denominator,
1582 JType op_jty) {
1583 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
1584
1585 llvm::Constant* zero = irb_.getJZero(op_jty);
1586
1587 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
1588
1589 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
1590
1591 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
1592
1593 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
1594
1595 irb_.SetInsertPoint(block_exception);
1596 EmitUpdateDexPC(dex_pc);
1597 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
1598 EmitBranchExceptionLandingPad(dex_pc);
1599
1600 irb_.SetInsertPoint(block_continue);
1601}
1602
1603void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
1604 llvm::Value* object) {
1605 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
1606
1607 llvm::BasicBlock* block_exception =
1608 CreateBasicBlockWithDexPC(dex_pc, "nullp");
1609
1610 llvm::BasicBlock* block_continue =
1611 CreateBasicBlockWithDexPC(dex_pc, "cont");
1612
1613 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
1614
1615 irb_.SetInsertPoint(block_exception);
1616 EmitUpdateDexPC(dex_pc);
1617 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
1618 irb_.getInt32(dex_pc));
1619 EmitBranchExceptionLandingPad(dex_pc);
1620
1621 irb_.SetInsertPoint(block_continue);
1622}
1623
1624void
1625GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
1626 llvm::Value* array,
1627 llvm::Value* index) {
1628 llvm::Value* array_len = EmitLoadArrayLength(array);
1629
1630 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
1631
1632 llvm::BasicBlock* block_exception =
1633 CreateBasicBlockWithDexPC(dex_pc, "overflow");
1634
1635 llvm::BasicBlock* block_continue =
1636 CreateBasicBlockWithDexPC(dex_pc, "cont");
1637
1638 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
1639
1640 irb_.SetInsertPoint(block_exception);
1641
1642 EmitUpdateDexPC(dex_pc);
1643 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
1644 EmitBranchExceptionLandingPad(dex_pc);
1645
1646 irb_.SetInsertPoint(block_continue);
1647}
1648
1649void GBCExpanderPass::EmitGuard_ArrayException(uint32_t dex_pc,
1650 llvm::Value* array,
1651 llvm::Value* index) {
1652 EmitGuard_NullPointerException(dex_pc, array);
1653 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
1654}
1655
1656llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
1657 bool is_static) {
1658 // Get method signature
1659 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
1660
1661 uint32_t shorty_size;
1662 const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
1663 CHECK_GE(shorty_size, 1u);
1664
1665 // Get return type
1666 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
1667
1668 // Get argument type
1669 std::vector<llvm::Type*> args_type;
1670
1671 args_type.push_back(irb_.getJObjectTy()); // method object pointer
1672
1673 if (!is_static) {
1674 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
1675 }
1676
1677 for (uint32_t i = 1; i < shorty_size; ++i) {
1678 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
1679 }
1680
1681 return llvm::FunctionType::get(ret_type, args_type, false);
1682}
1683
1684
1685llvm::BasicBlock* GBCExpanderPass::
1686CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
1687 std::string name;
1688
1689#if !defined(NDEBUG)
1690 StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
1691#endif
1692
1693 return llvm::BasicBlock::Create(context_, name, func_);
1694}
1695
1696llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
1697 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
1698
1699 return basic_blocks_[dex_pc];
1700}
1701
1702int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
1703 int32_t min = 0;
1704 int32_t max = code_item_->tries_size_ - 1;
1705
1706 while (min <= max) {
1707 int32_t mid = min + (max - min) / 2;
1708
1709 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, mid);
1710 uint32_t start = ti->start_addr_;
1711 uint32_t end = start + ti->insn_count_;
1712
1713 if (dex_pc < start) {
1714 max = mid - 1;
1715 } else if (dex_pc >= end) {
1716 min = mid + 1;
1717 } else {
1718 return mid; // found
1719 }
1720 }
1721
1722 return -1; // not found
1723}
1724
1725llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
1726 // Find the try item for this address in this method
1727 int32_t ti_offset = GetTryItemOffset(dex_pc);
1728
1729 if (ti_offset == -1) {
1730 return NULL; // No landing pad is available for this address.
1731 }
1732
1733 // Check for the existing landing pad basic block
1734 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
1735 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
1736
1737 if (block_lpad) {
1738 // We have generated landing pad for this try item already. Return the
1739 // same basic block.
1740 return block_lpad;
1741 }
1742
1743 // Get try item from code item
1744 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, ti_offset);
1745
1746 std::string lpadname;
1747
1748#if !defined(NDEBUG)
1749 StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
1750#endif
1751
1752 // Create landing pad basic block
1753 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
1754
1755 // Change IRBuilder insert point
1756 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1757 irb_.SetInsertPoint(block_lpad);
1758
1759 // Find catch block with matching type
1760 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1761
1762 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
1763
1764 llvm::Value* catch_handler_index_value =
1765 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
1766 method_object_addr, ti_offset_value);
1767
1768 // Switch instruction (Go to unwind basic block by default)
1769 llvm::SwitchInst* sw =
1770 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
1771
1772 // Cases with matched catch block
1773 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
1774
1775 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
1776 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
1777 }
1778
1779 // Restore the orignal insert point for IRBuilder
1780 irb_.restoreIP(irb_ip_original);
1781
1782 // Cache this landing pad
1783 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
1784 basic_block_landing_pads_[ti_offset] = block_lpad;
1785
1786 return block_lpad;
1787}
1788
1789llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
1790 // Check the existing unwinding baisc block block
1791 if (basic_block_unwind_ != NULL) {
1792 return basic_block_unwind_;
1793 }
1794
1795 // Create new basic block for unwinding
1796 basic_block_unwind_ =
1797 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
1798
1799 // Change IRBuilder insert point
1800 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1801 irb_.SetInsertPoint(basic_block_unwind_);
1802
1803 // Pop the shadow frame
1804 Expand_PopShadowFrame();
1805
1806 // Emit the code to return default value (zero) for the given return type.
1807 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
1808 if (ret_shorty == 'V') {
1809 irb_.CreateRetVoid();
1810 } else {
1811 irb_.CreateRet(irb_.getJZero(ret_shorty));
1812 }
1813
1814 // Restore the orignal insert point for IRBuilder
1815 irb_.restoreIP(irb_ip_original);
1816
1817 return basic_block_unwind_;
1818}
1819
1820void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
1821 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
1822 irb_.CreateBr(lpad);
1823 } else {
1824 irb_.CreateBr(GetUnwindBasicBlock());
1825 }
1826}
1827
1828void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
1829 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
1830
1831 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1832
1833 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
1834 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
1835 } else {
1836 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
1837 }
1838
1839 irb_.SetInsertPoint(block_cont);
1840}
1841
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001842llvm::Value*
1843GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
1844 llvm::CallInst& call_inst) {
1845 switch (intr_id) {
1846 //==- Thread -----------------------------------------------------------==//
1847 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07001848 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001849 }
Logan Chiend54a23d2012-07-24 11:19:23 -07001850 case IntrinsicHelper::TestSuspend:
Logan Chien75e4b602012-07-23 14:24:12 -07001851 case IntrinsicHelper::CheckSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07001852 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07001853 return NULL;
1854 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001855 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07001856 Expand_MarkGCCard(call_inst);
1857 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001858 }
Logan Chien75e4b602012-07-23 14:24:12 -07001859
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001860 //==- Exception --------------------------------------------------------==//
1861 case IntrinsicHelper::ThrowException: {
1862 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
1863 }
1864 case IntrinsicHelper::GetException: {
1865 return Expand_GetException();
1866 }
1867 case IntrinsicHelper::IsExceptionPending: {
1868 return irb_.Runtime().EmitIsExceptionPending();
1869 }
1870 case IntrinsicHelper::FindCatchBlock: {
1871 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
1872 }
1873 case IntrinsicHelper::ThrowDivZeroException: {
1874 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
1875 }
1876 case IntrinsicHelper::ThrowNullPointerException: {
1877 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
1878 }
1879 case IntrinsicHelper::ThrowIndexOutOfBounds: {
1880 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
1881 }
Logan Chien75e4b602012-07-23 14:24:12 -07001882
1883 //==- Const String -----------------------------------------------------==//
1884 case IntrinsicHelper::ConstString: {
1885 UNIMPLEMENTED(FATAL);
1886 return NULL;
1887 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001888 case IntrinsicHelper::LoadStringFromDexCache: {
1889 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
1890 }
1891 case IntrinsicHelper::ResolveString: {
1892 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
1893 }
Logan Chien75e4b602012-07-23 14:24:12 -07001894
1895 //==- Const Class ------------------------------------------------------==//
1896 case IntrinsicHelper::ConstClass: {
1897 UNIMPLEMENTED(FATAL);
1898 return NULL;
1899 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001900 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
1901 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
1902 }
1903 case IntrinsicHelper::LoadTypeFromDexCache: {
1904 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
1905 }
1906 case IntrinsicHelper::InitializeType: {
1907 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
1908 }
Logan Chien75e4b602012-07-23 14:24:12 -07001909
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001910 //==- Lock -------------------------------------------------------------==//
1911 case IntrinsicHelper::LockObject: {
1912 Expand_LockObject(call_inst.getArgOperand(0));
1913 return NULL;
1914 }
1915 case IntrinsicHelper::UnlockObject: {
1916 Expand_UnlockObject(call_inst.getArgOperand(0));
1917 return NULL;
1918 }
Logan Chien75e4b602012-07-23 14:24:12 -07001919
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001920 //==- Cast -------------------------------------------------------------==//
1921 case IntrinsicHelper::CheckCast: {
1922 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
1923 }
Logan Chien75e4b602012-07-23 14:24:12 -07001924 case IntrinsicHelper::HLCheckCast: {
1925 UNIMPLEMENTED(FATAL);
1926 return NULL;
1927 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001928 case IntrinsicHelper::IsAssignable: {
1929 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
1930 }
Logan Chien75e4b602012-07-23 14:24:12 -07001931
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001932 //==- Alloc ------------------------------------------------------------==//
1933 case IntrinsicHelper::AllocObject: {
1934 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
1935 }
1936 case IntrinsicHelper::AllocObjectWithAccessCheck: {
1937 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
1938 }
Logan Chien75e4b602012-07-23 14:24:12 -07001939
1940 //==- Instance ---------------------------------------------------------==//
1941 case IntrinsicHelper::NewInstance: {
1942 UNIMPLEMENTED(FATAL);
1943 return NULL;
1944 }
1945 case IntrinsicHelper::InstanceOf: {
1946 UNIMPLEMENTED(FATAL);
1947 return NULL;
1948 }
1949
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001950 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07001951 case IntrinsicHelper::NewArray: {
1952 UNIMPLEMENTED(FATAL);
1953 return NULL;
1954 }
1955 case IntrinsicHelper::OptArrayLength: {
1956 UNIMPLEMENTED(FATAL);
1957 return NULL;
1958 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001959 case IntrinsicHelper::ArrayLength: {
1960 return EmitLoadArrayLength(call_inst.getArgOperand(0));
1961 }
1962 case IntrinsicHelper::AllocArray: {
1963 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
1964 }
1965 case IntrinsicHelper::AllocArrayWithAccessCheck: {
1966 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
1967 call_inst);
1968 }
1969 case IntrinsicHelper::CheckAndAllocArray: {
1970 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
1971 }
1972 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
1973 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
1974 call_inst);
1975 }
1976 case IntrinsicHelper::ArrayGet: {
1977 return Expand_ArrayGet(call_inst.getArgOperand(0),
1978 call_inst.getArgOperand(1),
1979 kInt);
1980 }
1981 case IntrinsicHelper::ArrayGetWide: {
1982 return Expand_ArrayGet(call_inst.getArgOperand(0),
1983 call_inst.getArgOperand(1),
1984 kLong);
1985 }
1986 case IntrinsicHelper::ArrayGetObject: {
1987 return Expand_ArrayGet(call_inst.getArgOperand(0),
1988 call_inst.getArgOperand(1),
1989 kObject);
1990 }
1991 case IntrinsicHelper::ArrayGetBoolean: {
1992 return Expand_ArrayGet(call_inst.getArgOperand(0),
1993 call_inst.getArgOperand(1),
1994 kBoolean);
1995 }
1996 case IntrinsicHelper::ArrayGetByte: {
1997 return Expand_ArrayGet(call_inst.getArgOperand(0),
1998 call_inst.getArgOperand(1),
1999 kByte);
2000 }
2001 case IntrinsicHelper::ArrayGetChar: {
2002 return Expand_ArrayGet(call_inst.getArgOperand(0),
2003 call_inst.getArgOperand(1),
2004 kChar);
2005 }
2006 case IntrinsicHelper::ArrayGetShort: {
2007 return Expand_ArrayGet(call_inst.getArgOperand(0),
2008 call_inst.getArgOperand(1),
2009 kShort);
2010 }
2011 case IntrinsicHelper::ArrayPut: {
2012 Expand_ArrayPut(call_inst.getArgOperand(0),
2013 call_inst.getArgOperand(1),
2014 call_inst.getArgOperand(2),
2015 kInt);
2016 return NULL;
2017 }
2018 case IntrinsicHelper::ArrayPutWide: {
2019 Expand_ArrayPut(call_inst.getArgOperand(0),
2020 call_inst.getArgOperand(1),
2021 call_inst.getArgOperand(2),
2022 kLong);
2023 return NULL;
2024 }
2025 case IntrinsicHelper::ArrayPutObject: {
2026 Expand_ArrayPut(call_inst.getArgOperand(0),
2027 call_inst.getArgOperand(1),
2028 call_inst.getArgOperand(2),
2029 kObject);
2030 return NULL;
2031 }
2032 case IntrinsicHelper::ArrayPutBoolean: {
2033 Expand_ArrayPut(call_inst.getArgOperand(0),
2034 call_inst.getArgOperand(1),
2035 call_inst.getArgOperand(2),
2036 kBoolean);
2037 return NULL;
2038 }
2039 case IntrinsicHelper::ArrayPutByte: {
2040 Expand_ArrayPut(call_inst.getArgOperand(0),
2041 call_inst.getArgOperand(1),
2042 call_inst.getArgOperand(2),
2043 kByte);
2044 return NULL;
2045 }
2046 case IntrinsicHelper::ArrayPutChar: {
2047 Expand_ArrayPut(call_inst.getArgOperand(0),
2048 call_inst.getArgOperand(1),
2049 call_inst.getArgOperand(2),
2050 kChar);
2051 return NULL;
2052 }
2053 case IntrinsicHelper::ArrayPutShort: {
2054 Expand_ArrayPut(call_inst.getArgOperand(0),
2055 call_inst.getArgOperand(1),
2056 call_inst.getArgOperand(2),
2057 kShort);
2058 return NULL;
2059 }
2060 case IntrinsicHelper::CheckPutArrayElement: {
2061 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
2062 }
2063 case IntrinsicHelper::FilledNewArray: {
2064 Expand_FilledNewArray(call_inst);
2065 return NULL;
2066 }
2067 case IntrinsicHelper::FillArrayData: {
2068 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
2069 }
Logan Chien75e4b602012-07-23 14:24:12 -07002070 case IntrinsicHelper::HLFillArrayData: {
2071 UNIMPLEMENTED(FATAL);
2072 return NULL;
2073 }
2074 case IntrinsicHelper::HLFilledNewArray: {
2075 UNIMPLEMENTED(FATAL);
2076 return NULL;
2077 }
2078
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002079 //==- Instance Field ---------------------------------------------------==//
2080 case IntrinsicHelper::InstanceFieldGet:
2081 case IntrinsicHelper::InstanceFieldGetBoolean:
2082 case IntrinsicHelper::InstanceFieldGetByte:
2083 case IntrinsicHelper::InstanceFieldGetChar:
2084 case IntrinsicHelper::InstanceFieldGetShort: {
2085 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
2086 }
2087 case IntrinsicHelper::InstanceFieldGetWide: {
2088 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
2089 }
2090 case IntrinsicHelper::InstanceFieldGetObject: {
2091 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
2092 }
2093 case IntrinsicHelper::InstanceFieldGetFast: {
2094 return Expand_IGetFast(call_inst.getArgOperand(0),
2095 call_inst.getArgOperand(1),
2096 call_inst.getArgOperand(2),
2097 kInt);
2098 }
2099 case IntrinsicHelper::InstanceFieldGetWideFast: {
2100 return Expand_IGetFast(call_inst.getArgOperand(0),
2101 call_inst.getArgOperand(1),
2102 call_inst.getArgOperand(2),
2103 kLong);
2104 }
2105 case IntrinsicHelper::InstanceFieldGetObjectFast: {
2106 return Expand_IGetFast(call_inst.getArgOperand(0),
2107 call_inst.getArgOperand(1),
2108 call_inst.getArgOperand(2),
2109 kObject);
2110 }
2111 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
2112 return Expand_IGetFast(call_inst.getArgOperand(0),
2113 call_inst.getArgOperand(1),
2114 call_inst.getArgOperand(2),
2115 kBoolean);
2116 }
2117 case IntrinsicHelper::InstanceFieldGetByteFast: {
2118 return Expand_IGetFast(call_inst.getArgOperand(0),
2119 call_inst.getArgOperand(1),
2120 call_inst.getArgOperand(2),
2121 kByte);
2122 }
2123 case IntrinsicHelper::InstanceFieldGetCharFast: {
2124 return Expand_IGetFast(call_inst.getArgOperand(0),
2125 call_inst.getArgOperand(1),
2126 call_inst.getArgOperand(2),
2127 kChar);
2128 }
2129 case IntrinsicHelper::InstanceFieldGetShortFast: {
2130 return Expand_IGetFast(call_inst.getArgOperand(0),
2131 call_inst.getArgOperand(1),
2132 call_inst.getArgOperand(2),
2133 kShort);
2134 }
2135 case IntrinsicHelper::InstanceFieldPut:
2136 case IntrinsicHelper::InstanceFieldPutBoolean:
2137 case IntrinsicHelper::InstanceFieldPutByte:
2138 case IntrinsicHelper::InstanceFieldPutChar:
2139 case IntrinsicHelper::InstanceFieldPutShort: {
2140 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
2141 }
2142 case IntrinsicHelper::InstanceFieldPutWide: {
2143 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
2144 }
2145 case IntrinsicHelper::InstanceFieldPutObject: {
2146 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
2147 }
2148 case IntrinsicHelper::InstanceFieldPutFast: {
2149 Expand_IPutFast(call_inst.getArgOperand(0),
2150 call_inst.getArgOperand(1),
2151 call_inst.getArgOperand(2),
2152 call_inst.getArgOperand(3),
2153 kInt);
2154 return NULL;
2155 }
2156 case IntrinsicHelper::InstanceFieldPutWideFast: {
2157 Expand_IPutFast(call_inst.getArgOperand(0),
2158 call_inst.getArgOperand(1),
2159 call_inst.getArgOperand(2),
2160 call_inst.getArgOperand(3),
2161 kLong);
2162 return NULL;
2163 }
2164 case IntrinsicHelper::InstanceFieldPutObjectFast: {
2165 Expand_IPutFast(call_inst.getArgOperand(0),
2166 call_inst.getArgOperand(1),
2167 call_inst.getArgOperand(2),
2168 call_inst.getArgOperand(3),
2169 kObject);
2170 return NULL;
2171 }
2172 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
2173 Expand_IPutFast(call_inst.getArgOperand(0),
2174 call_inst.getArgOperand(1),
2175 call_inst.getArgOperand(2),
2176 call_inst.getArgOperand(3),
2177 kBoolean);
2178 return NULL;
2179 }
2180 case IntrinsicHelper::InstanceFieldPutByteFast: {
2181 Expand_IPutFast(call_inst.getArgOperand(0),
2182 call_inst.getArgOperand(1),
2183 call_inst.getArgOperand(2),
2184 call_inst.getArgOperand(3),
2185 kByte);
2186 return NULL;
2187 }
2188 case IntrinsicHelper::InstanceFieldPutCharFast: {
2189 Expand_IPutFast(call_inst.getArgOperand(0),
2190 call_inst.getArgOperand(1),
2191 call_inst.getArgOperand(2),
2192 call_inst.getArgOperand(3),
2193 kChar);
2194 return NULL;
2195 }
2196 case IntrinsicHelper::InstanceFieldPutShortFast: {
2197 Expand_IPutFast(call_inst.getArgOperand(0),
2198 call_inst.getArgOperand(1),
2199 call_inst.getArgOperand(2),
2200 call_inst.getArgOperand(3),
2201 kShort);
2202 return NULL;
2203 }
Logan Chien75e4b602012-07-23 14:24:12 -07002204
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002205 //==- Static Field -----------------------------------------------------==//
2206 case IntrinsicHelper::StaticFieldGet:
2207 case IntrinsicHelper::StaticFieldGetBoolean:
2208 case IntrinsicHelper::StaticFieldGetByte:
2209 case IntrinsicHelper::StaticFieldGetChar:
2210 case IntrinsicHelper::StaticFieldGetShort: {
2211 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
2212 }
2213 case IntrinsicHelper::StaticFieldGetWide: {
2214 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
2215 }
2216 case IntrinsicHelper::StaticFieldGetObject: {
2217 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
2218 }
2219 case IntrinsicHelper::StaticFieldGetFast: {
2220 return Expand_SGetFast(call_inst.getArgOperand(0),
2221 call_inst.getArgOperand(1),
2222 call_inst.getArgOperand(2),
2223 kInt);
2224 }
2225 case IntrinsicHelper::StaticFieldGetWideFast: {
2226 return Expand_SGetFast(call_inst.getArgOperand(0),
2227 call_inst.getArgOperand(1),
2228 call_inst.getArgOperand(2),
2229 kLong);
2230 }
2231 case IntrinsicHelper::StaticFieldGetObjectFast: {
2232 return Expand_SGetFast(call_inst.getArgOperand(0),
2233 call_inst.getArgOperand(1),
2234 call_inst.getArgOperand(2),
2235 kObject);
2236 }
2237 case IntrinsicHelper::StaticFieldGetBooleanFast: {
2238 return Expand_SGetFast(call_inst.getArgOperand(0),
2239 call_inst.getArgOperand(1),
2240 call_inst.getArgOperand(2),
2241 kBoolean);
2242 }
2243 case IntrinsicHelper::StaticFieldGetByteFast: {
2244 return Expand_SGetFast(call_inst.getArgOperand(0),
2245 call_inst.getArgOperand(1),
2246 call_inst.getArgOperand(2),
2247 kByte);
2248 }
2249 case IntrinsicHelper::StaticFieldGetCharFast: {
2250 return Expand_SGetFast(call_inst.getArgOperand(0),
2251 call_inst.getArgOperand(1),
2252 call_inst.getArgOperand(2),
2253 kChar);
2254 }
2255 case IntrinsicHelper::StaticFieldGetShortFast: {
2256 return Expand_SGetFast(call_inst.getArgOperand(0),
2257 call_inst.getArgOperand(1),
2258 call_inst.getArgOperand(2),
2259 kShort);
2260 }
2261 case IntrinsicHelper::StaticFieldPut:
2262 case IntrinsicHelper::StaticFieldPutBoolean:
2263 case IntrinsicHelper::StaticFieldPutByte:
2264 case IntrinsicHelper::StaticFieldPutChar:
2265 case IntrinsicHelper::StaticFieldPutShort: {
2266 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
2267 }
2268 case IntrinsicHelper::StaticFieldPutWide: {
2269 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
2270 }
2271 case IntrinsicHelper::StaticFieldPutObject: {
2272 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
2273 }
2274 case IntrinsicHelper::StaticFieldPutFast: {
2275 Expand_SPutFast(call_inst.getArgOperand(0),
2276 call_inst.getArgOperand(1),
2277 call_inst.getArgOperand(2),
2278 call_inst.getArgOperand(3),
2279 kInt);
2280 return NULL;
2281 }
2282 case IntrinsicHelper::StaticFieldPutWideFast: {
2283 Expand_SPutFast(call_inst.getArgOperand(0),
2284 call_inst.getArgOperand(1),
2285 call_inst.getArgOperand(2),
2286 call_inst.getArgOperand(3),
2287 kLong);
2288 return NULL;
2289 }
2290 case IntrinsicHelper::StaticFieldPutObjectFast: {
2291 Expand_SPutFast(call_inst.getArgOperand(0),
2292 call_inst.getArgOperand(1),
2293 call_inst.getArgOperand(2),
2294 call_inst.getArgOperand(3),
2295 kObject);
2296 return NULL;
2297 }
2298 case IntrinsicHelper::StaticFieldPutBooleanFast: {
2299 Expand_SPutFast(call_inst.getArgOperand(0),
2300 call_inst.getArgOperand(1),
2301 call_inst.getArgOperand(2),
2302 call_inst.getArgOperand(3),
2303 kBoolean);
2304 return NULL;
2305 }
2306 case IntrinsicHelper::StaticFieldPutByteFast: {
2307 Expand_SPutFast(call_inst.getArgOperand(0),
2308 call_inst.getArgOperand(1),
2309 call_inst.getArgOperand(2),
2310 call_inst.getArgOperand(3),
2311 kByte);
2312 return NULL;
2313 }
2314 case IntrinsicHelper::StaticFieldPutCharFast: {
2315 Expand_SPutFast(call_inst.getArgOperand(0),
2316 call_inst.getArgOperand(1),
2317 call_inst.getArgOperand(2),
2318 call_inst.getArgOperand(3),
2319 kChar);
2320 return NULL;
2321 }
2322 case IntrinsicHelper::StaticFieldPutShortFast: {
2323 Expand_SPutFast(call_inst.getArgOperand(0),
2324 call_inst.getArgOperand(1),
2325 call_inst.getArgOperand(2),
2326 call_inst.getArgOperand(3),
2327 kShort);
2328 return NULL;
2329 }
2330 case IntrinsicHelper::LoadDeclaringClassSSB: {
2331 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
2332 }
2333 case IntrinsicHelper::LoadClassSSBFromDexCache: {
2334 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
2335 }
2336 case IntrinsicHelper::InitializeAndLoadClassSSB: {
2337 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
2338 }
Logan Chien75e4b602012-07-23 14:24:12 -07002339
2340 //==- High-level Array -------------------------------------------------==//
2341 case IntrinsicHelper::HLArrayGet: {
TDYa1275a26d442012-07-26 18:58:38 -07002342 return Expand_HLArrayGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002343 }
2344 case IntrinsicHelper::HLArrayGetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07002345 return Expand_HLArrayGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002346 }
2347 case IntrinsicHelper::HLArrayGetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07002348 return Expand_HLArrayGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002349 }
2350 case IntrinsicHelper::HLArrayGetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07002351 return Expand_HLArrayGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002352 }
2353 case IntrinsicHelper::HLArrayGetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07002354 return Expand_HLArrayGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002355 }
2356 case IntrinsicHelper::HLArrayGetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07002357 return Expand_HLArrayGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002358 }
2359 case IntrinsicHelper::HLArrayGetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07002360 return Expand_HLArrayGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002361 }
2362 case IntrinsicHelper::HLArrayGetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07002363 return Expand_HLArrayGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002364 }
2365 case IntrinsicHelper::HLArrayGetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07002366 return Expand_HLArrayGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002367 }
2368 case IntrinsicHelper::HLArrayPut: {
TDYa1275a26d442012-07-26 18:58:38 -07002369 Expand_HLArrayPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002370 return NULL;
2371 }
2372 case IntrinsicHelper::HLArrayPutBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07002373 Expand_HLArrayPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002374 return NULL;
2375 }
2376 case IntrinsicHelper::HLArrayPutByte: {
TDYa1275a26d442012-07-26 18:58:38 -07002377 Expand_HLArrayPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002378 return NULL;
2379 }
2380 case IntrinsicHelper::HLArrayPutChar: {
TDYa1275a26d442012-07-26 18:58:38 -07002381 Expand_HLArrayPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002382 return NULL;
2383 }
2384 case IntrinsicHelper::HLArrayPutShort: {
TDYa1275a26d442012-07-26 18:58:38 -07002385 Expand_HLArrayPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002386 return NULL;
2387 }
2388 case IntrinsicHelper::HLArrayPutFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07002389 Expand_HLArrayPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002390 return NULL;
2391 }
2392 case IntrinsicHelper::HLArrayPutWide: {
TDYa1275a26d442012-07-26 18:58:38 -07002393 Expand_HLArrayPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002394 return NULL;
2395 }
2396 case IntrinsicHelper::HLArrayPutDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07002397 Expand_HLArrayPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002398 return NULL;
2399 }
2400 case IntrinsicHelper::HLArrayPutObject: {
TDYa1275a26d442012-07-26 18:58:38 -07002401 Expand_HLArrayPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002402 return NULL;
2403 }
2404
2405 //==- High-level Instance ----------------------------------------------==//
2406 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07002407 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002408 }
2409 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07002410 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002411 }
2412 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07002413 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002414 }
2415 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07002416 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002417 }
2418 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07002419 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002420 }
2421 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07002422 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002423 }
2424 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07002425 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002426 }
2427 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07002428 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002429 }
2430 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07002431 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002432 }
2433 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07002434 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002435 return NULL;
2436 }
2437 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07002438 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002439 return NULL;
2440 }
2441 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07002442 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002443 return NULL;
2444 }
2445 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07002446 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002447 return NULL;
2448 }
2449 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07002450 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002451 return NULL;
2452 }
2453 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07002454 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002455 return NULL;
2456 }
2457 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07002458 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002459 return NULL;
2460 }
2461 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07002462 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002463 return NULL;
2464 }
2465 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07002466 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002467 return NULL;
2468 }
2469
2470 //==- High-level Invoke ------------------------------------------------==//
2471 case IntrinsicHelper::HLInvokeVoid: {
2472 UNIMPLEMENTED(FATAL);
2473 return NULL;
2474 }
2475 case IntrinsicHelper::HLInvokeObj: {
2476 UNIMPLEMENTED(FATAL);
2477 return NULL;
2478 }
2479 case IntrinsicHelper::HLInvokeInt: {
2480 UNIMPLEMENTED(FATAL);
2481 return NULL;
2482 }
2483 case IntrinsicHelper::HLInvokeFloat: {
2484 UNIMPLEMENTED(FATAL);
2485 return NULL;
2486 }
2487 case IntrinsicHelper::HLInvokeLong: {
2488 UNIMPLEMENTED(FATAL);
2489 return NULL;
2490 }
2491 case IntrinsicHelper::HLInvokeDouble: {
2492 UNIMPLEMENTED(FATAL);
2493 return NULL;
2494 }
2495
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002496 //==- Invoke -----------------------------------------------------------==//
2497 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
2498 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
2499 }
2500 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
2501 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
2502 }
2503 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
2504 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
2505 }
2506 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
2507 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
2508 }
2509 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
2510 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
2511 }
2512 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
2513 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
2514 }
2515 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
2516 return Expand_GetVirtualCalleeMethodObjAddrFast(
2517 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
2518 }
2519 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
2520 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
2521 }
2522 case IntrinsicHelper::InvokeRetVoid:
2523 case IntrinsicHelper::InvokeRetBoolean:
2524 case IntrinsicHelper::InvokeRetByte:
2525 case IntrinsicHelper::InvokeRetChar:
2526 case IntrinsicHelper::InvokeRetShort:
2527 case IntrinsicHelper::InvokeRetInt:
2528 case IntrinsicHelper::InvokeRetLong:
2529 case IntrinsicHelper::InvokeRetFloat:
2530 case IntrinsicHelper::InvokeRetDouble:
2531 case IntrinsicHelper::InvokeRetObject: {
2532 return Expand_Invoke(call_inst);
2533 }
Logan Chien75e4b602012-07-23 14:24:12 -07002534
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002535 //==- Math -------------------------------------------------------------==//
2536 case IntrinsicHelper::DivInt: {
2537 return Expand_DivRem(call_inst.getArgOperand(0),
2538 call_inst.getArgOperand(1),
2539 /* is_div */true, kInt);
2540 }
2541 case IntrinsicHelper::RemInt: {
2542 return Expand_DivRem(call_inst.getArgOperand(0),
2543 call_inst.getArgOperand(1),
2544 /* is_div */false, kInt);
2545 }
2546 case IntrinsicHelper::DivLong: {
2547 return Expand_DivRem(call_inst.getArgOperand(0),
2548 call_inst.getArgOperand(1),
2549 /* is_div */true, kLong);
2550 }
2551 case IntrinsicHelper::RemLong: {
2552 return Expand_DivRem(call_inst.getArgOperand(0),
2553 call_inst.getArgOperand(1),
2554 /* is_div */false, kLong);
2555 }
2556 case IntrinsicHelper::D2L: {
2557 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
2558 }
2559 case IntrinsicHelper::D2I: {
2560 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
2561 }
2562 case IntrinsicHelper::F2L: {
2563 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
2564 }
2565 case IntrinsicHelper::F2I: {
2566 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
2567 }
Logan Chien75e4b602012-07-23 14:24:12 -07002568
2569 //==- High-level Static ------------------------------------------------==//
2570 case IntrinsicHelper::HLSget: {
TDYa1275a26d442012-07-26 18:58:38 -07002571 return Expand_HLSget(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002572 }
2573 case IntrinsicHelper::HLSgetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07002574 return Expand_HLSget(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002575 }
2576 case IntrinsicHelper::HLSgetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07002577 return Expand_HLSget(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002578 }
2579 case IntrinsicHelper::HLSgetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07002580 return Expand_HLSget(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002581 }
2582 case IntrinsicHelper::HLSgetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07002583 return Expand_HLSget(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002584 }
2585 case IntrinsicHelper::HLSgetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07002586 return Expand_HLSget(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002587 }
2588 case IntrinsicHelper::HLSgetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07002589 return Expand_HLSget(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002590 }
2591 case IntrinsicHelper::HLSgetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07002592 return Expand_HLSget(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002593 }
2594 case IntrinsicHelper::HLSgetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07002595 return Expand_HLSget(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002596 }
2597 case IntrinsicHelper::HLSput: {
TDYa1275a26d442012-07-26 18:58:38 -07002598 Expand_HLSput(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002599 return NULL;
2600 }
2601 case IntrinsicHelper::HLSputBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07002602 Expand_HLSput(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002603 return NULL;
2604 }
2605 case IntrinsicHelper::HLSputByte: {
TDYa1275a26d442012-07-26 18:58:38 -07002606 Expand_HLSput(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002607 return NULL;
2608 }
2609 case IntrinsicHelper::HLSputChar: {
TDYa1275a26d442012-07-26 18:58:38 -07002610 Expand_HLSput(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002611 return NULL;
2612 }
2613 case IntrinsicHelper::HLSputShort: {
TDYa1275a26d442012-07-26 18:58:38 -07002614 Expand_HLSput(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002615 return NULL;
2616 }
2617 case IntrinsicHelper::HLSputFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07002618 Expand_HLSput(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002619 return NULL;
2620 }
2621 case IntrinsicHelper::HLSputWide: {
TDYa1275a26d442012-07-26 18:58:38 -07002622 Expand_HLSput(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002623 return NULL;
2624 }
2625 case IntrinsicHelper::HLSputDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07002626 Expand_HLSput(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002627 return NULL;
2628 }
2629 case IntrinsicHelper::HLSputObject: {
TDYa1275a26d442012-07-26 18:58:38 -07002630 Expand_HLSput(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002631 return NULL;
2632 }
2633
2634 //==- High-level Monitor -----------------------------------------------==//
2635 case IntrinsicHelper::MonitorEnter: {
2636 UNIMPLEMENTED(FATAL);
2637 return NULL;
2638 }
2639 case IntrinsicHelper::MonitorExit: {
2640 UNIMPLEMENTED(FATAL);
2641 return NULL;
2642 }
2643
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002644 //==- Shadow Frame -----------------------------------------------------==//
2645 case IntrinsicHelper::AllocaShadowFrame: {
2646 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
2647 return NULL;
2648 }
2649 case IntrinsicHelper::SetShadowFrameEntry: {
2650 Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
2651 call_inst.getArgOperand(1));
2652 return NULL;
2653 }
2654 case IntrinsicHelper::PopShadowFrame: {
2655 Expand_PopShadowFrame();
2656 return NULL;
2657 }
2658 case IntrinsicHelper::UpdateDexPC: {
2659 Expand_UpdateDexPC(call_inst.getArgOperand(0));
2660 return NULL;
2661 }
TDYa127a1b21852012-07-23 03:20:39 -07002662
Logan Chien75e4b602012-07-23 14:24:12 -07002663 //==- Comparison -------------------------------------------------------==//
2664 case IntrinsicHelper::CmplFloat:
2665 case IntrinsicHelper::CmplDouble: {
2666 return Expand_FPCompare(call_inst.getArgOperand(0),
2667 call_inst.getArgOperand(1),
2668 false);
2669 }
2670 case IntrinsicHelper::CmpgFloat:
2671 case IntrinsicHelper::CmpgDouble: {
2672 return Expand_FPCompare(call_inst.getArgOperand(0),
2673 call_inst.getArgOperand(1),
2674 true);
2675 }
2676 case IntrinsicHelper::CmpLong: {
2677 return Expand_LongCompare(call_inst.getArgOperand(0),
2678 call_inst.getArgOperand(1));
2679 }
TDYa127a1b21852012-07-23 03:20:39 -07002680
Logan Chien75e4b602012-07-23 14:24:12 -07002681 //==- Switch -----------------------------------------------------------==//
2682 case greenland::IntrinsicHelper::SparseSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07002683 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002684 return NULL;
2685 }
2686 case greenland::IntrinsicHelper::PackedSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07002687 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002688 return NULL;
2689 }
2690
2691 //==- Const ------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07002692 case greenland::IntrinsicHelper::ConstInt:
Logan Chien75e4b602012-07-23 14:24:12 -07002693 case greenland::IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002694 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07002695 }
2696 case greenland::IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002697 return irb_.CreateBitCast(call_inst.getArgOperand(0),
2698 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07002699 }
2700 case greenland::IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002701 return irb_.CreateBitCast(call_inst.getArgOperand(0),
2702 irb_.getJDoubleTy());
2703 }
2704 case greenland::IntrinsicHelper::ConstObj: {
2705 LOG(FATAL) << "ConstObj should not occur at all";
Logan Chien75e4b602012-07-23 14:24:12 -07002706 return NULL;
2707 }
2708
2709 //==- Method Info ------------------------------------------------------==//
2710 case greenland::IntrinsicHelper::MethodInfo: {
TDYa1275e869b62012-07-25 00:45:39 -07002711 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002712 return NULL;
2713 }
2714
2715 //==- Copy -------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07002716 case greenland::IntrinsicHelper::CopyInt:
2717 case greenland::IntrinsicHelper::CopyFloat:
2718 case greenland::IntrinsicHelper::CopyLong:
TDYa1275e869b62012-07-25 00:45:39 -07002719 case greenland::IntrinsicHelper::CopyDouble:
Logan Chien75e4b602012-07-23 14:24:12 -07002720 case greenland::IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002721 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07002722 }
2723
2724 //==- Shift ------------------------------------------------------------==//
2725 case greenland::IntrinsicHelper::SHLLong: {
2726 return Expand_IntegerShift(call_inst.getArgOperand(0),
2727 call_inst.getArgOperand(1),
2728 kIntegerSHL, kLong);
2729 }
2730 case greenland::IntrinsicHelper::SHRLong: {
2731 return Expand_IntegerShift(call_inst.getArgOperand(0),
2732 call_inst.getArgOperand(1),
2733 kIntegerSHR, kLong);
2734 }
2735 case greenland::IntrinsicHelper::USHRLong: {
2736 return Expand_IntegerShift(call_inst.getArgOperand(0),
2737 call_inst.getArgOperand(1),
2738 kIntegerUSHR, kLong);
2739 }
2740 case greenland::IntrinsicHelper::SHLInt: {
2741 return Expand_IntegerShift(call_inst.getArgOperand(0),
2742 call_inst.getArgOperand(1),
2743 kIntegerSHL, kInt);
2744 }
2745 case greenland::IntrinsicHelper::SHRInt: {
2746 return Expand_IntegerShift(call_inst.getArgOperand(0),
2747 call_inst.getArgOperand(1),
2748 kIntegerSHR, kInt);
2749 }
2750 case greenland::IntrinsicHelper::USHRInt: {
2751 return Expand_IntegerShift(call_inst.getArgOperand(0),
2752 call_inst.getArgOperand(1),
2753 kIntegerUSHR, kInt);
2754 }
2755
2756 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07002757 case IntrinsicHelper::IntToChar: {
2758 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
2759 irb_.getJIntTy());
2760 }
2761 case IntrinsicHelper::IntToShort: {
2762 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
2763 irb_.getJIntTy());
2764 }
2765 case IntrinsicHelper::IntToByte: {
2766 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
2767 irb_.getJIntTy());
2768 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002769
Logan Chien75e4b602012-07-23 14:24:12 -07002770 //==- Unknown Cases ----------------------------------------------------==//
2771 case IntrinsicHelper::MaxIntrinsicId:
2772 case IntrinsicHelper::UnknownId:
2773 //default:
2774 // NOTE: "default" is intentionally commented so that C/C++ compiler will
2775 // give some warning on unmatched cases.
2776 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002777 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002778 }
Logan Chien75e4b602012-07-23 14:24:12 -07002779 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002780 return NULL;
2781}
2782
2783} // anonymous namespace
2784
2785namespace art {
2786namespace compiler_llvm {
2787
2788llvm::FunctionPass*
2789CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
2790 return new GBCExpanderPass(intrinsic_helper, irb);
2791}
2792
2793} // namespace compiler_llvm
2794} // namespace art