blob: 014654285ecce5cf60cb1457d72be4e9bfe17415 [file] [log] [blame]
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ir_builder.h"
18#include "utils_llvm.h"
19
TDYa1275e869b62012-07-25 00:45:39 -070020#include "compiler.h"
Ian Rogers76ae4fe2013-02-27 16:03:41 -080021#include "intrinsic_helper.h"
Ian Rogers98573f92013-01-30 17:26:32 -080022#include "mirror/abstract_method.h"
23#include "mirror/array.h"
TDYa1275e869b62012-07-25 00:45:39 -070024#include "oat_compilation_unit.h"
Shih-wei Liao21d28f52012-06-12 05:55:00 -070025#include "thread.h"
TDYa1275e869b62012-07-25 00:45:39 -070026#include "verifier/method_verifier.h"
Shih-wei Liao21d28f52012-06-12 05:55:00 -070027
buzbee395116c2013-02-27 14:30:25 -080028#include "compiler/dex/compiler_ir.h"
29#include "compiler/dex/quick/codegen.h"
TDYa127920be7c2012-09-10 17:13:22 -070030using art::kMIRIgnoreNullCheck;
31using art::kMIRIgnoreRangeCheck;
32
Shih-wei Liao21d28f52012-06-12 05:55:00 -070033#include <llvm/ADT/STLExtras.h>
34#include <llvm/Intrinsics.h>
Logan Chiend36a2ac2012-08-04 00:37:30 +080035#include <llvm/Metadata.h>
Shih-wei Liao21d28f52012-06-12 05:55:00 -070036#include <llvm/Pass.h>
37#include <llvm/Support/CFG.h>
38#include <llvm/Support/InstIterator.h>
39
40#include <vector>
TDYa127aa558872012-08-16 05:11:07 -070041#include <map>
42#include <utility>
Shih-wei Liao21d28f52012-06-12 05:55:00 -070043
TDYa127920be7c2012-09-10 17:13:22 -070044using namespace art::compiler_llvm;
Shih-wei Liao21d28f52012-06-12 05:55:00 -070045
Ian Rogers76ae4fe2013-02-27 16:03:41 -080046using art::compiler_llvm::IntrinsicHelper;
Shih-wei Liao21d28f52012-06-12 05:55:00 -070047
Shih-wei Liaob2596522012-09-14 16:36:11 -070048namespace art {
buzbee26f10ee2012-12-21 11:16:29 -080049extern char RemapShorty(char shortyType);
Shih-wei Liaob2596522012-09-14 16:36:11 -070050};
51
Shih-wei Liao21d28f52012-06-12 05:55:00 -070052namespace {
53
54class GBCExpanderPass : public llvm::FunctionPass {
55 private:
56 const IntrinsicHelper& intrinsic_helper_;
57 IRBuilder& irb_;
58
59 llvm::LLVMContext& context_;
60 RuntimeSupportBuilder& rtb_;
61
62 private:
63 llvm::AllocaInst* shadow_frame_;
64 llvm::Value* old_shadow_frame_;
Shih-wei Liao21d28f52012-06-12 05:55:00 -070065
66 private:
TDYa127920be7c2012-09-10 17:13:22 -070067 art::Compiler* compiler_;
TDYa1275e869b62012-07-25 00:45:39 -070068
TDYa127920be7c2012-09-10 17:13:22 -070069 const art::DexFile* dex_file_;
70 const art::DexFile::CodeItem* code_item_;
TDYa1275e869b62012-07-25 00:45:39 -070071
TDYa127920be7c2012-09-10 17:13:22 -070072 art::OatCompilationUnit* oat_compilation_unit_;
TDYa1275e869b62012-07-25 00:45:39 -070073
74 uint32_t method_idx_;
75
76 llvm::Function* func_;
77
78 std::vector<llvm::BasicBlock*> basic_blocks_;
79
80 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
TDYa12755e5e6c2012-09-11 15:14:42 -070081 llvm::BasicBlock* current_bb_;
TDYa127aa558872012-08-16 05:11:07 -070082 std::map<llvm::BasicBlock*, std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> > >
83 landing_pad_phi_mapping_;
TDYa1275e869b62012-07-25 00:45:39 -070084 llvm::BasicBlock* basic_block_unwind_;
85
Logan Chien67645d82012-08-17 09:10:54 +080086 bool changed_;
87
TDYa1275e869b62012-07-25 00:45:39 -070088 private:
Shih-wei Liao21d28f52012-06-12 05:55:00 -070089 //----------------------------------------------------------------------------
Logan Chien75e4b602012-07-23 14:24:12 -070090 // Constant for GBC expansion
91 //----------------------------------------------------------------------------
92 enum IntegerShiftKind {
93 kIntegerSHL,
94 kIntegerSHR,
95 kIntegerUSHR,
96 };
97
98 private:
99 //----------------------------------------------------------------------------
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700100 // Helper function for GBC expansion
101 //----------------------------------------------------------------------------
102
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700103 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
104 llvm::CallInst& inst);
105
TDYa1275e869b62012-07-25 00:45:39 -0700106 uint64_t LV2UInt(llvm::Value* lv) {
107 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
108 }
109
110 int64_t LV2SInt(llvm::Value* lv) {
111 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
112 }
113
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700114 private:
115 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
116 // Refactor these utility functions from MethodCompiler to avoid forking.
117
Logan Chien67645d82012-08-17 09:10:54 +0800118 void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
119
120 void RewriteFunction();
121
122 void RewriteBasicBlock(llvm::BasicBlock* original_block);
123
124 void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
125 llvm::BasicBlock* new_basic_block);
126
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700127
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800128 // Sign or zero extend category 1 types < 32bits in size to 32bits.
129 llvm::Value* SignOrZeroExtendCat1Types(llvm::Value* value, JType jty);
130
131 // Truncate category 1 types from 32bits to the given JType size.
132 llvm::Value* TruncateCat1Types(llvm::Value* value, JType jty);
133
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700134 //----------------------------------------------------------------------------
135 // Dex cache code generation helper function
136 //----------------------------------------------------------------------------
TDYa127920be7c2012-09-10 17:13:22 -0700137 llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700138
139 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
140
141 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
142
143 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
144
145 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
146
147 //----------------------------------------------------------------------------
148 // Code generation helper function
149 //----------------------------------------------------------------------------
150 llvm::Value* EmitLoadMethodObjectAddr();
151
152 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
153
154 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
155
156 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
157 llvm::Value* this_addr);
158
159 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
160 llvm::Value* index_value,
161 JType elem_jty);
162
163 private:
164 //----------------------------------------------------------------------------
165 // Expand Greenland intrinsics
166 //----------------------------------------------------------------------------
167 void Expand_TestSuspend(llvm::CallInst& call_inst);
168
TDYa1279a129452012-07-19 03:10:08 -0700169 void Expand_MarkGCCard(llvm::CallInst& call_inst);
170
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700171 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
172
173 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
174
175 void Expand_LockObject(llvm::Value* obj);
176
177 void Expand_UnlockObject(llvm::Value* obj);
178
179 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
180 llvm::Value* index_value,
181 JType elem_jty);
182
183 void Expand_ArrayPut(llvm::Value* new_value,
184 llvm::Value* array_addr,
185 llvm::Value* index_value,
186 JType elem_jty);
187
188 void Expand_FilledNewArray(llvm::CallInst& call_inst);
189
190 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
191 llvm::Value* is_volatile_value,
192 llvm::Value* object_addr,
193 JType field_jty);
194
195 void Expand_IPutFast(llvm::Value* field_offset_value,
196 llvm::Value* is_volatile_value,
197 llvm::Value* object_addr,
198 llvm::Value* new_value,
199 JType field_jty);
200
201 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
202 llvm::Value* field_offset_value,
203 llvm::Value* is_volatile_value,
204 JType field_jty);
205
206 void Expand_SPutFast(llvm::Value* static_storage_addr,
207 llvm::Value* field_offset_value,
208 llvm::Value* is_volatile_value,
209 llvm::Value* new_value,
210 JType field_jty);
211
212 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
213
214 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
215
216 llvm::Value*
217 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
218
219 llvm::Value*
220 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
221 llvm::Value* this_addr);
222
223 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
224
TDYa1274ec8ccd2012-08-11 07:04:57 -0700225 llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700226
TDYa127ce4cc0d2012-11-18 16:59:53 -0800227 void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700228
TDYa1278e950c12012-11-02 09:58:19 -0700229 void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
230
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700231 void Expand_PopShadowFrame();
232
233 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
234
TDYa127a1b21852012-07-23 03:20:39 -0700235 //----------------------------------------------------------------------------
236 // Quick
237 //----------------------------------------------------------------------------
238
239 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
240 llvm::Value* src2_value,
241 bool gt_bias);
242
243 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
244
245 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
246 llvm::Value* cmp_lt);
247
TDYa127f71bf5a2012-07-29 20:09:52 -0700248 llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
TDYa1275a26d442012-07-26 18:58:38 -0700249 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
250
TDYa1275e869b62012-07-25 00:45:39 -0700251 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
252 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
253
TDYa1275a26d442012-07-26 18:58:38 -0700254 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
255 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
256
257 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
258 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
259
TDYa127f71bf5a2012-07-29 20:09:52 -0700260 llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
261 llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
262
263 void Expand_MonitorEnter(llvm::CallInst& call_inst);
264 void Expand_MonitorExit(llvm::CallInst& call_inst);
265
266 void Expand_HLCheckCast(llvm::CallInst& call_inst);
267 llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
268
269 llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
270
271 llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
272
273 llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
274 llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
275 llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
276 void Expand_HLFillArrayData(llvm::CallInst& call_inst);
277
278 llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
279 llvm::Value* array_length_value,
280 uint32_t type_idx,
281 bool is_filled_new_array);
282
283 llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -0700284 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -0700285 llvm::Value* this_addr,
286 uint32_t dex_pc,
287 bool is_fast_path);
288
TDYa1275e869b62012-07-25 00:45:39 -0700289 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
290
291 void EmitUpdateDexPC(uint32_t dex_pc);
292
293 void EmitGuard_DivZeroException(uint32_t dex_pc,
294 llvm::Value* denominator,
295 JType op_jty);
296
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +0100297 void EmitGuard_NullPointerException(uint32_t dex_pc, llvm::Value* object,
298 int opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -0700299
300 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
301 llvm::Value* array,
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +0100302 llvm::Value* index,
303 int opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -0700304
TDYa1275e869b62012-07-25 00:45:39 -0700305 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
306
307 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
308
309 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
310 const char* postfix);
311
312 int32_t GetTryItemOffset(uint32_t dex_pc);
313
314 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
315
316 llvm::BasicBlock* GetUnwindBasicBlock();
317
318 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
319
320 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
321
Logan Chien75e4b602012-07-23 14:24:12 -0700322 //----------------------------------------------------------------------------
323 // Expand Arithmetic Helper Intrinsics
324 //----------------------------------------------------------------------------
325
326 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
327 llvm::Value* src2_value,
328 IntegerShiftKind kind,
329 JType op_jty);
330
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700331 public:
332 static char ID;
333
334 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
335 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
Logan Chiene5b8f8b2012-08-13 11:45:05 +0800336 context_(irb.getContext()), rtb_(irb.Runtime()),
TDYa1278e950c12012-11-02 09:58:19 -0700337 shadow_frame_(NULL), old_shadow_frame_(NULL),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700338 compiler_(NULL), dex_file_(NULL), code_item_(NULL),
Logan Chien67645d82012-08-17 09:10:54 +0800339 oat_compilation_unit_(NULL), method_idx_(-1u), func_(NULL),
340 changed_(false)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700341 { }
342
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700343 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
TDYa127920be7c2012-09-10 17:13:22 -0700344 art::Compiler* compiler, art::OatCompilationUnit* oat_compilation_unit)
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700345 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
346 context_(irb.getContext()), rtb_(irb.Runtime()),
TDYa1278e950c12012-11-02 09:58:19 -0700347 shadow_frame_(NULL), old_shadow_frame_(NULL),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700348 compiler_(compiler),
349 dex_file_(oat_compilation_unit->GetDexFile()),
350 code_item_(oat_compilation_unit->GetCodeItem()),
351 oat_compilation_unit_(oat_compilation_unit),
352 method_idx_(oat_compilation_unit->GetDexMethodIndex()),
353 func_(NULL), changed_(false)
354 { }
355
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700356 bool runOnFunction(llvm::Function& func);
357
358 private:
Logan Chien67645d82012-08-17 09:10:54 +0800359 void InsertStackOverflowCheck(llvm::Function& func);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700360
361 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
362 llvm::CallInst& call_inst);
363
364};
365
366char GBCExpanderPass::ID = 0;
367
368bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700369 // Runtime support or stub
370 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
371 return false;
372 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700373
Logan Chien67645d82012-08-17 09:10:54 +0800374 // Setup rewrite context
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700375 shadow_frame_ = NULL;
376 old_shadow_frame_ = NULL;
TDYa1275e869b62012-07-25 00:45:39 -0700377 func_ = &func;
Logan Chien67645d82012-08-17 09:10:54 +0800378 changed_ = false; // Assume unchanged
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700379
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700380 basic_blocks_.resize(code_item_->insns_size_in_code_units_);
381 basic_block_landing_pads_.resize(code_item_->tries_size_, NULL);
382 basic_block_unwind_ = NULL;
383 for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
384 bb_iter != bb_end;
385 ++bb_iter) {
386 if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
387 continue;
388 }
389 uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
390 basic_blocks_[dex_pc] = bb_iter;
391 }
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700392
Logan Chien67645d82012-08-17 09:10:54 +0800393 // Insert stack overflow check
394 InsertStackOverflowCheck(func); // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700395
Logan Chien67645d82012-08-17 09:10:54 +0800396 // Rewrite the intrinsics
397 RewriteFunction();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700398
399 VERIFY_LLVM_FUNCTION(func);
400
Logan Chien67645d82012-08-17 09:10:54 +0800401 return changed_;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700402}
403
Logan Chien67645d82012-08-17 09:10:54 +0800404void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
405 llvm::BasicBlock* curr_basic_block = original_block;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700406
Logan Chien67645d82012-08-17 09:10:54 +0800407 llvm::BasicBlock::iterator inst_iter = original_block->begin();
408 llvm::BasicBlock::iterator inst_end = original_block->end();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700409
Logan Chien67645d82012-08-17 09:10:54 +0800410 while (inst_iter != inst_end) {
411 llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
412 IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700413
Logan Chien67645d82012-08-17 09:10:54 +0800414 if (call_inst) {
415 llvm::Function* callee_func = call_inst->getCalledFunction();
416 intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
417 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700418
Logan Chien67645d82012-08-17 09:10:54 +0800419 if (intr_id == IntrinsicHelper::UnknownId) {
420 // This is not intrinsic call. Skip this instruction.
421 ++inst_iter;
422 continue;
423 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700424
Logan Chien67645d82012-08-17 09:10:54 +0800425 // Rewrite the intrinsic and change the function
426 changed_ = true;
427 irb_.SetInsertPoint(inst_iter);
428
429 // Expand the intrinsic
430 if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
431 inst_iter->replaceAllUsesWith(new_value);
432 }
433
434 // Remove the old intrinsic call instruction
435 llvm::BasicBlock::iterator old_inst = inst_iter++;
436 old_inst->eraseFromParent();
437
438 // Splice the instruction to the new basic block
439 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
440 if (next_basic_block != curr_basic_block) {
441 next_basic_block->getInstList().splice(
442 irb_.GetInsertPoint(), curr_basic_block->getInstList(),
443 inst_iter, inst_end);
444 curr_basic_block = next_basic_block;
445 inst_end = curr_basic_block->end();
446 }
447 }
448}
449
450
451void GBCExpanderPass::RewriteFunction() {
452 size_t num_basic_blocks = func_->getBasicBlockList().size();
453 // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
454 // because we will create new basic block while expanding the intrinsics.
455 // We only want to iterate through the input basic blocks.
456
TDYa127aa558872012-08-16 05:11:07 -0700457 landing_pad_phi_mapping_.clear();
458
Logan Chien67645d82012-08-17 09:10:54 +0800459 for (llvm::Function::iterator bb_iter = func_->begin();
460 num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
Shih-wei Liao627d8c42012-08-24 08:31:18 -0700461 // Set insert point to current basic block.
462 irb_.SetInsertPoint(bb_iter);
Logan Chien67645d82012-08-17 09:10:54 +0800463
TDYa12755e5e6c2012-09-11 15:14:42 -0700464 current_bb_ = bb_iter;
TDYa127aa558872012-08-16 05:11:07 -0700465
Logan Chien67645d82012-08-17 09:10:54 +0800466 // Rewrite the basic block
467 RewriteBasicBlock(bb_iter);
468
469 // Update the phi-instructions in the successor basic block
470 llvm::BasicBlock* last_block = irb_.GetInsertBlock();
471 if (last_block != bb_iter) {
472 UpdatePhiInstruction(bb_iter, last_block);
473 }
474 }
TDYa127aa558872012-08-16 05:11:07 -0700475
476 typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
477 HandlerPHIMap handler_phi;
478 // Iterate every used landing pad basic block
479 for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
480 llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
481 if (lbb == NULL) {
482 continue;
483 }
484
485 llvm::TerminatorInst* term_inst = lbb->getTerminator();
486 std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> >& rewrite_pair
487 = landing_pad_phi_mapping_[lbb];
488 irb_.SetInsertPoint(lbb->begin());
489
490 // Iterate every succeeding basic block (catch block)
491 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
492 succ_iter != succ_end; ++succ_iter) {
493 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
494
495 // Iterate every phi instructions in the succeeding basic block
496 for (llvm::BasicBlock::iterator
497 inst_iter = succ_basic_block->begin(),
498 inst_end = succ_basic_block->end();
499 inst_iter != inst_end; ++inst_iter) {
500 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
501
502 if (!phi) {
503 break; // Meet non-phi instruction. Done.
504 }
505
506 if (handler_phi[phi] == NULL) {
507 handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
508 }
509
510 // Create new_phi in landing pad
511 llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
512 // Insert all incoming value into new_phi by rewrite_pair
513 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
514 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
515 llvm::BasicBlock* new_bb = rewrite_pair[j].second;
516 new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
517 }
518 // Delete all incoming value from phi by rewrite_pair
519 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
520 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
521 int old_bb_idx = phi->getBasicBlockIndex(old_bb);
522 if (old_bb_idx >= 0) {
523 phi->removeIncomingValue(old_bb_idx, false);
524 }
525 }
526 // Insert new_phi into new handler phi
527 handler_phi[phi]->addIncoming(new_phi, lbb);
528 }
529 }
530 }
531
532 // Replace all handler phi
533 // We can't just use the old handler phi, because some exception edges will disappear after we
534 // compute fast-path.
535 for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
536 llvm::PHINode* old_phi = it->first;
537 llvm::PHINode* new_phi = it->second;
538 new_phi->insertBefore(old_phi);
539 old_phi->replaceAllUsesWith(new_phi);
540 old_phi->eraseFromParent();
541 }
Logan Chien67645d82012-08-17 09:10:54 +0800542}
543
544void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
545 llvm::BasicBlock* new_basic_block) {
546 llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
547
548 if (!term_inst) {
549 return; // No terminating instruction in new_basic_block. Nothing to do.
550 }
551
552 // Iterate every succeeding basic 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) {
565 break; // Meet non-phi instruction. Done.
566 }
567
568 // Update the incoming block of this phi instruction
569 for (llvm::PHINode::block_iterator
570 ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
571 ibb_iter != ibb_end; ++ibb_iter) {
572 if (*ibb_iter == old_basic_block) {
573 *ibb_iter = new_basic_block;
574 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700575 }
576 }
577 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700578}
579
580llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
581 llvm::CallInst& inst) {
582 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
583 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
584 // function, therefore only called function is needed to change.
585 unsigned num_args = inst.getNumArgOperands();
586
587 if (num_args <= 0) {
588 return irb_.CreateCall(irb_.GetRuntime(rt));
589 } else {
590 std::vector<llvm::Value*> args;
591 for (unsigned i = 0; i < num_args; i++) {
592 args.push_back(inst.getArgOperand(i));
593 }
594
595 return irb_.CreateCall(irb_.GetRuntime(rt), args);
596 }
597}
598
Logan Chien67645d82012-08-17 09:10:54 +0800599void
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700600GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
601 llvm::Function* func = first_non_alloca->getParent()->getParent();
602 llvm::Module* module = func->getParent();
603
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700604 // Call llvm intrinsic function to get frame address.
605 llvm::Function* frameaddress =
606 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
607
608 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
609 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
610
611 // Cast i8* to int
612 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
613
614 // Get thread.stack_end_
615 llvm::Value* stack_end =
TDYa127920be7c2012-09-10 17:13:22 -0700616 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700617 irb_.getPtrEquivIntTy(),
618 kTBAARuntimeInfo);
619
620 // Check the frame address < thread.stack_end_ ?
621 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
622
623 llvm::BasicBlock* block_exception =
624 llvm::BasicBlock::Create(context_, "stack_overflow", func);
625
626 llvm::BasicBlock* block_continue =
627 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
628
629 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
630
631 // If stack overflow, throw exception.
632 irb_.SetInsertPoint(block_exception);
633 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
634
635 // Unwind.
636 llvm::Type* ret_type = func->getReturnType();
637 if (ret_type->isVoidTy()) {
638 irb_.CreateRetVoid();
639 } else {
640 // The return value is ignored when there's an exception. MethodCompiler
641 // returns zero value under the the corresponding return type in this case.
642 // GBCExpander returns LLVM undef value here for brevity
643 irb_.CreateRet(llvm::UndefValue::get(ret_type));
644 }
645
646 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700647}
648
TDYa127920be7c2012-09-10 17:13:22 -0700649llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700650 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
651
652 return irb_.LoadFromObjectOffset(method_object_addr,
653 offset.Int32Value(),
654 irb_.getJObjectTy(),
655 kTBAAConstJObject);
656}
657
658llvm::Value*
659GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
660 llvm::Value* static_storage_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800661 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700662
663 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
664
665 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
666}
667
668llvm::Value*
669GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
670 llvm::Value* resolved_type_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800671 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedTypesOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700672
673 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
674
675 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
676}
677
678llvm::Value* GBCExpanderPass::
679EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
680 llvm::Value* resolved_method_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800681 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedMethodsOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700682
683 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
684
685 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
686}
687
688llvm::Value* GBCExpanderPass::
689EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
690 llvm::Value* string_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800691 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheStringsOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700692
693 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
694
695 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
696}
697
698llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
699 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
700 return parent_func->arg_begin();
701}
702
703llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
704 // Load array length
705 return irb_.LoadFromObjectOffset(array,
Ian Rogers98573f92013-01-30 17:26:32 -0800706 art::mirror::Array::LengthOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700707 irb_.getJIntTy(),
708 kTBAAConstJObject);
709
710}
711
712llvm::Value*
713GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
714 llvm::Value* callee_method_object_field_addr =
715 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
716
TDYa127ce4cc0d2012-11-18 16:59:53 -0800717 return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700718}
719
720llvm::Value* GBCExpanderPass::
721EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
722 // Load class object of *this* pointer
723 llvm::Value* class_object_addr =
724 irb_.LoadFromObjectOffset(this_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800725 art::mirror::Object::ClassOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700726 irb_.getJObjectTy(),
727 kTBAAConstJObject);
728
729 // Load vtable address
730 llvm::Value* vtable_addr =
731 irb_.LoadFromObjectOffset(class_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800732 art::mirror::Class::VTableOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700733 irb_.getJObjectTy(),
734 kTBAAConstJObject);
735
736 // Load callee method object
737 llvm::Value* vtable_idx_value =
738 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
739
740 llvm::Value* method_field_addr =
741 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
742
743 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
744}
745
746// Emit Array GetElementPtr
747llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
748 llvm::Value* index_value,
749 JType elem_jty) {
750
751 int data_offset;
752 if (elem_jty == kLong || elem_jty == kDouble ||
Ian Rogers98573f92013-01-30 17:26:32 -0800753 (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::mirror::Object*))) {
754 data_offset = art::mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700755 } else {
Ian Rogers98573f92013-01-30 17:26:32 -0800756 data_offset = art::mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700757 }
758
759 llvm::Constant* data_offset_value =
760 irb_.getPtrEquivInt(data_offset);
761
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800762 llvm::Type* elem_type = irb_.getJType(elem_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700763
764 llvm::Value* array_data_addr =
765 irb_.CreatePtrDisp(array_addr, data_offset_value,
766 elem_type->getPointerTo());
767
768 return irb_.CreateGEP(array_data_addr, index_value);
769}
770
771void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
TDYa127ce4cc0d2012-11-18 16:59:53 -0800772 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
773
774 llvm::Value* suspend_count =
775 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
776 irb_.getInt16Ty(),
777 kTBAARuntimeInfo);
778 llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
779
780 llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
781 llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
782
783 irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
784
785 irb_.SetInsertPoint(basic_block_suspend);
786 if (dex_pc != art::DexFile::kDexNoIndex) {
787 EmitUpdateDexPC(dex_pc);
788 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700789 irb_.Runtime().EmitTestSuspend();
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800790
791 llvm::BasicBlock* basic_block_exception = CreateBasicBlockWithDexPC(dex_pc, "exception");
792 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
793 irb_.CreateCondBr(exception_pending, basic_block_exception, basic_block_cont, kUnlikely);
794
795 irb_.SetInsertPoint(basic_block_exception);
796 llvm::Type* ret_type = call_inst.getParent()->getParent()->getReturnType();
797 if (ret_type->isVoidTy()) {
798 irb_.CreateRetVoid();
799 } else {
800 // The return value is ignored when there's an exception.
801 irb_.CreateRet(llvm::UndefValue::get(ret_type));
802 }
TDYa127ce4cc0d2012-11-18 16:59:53 -0800803
804 irb_.SetInsertPoint(basic_block_cont);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700805 return;
806}
807
TDYa1279a129452012-07-19 03:10:08 -0700808void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1279a129452012-07-19 03:10:08 -0700809 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700810 return;
811}
812
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700813llvm::Value*
814GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
815 uint32_t string_idx =
816 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
817
818 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
819
TDYa127ce4cc0d2012-11-18 16:59:53 -0800820 return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700821}
822
823llvm::Value*
824GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
825 uint32_t type_idx =
826 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
827
828 llvm::Value* type_field_addr =
829 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
830
TDYa127ce4cc0d2012-11-18 16:59:53 -0800831 return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700832}
833
834void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700835 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700836 return;
837}
838
839void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700840 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700841 return;
842}
843
844llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
845 llvm::Value* index_value,
846 JType elem_jty) {
847 llvm::Value* array_elem_addr =
848 EmitArrayGEP(array_addr, index_value, elem_jty);
849
850 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
851}
852
853void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
854 llvm::Value* array_addr,
855 llvm::Value* index_value,
856 JType elem_jty) {
857 llvm::Value* array_elem_addr =
858 EmitArrayGEP(array_addr, index_value, elem_jty);
859
860 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
861
862 return;
863}
864
865void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
866 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
867 llvm::Value* array = call_inst.getArgOperand(0);
868
869 uint32_t element_jty =
870 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
871
872 DCHECK(call_inst.getNumArgOperands() > 2);
873 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
874
875 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
876
877 uint32_t alignment;
878 llvm::Constant* elem_size;
879 llvm::PointerType* field_type;
880
881 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
882 // as the element, thus we are only checking 2 cases: primitive int and
883 // non-primitive type.
884 if (is_elem_int_ty) {
885 alignment = sizeof(int32_t);
886 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
887 field_type = irb_.getJIntTy()->getPointerTo();
888 } else {
889 alignment = irb_.getSizeOfPtrEquivInt();
890 elem_size = irb_.getSizeOfPtrEquivIntValue();
891 field_type = irb_.getJObjectTy()->getPointerTo();
892 }
893
894 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -0800895 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700896
897 llvm::Value* data_field_addr =
898 irb_.CreatePtrDisp(array, data_field_offset, field_type);
899
900 for (unsigned i = 0; i < num_elements; ++i) {
901 // Values to fill the array begin at the 3rd argument
902 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
903
904 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
905
906 data_field_addr =
907 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
908 }
909
910 return;
911}
912
913llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
914 llvm::Value* /*is_volatile_value*/,
915 llvm::Value* object_addr,
916 JType field_jty) {
917 int field_offset =
918 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
919
920 DCHECK_GE(field_offset, 0);
921
922 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800923 irb_.getJType(field_jty)->getPointerTo();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700924
925 field_offset_value = irb_.getPtrEquivInt(field_offset);
926
927 llvm::Value* field_addr =
928 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
929
930 // TODO: Check is_volatile. We need to generate atomic load instruction
931 // when is_volatile is true.
932 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
933}
934
935void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
936 llvm::Value* /* is_volatile_value */,
937 llvm::Value* object_addr,
938 llvm::Value* new_value,
939 JType field_jty) {
940 int field_offset =
941 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
942
943 DCHECK_GE(field_offset, 0);
944
945 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800946 irb_.getJType(field_jty)->getPointerTo();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700947
948 field_offset_value = irb_.getPtrEquivInt(field_offset);
949
950 llvm::Value* field_addr =
951 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
952
953 // TODO: Check is_volatile. We need to generate atomic store instruction
954 // when is_volatile is true.
955 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
956
957 return;
958}
959
960llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
961 llvm::Value* field_offset_value,
962 llvm::Value* /*is_volatile_value*/,
963 JType field_jty) {
964 int field_offset =
965 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
966
967 DCHECK_GE(field_offset, 0);
968
969 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
970
971 llvm::Value* static_field_addr =
972 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800973 irb_.getJType(field_jty)->getPointerTo());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700974
975 // TODO: Check is_volatile. We need to generate atomic store instruction
976 // when is_volatile is true.
977 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
978}
979
980void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
981 llvm::Value* field_offset_value,
982 llvm::Value* /* is_volatile_value */,
983 llvm::Value* new_value,
984 JType field_jty) {
985 int field_offset =
986 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
987
988 DCHECK_GE(field_offset, 0);
989
990 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
991
992 llvm::Value* static_field_addr =
993 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800994 irb_.getJType(field_jty)->getPointerTo());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700995
996 // TODO: Check is_volatile. We need to generate atomic store instruction
997 // when is_volatile is true.
998 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
999
1000 return;
1001}
1002
1003llvm::Value*
1004GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
1005 return irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001006 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001007 irb_.getJObjectTy(),
1008 kTBAAConstJObject);
1009}
1010
1011llvm::Value*
1012GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
1013 uint32_t type_idx =
1014 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
1015
1016 llvm::Value* storage_field_addr =
1017 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1018
TDYa127ce4cc0d2012-11-18 16:59:53 -08001019 return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001020}
1021
1022llvm::Value*
1023GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
1024 uint32_t callee_method_idx =
1025 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
1026
1027 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
1028}
1029
1030llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
1031 llvm::Value* vtable_idx_value,
1032 llvm::Value* this_addr) {
1033 int vtable_idx =
1034 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
1035
1036 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
1037}
1038
1039llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
1040 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
1041 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
1042 unsigned num_args = call_inst.getNumArgOperands();
1043 llvm::Type* ret_type = call_inst.getType();
1044
1045 // Determine the function type of the callee method
1046 std::vector<llvm::Type*> args_type;
1047 std::vector<llvm::Value*> args;
1048 for (unsigned i = 0; i < num_args; i++) {
1049 args.push_back(call_inst.getArgOperand(i));
1050 args_type.push_back(args[i]->getType());
1051 }
1052
1053 llvm::FunctionType* callee_method_type =
1054 llvm::FunctionType::get(ret_type, args_type, false);
1055
1056 llvm::Value* code_addr =
1057 irb_.LoadFromObjectOffset(callee_method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001058 art::mirror::AbstractMethod::GetCodeOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001059 callee_method_type->getPointerTo(),
TDYa127ce4cc0d2012-11-18 16:59:53 -08001060 kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001061
1062 // Invoke callee
1063 llvm::Value* retval = irb_.CreateCall(code_addr, args);
1064
1065 return retval;
1066}
1067
TDYa1274ec8ccd2012-08-11 07:04:57 -07001068llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001069 bool is_div, JType op_jty) {
TDYa1274ec8ccd2012-08-11 07:04:57 -07001070 llvm::Value* dividend = call_inst.getArgOperand(0);
1071 llvm::Value* divisor = call_inst.getArgOperand(1);
TDYa1274ec8ccd2012-08-11 07:04:57 -07001072 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1073 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001074 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
1075
1076 // Check the special case: MININT / -1 = MININT
1077 // That case will cause overflow, which is undefined behavior in llvm.
1078 // So we check the divisor is -1 or not, if the divisor is -1, we do
1079 // the special path to avoid undefined behavior.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001080 llvm::Type* op_type = irb_.getJType(op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001081 llvm::Value* zero = irb_.getJZero(op_jty);
1082 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
1083
TDYa1275e869b62012-07-25 00:45:39 -07001084 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001085 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1086 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1087 llvm::BasicBlock* neg_one_cont =
1088 llvm::BasicBlock::Create(context_, "", parent);
1089
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001090 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
1091 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
1092
1093 // If divisor == -1
1094 irb_.SetInsertPoint(eq_neg_one);
1095 llvm::Value* eq_result;
1096 if (is_div) {
1097 // We can just change from "dividend div -1" to "neg dividend". The sub
1098 // don't care the sign/unsigned because of two's complement representation.
1099 // And the behavior is what we want:
1100 // -(2^n) (2^n)-1
1101 // MININT < k <= MAXINT -> mul k -1 = -k
1102 // MININT == k -> mul k -1 = k
1103 //
1104 // LLVM use sub to represent 'neg'
1105 eq_result = irb_.CreateSub(zero, dividend);
1106 } else {
1107 // Everything modulo -1 will be 0.
1108 eq_result = zero;
1109 }
1110 irb_.CreateBr(neg_one_cont);
1111
1112 // If divisor != -1, just do the division.
1113 irb_.SetInsertPoint(ne_neg_one);
1114 llvm::Value* ne_result;
1115 if (is_div) {
1116 ne_result = irb_.CreateSDiv(dividend, divisor);
1117 } else {
1118 ne_result = irb_.CreateSRem(dividend, divisor);
1119 }
1120 irb_.CreateBr(neg_one_cont);
1121
1122 irb_.SetInsertPoint(neg_one_cont);
1123 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
1124 result->addIncoming(eq_result, eq_neg_one);
1125 result->addIncoming(ne_result, ne_neg_one);
1126
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001127 return result;
1128}
1129
TDYa127ce4cc0d2012-11-18 16:59:53 -08001130void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001131 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
1132 // MethodCompiler::EmitPushShadowFrame
TDYa1278e950c12012-11-02 09:58:19 -07001133 uint16_t num_vregs =
1134 llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001135
1136 llvm::StructType* shadow_frame_type =
TDYa127ce4cc0d2012-11-18 16:59:53 -08001137 irb_.getShadowFrameTy(num_vregs);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001138
Sebastien Hertz77209702013-02-28 16:34:13 +01001139 // Create allocas at the start of entry block.
1140 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1141 llvm::BasicBlock* entry_block = &func_->front();
1142 irb_.SetInsertPoint(&entry_block->front());
1143
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001144 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
1145
1146 // Alloca a pointer to old shadow frame
1147 old_shadow_frame_ =
1148 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
1149
Sebastien Hertz77209702013-02-28 16:34:13 +01001150 irb_.restoreIP(irb_ip_original);
1151
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001152 // Push the shadow frame
1153 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1154
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001155 llvm::Value* shadow_frame_upcast =
1156 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1157
1158 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1159 method_object_addr,
TDYa1278e950c12012-11-02 09:58:19 -07001160 num_vregs);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001161
1162 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1163
1164 return;
1165}
1166
TDYa1278e950c12012-11-02 09:58:19 -07001167void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
1168 llvm::Value* value) {
1169 DCHECK(shadow_frame_ != NULL);
1170
1171 llvm::Value* gep_index[] = {
1172 irb_.getInt32(0), // No pointer displacement
TDYa127ce4cc0d2012-11-18 16:59:53 -08001173 irb_.getInt32(1), // VRegs
TDYa1278e950c12012-11-02 09:58:19 -07001174 entry_idx // Pointer field
1175 };
1176
1177 llvm::Value* vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1178
1179 irb_.CreateStore(value,
1180 irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
1181 kTBAAShadowFrame);
1182 return;
1183}
1184
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001185void GBCExpanderPass::Expand_PopShadowFrame() {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001186 if (old_shadow_frame_ == NULL) {
1187 return;
1188 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001189 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1190 return;
1191}
1192
1193void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1194 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07001195 art::ShadowFrame::DexPCOffset(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001196 dex_pc_value,
1197 kTBAAShadowFrame);
1198 return;
1199}
1200
Logan Chien67645d82012-08-17 09:10:54 +08001201void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
jeffhao40283122013-01-15 13:15:24 -08001202 // All alloca instructions are generated in the first basic block of the
1203 // function, and there are no alloca instructions after the first non-alloca
1204 // instruction.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001205
Logan Chien67645d82012-08-17 09:10:54 +08001206 llvm::BasicBlock* first_basic_block = &func.front();
1207
1208 // Look for first non-alloca instruction
1209 llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001210 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1211 ++first_non_alloca;
1212 }
1213
Logan Chien67645d82012-08-17 09:10:54 +08001214 irb_.SetInsertPoint(first_non_alloca);
1215
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001216 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1217 // alloca instructions)
Logan Chien67645d82012-08-17 09:10:54 +08001218 EmitStackOverflowCheck(&*first_non_alloca);
1219
TDYa127890ea892012-08-22 10:49:42 -07001220 irb_.Runtime().EmitTestSuspend();
TDYa127890ea892012-08-22 10:49:42 -07001221
Logan Chien67645d82012-08-17 09:10:54 +08001222 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
1223 if (next_basic_block != first_basic_block) {
1224 // Splice the rest of the instruction to the continuing basic block
1225 next_basic_block->getInstList().splice(
1226 irb_.GetInsertPoint(), first_basic_block->getInstList(),
1227 first_non_alloca, first_basic_block->end());
1228
1229 // Rewrite the basic block
1230 RewriteBasicBlock(next_basic_block);
1231
1232 // Update the phi-instructions in the successor basic block
1233 UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
1234 }
1235
1236 // We have changed the basic block
1237 changed_ = true;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001238}
1239
TDYa1275e869b62012-07-25 00:45:39 -07001240// ==== High-level intrinsic expander ==========================================
1241
TDYa127a1b21852012-07-23 03:20:39 -07001242llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1243 llvm::Value* src2_value,
1244 bool gt_bias) {
1245 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1246 llvm::Value* cmp_lt;
1247
1248 if (gt_bias) {
1249 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1250 } else {
1251 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1252 }
1253
1254 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1255}
1256
1257llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1258 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1259 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1260
1261 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1262}
1263
1264llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1265 llvm::Value* cmp_lt) {
1266
1267 llvm::Constant* zero = irb_.getJInt(0);
1268 llvm::Constant* pos1 = irb_.getJInt(1);
1269 llvm::Constant* neg1 = irb_.getJInt(-1);
1270
1271 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1272 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1273
1274 return result_eq;
1275}
1276
Logan Chien75e4b602012-07-23 14:24:12 -07001277llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1278 llvm::Value* src2_value,
1279 IntegerShiftKind kind,
1280 JType op_jty) {
1281 DCHECK(op_jty == kInt || op_jty == kLong);
1282
1283 // Mask and zero-extend RHS properly
1284 if (op_jty == kInt) {
1285 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1286 } else {
1287 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1288 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1289 }
1290
1291 // Create integer shift llvm instruction
1292 switch (kind) {
1293 case kIntegerSHL:
1294 return irb_.CreateShl(src1_value, src2_value);
1295
1296 case kIntegerSHR:
1297 return irb_.CreateAShr(src1_value, src2_value);
1298
1299 case kIntegerUSHR:
1300 return irb_.CreateLShr(src1_value, src2_value);
1301
1302 default:
1303 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1304 return NULL;
1305 }
1306}
1307
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001308llvm::Value* GBCExpanderPass::SignOrZeroExtendCat1Types(llvm::Value* value, JType jty) {
1309 switch (jty) {
1310 case kBoolean:
1311 case kChar:
1312 return irb_.CreateZExt(value, irb_.getJType(kInt));
1313 case kByte:
1314 case kShort:
1315 return irb_.CreateSExt(value, irb_.getJType(kInt));
1316 case kVoid:
1317 case kInt:
1318 case kLong:
1319 case kFloat:
1320 case kDouble:
1321 case kObject:
1322 return value; // Nothing to do.
1323 default:
1324 LOG(FATAL) << "Unknown java type: " << jty;
1325 return NULL;
1326 }
1327}
1328
1329llvm::Value* GBCExpanderPass::TruncateCat1Types(llvm::Value* value, JType jty) {
1330 switch (jty) {
1331 case kBoolean:
1332 case kChar:
1333 case kByte:
1334 case kShort:
1335 return irb_.CreateTrunc(value, irb_.getJType(jty));
1336 case kVoid:
1337 case kInt:
1338 case kLong:
1339 case kFloat:
1340 case kDouble:
1341 case kObject:
1342 return value; // Nothing to do.
1343 default:
1344 LOG(FATAL) << "Unknown java type: " << jty;
1345 return NULL;
1346 }
1347}
1348
TDYa1275a26d442012-07-26 18:58:38 -07001349llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1350 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001351 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1352 llvm::Value* array_addr = call_inst.getArgOperand(1);
1353 llvm::Value* index_value = call_inst.getArgOperand(2);
TDYa127920be7c2012-09-10 17:13:22 -07001354 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275a26d442012-07-26 18:58:38 -07001355
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001356 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
1357 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
1358 opt_flags);
TDYa1275a26d442012-07-26 18:58:38 -07001359
1360 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1361
1362 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1363
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001364 return SignOrZeroExtendCat1Types(array_elem_value, elem_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001365}
1366
1367
1368void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1369 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001370 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1371 llvm::Value* new_value = call_inst.getArgOperand(1);
1372 llvm::Value* array_addr = call_inst.getArgOperand(2);
1373 llvm::Value* index_value = call_inst.getArgOperand(3);
TDYa127920be7c2012-09-10 17:13:22 -07001374 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275a26d442012-07-26 18:58:38 -07001375
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001376 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
1377 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
1378 opt_flags);
TDYa1275a26d442012-07-26 18:58:38 -07001379
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001380 new_value = TruncateCat1Types(new_value, elem_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001381
1382 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1383
1384 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
1385 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
1386
1387 irb_.CreateCall2(runtime_func, new_value, array_addr);
1388
1389 EmitGuard_ExceptionLandingPad(dex_pc);
1390
1391 EmitMarkGCCard(new_value, array_addr);
1392 }
1393
1394 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1395
1396 return;
1397}
1398
TDYa1275e869b62012-07-25 00:45:39 -07001399llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1400 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001401 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1402 llvm::Value* object_addr = call_inst.getArgOperand(1);
1403 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
TDYa127920be7c2012-09-10 17:13:22 -07001404 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001405
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001406 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -07001407
1408 llvm::Value* field_value;
1409
1410 int field_offset;
1411 bool is_volatile;
1412 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1413 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
1414
1415 if (!is_fast_path) {
1416 llvm::Function* runtime_func;
1417
1418 if (field_jty == kObject) {
1419 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1420 } else if (field_jty == kLong || field_jty == kDouble) {
1421 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1422 } else {
1423 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1424 }
1425
1426 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1427
1428 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1429
1430 EmitUpdateDexPC(dex_pc);
1431
1432 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1433 method_object_addr, object_addr);
1434
1435 EmitGuard_ExceptionLandingPad(dex_pc);
1436
1437 } else {
1438 DCHECK_GE(field_offset, 0);
1439
1440 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001441 irb_.getJType(field_jty)->getPointerTo();
TDYa1275e869b62012-07-25 00:45:39 -07001442
1443 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1444
1445 llvm::Value* field_addr =
1446 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1447
1448 // TODO: Check is_volatile. We need to generate atomic load instruction
1449 // when is_volatile is true.
1450 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001451 field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
TDYa1275e869b62012-07-25 00:45:39 -07001452 }
1453
1454 if (field_jty == kFloat || field_jty == kDouble) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001455 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty));
TDYa1275e869b62012-07-25 00:45:39 -07001456 }
1457
1458 return field_value;
1459}
1460
1461void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1462 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001463 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001464 llvm::Value* new_value = call_inst.getArgOperand(1);
1465 llvm::Value* object_addr = call_inst.getArgOperand(2);
TDYa1275e869b62012-07-25 00:45:39 -07001466 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
TDYa127920be7c2012-09-10 17:13:22 -07001467 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001468
1469 if (field_jty == kFloat || field_jty == kDouble) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001470 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
TDYa1275e869b62012-07-25 00:45:39 -07001471 }
1472
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001473 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -07001474
1475 int field_offset;
1476 bool is_volatile;
1477 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1478 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
1479
1480 if (!is_fast_path) {
1481 llvm::Function* runtime_func;
1482
1483 if (field_jty == kObject) {
1484 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1485 } else if (field_jty == kLong || field_jty == kDouble) {
1486 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1487 } else {
1488 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1489 }
1490
1491 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1492
1493 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1494
1495 EmitUpdateDexPC(dex_pc);
1496
1497 irb_.CreateCall4(runtime_func, field_idx_value,
1498 method_object_addr, object_addr, new_value);
1499
1500 EmitGuard_ExceptionLandingPad(dex_pc);
1501
1502 } else {
1503 DCHECK_GE(field_offset, 0);
1504
1505 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001506 irb_.getJType(field_jty)->getPointerTo();
TDYa1275e869b62012-07-25 00:45:39 -07001507
1508 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1509
1510 llvm::Value* field_addr =
1511 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1512
1513 // TODO: Check is_volatile. We need to generate atomic store instruction
1514 // when is_volatile is true.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001515 new_value = TruncateCat1Types(new_value, field_jty);
TDYa1275e869b62012-07-25 00:45:39 -07001516 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1517
1518 if (field_jty == kObject) { // If put an object, mark the GC card table.
1519 EmitMarkGCCard(new_value, object_addr);
1520 }
1521 }
1522
1523 return;
1524}
1525
TDYa127f71bf5a2012-07-29 20:09:52 -07001526llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1527 uint32_t type_idx) {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001528 if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001529 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1530
1531 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1532
1533 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1534
1535 llvm::Function* runtime_func =
1536 irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
1537
1538 EmitUpdateDexPC(dex_pc);
1539
1540 llvm::Value* type_object_addr =
1541 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1542
1543 EmitGuard_ExceptionLandingPad(dex_pc);
1544
1545 return type_object_addr;
1546
1547 } else {
1548 // Try to load the class (type) object from the test cache.
1549 llvm::Value* type_field_addr =
1550 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1551
TDYa127ce4cc0d2012-11-18 16:59:53 -08001552 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001553
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001554 if (compiler_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001555 return type_object_addr;
1556 }
1557
1558 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1559
1560 // Test whether class (type) object is in the dex cache or not
1561 llvm::Value* equal_null =
1562 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1563
1564 llvm::BasicBlock* block_cont =
1565 CreateBasicBlockWithDexPC(dex_pc, "cont");
1566
1567 llvm::BasicBlock* block_load_class =
1568 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1569
1570 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1571
1572 // Failback routine to load the class object
1573 irb_.SetInsertPoint(block_load_class);
1574
1575 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
1576
1577 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1578
1579 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1580
1581 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1582
1583 EmitUpdateDexPC(dex_pc);
1584
1585 llvm::Value* loaded_type_object_addr =
1586 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1587
1588 EmitGuard_ExceptionLandingPad(dex_pc);
1589
1590 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1591
1592 irb_.CreateBr(block_cont);
1593
1594 // Now the class object must be loaded
1595 irb_.SetInsertPoint(block_cont);
1596
1597 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1598
1599 phi->addIncoming(type_object_addr, block_original);
1600 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1601
1602 return phi;
1603 }
1604}
1605
TDYa1275a26d442012-07-26 18:58:38 -07001606llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1607 uint32_t type_idx) {
1608 llvm::BasicBlock* block_load_static =
1609 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1610
1611 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1612
1613 // Load static storage from dex cache
1614 llvm::Value* storage_field_addr =
1615 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1616
TDYa127ce4cc0d2012-11-18 16:59:53 -08001617 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
TDYa1275a26d442012-07-26 18:58:38 -07001618
1619 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1620
1621 // Test: Is the static storage of this class initialized?
1622 llvm::Value* equal_null =
1623 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1624
1625 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1626
1627 // Failback routine to load the class object
1628 irb_.SetInsertPoint(block_load_static);
1629
1630 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
1631
1632 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1633
1634 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1635
1636 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1637
1638 EmitUpdateDexPC(dex_pc);
1639
1640 llvm::Value* loaded_storage_object_addr =
1641 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1642
1643 EmitGuard_ExceptionLandingPad(dex_pc);
1644
1645 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1646
1647 irb_.CreateBr(block_cont);
1648
1649 // Now the class object must be loaded
1650 irb_.SetInsertPoint(block_cont);
1651
1652 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1653
1654 phi->addIncoming(storage_object_addr, block_original);
1655 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1656
1657 return phi;
1658}
1659
1660llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1661 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001662 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1663 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1664
1665 int field_offset;
1666 int ssb_index;
1667 bool is_referrers_class;
1668 bool is_volatile;
1669
1670 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1671 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1672 is_referrers_class, is_volatile, false);
1673
1674 llvm::Value* static_field_value;
1675
1676 if (!is_fast_path) {
1677 llvm::Function* runtime_func;
1678
1679 if (field_jty == kObject) {
1680 runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
1681 } else if (field_jty == kLong || field_jty == kDouble) {
1682 runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
1683 } else {
1684 runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
1685 }
1686
1687 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1688
1689 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1690
1691 EmitUpdateDexPC(dex_pc);
1692
1693 static_field_value =
1694 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1695
1696 EmitGuard_ExceptionLandingPad(dex_pc);
1697
1698 } else {
1699 DCHECK_GE(field_offset, 0);
1700
1701 llvm::Value* static_storage_addr = NULL;
1702
1703 if (is_referrers_class) {
1704 // Fast path, static storage base is this method's class
1705 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1706
1707 static_storage_addr =
1708 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001709 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001710 irb_.getJObjectTy(),
1711 kTBAAConstJObject);
1712 } else {
1713 // Medium path, static storage base in a different class which
1714 // requires checks that the other class is initialized
1715 DCHECK_GE(ssb_index, 0);
1716 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1717 }
1718
1719 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1720
1721 llvm::Value* static_field_addr =
1722 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001723 irb_.getJType(field_jty)->getPointerTo());
TDYa1275a26d442012-07-26 18:58:38 -07001724
1725 // TODO: Check is_volatile. We need to generate atomic load instruction
1726 // when is_volatile is true.
1727 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001728 static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001729 }
1730
1731 if (field_jty == kFloat || field_jty == kDouble) {
1732 static_field_value =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001733 irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty));
TDYa1275a26d442012-07-26 18:58:38 -07001734 }
1735
1736 return static_field_value;
1737}
1738
1739void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1740 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001741 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1742 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1743 llvm::Value* new_value = call_inst.getArgOperand(1);
1744
1745 if (field_jty == kFloat || field_jty == kDouble) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001746 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
TDYa1275a26d442012-07-26 18:58:38 -07001747 }
1748
1749 int field_offset;
1750 int ssb_index;
1751 bool is_referrers_class;
1752 bool is_volatile;
1753
1754 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1755 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1756 is_referrers_class, is_volatile, true);
1757
1758 if (!is_fast_path) {
1759 llvm::Function* runtime_func;
1760
1761 if (field_jty == kObject) {
1762 runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
1763 } else if (field_jty == kLong || field_jty == kDouble) {
1764 runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
1765 } else {
1766 runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
1767 }
1768
1769 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1770
1771 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1772
1773 EmitUpdateDexPC(dex_pc);
1774
1775 irb_.CreateCall3(runtime_func, field_idx_value,
1776 method_object_addr, new_value);
1777
1778 EmitGuard_ExceptionLandingPad(dex_pc);
1779
1780 } else {
1781 DCHECK_GE(field_offset, 0);
1782
1783 llvm::Value* static_storage_addr = NULL;
1784
1785 if (is_referrers_class) {
1786 // Fast path, static storage base is this method's class
1787 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1788
1789 static_storage_addr =
1790 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001791 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001792 irb_.getJObjectTy(),
1793 kTBAAConstJObject);
1794 } else {
1795 // Medium path, static storage base in a different class which
1796 // requires checks that the other class is initialized
1797 DCHECK_GE(ssb_index, 0);
1798 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1799 }
1800
1801 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1802
1803 llvm::Value* static_field_addr =
1804 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001805 irb_.getJType(field_jty)->getPointerTo());
TDYa1275a26d442012-07-26 18:58:38 -07001806
1807 // TODO: Check is_volatile. We need to generate atomic store instruction
1808 // when is_volatile is true.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001809 new_value = TruncateCat1Types(new_value, field_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001810 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1811
1812 if (field_jty == kObject) { // If put an object, mark the GC card table.
1813 EmitMarkGCCard(new_value, static_storage_addr);
1814 }
1815 }
1816
1817 return;
1818}
1819
TDYa127f71bf5a2012-07-29 20:09:52 -07001820llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001821 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1822 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
1823
1824 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1825
TDYa127ce4cc0d2012-11-18 16:59:53 -08001826 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001827
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001828 if (!compiler_->CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001829 llvm::BasicBlock* block_str_exist =
1830 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1831
1832 llvm::BasicBlock* block_str_resolve =
1833 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1834
1835 llvm::BasicBlock* block_cont =
1836 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
1837
1838 // Test: Is the string resolved and in the dex cache?
1839 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1840
1841 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
1842
1843 // String is resolved, go to next basic block.
1844 irb_.SetInsertPoint(block_str_exist);
1845 irb_.CreateBr(block_cont);
1846
1847 // String is not resolved yet, resolve it now.
1848 irb_.SetInsertPoint(block_str_resolve);
1849
1850 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
1851
1852 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1853
1854 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1855
1856 EmitUpdateDexPC(dex_pc);
1857
1858 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
1859 string_idx_value);
1860
1861 EmitGuard_ExceptionLandingPad(dex_pc);
1862
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001863 irb_.CreateBr(block_cont);
1864
1865
TDYa127f71bf5a2012-07-29 20:09:52 -07001866 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
1867
1868 irb_.SetInsertPoint(block_cont);
1869
1870 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1871
1872 phi->addIncoming(string_addr, block_str_exist);
1873 phi->addIncoming(result, block_pre_cont);
1874
1875 string_addr = phi;
1876 }
1877
1878 return string_addr;
1879}
1880
1881llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001882 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1883 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1884
1885 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1886
1887 return type_object_addr;
1888}
1889
1890void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001891 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1892 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07001893 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07001894
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001895 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07001896
TDYa127ce4cc0d2012-11-18 16:59:53 -08001897 EmitUpdateDexPC(dex_pc);
1898
TDYa127f71bf5a2012-07-29 20:09:52 -07001899 irb_.Runtime().EmitLockObject(object_addr);
1900
1901 return;
1902}
1903
1904void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001905 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1906 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07001907 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07001908
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001909 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07001910
1911 EmitUpdateDexPC(dex_pc);
1912
1913 irb_.Runtime().EmitUnlockObject(object_addr);
1914
1915 EmitGuard_ExceptionLandingPad(dex_pc);
1916
1917 return;
1918}
1919
1920void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001921 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1922 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1923 llvm::Value* object_addr = call_inst.getArgOperand(1);
1924
1925 llvm::BasicBlock* block_test_class =
1926 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1927
1928 llvm::BasicBlock* block_test_sub_class =
1929 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1930
1931 llvm::BasicBlock* block_cont =
1932 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
1933
1934 // Test: Is the reference equal to null? Act as no-op when it is null.
1935 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1936
1937 irb_.CreateCondBr(equal_null,
1938 block_cont,
1939 block_test_class);
1940
1941 // Test: Is the object instantiated from the given class?
1942 irb_.SetInsertPoint(block_test_class);
1943 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08001944 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07001945
1946 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1947
1948 llvm::Value* object_type_field_addr =
1949 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1950
1951 llvm::Value* object_type_object_addr =
1952 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
1953
1954 llvm::Value* equal_class =
1955 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1956
1957 irb_.CreateCondBr(equal_class,
1958 block_cont,
1959 block_test_sub_class);
1960
1961 // Test: Is the object instantiated from the subclass of the given class?
1962 irb_.SetInsertPoint(block_test_sub_class);
1963
1964 EmitUpdateDexPC(dex_pc);
1965
1966 irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
1967 type_object_addr, object_type_object_addr);
1968
1969 EmitGuard_ExceptionLandingPad(dex_pc);
1970
1971 irb_.CreateBr(block_cont);
1972
1973 irb_.SetInsertPoint(block_cont);
1974
1975 return;
1976}
1977
1978llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001979 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1980 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1981 llvm::Value* object_addr = call_inst.getArgOperand(1);
1982
1983 llvm::BasicBlock* block_nullp =
1984 CreateBasicBlockWithDexPC(dex_pc, "nullp");
1985
1986 llvm::BasicBlock* block_test_class =
1987 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1988
1989 llvm::BasicBlock* block_class_equals =
1990 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
1991
1992 llvm::BasicBlock* block_test_sub_class =
1993 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1994
1995 llvm::BasicBlock* block_cont =
1996 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
1997
1998 // Overview of the following code :
1999 // We check for null, if so, then false, otherwise check for class == . If so
2000 // then true, otherwise do callout slowpath.
2001 //
2002 // Test: Is the reference equal to null? Set 0 when it is null.
2003 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2004
2005 irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
2006
2007 irb_.SetInsertPoint(block_nullp);
2008 irb_.CreateBr(block_cont);
2009
2010 // Test: Is the object instantiated from the given class?
2011 irb_.SetInsertPoint(block_test_class);
2012 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08002013 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002014
2015 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2016
2017 llvm::Value* object_type_field_addr =
2018 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2019
2020 llvm::Value* object_type_object_addr =
2021 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2022
2023 llvm::Value* equal_class =
2024 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2025
2026 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
2027
2028 irb_.SetInsertPoint(block_class_equals);
2029 irb_.CreateBr(block_cont);
2030
2031 // Test: Is the object instantiated from the subclass of the given class?
2032 irb_.SetInsertPoint(block_test_sub_class);
2033 llvm::Value* result =
2034 irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
2035 type_object_addr, object_type_object_addr);
2036 irb_.CreateBr(block_cont);
2037
2038 irb_.SetInsertPoint(block_cont);
2039
2040 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
2041
2042 phi->addIncoming(irb_.getJInt(0), block_nullp);
2043 phi->addIncoming(irb_.getJInt(1), block_class_equals);
2044 phi->addIncoming(result, block_test_sub_class);
2045
2046 return phi;
2047}
2048
2049llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002050 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2051 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2052
2053 llvm::Function* runtime_func;
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002054 if (compiler_->CanAccessInstantiableTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002055 runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
2056 } else {
2057 runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
2058 }
2059
2060 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2061
2062 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2063
2064 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2065
2066 EmitUpdateDexPC(dex_pc);
2067
2068 llvm::Value* object_addr =
2069 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
2070
2071 EmitGuard_ExceptionLandingPad(dex_pc);
2072
2073 return object_addr;
2074}
2075
2076llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002077 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
TDYa127920be7c2012-09-10 17:13:22 -07002078 art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
2079 bool is_static = (invoke_type == art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002080 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
TDYa127920be7c2012-09-10 17:13:22 -07002081 int opt_flags = LV2UInt(call_inst.getArgOperand(2));
TDYa127f71bf5a2012-07-29 20:09:52 -07002082
2083 // Compute invoke related information for compiler decision
2084 int vtable_idx = -1;
2085 uintptr_t direct_code = 0;
2086 uintptr_t direct_method = 0;
2087 bool is_fast_path = compiler_->
2088 ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
2089 invoke_type, vtable_idx, direct_code, direct_method);
2090
2091 // Load *this* actual parameter
2092 llvm::Value* this_addr = NULL;
2093
2094 if (!is_static) {
2095 // Test: Is *this* parameter equal to null?
2096 this_addr = call_inst.getArgOperand(3);
2097 }
2098
2099 // Load the method object
2100 llvm::Value* callee_method_object_addr = NULL;
2101
2102 if (!is_fast_path) {
2103 callee_method_object_addr =
2104 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
2105 this_addr, dex_pc, is_fast_path);
2106
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002107 if (!is_static) {
2108 EmitGuard_NullPointerException(dex_pc, this_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002109 }
2110 } else {
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002111 if (!is_static) {
2112 EmitGuard_NullPointerException(dex_pc, this_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002113 }
2114
2115 switch (invoke_type) {
TDYa127920be7c2012-09-10 17:13:22 -07002116 case art::kStatic:
2117 case art::kDirect:
TDYa127f71bf5a2012-07-29 20:09:52 -07002118 if (direct_method != 0u &&
2119 direct_method != static_cast<uintptr_t>(-1)) {
2120 callee_method_object_addr =
2121 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
2122 irb_.getJObjectTy());
2123 } else {
2124 callee_method_object_addr =
2125 EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
2126 }
2127 break;
2128
TDYa127920be7c2012-09-10 17:13:22 -07002129 case art::kVirtual:
TDYa127f71bf5a2012-07-29 20:09:52 -07002130 DCHECK(vtable_idx != -1);
2131 callee_method_object_addr =
2132 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
2133 break;
2134
TDYa127920be7c2012-09-10 17:13:22 -07002135 case art::kSuper:
TDYa127f71bf5a2012-07-29 20:09:52 -07002136 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
2137 "the fast path.";
2138 break;
2139
TDYa127920be7c2012-09-10 17:13:22 -07002140 case art::kInterface:
TDYa127f71bf5a2012-07-29 20:09:52 -07002141 callee_method_object_addr =
2142 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
2143 invoke_type, this_addr,
2144 dex_pc, is_fast_path);
2145 break;
2146 }
2147 }
2148
2149 // Load the actual parameter
2150 std::vector<llvm::Value*> args;
2151
2152 args.push_back(callee_method_object_addr); // method object for callee
2153
2154 for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
2155 args.push_back(call_inst.getArgOperand(i));
2156 }
2157
2158 llvm::Value* code_addr;
2159 if (direct_code != 0u &&
2160 direct_code != static_cast<uintptr_t>(-1)) {
2161 code_addr =
2162 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
2163 GetFunctionType(callee_method_idx, is_static)->getPointerTo());
2164 } else {
2165 code_addr =
2166 irb_.LoadFromObjectOffset(callee_method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08002167 art::mirror::AbstractMethod::GetCodeOffset().Int32Value(),
TDYa127f71bf5a2012-07-29 20:09:52 -07002168 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
TDYa127ce4cc0d2012-11-18 16:59:53 -08002169 kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07002170 }
2171
2172 // Invoke callee
2173 EmitUpdateDexPC(dex_pc);
2174 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2175 EmitGuard_ExceptionLandingPad(dex_pc);
2176
2177 return retval;
2178}
2179
2180llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002181 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2182 // Get the array object address
2183 llvm::Value* array_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002184 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002185
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002186 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002187
2188 // Get the array length and store it to the register
2189 return EmitLoadArrayLength(array_addr);
2190}
2191
2192llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002193 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2194 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2195 llvm::Value* length = call_inst.getArgOperand(1);
2196
2197 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2198}
2199
2200llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002201 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2202 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2203 uint32_t length = call_inst.getNumArgOperands() - 3;
2204
2205 llvm::Value* object_addr =
2206 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2207
2208 if (length > 0) {
2209 // Check for the element type
2210 uint32_t type_desc_len = 0;
2211 const char* type_desc =
2212 dex_file_->StringByTypeIdx(type_idx, &type_desc_len);
2213
2214 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2215 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2216 bool is_elem_int_ty = (type_desc[1] == 'I');
2217
2218 uint32_t alignment;
2219 llvm::Constant* elem_size;
2220 llvm::PointerType* field_type;
2221
2222 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2223 // as the element, thus we are only checking 2 cases: primitive int and
2224 // non-primitive type.
2225 if (is_elem_int_ty) {
2226 alignment = sizeof(int32_t);
2227 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2228 field_type = irb_.getJIntTy()->getPointerTo();
2229 } else {
2230 alignment = irb_.getSizeOfPtrEquivInt();
2231 elem_size = irb_.getSizeOfPtrEquivIntValue();
2232 field_type = irb_.getJObjectTy()->getPointerTo();
2233 }
2234
2235 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -08002236 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
TDYa127f71bf5a2012-07-29 20:09:52 -07002237
2238 llvm::Value* data_field_addr =
2239 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2240
2241 // TODO: Tune this code. Currently we are generating one instruction for
2242 // one element which may be very space consuming. Maybe changing to use
2243 // memcpy may help; however, since we can't guarantee that the alloca of
2244 // dalvik register are continuous, we can't perform such optimization yet.
2245 for (uint32_t i = 0; i < length; ++i) {
2246 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2247
2248 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2249
2250 data_field_addr =
2251 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2252 }
2253 }
2254
2255 return object_addr;
2256}
2257
2258void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002259 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2260 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2261 LV2SInt(call_inst.getArgOperand(0));
2262 llvm::Value* array_addr = call_inst.getArgOperand(1);
2263
TDYa127920be7c2012-09-10 17:13:22 -07002264 const art::Instruction::ArrayDataPayload* payload =
2265 reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
TDYa127f71bf5a2012-07-29 20:09:52 -07002266 code_item_->insns_ + payload_offset);
2267
2268 if (payload->element_count == 0) {
2269 // When the number of the elements in the payload is zero, we don't have
2270 // to copy any numbers. However, we should check whether the array object
2271 // address is equal to null or not.
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002272 EmitGuard_NullPointerException(dex_pc, array_addr, 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002273 } else {
2274 // To save the code size, we are going to call the runtime function to
2275 // copy the content from DexFile.
2276
2277 // NOTE: We will check for the NullPointerException in the runtime.
2278
2279 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
2280
2281 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2282
2283 EmitUpdateDexPC(dex_pc);
2284
2285 irb_.CreateCall4(runtime_func,
2286 method_object_addr, irb_.getInt32(dex_pc),
2287 array_addr, irb_.getInt32(payload_offset));
2288
2289 EmitGuard_ExceptionLandingPad(dex_pc);
2290 }
2291
2292 return;
2293}
2294
2295llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2296 llvm::Value* array_length_value,
2297 uint32_t type_idx,
2298 bool is_filled_new_array) {
2299 llvm::Function* runtime_func;
2300
2301 bool skip_access_check =
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002302 compiler_->CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx);
TDYa127f71bf5a2012-07-29 20:09:52 -07002303
2304
2305 if (is_filled_new_array) {
2306 runtime_func = skip_access_check ?
2307 irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
2308 irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
2309 } else {
2310 runtime_func = skip_access_check ?
2311 irb_.GetRuntime(runtime_support::AllocArray) :
2312 irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
2313 }
2314
2315 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2316
2317 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2318
2319 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2320
2321 EmitUpdateDexPC(dex_pc);
2322
2323 llvm::Value* object_addr =
2324 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2325 array_length_value, thread_object_addr);
2326
2327 EmitGuard_ExceptionLandingPad(dex_pc);
2328
2329 return object_addr;
2330}
2331
2332llvm::Value* GBCExpanderPass::
2333EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -07002334 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -07002335 llvm::Value* this_addr,
2336 uint32_t dex_pc,
2337 bool is_fast_path) {
2338
2339 llvm::Function* runtime_func = NULL;
2340
2341 switch (invoke_type) {
TDYa127920be7c2012-09-10 17:13:22 -07002342 case art::kStatic:
TDYa127f71bf5a2012-07-29 20:09:52 -07002343 runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
2344 break;
2345
TDYa127920be7c2012-09-10 17:13:22 -07002346 case art::kDirect:
TDYa127f71bf5a2012-07-29 20:09:52 -07002347 runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
2348 break;
2349
TDYa127920be7c2012-09-10 17:13:22 -07002350 case art::kVirtual:
TDYa127f71bf5a2012-07-29 20:09:52 -07002351 runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
2352 break;
2353
TDYa127920be7c2012-09-10 17:13:22 -07002354 case art::kSuper:
TDYa127f71bf5a2012-07-29 20:09:52 -07002355 runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
2356 break;
2357
TDYa127920be7c2012-09-10 17:13:22 -07002358 case art::kInterface:
TDYa127f71bf5a2012-07-29 20:09:52 -07002359 if (is_fast_path) {
2360 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
2361 } else {
2362 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
2363 }
2364 break;
2365 }
2366
2367 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2368
2369 if (this_addr == NULL) {
TDYa127920be7c2012-09-10 17:13:22 -07002370 DCHECK_EQ(invoke_type, art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002371 this_addr = irb_.getJNull();
2372 }
2373
2374 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2375
2376 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2377
2378 EmitUpdateDexPC(dex_pc);
2379
2380 llvm::Value* callee_method_object_addr =
2381 irb_.CreateCall4(runtime_func,
2382 callee_method_idx_value,
2383 this_addr,
2384 caller_method_object_addr,
2385 thread_object_addr);
2386
2387 EmitGuard_ExceptionLandingPad(dex_pc);
2388
2389 return callee_method_object_addr;
2390}
2391
TDYa1275e869b62012-07-25 00:45:39 -07002392void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2393 // Using runtime support, let the target can override by InlineAssembly.
2394 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2395}
2396
2397void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002398 if (shadow_frame_ == NULL) {
2399 return;
2400 }
TDYa1275e869b62012-07-25 00:45:39 -07002401 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07002402 art::ShadowFrame::DexPCOffset(),
TDYa1275e869b62012-07-25 00:45:39 -07002403 irb_.getInt32(dex_pc),
2404 kTBAAShadowFrame);
2405}
2406
2407void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2408 llvm::Value* denominator,
2409 JType op_jty) {
2410 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2411
2412 llvm::Constant* zero = irb_.getJZero(op_jty);
2413
2414 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2415
2416 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2417
2418 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2419
2420 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2421
2422 irb_.SetInsertPoint(block_exception);
2423 EmitUpdateDexPC(dex_pc);
2424 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
2425 EmitBranchExceptionLandingPad(dex_pc);
2426
2427 irb_.SetInsertPoint(block_continue);
2428}
2429
2430void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002431 llvm::Value* object,
2432 int opt_flags) {
2433 bool ignore_null_check = ((opt_flags & MIR_IGNORE_NULL_CHECK) != 0);
2434 if (ignore_null_check) {
2435 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2436 if (lpad) {
2437 // There is at least one catch: create a "fake" conditional branch to
2438 // keep the exception edge to the catch block.
2439 landing_pad_phi_mapping_[lpad].push_back(
2440 std::make_pair(current_bb_->getUniquePredecessor(),
2441 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002442
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002443 llvm::BasicBlock* block_continue =
2444 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002445
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002446 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue);
TDYa1275e869b62012-07-25 00:45:39 -07002447
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002448 irb_.SetInsertPoint(block_continue);
2449 }
2450 } else {
2451 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
TDYa1275e869b62012-07-25 00:45:39 -07002452
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002453 llvm::BasicBlock* block_exception =
2454 CreateBasicBlockWithDexPC(dex_pc, "nullp");
TDYa1275e869b62012-07-25 00:45:39 -07002455
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002456 llvm::BasicBlock* block_continue =
2457 CreateBasicBlockWithDexPC(dex_pc, "cont");
2458
2459 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2460
2461 irb_.SetInsertPoint(block_exception);
2462 EmitUpdateDexPC(dex_pc);
2463 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
2464 irb_.getInt32(dex_pc));
2465 EmitBranchExceptionLandingPad(dex_pc);
2466
2467 irb_.SetInsertPoint(block_continue);
2468 }
TDYa1275e869b62012-07-25 00:45:39 -07002469}
2470
2471void
2472GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2473 llvm::Value* array,
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002474 llvm::Value* index,
2475 int opt_flags) {
2476 bool ignore_range_check = ((opt_flags & MIR_IGNORE_RANGE_CHECK) != 0);
2477 if (ignore_range_check) {
2478 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2479 if (lpad) {
2480 // There is at least one catch: create a "fake" conditional branch to
2481 // keep the exception edge to the catch block.
2482 landing_pad_phi_mapping_[lpad].push_back(
2483 std::make_pair(current_bb_->getUniquePredecessor(),
2484 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002485
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002486 llvm::BasicBlock* block_continue =
2487 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002488
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002489 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue);
TDYa1275e869b62012-07-25 00:45:39 -07002490
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002491 irb_.SetInsertPoint(block_continue);
2492 }
2493 } else {
2494 llvm::Value* array_len = EmitLoadArrayLength(array);
TDYa1275e869b62012-07-25 00:45:39 -07002495
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002496 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
TDYa1275e869b62012-07-25 00:45:39 -07002497
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002498 llvm::BasicBlock* block_exception =
2499 CreateBasicBlockWithDexPC(dex_pc, "overflow");
TDYa1275e869b62012-07-25 00:45:39 -07002500
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002501 llvm::BasicBlock* block_continue =
2502 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002503
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002504 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2505
2506 irb_.SetInsertPoint(block_exception);
2507
2508 EmitUpdateDexPC(dex_pc);
2509 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
2510 EmitBranchExceptionLandingPad(dex_pc);
2511
2512 irb_.SetInsertPoint(block_continue);
2513 }
TDYa1275e869b62012-07-25 00:45:39 -07002514}
2515
TDYa1275e869b62012-07-25 00:45:39 -07002516llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
2517 bool is_static) {
2518 // Get method signature
TDYa127920be7c2012-09-10 17:13:22 -07002519 art::DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
TDYa1275e869b62012-07-25 00:45:39 -07002520
2521 uint32_t shorty_size;
2522 const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
2523 CHECK_GE(shorty_size, 1u);
2524
2525 // Get return type
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002526
2527 char ret_shorty = shorty[0];
buzbee26f10ee2012-12-21 11:16:29 -08002528 ret_shorty = art::RemapShorty(ret_shorty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002529 llvm::Type* ret_type = irb_.getJType(ret_shorty);
TDYa1275e869b62012-07-25 00:45:39 -07002530
2531 // Get argument type
2532 std::vector<llvm::Type*> args_type;
2533
2534 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2535
2536 if (!is_static) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002537 args_type.push_back(irb_.getJType('L')); // "this" object pointer
TDYa1275e869b62012-07-25 00:45:39 -07002538 }
2539
2540 for (uint32_t i = 1; i < shorty_size; ++i) {
buzbee26f10ee2012-12-21 11:16:29 -08002541 char shorty_type = art::RemapShorty(shorty[i]);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002542 args_type.push_back(irb_.getJType(shorty_type));
TDYa1275e869b62012-07-25 00:45:39 -07002543 }
2544
2545 return llvm::FunctionType::get(ret_type, args_type, false);
2546}
2547
2548
2549llvm::BasicBlock* GBCExpanderPass::
2550CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2551 std::string name;
2552
2553#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002554 art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
TDYa1275e869b62012-07-25 00:45:39 -07002555#endif
2556
2557 return llvm::BasicBlock::Create(context_, name, func_);
2558}
2559
2560llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
2561 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002562 CHECK(basic_blocks_[dex_pc] != NULL);
TDYa1275e869b62012-07-25 00:45:39 -07002563 return basic_blocks_[dex_pc];
2564}
2565
2566int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2567 int32_t min = 0;
2568 int32_t max = code_item_->tries_size_ - 1;
2569
2570 while (min <= max) {
2571 int32_t mid = min + (max - min) / 2;
2572
TDYa127920be7c2012-09-10 17:13:22 -07002573 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*code_item_, mid);
TDYa1275e869b62012-07-25 00:45:39 -07002574 uint32_t start = ti->start_addr_;
2575 uint32_t end = start + ti->insn_count_;
2576
2577 if (dex_pc < start) {
2578 max = mid - 1;
2579 } else if (dex_pc >= end) {
2580 min = mid + 1;
2581 } else {
2582 return mid; // found
2583 }
2584 }
2585
2586 return -1; // not found
2587}
2588
2589llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2590 // Find the try item for this address in this method
2591 int32_t ti_offset = GetTryItemOffset(dex_pc);
2592
2593 if (ti_offset == -1) {
2594 return NULL; // No landing pad is available for this address.
2595 }
2596
2597 // Check for the existing landing pad basic block
2598 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2599 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2600
2601 if (block_lpad) {
2602 // We have generated landing pad for this try item already. Return the
2603 // same basic block.
2604 return block_lpad;
2605 }
2606
2607 // Get try item from code item
TDYa127920be7c2012-09-10 17:13:22 -07002608 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*code_item_, ti_offset);
TDYa1275e869b62012-07-25 00:45:39 -07002609
2610 std::string lpadname;
2611
2612#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002613 art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
TDYa1275e869b62012-07-25 00:45:39 -07002614#endif
2615
2616 // Create landing pad basic block
2617 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2618
2619 // Change IRBuilder insert point
2620 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2621 irb_.SetInsertPoint(block_lpad);
2622
2623 // Find catch block with matching type
2624 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2625
2626 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2627
2628 llvm::Value* catch_handler_index_value =
2629 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
2630 method_object_addr, ti_offset_value);
2631
2632 // Switch instruction (Go to unwind basic block by default)
2633 llvm::SwitchInst* sw =
2634 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2635
2636 // Cases with matched catch block
TDYa127920be7c2012-09-10 17:13:22 -07002637 art::CatchHandlerIterator iter(*code_item_, ti->start_addr_);
TDYa1275e869b62012-07-25 00:45:39 -07002638
2639 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2640 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2641 }
2642
2643 // Restore the orignal insert point for IRBuilder
2644 irb_.restoreIP(irb_ip_original);
2645
2646 // Cache this landing pad
2647 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2648 basic_block_landing_pads_[ti_offset] = block_lpad;
2649
2650 return block_lpad;
2651}
2652
2653llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2654 // Check the existing unwinding baisc block block
2655 if (basic_block_unwind_ != NULL) {
2656 return basic_block_unwind_;
2657 }
2658
2659 // Create new basic block for unwinding
2660 basic_block_unwind_ =
2661 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2662
2663 // Change IRBuilder insert point
2664 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2665 irb_.SetInsertPoint(basic_block_unwind_);
2666
2667 // Pop the shadow frame
2668 Expand_PopShadowFrame();
2669
2670 // Emit the code to return default value (zero) for the given return type.
2671 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
buzbee26f10ee2012-12-21 11:16:29 -08002672 ret_shorty = art::RemapShorty(ret_shorty);
TDYa1275e869b62012-07-25 00:45:39 -07002673 if (ret_shorty == 'V') {
2674 irb_.CreateRetVoid();
2675 } else {
2676 irb_.CreateRet(irb_.getJZero(ret_shorty));
2677 }
2678
2679 // Restore the orignal insert point for IRBuilder
2680 irb_.restoreIP(irb_ip_original);
2681
2682 return basic_block_unwind_;
2683}
2684
2685void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2686 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002687 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002688 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002689 irb_.CreateBr(lpad);
2690 } else {
2691 irb_.CreateBr(GetUnwindBasicBlock());
2692 }
2693}
2694
2695void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
Jeff Hao9a142652013-01-17 23:10:19 +00002696 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2697
TDYa1275e869b62012-07-25 00:45:39 -07002698 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2699
2700 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002701 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002702 irb_.GetInsertBlock()));
Jeff Hao9a142652013-01-17 23:10:19 +00002703 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002704 } else {
Jeff Hao9a142652013-01-17 23:10:19 +00002705 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002706 }
2707
2708 irb_.SetInsertPoint(block_cont);
2709}
2710
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002711llvm::Value*
2712GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2713 llvm::CallInst& call_inst) {
2714 switch (intr_id) {
2715 //==- Thread -----------------------------------------------------------==//
2716 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07002717 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002718 }
Logan Chien75e4b602012-07-23 14:24:12 -07002719 case IntrinsicHelper::CheckSuspend: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08002720 Expand_TestSuspend(call_inst);
TDYa127890ea892012-08-22 10:49:42 -07002721 return NULL;
2722 }
2723 case IntrinsicHelper::TestSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002724 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002725 return NULL;
2726 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002727 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07002728 Expand_MarkGCCard(call_inst);
2729 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002730 }
Logan Chien75e4b602012-07-23 14:24:12 -07002731
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002732 //==- Exception --------------------------------------------------------==//
2733 case IntrinsicHelper::ThrowException: {
2734 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
2735 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002736 case IntrinsicHelper::HLThrowException: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002737 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2738
2739 EmitUpdateDexPC(dex_pc);
2740
2741 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
2742 call_inst.getArgOperand(0));
2743
2744 EmitGuard_ExceptionLandingPad(dex_pc);
2745 return NULL;
2746 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002747 case IntrinsicHelper::GetException: {
TDYa127823433d2012-09-26 16:03:51 -07002748 return irb_.Runtime().EmitGetAndClearException();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002749 }
2750 case IntrinsicHelper::IsExceptionPending: {
2751 return irb_.Runtime().EmitIsExceptionPending();
2752 }
2753 case IntrinsicHelper::FindCatchBlock: {
2754 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
2755 }
2756 case IntrinsicHelper::ThrowDivZeroException: {
2757 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
2758 }
2759 case IntrinsicHelper::ThrowNullPointerException: {
2760 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
2761 }
2762 case IntrinsicHelper::ThrowIndexOutOfBounds: {
2763 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
2764 }
Logan Chien75e4b602012-07-23 14:24:12 -07002765
2766 //==- Const String -----------------------------------------------------==//
2767 case IntrinsicHelper::ConstString: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002768 return Expand_ConstString(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002769 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002770 case IntrinsicHelper::LoadStringFromDexCache: {
2771 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2772 }
2773 case IntrinsicHelper::ResolveString: {
2774 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
2775 }
Logan Chien75e4b602012-07-23 14:24:12 -07002776
2777 //==- Const Class ------------------------------------------------------==//
2778 case IntrinsicHelper::ConstClass: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002779 return Expand_ConstClass(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002780 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002781 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
2782 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
2783 }
2784 case IntrinsicHelper::LoadTypeFromDexCache: {
2785 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2786 }
2787 case IntrinsicHelper::InitializeType: {
2788 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
2789 }
Logan Chien75e4b602012-07-23 14:24:12 -07002790
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002791 //==- Lock -------------------------------------------------------------==//
2792 case IntrinsicHelper::LockObject: {
2793 Expand_LockObject(call_inst.getArgOperand(0));
2794 return NULL;
2795 }
2796 case IntrinsicHelper::UnlockObject: {
2797 Expand_UnlockObject(call_inst.getArgOperand(0));
2798 return NULL;
2799 }
Logan Chien75e4b602012-07-23 14:24:12 -07002800
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002801 //==- Cast -------------------------------------------------------------==//
2802 case IntrinsicHelper::CheckCast: {
2803 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
2804 }
Logan Chien75e4b602012-07-23 14:24:12 -07002805 case IntrinsicHelper::HLCheckCast: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002806 Expand_HLCheckCast(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002807 return NULL;
2808 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002809 case IntrinsicHelper::IsAssignable: {
2810 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
2811 }
Logan Chien75e4b602012-07-23 14:24:12 -07002812
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002813 //==- Alloc ------------------------------------------------------------==//
2814 case IntrinsicHelper::AllocObject: {
2815 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
2816 }
2817 case IntrinsicHelper::AllocObjectWithAccessCheck: {
2818 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
2819 }
Logan Chien75e4b602012-07-23 14:24:12 -07002820
2821 //==- Instance ---------------------------------------------------------==//
2822 case IntrinsicHelper::NewInstance: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002823 return Expand_NewInstance(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002824 }
2825 case IntrinsicHelper::InstanceOf: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002826 return Expand_InstanceOf(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002827 }
2828
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002829 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07002830 case IntrinsicHelper::NewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002831 return Expand_NewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002832 }
2833 case IntrinsicHelper::OptArrayLength: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002834 return Expand_OptArrayLength(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002835 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002836 case IntrinsicHelper::ArrayLength: {
2837 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2838 }
2839 case IntrinsicHelper::AllocArray: {
2840 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
2841 }
2842 case IntrinsicHelper::AllocArrayWithAccessCheck: {
2843 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
2844 call_inst);
2845 }
2846 case IntrinsicHelper::CheckAndAllocArray: {
2847 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
2848 }
2849 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
2850 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
2851 call_inst);
2852 }
2853 case IntrinsicHelper::ArrayGet: {
2854 return Expand_ArrayGet(call_inst.getArgOperand(0),
2855 call_inst.getArgOperand(1),
2856 kInt);
2857 }
2858 case IntrinsicHelper::ArrayGetWide: {
2859 return Expand_ArrayGet(call_inst.getArgOperand(0),
2860 call_inst.getArgOperand(1),
2861 kLong);
2862 }
2863 case IntrinsicHelper::ArrayGetObject: {
2864 return Expand_ArrayGet(call_inst.getArgOperand(0),
2865 call_inst.getArgOperand(1),
2866 kObject);
2867 }
2868 case IntrinsicHelper::ArrayGetBoolean: {
2869 return Expand_ArrayGet(call_inst.getArgOperand(0),
2870 call_inst.getArgOperand(1),
2871 kBoolean);
2872 }
2873 case IntrinsicHelper::ArrayGetByte: {
2874 return Expand_ArrayGet(call_inst.getArgOperand(0),
2875 call_inst.getArgOperand(1),
2876 kByte);
2877 }
2878 case IntrinsicHelper::ArrayGetChar: {
2879 return Expand_ArrayGet(call_inst.getArgOperand(0),
2880 call_inst.getArgOperand(1),
2881 kChar);
2882 }
2883 case IntrinsicHelper::ArrayGetShort: {
2884 return Expand_ArrayGet(call_inst.getArgOperand(0),
2885 call_inst.getArgOperand(1),
2886 kShort);
2887 }
2888 case IntrinsicHelper::ArrayPut: {
2889 Expand_ArrayPut(call_inst.getArgOperand(0),
2890 call_inst.getArgOperand(1),
2891 call_inst.getArgOperand(2),
2892 kInt);
2893 return NULL;
2894 }
2895 case IntrinsicHelper::ArrayPutWide: {
2896 Expand_ArrayPut(call_inst.getArgOperand(0),
2897 call_inst.getArgOperand(1),
2898 call_inst.getArgOperand(2),
2899 kLong);
2900 return NULL;
2901 }
2902 case IntrinsicHelper::ArrayPutObject: {
2903 Expand_ArrayPut(call_inst.getArgOperand(0),
2904 call_inst.getArgOperand(1),
2905 call_inst.getArgOperand(2),
2906 kObject);
2907 return NULL;
2908 }
2909 case IntrinsicHelper::ArrayPutBoolean: {
2910 Expand_ArrayPut(call_inst.getArgOperand(0),
2911 call_inst.getArgOperand(1),
2912 call_inst.getArgOperand(2),
2913 kBoolean);
2914 return NULL;
2915 }
2916 case IntrinsicHelper::ArrayPutByte: {
2917 Expand_ArrayPut(call_inst.getArgOperand(0),
2918 call_inst.getArgOperand(1),
2919 call_inst.getArgOperand(2),
2920 kByte);
2921 return NULL;
2922 }
2923 case IntrinsicHelper::ArrayPutChar: {
2924 Expand_ArrayPut(call_inst.getArgOperand(0),
2925 call_inst.getArgOperand(1),
2926 call_inst.getArgOperand(2),
2927 kChar);
2928 return NULL;
2929 }
2930 case IntrinsicHelper::ArrayPutShort: {
2931 Expand_ArrayPut(call_inst.getArgOperand(0),
2932 call_inst.getArgOperand(1),
2933 call_inst.getArgOperand(2),
2934 kShort);
2935 return NULL;
2936 }
2937 case IntrinsicHelper::CheckPutArrayElement: {
2938 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
2939 }
2940 case IntrinsicHelper::FilledNewArray: {
2941 Expand_FilledNewArray(call_inst);
2942 return NULL;
2943 }
2944 case IntrinsicHelper::FillArrayData: {
2945 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
2946 }
Logan Chien75e4b602012-07-23 14:24:12 -07002947 case IntrinsicHelper::HLFillArrayData: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002948 Expand_HLFillArrayData(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002949 return NULL;
2950 }
2951 case IntrinsicHelper::HLFilledNewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002952 return Expand_HLFilledNewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002953 }
2954
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002955 //==- Instance Field ---------------------------------------------------==//
2956 case IntrinsicHelper::InstanceFieldGet:
2957 case IntrinsicHelper::InstanceFieldGetBoolean:
2958 case IntrinsicHelper::InstanceFieldGetByte:
2959 case IntrinsicHelper::InstanceFieldGetChar:
2960 case IntrinsicHelper::InstanceFieldGetShort: {
2961 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
2962 }
2963 case IntrinsicHelper::InstanceFieldGetWide: {
2964 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
2965 }
2966 case IntrinsicHelper::InstanceFieldGetObject: {
2967 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
2968 }
2969 case IntrinsicHelper::InstanceFieldGetFast: {
2970 return Expand_IGetFast(call_inst.getArgOperand(0),
2971 call_inst.getArgOperand(1),
2972 call_inst.getArgOperand(2),
2973 kInt);
2974 }
2975 case IntrinsicHelper::InstanceFieldGetWideFast: {
2976 return Expand_IGetFast(call_inst.getArgOperand(0),
2977 call_inst.getArgOperand(1),
2978 call_inst.getArgOperand(2),
2979 kLong);
2980 }
2981 case IntrinsicHelper::InstanceFieldGetObjectFast: {
2982 return Expand_IGetFast(call_inst.getArgOperand(0),
2983 call_inst.getArgOperand(1),
2984 call_inst.getArgOperand(2),
2985 kObject);
2986 }
2987 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
2988 return Expand_IGetFast(call_inst.getArgOperand(0),
2989 call_inst.getArgOperand(1),
2990 call_inst.getArgOperand(2),
2991 kBoolean);
2992 }
2993 case IntrinsicHelper::InstanceFieldGetByteFast: {
2994 return Expand_IGetFast(call_inst.getArgOperand(0),
2995 call_inst.getArgOperand(1),
2996 call_inst.getArgOperand(2),
2997 kByte);
2998 }
2999 case IntrinsicHelper::InstanceFieldGetCharFast: {
3000 return Expand_IGetFast(call_inst.getArgOperand(0),
3001 call_inst.getArgOperand(1),
3002 call_inst.getArgOperand(2),
3003 kChar);
3004 }
3005 case IntrinsicHelper::InstanceFieldGetShortFast: {
3006 return Expand_IGetFast(call_inst.getArgOperand(0),
3007 call_inst.getArgOperand(1),
3008 call_inst.getArgOperand(2),
3009 kShort);
3010 }
3011 case IntrinsicHelper::InstanceFieldPut:
3012 case IntrinsicHelper::InstanceFieldPutBoolean:
3013 case IntrinsicHelper::InstanceFieldPutByte:
3014 case IntrinsicHelper::InstanceFieldPutChar:
3015 case IntrinsicHelper::InstanceFieldPutShort: {
3016 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
3017 }
3018 case IntrinsicHelper::InstanceFieldPutWide: {
3019 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
3020 }
3021 case IntrinsicHelper::InstanceFieldPutObject: {
3022 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
3023 }
3024 case IntrinsicHelper::InstanceFieldPutFast: {
3025 Expand_IPutFast(call_inst.getArgOperand(0),
3026 call_inst.getArgOperand(1),
3027 call_inst.getArgOperand(2),
3028 call_inst.getArgOperand(3),
3029 kInt);
3030 return NULL;
3031 }
3032 case IntrinsicHelper::InstanceFieldPutWideFast: {
3033 Expand_IPutFast(call_inst.getArgOperand(0),
3034 call_inst.getArgOperand(1),
3035 call_inst.getArgOperand(2),
3036 call_inst.getArgOperand(3),
3037 kLong);
3038 return NULL;
3039 }
3040 case IntrinsicHelper::InstanceFieldPutObjectFast: {
3041 Expand_IPutFast(call_inst.getArgOperand(0),
3042 call_inst.getArgOperand(1),
3043 call_inst.getArgOperand(2),
3044 call_inst.getArgOperand(3),
3045 kObject);
3046 return NULL;
3047 }
3048 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
3049 Expand_IPutFast(call_inst.getArgOperand(0),
3050 call_inst.getArgOperand(1),
3051 call_inst.getArgOperand(2),
3052 call_inst.getArgOperand(3),
3053 kBoolean);
3054 return NULL;
3055 }
3056 case IntrinsicHelper::InstanceFieldPutByteFast: {
3057 Expand_IPutFast(call_inst.getArgOperand(0),
3058 call_inst.getArgOperand(1),
3059 call_inst.getArgOperand(2),
3060 call_inst.getArgOperand(3),
3061 kByte);
3062 return NULL;
3063 }
3064 case IntrinsicHelper::InstanceFieldPutCharFast: {
3065 Expand_IPutFast(call_inst.getArgOperand(0),
3066 call_inst.getArgOperand(1),
3067 call_inst.getArgOperand(2),
3068 call_inst.getArgOperand(3),
3069 kChar);
3070 return NULL;
3071 }
3072 case IntrinsicHelper::InstanceFieldPutShortFast: {
3073 Expand_IPutFast(call_inst.getArgOperand(0),
3074 call_inst.getArgOperand(1),
3075 call_inst.getArgOperand(2),
3076 call_inst.getArgOperand(3),
3077 kShort);
3078 return NULL;
3079 }
Logan Chien75e4b602012-07-23 14:24:12 -07003080
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003081 //==- Static Field -----------------------------------------------------==//
3082 case IntrinsicHelper::StaticFieldGet:
3083 case IntrinsicHelper::StaticFieldGetBoolean:
3084 case IntrinsicHelper::StaticFieldGetByte:
3085 case IntrinsicHelper::StaticFieldGetChar:
3086 case IntrinsicHelper::StaticFieldGetShort: {
3087 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
3088 }
3089 case IntrinsicHelper::StaticFieldGetWide: {
3090 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
3091 }
3092 case IntrinsicHelper::StaticFieldGetObject: {
3093 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
3094 }
3095 case IntrinsicHelper::StaticFieldGetFast: {
3096 return Expand_SGetFast(call_inst.getArgOperand(0),
3097 call_inst.getArgOperand(1),
3098 call_inst.getArgOperand(2),
3099 kInt);
3100 }
3101 case IntrinsicHelper::StaticFieldGetWideFast: {
3102 return Expand_SGetFast(call_inst.getArgOperand(0),
3103 call_inst.getArgOperand(1),
3104 call_inst.getArgOperand(2),
3105 kLong);
3106 }
3107 case IntrinsicHelper::StaticFieldGetObjectFast: {
3108 return Expand_SGetFast(call_inst.getArgOperand(0),
3109 call_inst.getArgOperand(1),
3110 call_inst.getArgOperand(2),
3111 kObject);
3112 }
3113 case IntrinsicHelper::StaticFieldGetBooleanFast: {
3114 return Expand_SGetFast(call_inst.getArgOperand(0),
3115 call_inst.getArgOperand(1),
3116 call_inst.getArgOperand(2),
3117 kBoolean);
3118 }
3119 case IntrinsicHelper::StaticFieldGetByteFast: {
3120 return Expand_SGetFast(call_inst.getArgOperand(0),
3121 call_inst.getArgOperand(1),
3122 call_inst.getArgOperand(2),
3123 kByte);
3124 }
3125 case IntrinsicHelper::StaticFieldGetCharFast: {
3126 return Expand_SGetFast(call_inst.getArgOperand(0),
3127 call_inst.getArgOperand(1),
3128 call_inst.getArgOperand(2),
3129 kChar);
3130 }
3131 case IntrinsicHelper::StaticFieldGetShortFast: {
3132 return Expand_SGetFast(call_inst.getArgOperand(0),
3133 call_inst.getArgOperand(1),
3134 call_inst.getArgOperand(2),
3135 kShort);
3136 }
3137 case IntrinsicHelper::StaticFieldPut:
3138 case IntrinsicHelper::StaticFieldPutBoolean:
3139 case IntrinsicHelper::StaticFieldPutByte:
3140 case IntrinsicHelper::StaticFieldPutChar:
3141 case IntrinsicHelper::StaticFieldPutShort: {
3142 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
3143 }
3144 case IntrinsicHelper::StaticFieldPutWide: {
3145 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
3146 }
3147 case IntrinsicHelper::StaticFieldPutObject: {
3148 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
3149 }
3150 case IntrinsicHelper::StaticFieldPutFast: {
3151 Expand_SPutFast(call_inst.getArgOperand(0),
3152 call_inst.getArgOperand(1),
3153 call_inst.getArgOperand(2),
3154 call_inst.getArgOperand(3),
3155 kInt);
3156 return NULL;
3157 }
3158 case IntrinsicHelper::StaticFieldPutWideFast: {
3159 Expand_SPutFast(call_inst.getArgOperand(0),
3160 call_inst.getArgOperand(1),
3161 call_inst.getArgOperand(2),
3162 call_inst.getArgOperand(3),
3163 kLong);
3164 return NULL;
3165 }
3166 case IntrinsicHelper::StaticFieldPutObjectFast: {
3167 Expand_SPutFast(call_inst.getArgOperand(0),
3168 call_inst.getArgOperand(1),
3169 call_inst.getArgOperand(2),
3170 call_inst.getArgOperand(3),
3171 kObject);
3172 return NULL;
3173 }
3174 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3175 Expand_SPutFast(call_inst.getArgOperand(0),
3176 call_inst.getArgOperand(1),
3177 call_inst.getArgOperand(2),
3178 call_inst.getArgOperand(3),
3179 kBoolean);
3180 return NULL;
3181 }
3182 case IntrinsicHelper::StaticFieldPutByteFast: {
3183 Expand_SPutFast(call_inst.getArgOperand(0),
3184 call_inst.getArgOperand(1),
3185 call_inst.getArgOperand(2),
3186 call_inst.getArgOperand(3),
3187 kByte);
3188 return NULL;
3189 }
3190 case IntrinsicHelper::StaticFieldPutCharFast: {
3191 Expand_SPutFast(call_inst.getArgOperand(0),
3192 call_inst.getArgOperand(1),
3193 call_inst.getArgOperand(2),
3194 call_inst.getArgOperand(3),
3195 kChar);
3196 return NULL;
3197 }
3198 case IntrinsicHelper::StaticFieldPutShortFast: {
3199 Expand_SPutFast(call_inst.getArgOperand(0),
3200 call_inst.getArgOperand(1),
3201 call_inst.getArgOperand(2),
3202 call_inst.getArgOperand(3),
3203 kShort);
3204 return NULL;
3205 }
3206 case IntrinsicHelper::LoadDeclaringClassSSB: {
3207 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3208 }
3209 case IntrinsicHelper::LoadClassSSBFromDexCache: {
3210 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
3211 }
3212 case IntrinsicHelper::InitializeAndLoadClassSSB: {
3213 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
3214 }
Logan Chien75e4b602012-07-23 14:24:12 -07003215
3216 //==- High-level Array -------------------------------------------------==//
3217 case IntrinsicHelper::HLArrayGet: {
TDYa1275a26d442012-07-26 18:58:38 -07003218 return Expand_HLArrayGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003219 }
3220 case IntrinsicHelper::HLArrayGetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003221 return Expand_HLArrayGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003222 }
3223 case IntrinsicHelper::HLArrayGetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003224 return Expand_HLArrayGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003225 }
3226 case IntrinsicHelper::HLArrayGetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003227 return Expand_HLArrayGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003228 }
3229 case IntrinsicHelper::HLArrayGetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003230 return Expand_HLArrayGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003231 }
3232 case IntrinsicHelper::HLArrayGetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003233 return Expand_HLArrayGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003234 }
3235 case IntrinsicHelper::HLArrayGetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003236 return Expand_HLArrayGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003237 }
3238 case IntrinsicHelper::HLArrayGetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003239 return Expand_HLArrayGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003240 }
3241 case IntrinsicHelper::HLArrayGetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003242 return Expand_HLArrayGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003243 }
3244 case IntrinsicHelper::HLArrayPut: {
TDYa1275a26d442012-07-26 18:58:38 -07003245 Expand_HLArrayPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003246 return NULL;
3247 }
3248 case IntrinsicHelper::HLArrayPutBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003249 Expand_HLArrayPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003250 return NULL;
3251 }
3252 case IntrinsicHelper::HLArrayPutByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003253 Expand_HLArrayPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003254 return NULL;
3255 }
3256 case IntrinsicHelper::HLArrayPutChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003257 Expand_HLArrayPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003258 return NULL;
3259 }
3260 case IntrinsicHelper::HLArrayPutShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003261 Expand_HLArrayPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003262 return NULL;
3263 }
3264 case IntrinsicHelper::HLArrayPutFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003265 Expand_HLArrayPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003266 return NULL;
3267 }
3268 case IntrinsicHelper::HLArrayPutWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003269 Expand_HLArrayPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003270 return NULL;
3271 }
3272 case IntrinsicHelper::HLArrayPutDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003273 Expand_HLArrayPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003274 return NULL;
3275 }
3276 case IntrinsicHelper::HLArrayPutObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003277 Expand_HLArrayPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003278 return NULL;
3279 }
3280
3281 //==- High-level Instance ----------------------------------------------==//
3282 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07003283 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003284 }
3285 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003286 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003287 }
3288 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003289 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003290 }
3291 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003292 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003293 }
3294 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003295 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003296 }
3297 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003298 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003299 }
3300 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003301 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003302 }
3303 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003304 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003305 }
3306 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003307 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003308 }
3309 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07003310 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003311 return NULL;
3312 }
3313 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003314 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003315 return NULL;
3316 }
3317 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003318 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003319 return NULL;
3320 }
3321 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003322 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003323 return NULL;
3324 }
3325 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003326 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003327 return NULL;
3328 }
3329 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003330 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003331 return NULL;
3332 }
3333 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003334 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003335 return NULL;
3336 }
3337 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003338 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003339 return NULL;
3340 }
3341 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003342 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003343 return NULL;
3344 }
3345
3346 //==- High-level Invoke ------------------------------------------------==//
TDYa127f71bf5a2012-07-29 20:09:52 -07003347 case IntrinsicHelper::HLInvokeVoid:
3348 case IntrinsicHelper::HLInvokeObj:
3349 case IntrinsicHelper::HLInvokeInt:
3350 case IntrinsicHelper::HLInvokeFloat:
3351 case IntrinsicHelper::HLInvokeLong:
Logan Chien75e4b602012-07-23 14:24:12 -07003352 case IntrinsicHelper::HLInvokeDouble: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003353 return Expand_HLInvoke(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003354 }
3355
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003356 //==- Invoke -----------------------------------------------------------==//
3357 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
3358 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
3359 }
3360 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
3361 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
3362 }
3363 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
3364 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
3365 }
3366 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
3367 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
3368 }
3369 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
3370 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
3371 }
3372 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3373 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3374 }
3375 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3376 return Expand_GetVirtualCalleeMethodObjAddrFast(
3377 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3378 }
3379 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
3380 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
3381 }
3382 case IntrinsicHelper::InvokeRetVoid:
3383 case IntrinsicHelper::InvokeRetBoolean:
3384 case IntrinsicHelper::InvokeRetByte:
3385 case IntrinsicHelper::InvokeRetChar:
3386 case IntrinsicHelper::InvokeRetShort:
3387 case IntrinsicHelper::InvokeRetInt:
3388 case IntrinsicHelper::InvokeRetLong:
3389 case IntrinsicHelper::InvokeRetFloat:
3390 case IntrinsicHelper::InvokeRetDouble:
3391 case IntrinsicHelper::InvokeRetObject: {
3392 return Expand_Invoke(call_inst);
3393 }
Logan Chien75e4b602012-07-23 14:24:12 -07003394
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003395 //==- Math -------------------------------------------------------------==//
3396 case IntrinsicHelper::DivInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003397 return Expand_DivRem(call_inst, /* is_div */true, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003398 }
3399 case IntrinsicHelper::RemInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003400 return Expand_DivRem(call_inst, /* is_div */false, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003401 }
3402 case IntrinsicHelper::DivLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003403 return Expand_DivRem(call_inst, /* is_div */true, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003404 }
3405 case IntrinsicHelper::RemLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003406 return Expand_DivRem(call_inst, /* is_div */false, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003407 }
3408 case IntrinsicHelper::D2L: {
3409 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
3410 }
3411 case IntrinsicHelper::D2I: {
3412 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
3413 }
3414 case IntrinsicHelper::F2L: {
3415 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
3416 }
3417 case IntrinsicHelper::F2I: {
3418 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
3419 }
Logan Chien75e4b602012-07-23 14:24:12 -07003420
3421 //==- High-level Static ------------------------------------------------==//
3422 case IntrinsicHelper::HLSget: {
TDYa1275a26d442012-07-26 18:58:38 -07003423 return Expand_HLSget(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003424 }
3425 case IntrinsicHelper::HLSgetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003426 return Expand_HLSget(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003427 }
3428 case IntrinsicHelper::HLSgetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003429 return Expand_HLSget(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003430 }
3431 case IntrinsicHelper::HLSgetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003432 return Expand_HLSget(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003433 }
3434 case IntrinsicHelper::HLSgetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003435 return Expand_HLSget(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003436 }
3437 case IntrinsicHelper::HLSgetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003438 return Expand_HLSget(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003439 }
3440 case IntrinsicHelper::HLSgetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003441 return Expand_HLSget(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003442 }
3443 case IntrinsicHelper::HLSgetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003444 return Expand_HLSget(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003445 }
3446 case IntrinsicHelper::HLSgetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003447 return Expand_HLSget(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003448 }
3449 case IntrinsicHelper::HLSput: {
TDYa1275a26d442012-07-26 18:58:38 -07003450 Expand_HLSput(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003451 return NULL;
3452 }
3453 case IntrinsicHelper::HLSputBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003454 Expand_HLSput(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003455 return NULL;
3456 }
3457 case IntrinsicHelper::HLSputByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003458 Expand_HLSput(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003459 return NULL;
3460 }
3461 case IntrinsicHelper::HLSputChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003462 Expand_HLSput(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003463 return NULL;
3464 }
3465 case IntrinsicHelper::HLSputShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003466 Expand_HLSput(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003467 return NULL;
3468 }
3469 case IntrinsicHelper::HLSputFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003470 Expand_HLSput(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003471 return NULL;
3472 }
3473 case IntrinsicHelper::HLSputWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003474 Expand_HLSput(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003475 return NULL;
3476 }
3477 case IntrinsicHelper::HLSputDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003478 Expand_HLSput(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003479 return NULL;
3480 }
3481 case IntrinsicHelper::HLSputObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003482 Expand_HLSput(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003483 return NULL;
3484 }
3485
3486 //==- High-level Monitor -----------------------------------------------==//
3487 case IntrinsicHelper::MonitorEnter: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003488 Expand_MonitorEnter(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003489 return NULL;
3490 }
3491 case IntrinsicHelper::MonitorExit: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003492 Expand_MonitorExit(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003493 return NULL;
3494 }
3495
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003496 //==- Shadow Frame -----------------------------------------------------==//
3497 case IntrinsicHelper::AllocaShadowFrame: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08003498 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003499 return NULL;
3500 }
TDYa1278e950c12012-11-02 09:58:19 -07003501 case IntrinsicHelper::SetVReg: {
3502 Expand_SetVReg(call_inst.getArgOperand(0),
3503 call_inst.getArgOperand(1));
3504 return NULL;
3505 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003506 case IntrinsicHelper::PopShadowFrame: {
3507 Expand_PopShadowFrame();
3508 return NULL;
3509 }
3510 case IntrinsicHelper::UpdateDexPC: {
3511 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3512 return NULL;
3513 }
TDYa127a1b21852012-07-23 03:20:39 -07003514
Logan Chien75e4b602012-07-23 14:24:12 -07003515 //==- Comparison -------------------------------------------------------==//
3516 case IntrinsicHelper::CmplFloat:
3517 case IntrinsicHelper::CmplDouble: {
3518 return Expand_FPCompare(call_inst.getArgOperand(0),
3519 call_inst.getArgOperand(1),
3520 false);
3521 }
3522 case IntrinsicHelper::CmpgFloat:
3523 case IntrinsicHelper::CmpgDouble: {
3524 return Expand_FPCompare(call_inst.getArgOperand(0),
3525 call_inst.getArgOperand(1),
3526 true);
3527 }
3528 case IntrinsicHelper::CmpLong: {
3529 return Expand_LongCompare(call_inst.getArgOperand(0),
3530 call_inst.getArgOperand(1));
3531 }
TDYa127a1b21852012-07-23 03:20:39 -07003532
Logan Chien75e4b602012-07-23 14:24:12 -07003533 //==- Const ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003534 case IntrinsicHelper::ConstInt:
3535 case IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003536 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003537 }
TDYa127920be7c2012-09-10 17:13:22 -07003538 case IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003539 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3540 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07003541 }
TDYa127920be7c2012-09-10 17:13:22 -07003542 case IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003543 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3544 irb_.getJDoubleTy());
3545 }
TDYa127920be7c2012-09-10 17:13:22 -07003546 case IntrinsicHelper::ConstObj: {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003547 CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
3548 return irb_.getJNull();
Logan Chien75e4b602012-07-23 14:24:12 -07003549 }
3550
3551 //==- Method Info ------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003552 case IntrinsicHelper::MethodInfo: {
Shih-wei Liaob2596522012-09-14 16:36:11 -07003553 // Nothing to be done, because MethodInfo carries optional hints that are
3554 // not needed by the portable path.
Logan Chien75e4b602012-07-23 14:24:12 -07003555 return NULL;
3556 }
3557
3558 //==- Copy -------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003559 case IntrinsicHelper::CopyInt:
3560 case IntrinsicHelper::CopyFloat:
3561 case IntrinsicHelper::CopyLong:
3562 case IntrinsicHelper::CopyDouble:
3563 case IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003564 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003565 }
3566
3567 //==- Shift ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003568 case IntrinsicHelper::SHLLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003569 return Expand_IntegerShift(call_inst.getArgOperand(0),
3570 call_inst.getArgOperand(1),
3571 kIntegerSHL, kLong);
3572 }
TDYa127920be7c2012-09-10 17:13:22 -07003573 case IntrinsicHelper::SHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003574 return Expand_IntegerShift(call_inst.getArgOperand(0),
3575 call_inst.getArgOperand(1),
3576 kIntegerSHR, kLong);
3577 }
TDYa127920be7c2012-09-10 17:13:22 -07003578 case IntrinsicHelper::USHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003579 return Expand_IntegerShift(call_inst.getArgOperand(0),
3580 call_inst.getArgOperand(1),
3581 kIntegerUSHR, kLong);
3582 }
TDYa127920be7c2012-09-10 17:13:22 -07003583 case IntrinsicHelper::SHLInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003584 return Expand_IntegerShift(call_inst.getArgOperand(0),
3585 call_inst.getArgOperand(1),
3586 kIntegerSHL, kInt);
3587 }
TDYa127920be7c2012-09-10 17:13:22 -07003588 case IntrinsicHelper::SHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003589 return Expand_IntegerShift(call_inst.getArgOperand(0),
3590 call_inst.getArgOperand(1),
3591 kIntegerSHR, kInt);
3592 }
TDYa127920be7c2012-09-10 17:13:22 -07003593 case IntrinsicHelper::USHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003594 return Expand_IntegerShift(call_inst.getArgOperand(0),
3595 call_inst.getArgOperand(1),
3596 kIntegerUSHR, kInt);
3597 }
3598
3599 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07003600 case IntrinsicHelper::IntToChar: {
3601 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3602 irb_.getJIntTy());
3603 }
3604 case IntrinsicHelper::IntToShort: {
3605 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3606 irb_.getJIntTy());
3607 }
3608 case IntrinsicHelper::IntToByte: {
3609 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3610 irb_.getJIntTy());
3611 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003612
TDYa12787caa7e2012-08-25 23:23:27 -07003613 //==- Exception --------------------------------------------------------==//
3614 case IntrinsicHelper::CatchTargets: {
TDYa12755e5e6c2012-09-11 15:14:42 -07003615 UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
TDYa12787caa7e2012-08-25 23:23:27 -07003616 llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
3617 CHECK(si != NULL);
3618 irb_.CreateBr(si->getDefaultDest());
3619 si->eraseFromParent();
3620 return call_inst.getArgOperand(0);
3621 }
3622
Sebastien Hertz0d43d542013-02-27 19:02:16 +01003623 //==- Constructor barrier-----------------------------------------------==//
3624 case IntrinsicHelper::ConstructorBarrier: {
3625 irb_.CreateMemoryBarrier(art::kStoreStore);
3626 return NULL;
3627 }
3628
Logan Chien75e4b602012-07-23 14:24:12 -07003629 //==- Unknown Cases ----------------------------------------------------==//
3630 case IntrinsicHelper::MaxIntrinsicId:
3631 case IntrinsicHelper::UnknownId:
3632 //default:
3633 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3634 // give some warning on unmatched cases.
3635 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003636 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003637 }
Logan Chien75e4b602012-07-23 14:24:12 -07003638 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003639 return NULL;
3640}
3641
3642} // anonymous namespace
3643
3644namespace art {
Shih-wei Liaob2596522012-09-14 16:36:11 -07003645
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003646namespace compiler_llvm {
3647
3648llvm::FunctionPass*
3649CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
3650 return new GBCExpanderPass(intrinsic_helper, irb);
3651}
3652
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003653llvm::FunctionPass*
3654CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
3655 Compiler* compiler, OatCompilationUnit* oat_compilation_unit) {
3656 if (compiler != NULL) {
3657 return new GBCExpanderPass(intrinsic_helper, irb,
3658 compiler, oat_compilation_unit);
3659 } else {
3660 return new GBCExpanderPass(intrinsic_helper, irb);
3661 }
3662}
3663
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003664} // namespace compiler_llvm
3665} // namespace art