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