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