blob: 559ce4c8cb21edb397fb418f798a188d3c29e3e2 [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
Ian Rogers1212a022013-03-04 10:48:41 -080017#include "compiler/driver/compiler_driver.h"
Ian Rogers89756f22013-03-04 16:40:02 -080018#include "compiler/driver/dex_compilation_unit.h"
Ian Rogers76ae4fe2013-02-27 16:03:41 -080019#include "intrinsic_helper.h"
Ian Rogers8e696052013-03-04 09:00:40 -080020#include "ir_builder.h"
Ian Rogers98573f92013-01-30 17:26:32 -080021#include "mirror/abstract_method.h"
22#include "mirror/array.h"
Sebastien Hertz901d5ba2013-03-06 15:19:34 +010023#include "mirror/string.h"
Shih-wei Liao21d28f52012-06-12 05:55:00 -070024#include "thread.h"
Ian Rogers8e696052013-03-04 09:00:40 -080025#include "utils_llvm.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
Ian Rogers4c1c2832013-03-04 18:30:13 -080044using namespace art::llvm;
Shih-wei Liao21d28f52012-06-12 05:55:00 -070045
Ian Rogers4c1c2832013-03-04 18:30:13 -080046using art::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:
Ian Rogers1212a022013-03-04 10:48:41 -080067 art::CompilerDriver* const driver_;
TDYa1275e869b62012-07-25 00:45:39 -070068
Ian Rogers89756f22013-03-04 16:40:02 -080069 const art::DexCompilationUnit* const dex_compilation_unit_;
TDYa1275e869b62012-07-25 00:45:39 -070070
TDYa1275e869b62012-07-25 00:45:39 -070071 llvm::Function* func_;
72
73 std::vector<llvm::BasicBlock*> basic_blocks_;
74
75 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
TDYa12755e5e6c2012-09-11 15:14:42 -070076 llvm::BasicBlock* current_bb_;
TDYa127aa558872012-08-16 05:11:07 -070077 std::map<llvm::BasicBlock*, std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> > >
78 landing_pad_phi_mapping_;
TDYa1275e869b62012-07-25 00:45:39 -070079 llvm::BasicBlock* basic_block_unwind_;
80
Logan Chien67645d82012-08-17 09:10:54 +080081 bool changed_;
82
TDYa1275e869b62012-07-25 00:45:39 -070083 private:
Shih-wei Liao21d28f52012-06-12 05:55:00 -070084 //----------------------------------------------------------------------------
Logan Chien75e4b602012-07-23 14:24:12 -070085 // Constant for GBC expansion
86 //----------------------------------------------------------------------------
87 enum IntegerShiftKind {
88 kIntegerSHL,
89 kIntegerSHR,
90 kIntegerUSHR,
91 };
92
93 private:
94 //----------------------------------------------------------------------------
Shih-wei Liao21d28f52012-06-12 05:55:00 -070095 // Helper function for GBC expansion
96 //----------------------------------------------------------------------------
97
Shih-wei Liao21d28f52012-06-12 05:55:00 -070098 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
99 llvm::CallInst& inst);
100
TDYa1275e869b62012-07-25 00:45:39 -0700101 uint64_t LV2UInt(llvm::Value* lv) {
102 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
103 }
104
105 int64_t LV2SInt(llvm::Value* lv) {
106 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
107 }
108
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700109 private:
110 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
111 // Refactor these utility functions from MethodCompiler to avoid forking.
112
Logan Chien67645d82012-08-17 09:10:54 +0800113 void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
114
115 void RewriteFunction();
116
117 void RewriteBasicBlock(llvm::BasicBlock* original_block);
118
119 void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
120 llvm::BasicBlock* new_basic_block);
121
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700122
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800123 // Sign or zero extend category 1 types < 32bits in size to 32bits.
124 llvm::Value* SignOrZeroExtendCat1Types(llvm::Value* value, JType jty);
125
126 // Truncate category 1 types from 32bits to the given JType size.
127 llvm::Value* TruncateCat1Types(llvm::Value* value, JType jty);
128
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700129 //----------------------------------------------------------------------------
130 // Dex cache code generation helper function
131 //----------------------------------------------------------------------------
TDYa127920be7c2012-09-10 17:13:22 -0700132 llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700133
134 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
135
136 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
137
138 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
139
140 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
141
142 //----------------------------------------------------------------------------
143 // Code generation helper function
144 //----------------------------------------------------------------------------
145 llvm::Value* EmitLoadMethodObjectAddr();
146
147 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
148
149 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
150
151 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
152 llvm::Value* this_addr);
153
154 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
155 llvm::Value* index_value,
156 JType elem_jty);
157
Sebastien Hertz901d5ba2013-03-06 15:19:34 +0100158 //----------------------------------------------------------------------------
159 // Invoke helper function
160 //----------------------------------------------------------------------------
161 llvm::Value* EmitInvoke(llvm::CallInst& call_inst);
162
163 //----------------------------------------------------------------------------
164 // Inlining helper functions
165 //----------------------------------------------------------------------------
166 bool EmitIntrinsic(llvm::CallInst& call_inst, llvm::Value** result);
167
168 bool EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
169 llvm::Value** result, bool is_empty);
170
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700171 private:
172 //----------------------------------------------------------------------------
173 // Expand Greenland intrinsics
174 //----------------------------------------------------------------------------
175 void Expand_TestSuspend(llvm::CallInst& call_inst);
176
TDYa1279a129452012-07-19 03:10:08 -0700177 void Expand_MarkGCCard(llvm::CallInst& call_inst);
178
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700179 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
180
181 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
182
183 void Expand_LockObject(llvm::Value* obj);
184
185 void Expand_UnlockObject(llvm::Value* obj);
186
187 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
188 llvm::Value* index_value,
189 JType elem_jty);
190
191 void Expand_ArrayPut(llvm::Value* new_value,
192 llvm::Value* array_addr,
193 llvm::Value* index_value,
194 JType elem_jty);
195
196 void Expand_FilledNewArray(llvm::CallInst& call_inst);
197
198 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
199 llvm::Value* is_volatile_value,
200 llvm::Value* object_addr,
201 JType field_jty);
202
203 void Expand_IPutFast(llvm::Value* field_offset_value,
204 llvm::Value* is_volatile_value,
205 llvm::Value* object_addr,
206 llvm::Value* new_value,
207 JType field_jty);
208
209 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
210 llvm::Value* field_offset_value,
211 llvm::Value* is_volatile_value,
212 JType field_jty);
213
214 void Expand_SPutFast(llvm::Value* static_storage_addr,
215 llvm::Value* field_offset_value,
216 llvm::Value* is_volatile_value,
217 llvm::Value* new_value,
218 JType field_jty);
219
220 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
221
222 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
223
224 llvm::Value*
225 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
226
227 llvm::Value*
228 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
229 llvm::Value* this_addr);
230
231 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
232
TDYa1274ec8ccd2012-08-11 07:04:57 -0700233 llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700234
TDYa127ce4cc0d2012-11-18 16:59:53 -0800235 void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700236
TDYa1278e950c12012-11-02 09:58:19 -0700237 void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
238
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700239 void Expand_PopShadowFrame();
240
241 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
242
TDYa127a1b21852012-07-23 03:20:39 -0700243 //----------------------------------------------------------------------------
244 // Quick
245 //----------------------------------------------------------------------------
246
247 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
248 llvm::Value* src2_value,
249 bool gt_bias);
250
251 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
252
253 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
254 llvm::Value* cmp_lt);
255
TDYa127f71bf5a2012-07-29 20:09:52 -0700256 llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
TDYa1275a26d442012-07-26 18:58:38 -0700257 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
258
TDYa1275e869b62012-07-25 00:45:39 -0700259 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
260 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
261
TDYa1275a26d442012-07-26 18:58:38 -0700262 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
263 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
264
265 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
266 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
267
TDYa127f71bf5a2012-07-29 20:09:52 -0700268 llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
269 llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
270
271 void Expand_MonitorEnter(llvm::CallInst& call_inst);
272 void Expand_MonitorExit(llvm::CallInst& call_inst);
273
274 void Expand_HLCheckCast(llvm::CallInst& call_inst);
275 llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
276
277 llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
278
279 llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
280
281 llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
282 llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
283 llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
284 void Expand_HLFillArrayData(llvm::CallInst& call_inst);
285
286 llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
287 llvm::Value* array_length_value,
288 uint32_t type_idx,
289 bool is_filled_new_array);
290
291 llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -0700292 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -0700293 llvm::Value* this_addr,
294 uint32_t dex_pc,
295 bool is_fast_path);
296
TDYa1275e869b62012-07-25 00:45:39 -0700297 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
298
299 void EmitUpdateDexPC(uint32_t dex_pc);
300
301 void EmitGuard_DivZeroException(uint32_t dex_pc,
302 llvm::Value* denominator,
303 JType op_jty);
304
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +0100305 void EmitGuard_NullPointerException(uint32_t dex_pc, llvm::Value* object,
306 int opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -0700307
308 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
309 llvm::Value* array,
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +0100310 llvm::Value* index,
311 int opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -0700312
Ian Rogers8e696052013-03-04 09:00:40 -0800313 llvm::FunctionType* GetFunctionType(llvm::Type* ret_type, uint32_t method_idx, bool is_static);
TDYa1275e869b62012-07-25 00:45:39 -0700314
315 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
316
317 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
318 const char* postfix);
319
320 int32_t GetTryItemOffset(uint32_t dex_pc);
321
322 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
323
324 llvm::BasicBlock* GetUnwindBasicBlock();
325
326 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
327
328 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
329
Logan Chien75e4b602012-07-23 14:24:12 -0700330 //----------------------------------------------------------------------------
331 // Expand Arithmetic Helper Intrinsics
332 //----------------------------------------------------------------------------
333
334 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
335 llvm::Value* src2_value,
336 IntegerShiftKind kind,
337 JType op_jty);
338
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700339 public:
340 static char ID;
341
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700342 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
Ian Rogers0d94eb62013-03-06 15:20:50 -0800343 art::CompilerDriver* driver, const art::DexCompilationUnit* dex_compilation_unit)
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700344 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
345 context_(irb.getContext()), rtb_(irb.Runtime()),
TDYa1278e950c12012-11-02 09:58:19 -0700346 shadow_frame_(NULL), old_shadow_frame_(NULL),
Ian Rogers0d94eb62013-03-06 15:20:50 -0800347 driver_(driver),
Ian Rogers89756f22013-03-04 16:40:02 -0800348 dex_compilation_unit_(dex_compilation_unit),
Ian Rogers8e696052013-03-04 09:00:40 -0800349 func_(NULL), current_bb_(NULL), basic_block_unwind_(NULL), changed_(false) {}
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700350
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700351 bool runOnFunction(llvm::Function& func);
352
353 private:
Logan Chien67645d82012-08-17 09:10:54 +0800354 void InsertStackOverflowCheck(llvm::Function& func);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700355
356 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
357 llvm::CallInst& call_inst);
358
359};
360
361char GBCExpanderPass::ID = 0;
362
363bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
Ian Rogers8e696052013-03-04 09:00:40 -0800364 VLOG(compiler) << "GBC expansion on " << func.getName().str();
365
TDYa127b672d1e2012-06-28 21:21:45 -0700366 // Runtime support or stub
Brian Carlstrom265091e2013-01-30 14:08:26 -0800367 if (dex_compilation_unit_ == NULL) {
TDYa127b672d1e2012-06-28 21:21:45 -0700368 return false;
369 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700370
Logan Chien67645d82012-08-17 09:10:54 +0800371 // Setup rewrite context
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700372 shadow_frame_ = NULL;
373 old_shadow_frame_ = NULL;
TDYa1275e869b62012-07-25 00:45:39 -0700374 func_ = &func;
Logan Chien67645d82012-08-17 09:10:54 +0800375 changed_ = false; // Assume unchanged
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700376
Ian Rogers89756f22013-03-04 16:40:02 -0800377 basic_blocks_.resize(dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
378 basic_block_landing_pads_.resize(dex_compilation_unit_->GetCodeItem()->tries_size_, NULL);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700379 basic_block_unwind_ = NULL;
380 for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
381 bb_iter != bb_end;
382 ++bb_iter) {
383 if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
384 continue;
385 }
386 uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
387 basic_blocks_[dex_pc] = bb_iter;
388 }
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700389
Logan Chien67645d82012-08-17 09:10:54 +0800390 // Insert stack overflow check
391 InsertStackOverflowCheck(func); // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700392
Logan Chien67645d82012-08-17 09:10:54 +0800393 // Rewrite the intrinsics
394 RewriteFunction();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700395
396 VERIFY_LLVM_FUNCTION(func);
397
Logan Chien67645d82012-08-17 09:10:54 +0800398 return changed_;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700399}
400
Logan Chien67645d82012-08-17 09:10:54 +0800401void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
402 llvm::BasicBlock* curr_basic_block = original_block;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700403
Logan Chien67645d82012-08-17 09:10:54 +0800404 llvm::BasicBlock::iterator inst_iter = original_block->begin();
405 llvm::BasicBlock::iterator inst_end = original_block->end();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700406
Logan Chien67645d82012-08-17 09:10:54 +0800407 while (inst_iter != inst_end) {
408 llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
409 IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700410
Logan Chien67645d82012-08-17 09:10:54 +0800411 if (call_inst) {
412 llvm::Function* callee_func = call_inst->getCalledFunction();
413 intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
414 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700415
Logan Chien67645d82012-08-17 09:10:54 +0800416 if (intr_id == IntrinsicHelper::UnknownId) {
417 // This is not intrinsic call. Skip this instruction.
418 ++inst_iter;
419 continue;
420 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700421
Logan Chien67645d82012-08-17 09:10:54 +0800422 // Rewrite the intrinsic and change the function
423 changed_ = true;
424 irb_.SetInsertPoint(inst_iter);
425
426 // Expand the intrinsic
427 if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
428 inst_iter->replaceAllUsesWith(new_value);
429 }
430
431 // Remove the old intrinsic call instruction
432 llvm::BasicBlock::iterator old_inst = inst_iter++;
433 old_inst->eraseFromParent();
434
435 // Splice the instruction to the new basic block
436 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
437 if (next_basic_block != curr_basic_block) {
438 next_basic_block->getInstList().splice(
439 irb_.GetInsertPoint(), curr_basic_block->getInstList(),
440 inst_iter, inst_end);
441 curr_basic_block = next_basic_block;
442 inst_end = curr_basic_block->end();
443 }
444 }
445}
446
447
448void GBCExpanderPass::RewriteFunction() {
449 size_t num_basic_blocks = func_->getBasicBlockList().size();
450 // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
451 // because we will create new basic block while expanding the intrinsics.
452 // We only want to iterate through the input basic blocks.
453
TDYa127aa558872012-08-16 05:11:07 -0700454 landing_pad_phi_mapping_.clear();
455
Logan Chien67645d82012-08-17 09:10:54 +0800456 for (llvm::Function::iterator bb_iter = func_->begin();
457 num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
Shih-wei Liao627d8c42012-08-24 08:31:18 -0700458 // Set insert point to current basic block.
459 irb_.SetInsertPoint(bb_iter);
Logan Chien67645d82012-08-17 09:10:54 +0800460
TDYa12755e5e6c2012-09-11 15:14:42 -0700461 current_bb_ = bb_iter;
TDYa127aa558872012-08-16 05:11:07 -0700462
Logan Chien67645d82012-08-17 09:10:54 +0800463 // Rewrite the basic block
464 RewriteBasicBlock(bb_iter);
465
466 // Update the phi-instructions in the successor basic block
467 llvm::BasicBlock* last_block = irb_.GetInsertBlock();
468 if (last_block != bb_iter) {
469 UpdatePhiInstruction(bb_iter, last_block);
470 }
471 }
TDYa127aa558872012-08-16 05:11:07 -0700472
473 typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
474 HandlerPHIMap handler_phi;
475 // Iterate every used landing pad basic block
476 for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
477 llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
478 if (lbb == NULL) {
479 continue;
480 }
481
482 llvm::TerminatorInst* term_inst = lbb->getTerminator();
483 std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> >& rewrite_pair
484 = landing_pad_phi_mapping_[lbb];
485 irb_.SetInsertPoint(lbb->begin());
486
487 // Iterate every succeeding basic block (catch block)
488 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
489 succ_iter != succ_end; ++succ_iter) {
490 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
491
492 // Iterate every phi instructions in the succeeding basic block
493 for (llvm::BasicBlock::iterator
494 inst_iter = succ_basic_block->begin(),
495 inst_end = succ_basic_block->end();
496 inst_iter != inst_end; ++inst_iter) {
497 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
498
499 if (!phi) {
500 break; // Meet non-phi instruction. Done.
501 }
502
503 if (handler_phi[phi] == NULL) {
504 handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
505 }
506
507 // Create new_phi in landing pad
508 llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
509 // Insert all incoming value into new_phi by rewrite_pair
510 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
511 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
512 llvm::BasicBlock* new_bb = rewrite_pair[j].second;
513 new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
514 }
515 // Delete all incoming value from phi by rewrite_pair
516 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
517 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
518 int old_bb_idx = phi->getBasicBlockIndex(old_bb);
519 if (old_bb_idx >= 0) {
520 phi->removeIncomingValue(old_bb_idx, false);
521 }
522 }
523 // Insert new_phi into new handler phi
524 handler_phi[phi]->addIncoming(new_phi, lbb);
525 }
526 }
527 }
528
529 // Replace all handler phi
530 // We can't just use the old handler phi, because some exception edges will disappear after we
531 // compute fast-path.
532 for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
533 llvm::PHINode* old_phi = it->first;
534 llvm::PHINode* new_phi = it->second;
535 new_phi->insertBefore(old_phi);
536 old_phi->replaceAllUsesWith(new_phi);
537 old_phi->eraseFromParent();
538 }
Logan Chien67645d82012-08-17 09:10:54 +0800539}
540
541void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
542 llvm::BasicBlock* new_basic_block) {
543 llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
544
545 if (!term_inst) {
546 return; // No terminating instruction in new_basic_block. Nothing to do.
547 }
548
549 // Iterate every succeeding basic block
550 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
551 succ_iter != succ_end; ++succ_iter) {
552 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
553
554 // Iterate every phi instructions in the succeeding basic block
555 for (llvm::BasicBlock::iterator
556 inst_iter = succ_basic_block->begin(),
557 inst_end = succ_basic_block->end();
558 inst_iter != inst_end; ++inst_iter) {
559 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
560
561 if (!phi) {
562 break; // Meet non-phi instruction. Done.
563 }
564
565 // Update the incoming block of this phi instruction
566 for (llvm::PHINode::block_iterator
567 ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
568 ibb_iter != ibb_end; ++ibb_iter) {
569 if (*ibb_iter == old_basic_block) {
570 *ibb_iter = new_basic_block;
571 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700572 }
573 }
574 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700575}
576
577llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
578 llvm::CallInst& inst) {
579 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
580 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
581 // function, therefore only called function is needed to change.
582 unsigned num_args = inst.getNumArgOperands();
583
584 if (num_args <= 0) {
585 return irb_.CreateCall(irb_.GetRuntime(rt));
586 } else {
587 std::vector<llvm::Value*> args;
588 for (unsigned i = 0; i < num_args; i++) {
589 args.push_back(inst.getArgOperand(i));
590 }
591
592 return irb_.CreateCall(irb_.GetRuntime(rt), args);
593 }
594}
595
Logan Chien67645d82012-08-17 09:10:54 +0800596void
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700597GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
598 llvm::Function* func = first_non_alloca->getParent()->getParent();
599 llvm::Module* module = func->getParent();
600
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700601 // Call llvm intrinsic function to get frame address.
602 llvm::Function* frameaddress =
603 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
604
605 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
606 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
607
608 // Cast i8* to int
609 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
610
611 // Get thread.stack_end_
612 llvm::Value* stack_end =
TDYa127920be7c2012-09-10 17:13:22 -0700613 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700614 irb_.getPtrEquivIntTy(),
615 kTBAARuntimeInfo);
616
617 // Check the frame address < thread.stack_end_ ?
618 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
619
620 llvm::BasicBlock* block_exception =
621 llvm::BasicBlock::Create(context_, "stack_overflow", func);
622
623 llvm::BasicBlock* block_continue =
624 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
625
626 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
627
628 // If stack overflow, throw exception.
629 irb_.SetInsertPoint(block_exception);
630 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
631
632 // Unwind.
633 llvm::Type* ret_type = func->getReturnType();
634 if (ret_type->isVoidTy()) {
635 irb_.CreateRetVoid();
636 } else {
637 // The return value is ignored when there's an exception. MethodCompiler
638 // returns zero value under the the corresponding return type in this case.
639 // GBCExpander returns LLVM undef value here for brevity
640 irb_.CreateRet(llvm::UndefValue::get(ret_type));
641 }
642
643 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700644}
645
TDYa127920be7c2012-09-10 17:13:22 -0700646llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700647 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
648
649 return irb_.LoadFromObjectOffset(method_object_addr,
650 offset.Int32Value(),
651 irb_.getJObjectTy(),
652 kTBAAConstJObject);
653}
654
655llvm::Value*
656GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
657 llvm::Value* static_storage_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800658 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700659
660 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
661
662 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
663}
664
665llvm::Value*
666GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
667 llvm::Value* resolved_type_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800668 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedTypesOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700669
670 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
671
672 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
673}
674
675llvm::Value* GBCExpanderPass::
676EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
677 llvm::Value* resolved_method_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800678 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedMethodsOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700679
680 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
681
682 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
683}
684
685llvm::Value* GBCExpanderPass::
686EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
687 llvm::Value* string_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800688 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheStringsOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700689
690 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
691
692 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
693}
694
695llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
696 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
697 return parent_func->arg_begin();
698}
699
700llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
701 // Load array length
702 return irb_.LoadFromObjectOffset(array,
Ian Rogers98573f92013-01-30 17:26:32 -0800703 art::mirror::Array::LengthOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700704 irb_.getJIntTy(),
705 kTBAAConstJObject);
706
707}
708
709llvm::Value*
710GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
711 llvm::Value* callee_method_object_field_addr =
712 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
713
TDYa127ce4cc0d2012-11-18 16:59:53 -0800714 return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700715}
716
717llvm::Value* GBCExpanderPass::
718EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
719 // Load class object of *this* pointer
720 llvm::Value* class_object_addr =
721 irb_.LoadFromObjectOffset(this_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800722 art::mirror::Object::ClassOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700723 irb_.getJObjectTy(),
724 kTBAAConstJObject);
725
726 // Load vtable address
727 llvm::Value* vtable_addr =
728 irb_.LoadFromObjectOffset(class_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800729 art::mirror::Class::VTableOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700730 irb_.getJObjectTy(),
731 kTBAAConstJObject);
732
733 // Load callee method object
734 llvm::Value* vtable_idx_value =
735 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
736
737 llvm::Value* method_field_addr =
738 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
739
740 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
741}
742
743// Emit Array GetElementPtr
744llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
745 llvm::Value* index_value,
746 JType elem_jty) {
747
748 int data_offset;
749 if (elem_jty == kLong || elem_jty == kDouble ||
Ian Rogers98573f92013-01-30 17:26:32 -0800750 (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::mirror::Object*))) {
751 data_offset = art::mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700752 } else {
Ian Rogers98573f92013-01-30 17:26:32 -0800753 data_offset = art::mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700754 }
755
756 llvm::Constant* data_offset_value =
757 irb_.getPtrEquivInt(data_offset);
758
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800759 llvm::Type* elem_type = irb_.getJType(elem_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700760
761 llvm::Value* array_data_addr =
762 irb_.CreatePtrDisp(array_addr, data_offset_value,
763 elem_type->getPointerTo());
764
765 return irb_.CreateGEP(array_data_addr, index_value);
766}
767
Sebastien Hertz901d5ba2013-03-06 15:19:34 +0100768llvm::Value* GBCExpanderPass::EmitInvoke(llvm::CallInst& call_inst) {
769 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
770 art::InvokeType invoke_type =
771 static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
772 bool is_static = (invoke_type == art::kStatic);
773 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
774
775 // Load *this* actual parameter
776 llvm::Value* this_addr = (!is_static) ? call_inst.getArgOperand(3) : NULL;
777
778 // Compute invoke related information for compiler decision
779 int vtable_idx = -1;
780 uintptr_t direct_code = 0;
781 uintptr_t direct_method = 0;
782 bool is_fast_path = driver_->
783 ComputeInvokeInfo(callee_method_idx, dex_compilation_unit_,
784 invoke_type, vtable_idx, direct_code, direct_method);
785
786 // Load the method object
787 llvm::Value* callee_method_object_addr = NULL;
788
789 if (!is_fast_path) {
790 callee_method_object_addr =
791 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
792 this_addr, dex_pc, is_fast_path);
793 } else {
794 switch (invoke_type) {
795 case art::kStatic:
796 case art::kDirect:
797 if (direct_method != 0u &&
798 direct_method != static_cast<uintptr_t>(-1)) {
799 callee_method_object_addr =
800 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
801 irb_.getJObjectTy());
802 } else {
803 callee_method_object_addr =
804 EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
805 }
806 break;
807
808 case art::kVirtual:
809 DCHECK(vtable_idx != -1);
810 callee_method_object_addr =
811 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
812 break;
813
814 case art::kSuper:
815 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
816 "the fast path.";
817 break;
818
819 case art::kInterface:
820 callee_method_object_addr =
821 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
822 invoke_type, this_addr,
823 dex_pc, is_fast_path);
824 break;
825 }
826 }
827
828 // Load the actual parameter
829 std::vector<llvm::Value*> args;
830
831 args.push_back(callee_method_object_addr); // method object for callee
832
833 for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
834 args.push_back(call_inst.getArgOperand(i));
835 }
836
837 llvm::Value* code_addr;
838 llvm::Type* func_type = GetFunctionType(call_inst.getType(),
839 callee_method_idx, is_static);
840 if (direct_code != 0u && direct_code != static_cast<uintptr_t>(-1)) {
841 code_addr =
842 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
843 func_type->getPointerTo());
844 } else {
845 code_addr =
846 irb_.LoadFromObjectOffset(callee_method_object_addr,
847 art::mirror::AbstractMethod::GetCodeOffset().Int32Value(),
848 func_type->getPointerTo(), kTBAARuntimeInfo);
849 }
850
851 // Invoke callee
852 EmitUpdateDexPC(dex_pc);
853 llvm::Value* retval = irb_.CreateCall(code_addr, args);
854 EmitGuard_ExceptionLandingPad(dex_pc);
855
856 return retval;
857}
858
859bool GBCExpanderPass::EmitIntrinsic(llvm::CallInst& call_inst,
860 llvm::Value** result) {
861 DCHECK(result != NULL);
862
863 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
864 std::string callee_method_name(
865 PrettyMethod(callee_method_idx, *dex_compilation_unit_->GetDexFile()));
866
867 if (callee_method_name == "int java.lang.String.length()") {
868 return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
869 false /* is_empty */);
870 }
871 if (callee_method_name == "boolean java.lang.String.isEmpty()") {
872 return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
873 true /* is_empty */);
874 }
875
876 *result = NULL;
877 return false;
878}
879
880bool GBCExpanderPass::EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
881 llvm::Value** result,
882 bool is_empty) {
883 art::InvokeType invoke_type =
884 static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
885 DCHECK_NE(invoke_type, art::kStatic);
886 DCHECK_EQ(call_inst.getNumArgOperands(), 4U);
887
888 llvm::Value* this_object = call_inst.getArgOperand(3);
889 llvm::Value* string_count =
890 irb_.LoadFromObjectOffset(this_object,
891 art::mirror::String::CountOffset().Int32Value(),
892 irb_.getJIntTy(),
893 kTBAAConstJObject);
894 if (is_empty) {
895 llvm::Value* count_equals_zero = irb_.CreateICmpEQ(string_count,
896 irb_.getJInt(0));
897 llvm::Value* is_empty = irb_.CreateSelect(count_equals_zero,
898 irb_.getJBoolean(true),
899 irb_.getJBoolean(false));
900 is_empty = SignOrZeroExtendCat1Types(is_empty, kBoolean);
901 *result = is_empty;
902 } else {
903 *result = string_count;
904 }
905 return true;
906}
907
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700908void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
TDYa127ce4cc0d2012-11-18 16:59:53 -0800909 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
910
911 llvm::Value* suspend_count =
912 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
913 irb_.getInt16Ty(),
914 kTBAARuntimeInfo);
915 llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
916
917 llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
918 llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
919
920 irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
921
922 irb_.SetInsertPoint(basic_block_suspend);
923 if (dex_pc != art::DexFile::kDexNoIndex) {
924 EmitUpdateDexPC(dex_pc);
925 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700926 irb_.Runtime().EmitTestSuspend();
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800927
928 llvm::BasicBlock* basic_block_exception = CreateBasicBlockWithDexPC(dex_pc, "exception");
929 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
930 irb_.CreateCondBr(exception_pending, basic_block_exception, basic_block_cont, kUnlikely);
931
932 irb_.SetInsertPoint(basic_block_exception);
933 llvm::Type* ret_type = call_inst.getParent()->getParent()->getReturnType();
934 if (ret_type->isVoidTy()) {
935 irb_.CreateRetVoid();
936 } else {
937 // The return value is ignored when there's an exception.
938 irb_.CreateRet(llvm::UndefValue::get(ret_type));
939 }
TDYa127ce4cc0d2012-11-18 16:59:53 -0800940
941 irb_.SetInsertPoint(basic_block_cont);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700942 return;
943}
944
TDYa1279a129452012-07-19 03:10:08 -0700945void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1279a129452012-07-19 03:10:08 -0700946 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700947 return;
948}
949
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700950llvm::Value*
951GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
952 uint32_t string_idx =
953 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
954
955 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
956
TDYa127ce4cc0d2012-11-18 16:59:53 -0800957 return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700958}
959
960llvm::Value*
961GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
962 uint32_t type_idx =
963 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
964
965 llvm::Value* type_field_addr =
966 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
967
TDYa127ce4cc0d2012-11-18 16:59:53 -0800968 return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700969}
970
971void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700972 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700973 return;
974}
975
976void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700977 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700978 return;
979}
980
981llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
982 llvm::Value* index_value,
983 JType elem_jty) {
984 llvm::Value* array_elem_addr =
985 EmitArrayGEP(array_addr, index_value, elem_jty);
986
987 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
988}
989
990void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
991 llvm::Value* array_addr,
992 llvm::Value* index_value,
993 JType elem_jty) {
994 llvm::Value* array_elem_addr =
995 EmitArrayGEP(array_addr, index_value, elem_jty);
996
997 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
998
999 return;
1000}
1001
1002void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
1003 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
1004 llvm::Value* array = call_inst.getArgOperand(0);
1005
1006 uint32_t element_jty =
1007 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
1008
1009 DCHECK(call_inst.getNumArgOperands() > 2);
1010 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
1011
1012 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
1013
1014 uint32_t alignment;
1015 llvm::Constant* elem_size;
1016 llvm::PointerType* field_type;
1017
1018 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
1019 // as the element, thus we are only checking 2 cases: primitive int and
1020 // non-primitive type.
1021 if (is_elem_int_ty) {
1022 alignment = sizeof(int32_t);
1023 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
1024 field_type = irb_.getJIntTy()->getPointerTo();
1025 } else {
1026 alignment = irb_.getSizeOfPtrEquivInt();
1027 elem_size = irb_.getSizeOfPtrEquivIntValue();
1028 field_type = irb_.getJObjectTy()->getPointerTo();
1029 }
1030
1031 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -08001032 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001033
1034 llvm::Value* data_field_addr =
1035 irb_.CreatePtrDisp(array, data_field_offset, field_type);
1036
1037 for (unsigned i = 0; i < num_elements; ++i) {
1038 // Values to fill the array begin at the 3rd argument
1039 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
1040
1041 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
1042
1043 data_field_addr =
1044 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
1045 }
1046
1047 return;
1048}
1049
1050llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
1051 llvm::Value* /*is_volatile_value*/,
1052 llvm::Value* object_addr,
1053 JType field_jty) {
1054 int field_offset =
1055 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1056
1057 DCHECK_GE(field_offset, 0);
1058
1059 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001060 irb_.getJType(field_jty)->getPointerTo();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001061
1062 field_offset_value = irb_.getPtrEquivInt(field_offset);
1063
1064 llvm::Value* field_addr =
1065 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1066
1067 // TODO: Check is_volatile. We need to generate atomic load instruction
1068 // when is_volatile is true.
1069 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1070}
1071
1072void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
1073 llvm::Value* /* is_volatile_value */,
1074 llvm::Value* object_addr,
1075 llvm::Value* new_value,
1076 JType field_jty) {
1077 int field_offset =
1078 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1079
1080 DCHECK_GE(field_offset, 0);
1081
1082 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001083 irb_.getJType(field_jty)->getPointerTo();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001084
1085 field_offset_value = irb_.getPtrEquivInt(field_offset);
1086
1087 llvm::Value* field_addr =
1088 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1089
1090 // TODO: Check is_volatile. We need to generate atomic store instruction
1091 // when is_volatile is true.
1092 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1093
1094 return;
1095}
1096
1097llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
1098 llvm::Value* field_offset_value,
1099 llvm::Value* /*is_volatile_value*/,
1100 JType field_jty) {
1101 int field_offset =
1102 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1103
1104 DCHECK_GE(field_offset, 0);
1105
1106 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1107
1108 llvm::Value* static_field_addr =
1109 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001110 irb_.getJType(field_jty)->getPointerTo());
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001111
1112 // TODO: Check is_volatile. We need to generate atomic store instruction
1113 // when is_volatile is true.
1114 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1115}
1116
1117void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
1118 llvm::Value* field_offset_value,
1119 llvm::Value* /* is_volatile_value */,
1120 llvm::Value* new_value,
1121 JType field_jty) {
1122 int field_offset =
1123 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1124
1125 DCHECK_GE(field_offset, 0);
1126
1127 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1128
1129 llvm::Value* static_field_addr =
1130 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001131 irb_.getJType(field_jty)->getPointerTo());
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001132
1133 // TODO: Check is_volatile. We need to generate atomic store instruction
1134 // when is_volatile is true.
1135 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1136
1137 return;
1138}
1139
1140llvm::Value*
1141GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
1142 return irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001143 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001144 irb_.getJObjectTy(),
1145 kTBAAConstJObject);
1146}
1147
1148llvm::Value*
1149GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
1150 uint32_t type_idx =
1151 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
1152
1153 llvm::Value* storage_field_addr =
1154 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1155
TDYa127ce4cc0d2012-11-18 16:59:53 -08001156 return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001157}
1158
1159llvm::Value*
1160GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
1161 uint32_t callee_method_idx =
1162 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
1163
1164 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
1165}
1166
1167llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
1168 llvm::Value* vtable_idx_value,
1169 llvm::Value* this_addr) {
1170 int vtable_idx =
1171 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
1172
1173 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
1174}
1175
1176llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
1177 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
1178 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
1179 unsigned num_args = call_inst.getNumArgOperands();
1180 llvm::Type* ret_type = call_inst.getType();
1181
1182 // Determine the function type of the callee method
1183 std::vector<llvm::Type*> args_type;
1184 std::vector<llvm::Value*> args;
1185 for (unsigned i = 0; i < num_args; i++) {
1186 args.push_back(call_inst.getArgOperand(i));
1187 args_type.push_back(args[i]->getType());
1188 }
1189
1190 llvm::FunctionType* callee_method_type =
1191 llvm::FunctionType::get(ret_type, args_type, false);
1192
1193 llvm::Value* code_addr =
1194 irb_.LoadFromObjectOffset(callee_method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001195 art::mirror::AbstractMethod::GetCodeOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001196 callee_method_type->getPointerTo(),
TDYa127ce4cc0d2012-11-18 16:59:53 -08001197 kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001198
1199 // Invoke callee
1200 llvm::Value* retval = irb_.CreateCall(code_addr, args);
1201
1202 return retval;
1203}
1204
TDYa1274ec8ccd2012-08-11 07:04:57 -07001205llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001206 bool is_div, JType op_jty) {
TDYa1274ec8ccd2012-08-11 07:04:57 -07001207 llvm::Value* dividend = call_inst.getArgOperand(0);
1208 llvm::Value* divisor = call_inst.getArgOperand(1);
TDYa1274ec8ccd2012-08-11 07:04:57 -07001209 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1210 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001211 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
1212
1213 // Check the special case: MININT / -1 = MININT
1214 // That case will cause overflow, which is undefined behavior in llvm.
1215 // So we check the divisor is -1 or not, if the divisor is -1, we do
1216 // the special path to avoid undefined behavior.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001217 llvm::Type* op_type = irb_.getJType(op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001218 llvm::Value* zero = irb_.getJZero(op_jty);
1219 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
1220
TDYa1275e869b62012-07-25 00:45:39 -07001221 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001222 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1223 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1224 llvm::BasicBlock* neg_one_cont =
1225 llvm::BasicBlock::Create(context_, "", parent);
1226
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001227 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
1228 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
1229
1230 // If divisor == -1
1231 irb_.SetInsertPoint(eq_neg_one);
1232 llvm::Value* eq_result;
1233 if (is_div) {
1234 // We can just change from "dividend div -1" to "neg dividend". The sub
1235 // don't care the sign/unsigned because of two's complement representation.
1236 // And the behavior is what we want:
1237 // -(2^n) (2^n)-1
1238 // MININT < k <= MAXINT -> mul k -1 = -k
1239 // MININT == k -> mul k -1 = k
1240 //
1241 // LLVM use sub to represent 'neg'
1242 eq_result = irb_.CreateSub(zero, dividend);
1243 } else {
1244 // Everything modulo -1 will be 0.
1245 eq_result = zero;
1246 }
1247 irb_.CreateBr(neg_one_cont);
1248
1249 // If divisor != -1, just do the division.
1250 irb_.SetInsertPoint(ne_neg_one);
1251 llvm::Value* ne_result;
1252 if (is_div) {
1253 ne_result = irb_.CreateSDiv(dividend, divisor);
1254 } else {
1255 ne_result = irb_.CreateSRem(dividend, divisor);
1256 }
1257 irb_.CreateBr(neg_one_cont);
1258
1259 irb_.SetInsertPoint(neg_one_cont);
1260 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
1261 result->addIncoming(eq_result, eq_neg_one);
1262 result->addIncoming(ne_result, ne_neg_one);
1263
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001264 return result;
1265}
1266
TDYa127ce4cc0d2012-11-18 16:59:53 -08001267void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001268 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
1269 // MethodCompiler::EmitPushShadowFrame
TDYa1278e950c12012-11-02 09:58:19 -07001270 uint16_t num_vregs =
1271 llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001272
1273 llvm::StructType* shadow_frame_type =
TDYa127ce4cc0d2012-11-18 16:59:53 -08001274 irb_.getShadowFrameTy(num_vregs);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001275
Sebastien Hertz77209702013-02-28 16:34:13 +01001276 // Create allocas at the start of entry block.
1277 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1278 llvm::BasicBlock* entry_block = &func_->front();
1279 irb_.SetInsertPoint(&entry_block->front());
1280
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001281 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
1282
1283 // Alloca a pointer to old shadow frame
1284 old_shadow_frame_ =
1285 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
1286
Sebastien Hertz77209702013-02-28 16:34:13 +01001287 irb_.restoreIP(irb_ip_original);
1288
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001289 // Push the shadow frame
1290 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1291
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001292 llvm::Value* shadow_frame_upcast =
1293 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1294
1295 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1296 method_object_addr,
TDYa1278e950c12012-11-02 09:58:19 -07001297 num_vregs);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001298
1299 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1300
1301 return;
1302}
1303
TDYa1278e950c12012-11-02 09:58:19 -07001304void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
1305 llvm::Value* value) {
1306 DCHECK(shadow_frame_ != NULL);
1307
1308 llvm::Value* gep_index[] = {
1309 irb_.getInt32(0), // No pointer displacement
TDYa127ce4cc0d2012-11-18 16:59:53 -08001310 irb_.getInt32(1), // VRegs
TDYa1278e950c12012-11-02 09:58:19 -07001311 entry_idx // Pointer field
1312 };
1313
1314 llvm::Value* vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1315
1316 irb_.CreateStore(value,
1317 irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
1318 kTBAAShadowFrame);
1319 return;
1320}
1321
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001322void GBCExpanderPass::Expand_PopShadowFrame() {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001323 if (old_shadow_frame_ == NULL) {
1324 return;
1325 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001326 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1327 return;
1328}
1329
1330void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1331 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07001332 art::ShadowFrame::DexPCOffset(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001333 dex_pc_value,
1334 kTBAAShadowFrame);
1335 return;
1336}
1337
Logan Chien67645d82012-08-17 09:10:54 +08001338void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
jeffhao40283122013-01-15 13:15:24 -08001339 // All alloca instructions are generated in the first basic block of the
1340 // function, and there are no alloca instructions after the first non-alloca
1341 // instruction.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001342
Logan Chien67645d82012-08-17 09:10:54 +08001343 llvm::BasicBlock* first_basic_block = &func.front();
1344
1345 // Look for first non-alloca instruction
1346 llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001347 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1348 ++first_non_alloca;
1349 }
1350
Logan Chien67645d82012-08-17 09:10:54 +08001351 irb_.SetInsertPoint(first_non_alloca);
1352
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001353 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1354 // alloca instructions)
Logan Chien67645d82012-08-17 09:10:54 +08001355 EmitStackOverflowCheck(&*first_non_alloca);
1356
TDYa127890ea892012-08-22 10:49:42 -07001357 irb_.Runtime().EmitTestSuspend();
TDYa127890ea892012-08-22 10:49:42 -07001358
Logan Chien67645d82012-08-17 09:10:54 +08001359 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
1360 if (next_basic_block != first_basic_block) {
1361 // Splice the rest of the instruction to the continuing basic block
1362 next_basic_block->getInstList().splice(
1363 irb_.GetInsertPoint(), first_basic_block->getInstList(),
1364 first_non_alloca, first_basic_block->end());
1365
1366 // Rewrite the basic block
1367 RewriteBasicBlock(next_basic_block);
1368
1369 // Update the phi-instructions in the successor basic block
1370 UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
1371 }
1372
1373 // We have changed the basic block
1374 changed_ = true;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001375}
1376
TDYa1275e869b62012-07-25 00:45:39 -07001377// ==== High-level intrinsic expander ==========================================
1378
TDYa127a1b21852012-07-23 03:20:39 -07001379llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1380 llvm::Value* src2_value,
1381 bool gt_bias) {
1382 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1383 llvm::Value* cmp_lt;
1384
1385 if (gt_bias) {
1386 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1387 } else {
1388 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1389 }
1390
1391 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1392}
1393
1394llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1395 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1396 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1397
1398 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1399}
1400
1401llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1402 llvm::Value* cmp_lt) {
1403
1404 llvm::Constant* zero = irb_.getJInt(0);
1405 llvm::Constant* pos1 = irb_.getJInt(1);
1406 llvm::Constant* neg1 = irb_.getJInt(-1);
1407
1408 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1409 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1410
1411 return result_eq;
1412}
1413
Logan Chien75e4b602012-07-23 14:24:12 -07001414llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1415 llvm::Value* src2_value,
1416 IntegerShiftKind kind,
1417 JType op_jty) {
1418 DCHECK(op_jty == kInt || op_jty == kLong);
1419
1420 // Mask and zero-extend RHS properly
1421 if (op_jty == kInt) {
1422 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1423 } else {
1424 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1425 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1426 }
1427
1428 // Create integer shift llvm instruction
1429 switch (kind) {
1430 case kIntegerSHL:
1431 return irb_.CreateShl(src1_value, src2_value);
1432
1433 case kIntegerSHR:
1434 return irb_.CreateAShr(src1_value, src2_value);
1435
1436 case kIntegerUSHR:
1437 return irb_.CreateLShr(src1_value, src2_value);
1438
1439 default:
1440 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1441 return NULL;
1442 }
1443}
1444
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001445llvm::Value* GBCExpanderPass::SignOrZeroExtendCat1Types(llvm::Value* value, JType jty) {
1446 switch (jty) {
1447 case kBoolean:
1448 case kChar:
1449 return irb_.CreateZExt(value, irb_.getJType(kInt));
1450 case kByte:
1451 case kShort:
1452 return irb_.CreateSExt(value, irb_.getJType(kInt));
1453 case kVoid:
1454 case kInt:
1455 case kLong:
1456 case kFloat:
1457 case kDouble:
1458 case kObject:
1459 return value; // Nothing to do.
1460 default:
1461 LOG(FATAL) << "Unknown java type: " << jty;
1462 return NULL;
1463 }
1464}
1465
1466llvm::Value* GBCExpanderPass::TruncateCat1Types(llvm::Value* value, JType jty) {
1467 switch (jty) {
1468 case kBoolean:
1469 case kChar:
1470 case kByte:
1471 case kShort:
1472 return irb_.CreateTrunc(value, irb_.getJType(jty));
1473 case kVoid:
1474 case kInt:
1475 case kLong:
1476 case kFloat:
1477 case kDouble:
1478 case kObject:
1479 return value; // Nothing to do.
1480 default:
1481 LOG(FATAL) << "Unknown java type: " << jty;
1482 return NULL;
1483 }
1484}
1485
TDYa1275a26d442012-07-26 18:58:38 -07001486llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1487 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001488 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1489 llvm::Value* array_addr = call_inst.getArgOperand(1);
1490 llvm::Value* index_value = call_inst.getArgOperand(2);
TDYa127920be7c2012-09-10 17:13:22 -07001491 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275a26d442012-07-26 18:58:38 -07001492
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001493 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
1494 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
1495 opt_flags);
TDYa1275a26d442012-07-26 18:58:38 -07001496
1497 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1498
1499 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1500
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001501 return SignOrZeroExtendCat1Types(array_elem_value, elem_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001502}
1503
1504
1505void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1506 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001507 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1508 llvm::Value* new_value = call_inst.getArgOperand(1);
1509 llvm::Value* array_addr = call_inst.getArgOperand(2);
1510 llvm::Value* index_value = call_inst.getArgOperand(3);
TDYa127920be7c2012-09-10 17:13:22 -07001511 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275a26d442012-07-26 18:58:38 -07001512
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001513 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
1514 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
1515 opt_flags);
TDYa1275a26d442012-07-26 18:58:38 -07001516
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001517 new_value = TruncateCat1Types(new_value, elem_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001518
1519 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1520
1521 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
1522 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
1523
1524 irb_.CreateCall2(runtime_func, new_value, array_addr);
1525
1526 EmitGuard_ExceptionLandingPad(dex_pc);
1527
1528 EmitMarkGCCard(new_value, array_addr);
1529 }
1530
1531 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1532
1533 return;
1534}
1535
TDYa1275e869b62012-07-25 00:45:39 -07001536llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1537 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001538 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1539 llvm::Value* object_addr = call_inst.getArgOperand(1);
1540 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
TDYa127920be7c2012-09-10 17:13:22 -07001541 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001542
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001543 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -07001544
1545 llvm::Value* field_value;
1546
1547 int field_offset;
1548 bool is_volatile;
Ian Rogers1212a022013-03-04 10:48:41 -08001549 bool is_fast_path = driver_->ComputeInstanceFieldInfo(
Ian Rogers89756f22013-03-04 16:40:02 -08001550 field_idx, dex_compilation_unit_, field_offset, is_volatile, false);
TDYa1275e869b62012-07-25 00:45:39 -07001551
1552 if (!is_fast_path) {
1553 llvm::Function* runtime_func;
1554
1555 if (field_jty == kObject) {
1556 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1557 } else if (field_jty == kLong || field_jty == kDouble) {
1558 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1559 } else {
1560 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1561 }
1562
1563 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1564
1565 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1566
1567 EmitUpdateDexPC(dex_pc);
1568
1569 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1570 method_object_addr, object_addr);
1571
1572 EmitGuard_ExceptionLandingPad(dex_pc);
1573
Ian Rogers1b2b71f2013-03-01 11:31:30 -08001574 if (field_jty == kFloat || field_jty == kDouble) {
1575 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty));
1576 }
TDYa1275e869b62012-07-25 00:45:39 -07001577 } else {
1578 DCHECK_GE(field_offset, 0);
1579
1580 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001581 irb_.getJType(field_jty)->getPointerTo();
TDYa1275e869b62012-07-25 00:45:39 -07001582
1583 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1584
1585 llvm::Value* field_addr =
1586 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1587
TDYa1275e869b62012-07-25 00:45:39 -07001588 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001589 field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
Sebastien Hertz4b2e0b02013-03-06 16:24:00 +01001590
1591 if (is_volatile) {
1592 irb_.CreateMemoryBarrier(art::kLoadLoad);
1593 }
TDYa1275e869b62012-07-25 00:45:39 -07001594 }
1595
TDYa1275e869b62012-07-25 00:45:39 -07001596 return field_value;
1597}
1598
1599void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1600 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001601 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001602 llvm::Value* new_value = call_inst.getArgOperand(1);
1603 llvm::Value* object_addr = call_inst.getArgOperand(2);
TDYa1275e869b62012-07-25 00:45:39 -07001604 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
TDYa127920be7c2012-09-10 17:13:22 -07001605 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001606
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001607 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -07001608
1609 int field_offset;
1610 bool is_volatile;
Ian Rogers1212a022013-03-04 10:48:41 -08001611 bool is_fast_path = driver_->ComputeInstanceFieldInfo(
Ian Rogers89756f22013-03-04 16:40:02 -08001612 field_idx, dex_compilation_unit_, field_offset, is_volatile, true);
TDYa1275e869b62012-07-25 00:45:39 -07001613
1614 if (!is_fast_path) {
1615 llvm::Function* runtime_func;
1616
Ian Rogers1b2b71f2013-03-01 11:31:30 -08001617 if (field_jty == kFloat) {
1618 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
1619 } else if (field_jty == kDouble) {
1620 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
1621 }
1622
TDYa1275e869b62012-07-25 00:45:39 -07001623 if (field_jty == kObject) {
1624 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1625 } else if (field_jty == kLong || field_jty == kDouble) {
1626 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1627 } else {
1628 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1629 }
1630
1631 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1632
1633 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1634
1635 EmitUpdateDexPC(dex_pc);
1636
1637 irb_.CreateCall4(runtime_func, field_idx_value,
1638 method_object_addr, object_addr, new_value);
1639
1640 EmitGuard_ExceptionLandingPad(dex_pc);
1641
1642 } else {
1643 DCHECK_GE(field_offset, 0);
1644
Sebastien Hertz4b2e0b02013-03-06 16:24:00 +01001645 if (is_volatile) {
1646 irb_.CreateMemoryBarrier(art::kStoreStore);
1647 }
1648
TDYa1275e869b62012-07-25 00:45:39 -07001649 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001650 irb_.getJType(field_jty)->getPointerTo();
TDYa1275e869b62012-07-25 00:45:39 -07001651
1652 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1653
1654 llvm::Value* field_addr =
1655 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1656
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001657 new_value = TruncateCat1Types(new_value, field_jty);
TDYa1275e869b62012-07-25 00:45:39 -07001658 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1659
Sebastien Hertz4b2e0b02013-03-06 16:24:00 +01001660 if (is_volatile) {
1661 irb_.CreateMemoryBarrier(art::kLoadLoad);
1662 }
1663
TDYa1275e869b62012-07-25 00:45:39 -07001664 if (field_jty == kObject) { // If put an object, mark the GC card table.
1665 EmitMarkGCCard(new_value, object_addr);
1666 }
1667 }
1668
1669 return;
1670}
1671
TDYa127f71bf5a2012-07-29 20:09:52 -07001672llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1673 uint32_t type_idx) {
Ian Rogers89756f22013-03-04 16:40:02 -08001674 if (!driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
1675 *dex_compilation_unit_->GetDexFile(), type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001676 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1677
1678 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1679
1680 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1681
1682 llvm::Function* runtime_func =
1683 irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
1684
1685 EmitUpdateDexPC(dex_pc);
1686
1687 llvm::Value* type_object_addr =
1688 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1689
1690 EmitGuard_ExceptionLandingPad(dex_pc);
1691
1692 return type_object_addr;
1693
1694 } else {
1695 // Try to load the class (type) object from the test cache.
1696 llvm::Value* type_field_addr =
1697 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1698
TDYa127ce4cc0d2012-11-18 16:59:53 -08001699 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001700
Ian Rogers89756f22013-03-04 16:40:02 -08001701 if (driver_->CanAssumeTypeIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(), type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001702 return type_object_addr;
1703 }
1704
1705 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1706
1707 // Test whether class (type) object is in the dex cache or not
1708 llvm::Value* equal_null =
1709 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1710
1711 llvm::BasicBlock* block_cont =
1712 CreateBasicBlockWithDexPC(dex_pc, "cont");
1713
1714 llvm::BasicBlock* block_load_class =
1715 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1716
1717 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1718
1719 // Failback routine to load the class object
1720 irb_.SetInsertPoint(block_load_class);
1721
1722 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
1723
1724 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1725
1726 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1727
1728 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1729
1730 EmitUpdateDexPC(dex_pc);
1731
1732 llvm::Value* loaded_type_object_addr =
1733 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1734
1735 EmitGuard_ExceptionLandingPad(dex_pc);
1736
1737 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1738
1739 irb_.CreateBr(block_cont);
1740
1741 // Now the class object must be loaded
1742 irb_.SetInsertPoint(block_cont);
1743
1744 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1745
1746 phi->addIncoming(type_object_addr, block_original);
1747 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1748
1749 return phi;
1750 }
1751}
1752
TDYa1275a26d442012-07-26 18:58:38 -07001753llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1754 uint32_t type_idx) {
1755 llvm::BasicBlock* block_load_static =
1756 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1757
1758 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1759
1760 // Load static storage from dex cache
1761 llvm::Value* storage_field_addr =
1762 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1763
TDYa127ce4cc0d2012-11-18 16:59:53 -08001764 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
TDYa1275a26d442012-07-26 18:58:38 -07001765
1766 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1767
1768 // Test: Is the static storage of this class initialized?
1769 llvm::Value* equal_null =
1770 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1771
1772 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1773
1774 // Failback routine to load the class object
1775 irb_.SetInsertPoint(block_load_static);
1776
1777 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
1778
1779 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1780
1781 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1782
1783 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1784
1785 EmitUpdateDexPC(dex_pc);
1786
1787 llvm::Value* loaded_storage_object_addr =
1788 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1789
1790 EmitGuard_ExceptionLandingPad(dex_pc);
1791
1792 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1793
1794 irb_.CreateBr(block_cont);
1795
1796 // Now the class object must be loaded
1797 irb_.SetInsertPoint(block_cont);
1798
1799 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1800
1801 phi->addIncoming(storage_object_addr, block_original);
1802 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1803
1804 return phi;
1805}
1806
1807llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1808 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001809 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1810 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1811
1812 int field_offset;
1813 int ssb_index;
1814 bool is_referrers_class;
1815 bool is_volatile;
1816
Ian Rogers1212a022013-03-04 10:48:41 -08001817 bool is_fast_path = driver_->ComputeStaticFieldInfo(
Ian Rogers89756f22013-03-04 16:40:02 -08001818 field_idx, dex_compilation_unit_, field_offset, ssb_index,
TDYa1275a26d442012-07-26 18:58:38 -07001819 is_referrers_class, is_volatile, false);
1820
1821 llvm::Value* static_field_value;
1822
1823 if (!is_fast_path) {
1824 llvm::Function* runtime_func;
1825
1826 if (field_jty == kObject) {
1827 runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
1828 } else if (field_jty == kLong || field_jty == kDouble) {
1829 runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
1830 } else {
1831 runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
1832 }
1833
1834 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1835
1836 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1837
1838 EmitUpdateDexPC(dex_pc);
1839
1840 static_field_value =
1841 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1842
1843 EmitGuard_ExceptionLandingPad(dex_pc);
1844
Ian Rogers1b2b71f2013-03-01 11:31:30 -08001845 if (field_jty == kFloat || field_jty == kDouble) {
1846 static_field_value = irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty));
1847 }
TDYa1275a26d442012-07-26 18:58:38 -07001848 } else {
1849 DCHECK_GE(field_offset, 0);
1850
1851 llvm::Value* static_storage_addr = NULL;
1852
1853 if (is_referrers_class) {
1854 // Fast path, static storage base is this method's class
1855 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1856
1857 static_storage_addr =
1858 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001859 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001860 irb_.getJObjectTy(),
1861 kTBAAConstJObject);
1862 } else {
1863 // Medium path, static storage base in a different class which
1864 // requires checks that the other class is initialized
1865 DCHECK_GE(ssb_index, 0);
1866 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1867 }
1868
1869 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1870
1871 llvm::Value* static_field_addr =
1872 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001873 irb_.getJType(field_jty)->getPointerTo());
TDYa1275a26d442012-07-26 18:58:38 -07001874
TDYa1275a26d442012-07-26 18:58:38 -07001875 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001876 static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
Sebastien Hertz4b2e0b02013-03-06 16:24:00 +01001877
1878 if (is_volatile) {
1879 irb_.CreateMemoryBarrier(art::kLoadLoad);
1880 }
TDYa1275a26d442012-07-26 18:58:38 -07001881 }
1882
TDYa1275a26d442012-07-26 18:58:38 -07001883 return static_field_value;
1884}
1885
1886void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1887 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001888 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1889 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1890 llvm::Value* new_value = call_inst.getArgOperand(1);
1891
1892 if (field_jty == kFloat || field_jty == kDouble) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001893 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
TDYa1275a26d442012-07-26 18:58:38 -07001894 }
1895
1896 int field_offset;
1897 int ssb_index;
1898 bool is_referrers_class;
1899 bool is_volatile;
1900
Ian Rogers1212a022013-03-04 10:48:41 -08001901 bool is_fast_path = driver_->ComputeStaticFieldInfo(
Ian Rogers89756f22013-03-04 16:40:02 -08001902 field_idx, dex_compilation_unit_, field_offset, ssb_index,
TDYa1275a26d442012-07-26 18:58:38 -07001903 is_referrers_class, is_volatile, true);
1904
1905 if (!is_fast_path) {
1906 llvm::Function* runtime_func;
1907
1908 if (field_jty == kObject) {
1909 runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
1910 } else if (field_jty == kLong || field_jty == kDouble) {
1911 runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
1912 } else {
1913 runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
1914 }
1915
Ian Rogers1b2b71f2013-03-01 11:31:30 -08001916 if (field_jty == kFloat) {
1917 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
1918 } else if (field_jty == kDouble) {
1919 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
1920 }
1921
TDYa1275a26d442012-07-26 18:58:38 -07001922 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1923
1924 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1925
1926 EmitUpdateDexPC(dex_pc);
1927
1928 irb_.CreateCall3(runtime_func, field_idx_value,
1929 method_object_addr, new_value);
1930
1931 EmitGuard_ExceptionLandingPad(dex_pc);
1932
1933 } else {
1934 DCHECK_GE(field_offset, 0);
1935
1936 llvm::Value* static_storage_addr = NULL;
1937
1938 if (is_referrers_class) {
1939 // Fast path, static storage base is this method's class
1940 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1941
1942 static_storage_addr =
1943 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001944 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001945 irb_.getJObjectTy(),
1946 kTBAAConstJObject);
1947 } else {
1948 // Medium path, static storage base in a different class which
1949 // requires checks that the other class is initialized
1950 DCHECK_GE(ssb_index, 0);
1951 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1952 }
1953
Sebastien Hertz4b2e0b02013-03-06 16:24:00 +01001954 if (is_volatile) {
1955 irb_.CreateMemoryBarrier(art::kStoreStore);
1956 }
1957
TDYa1275a26d442012-07-26 18:58:38 -07001958 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1959
1960 llvm::Value* static_field_addr =
1961 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001962 irb_.getJType(field_jty)->getPointerTo());
TDYa1275a26d442012-07-26 18:58:38 -07001963
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001964 new_value = TruncateCat1Types(new_value, field_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001965 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1966
Sebastien Hertz4b2e0b02013-03-06 16:24:00 +01001967 if (is_volatile) {
1968 irb_.CreateMemoryBarrier(art::kStoreLoad);
1969 }
1970
TDYa1275a26d442012-07-26 18:58:38 -07001971 if (field_jty == kObject) { // If put an object, mark the GC card table.
1972 EmitMarkGCCard(new_value, static_storage_addr);
1973 }
1974 }
1975
1976 return;
1977}
1978
TDYa127f71bf5a2012-07-29 20:09:52 -07001979llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001980 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1981 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
1982
1983 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1984
TDYa127ce4cc0d2012-11-18 16:59:53 -08001985 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001986
Ian Rogers89756f22013-03-04 16:40:02 -08001987 if (!driver_->CanAssumeStringIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(),
1988 string_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001989 llvm::BasicBlock* block_str_exist =
1990 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1991
1992 llvm::BasicBlock* block_str_resolve =
1993 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1994
1995 llvm::BasicBlock* block_cont =
1996 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
1997
1998 // Test: Is the string resolved and in the dex cache?
1999 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
2000
2001 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
2002
2003 // String is resolved, go to next basic block.
2004 irb_.SetInsertPoint(block_str_exist);
2005 irb_.CreateBr(block_cont);
2006
2007 // String is not resolved yet, resolve it now.
2008 irb_.SetInsertPoint(block_str_resolve);
2009
2010 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
2011
2012 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2013
2014 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
2015
2016 EmitUpdateDexPC(dex_pc);
2017
2018 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
2019 string_idx_value);
2020
2021 EmitGuard_ExceptionLandingPad(dex_pc);
2022
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002023 irb_.CreateBr(block_cont);
2024
2025
TDYa127f71bf5a2012-07-29 20:09:52 -07002026 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
2027
2028 irb_.SetInsertPoint(block_cont);
2029
2030 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
2031
2032 phi->addIncoming(string_addr, block_str_exist);
2033 phi->addIncoming(result, block_pre_cont);
2034
2035 string_addr = phi;
2036 }
2037
2038 return string_addr;
2039}
2040
2041llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002042 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2043 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2044
2045 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2046
2047 return type_object_addr;
2048}
2049
2050void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002051 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2052 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002053 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002054
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002055 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002056
TDYa127ce4cc0d2012-11-18 16:59:53 -08002057 EmitUpdateDexPC(dex_pc);
2058
TDYa127f71bf5a2012-07-29 20:09:52 -07002059 irb_.Runtime().EmitLockObject(object_addr);
2060
2061 return;
2062}
2063
2064void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002065 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2066 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002067 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002068
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002069 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002070
2071 EmitUpdateDexPC(dex_pc);
2072
2073 irb_.Runtime().EmitUnlockObject(object_addr);
2074
2075 EmitGuard_ExceptionLandingPad(dex_pc);
2076
2077 return;
2078}
2079
2080void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002081 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2082 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2083 llvm::Value* object_addr = call_inst.getArgOperand(1);
2084
2085 llvm::BasicBlock* block_test_class =
2086 CreateBasicBlockWithDexPC(dex_pc, "test_class");
2087
2088 llvm::BasicBlock* block_test_sub_class =
2089 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2090
2091 llvm::BasicBlock* block_cont =
2092 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
2093
2094 // Test: Is the reference equal to null? Act as no-op when it is null.
2095 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2096
Ian Rogers8e696052013-03-04 09:00:40 -08002097 irb_.CreateCondBr(equal_null, block_cont, block_test_class, kUnlikely);
TDYa127f71bf5a2012-07-29 20:09:52 -07002098
2099 // Test: Is the object instantiated from the given class?
2100 irb_.SetInsertPoint(block_test_class);
2101 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08002102 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002103
2104 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2105
2106 llvm::Value* object_type_field_addr =
2107 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2108
2109 llvm::Value* object_type_object_addr =
2110 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2111
2112 llvm::Value* equal_class =
2113 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2114
Ian Rogers8e696052013-03-04 09:00:40 -08002115 irb_.CreateCondBr(equal_class, block_cont, block_test_sub_class, kLikely);
TDYa127f71bf5a2012-07-29 20:09:52 -07002116
2117 // Test: Is the object instantiated from the subclass of the given class?
2118 irb_.SetInsertPoint(block_test_sub_class);
2119
2120 EmitUpdateDexPC(dex_pc);
2121
2122 irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
2123 type_object_addr, object_type_object_addr);
2124
2125 EmitGuard_ExceptionLandingPad(dex_pc);
2126
2127 irb_.CreateBr(block_cont);
2128
2129 irb_.SetInsertPoint(block_cont);
2130
2131 return;
2132}
2133
2134llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002135 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2136 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2137 llvm::Value* object_addr = call_inst.getArgOperand(1);
2138
2139 llvm::BasicBlock* block_nullp =
2140 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2141
2142 llvm::BasicBlock* block_test_class =
2143 CreateBasicBlockWithDexPC(dex_pc, "test_class");
2144
2145 llvm::BasicBlock* block_class_equals =
2146 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
2147
2148 llvm::BasicBlock* block_test_sub_class =
2149 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2150
2151 llvm::BasicBlock* block_cont =
2152 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
2153
2154 // Overview of the following code :
2155 // We check for null, if so, then false, otherwise check for class == . If so
2156 // then true, otherwise do callout slowpath.
2157 //
2158 // Test: Is the reference equal to null? Set 0 when it is null.
2159 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2160
Ian Rogers8e696052013-03-04 09:00:40 -08002161 irb_.CreateCondBr(equal_null, block_nullp, block_test_class, kUnlikely);
TDYa127f71bf5a2012-07-29 20:09:52 -07002162
2163 irb_.SetInsertPoint(block_nullp);
2164 irb_.CreateBr(block_cont);
2165
2166 // Test: Is the object instantiated from the given class?
2167 irb_.SetInsertPoint(block_test_class);
2168 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08002169 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002170
2171 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2172
2173 llvm::Value* object_type_field_addr =
2174 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2175
2176 llvm::Value* object_type_object_addr =
2177 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2178
2179 llvm::Value* equal_class =
2180 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2181
Ian Rogers8e696052013-03-04 09:00:40 -08002182 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class, kLikely);
TDYa127f71bf5a2012-07-29 20:09:52 -07002183
2184 irb_.SetInsertPoint(block_class_equals);
2185 irb_.CreateBr(block_cont);
2186
2187 // Test: Is the object instantiated from the subclass of the given class?
2188 irb_.SetInsertPoint(block_test_sub_class);
2189 llvm::Value* result =
2190 irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
2191 type_object_addr, object_type_object_addr);
2192 irb_.CreateBr(block_cont);
2193
2194 irb_.SetInsertPoint(block_cont);
2195
2196 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
2197
2198 phi->addIncoming(irb_.getJInt(0), block_nullp);
2199 phi->addIncoming(irb_.getJInt(1), block_class_equals);
2200 phi->addIncoming(result, block_test_sub_class);
2201
2202 return phi;
2203}
2204
2205llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002206 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2207 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2208
2209 llvm::Function* runtime_func;
Ian Rogers89756f22013-03-04 16:40:02 -08002210 if (driver_->CanAccessInstantiableTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
2211 *dex_compilation_unit_->GetDexFile(),
2212 type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002213 runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
2214 } else {
2215 runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
2216 }
2217
2218 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2219
2220 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2221
2222 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2223
2224 EmitUpdateDexPC(dex_pc);
2225
2226 llvm::Value* object_addr =
2227 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
2228
2229 EmitGuard_ExceptionLandingPad(dex_pc);
2230
2231 return object_addr;
2232}
2233
2234llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
TDYa127920be7c2012-09-10 17:13:22 -07002235 art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
2236 bool is_static = (invoke_type == art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002237
2238 if (!is_static) {
2239 // Test: Is *this* parameter equal to null?
Sebastien Hertz901d5ba2013-03-06 15:19:34 +01002240 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2241 llvm::Value* this_addr = call_inst.getArgOperand(3);
2242 int opt_flags = LV2UInt(call_inst.getArgOperand(2));
2243
2244 EmitGuard_NullPointerException(dex_pc, this_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002245 }
2246
Sebastien Hertz901d5ba2013-03-06 15:19:34 +01002247 llvm::Value* result = NULL;
2248 if (EmitIntrinsic(call_inst, &result)) {
2249 return result;
TDYa127f71bf5a2012-07-29 20:09:52 -07002250 }
2251
Sebastien Hertz901d5ba2013-03-06 15:19:34 +01002252 return EmitInvoke(call_inst);
TDYa127f71bf5a2012-07-29 20:09:52 -07002253}
2254
2255llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002256 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2257 // Get the array object address
2258 llvm::Value* array_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002259 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002260
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002261 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002262
2263 // Get the array length and store it to the register
2264 return EmitLoadArrayLength(array_addr);
2265}
2266
2267llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002268 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2269 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2270 llvm::Value* length = call_inst.getArgOperand(1);
2271
2272 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2273}
2274
2275llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002276 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2277 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2278 uint32_t length = call_inst.getNumArgOperands() - 3;
2279
2280 llvm::Value* object_addr =
2281 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2282
2283 if (length > 0) {
2284 // Check for the element type
2285 uint32_t type_desc_len = 0;
2286 const char* type_desc =
Ian Rogers89756f22013-03-04 16:40:02 -08002287 dex_compilation_unit_->GetDexFile()->StringByTypeIdx(type_idx, &type_desc_len);
TDYa127f71bf5a2012-07-29 20:09:52 -07002288
2289 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2290 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2291 bool is_elem_int_ty = (type_desc[1] == 'I');
2292
2293 uint32_t alignment;
2294 llvm::Constant* elem_size;
2295 llvm::PointerType* field_type;
2296
2297 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2298 // as the element, thus we are only checking 2 cases: primitive int and
2299 // non-primitive type.
2300 if (is_elem_int_ty) {
2301 alignment = sizeof(int32_t);
2302 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2303 field_type = irb_.getJIntTy()->getPointerTo();
2304 } else {
2305 alignment = irb_.getSizeOfPtrEquivInt();
2306 elem_size = irb_.getSizeOfPtrEquivIntValue();
2307 field_type = irb_.getJObjectTy()->getPointerTo();
2308 }
2309
2310 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -08002311 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
TDYa127f71bf5a2012-07-29 20:09:52 -07002312
2313 llvm::Value* data_field_addr =
2314 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2315
2316 // TODO: Tune this code. Currently we are generating one instruction for
2317 // one element which may be very space consuming. Maybe changing to use
2318 // memcpy may help; however, since we can't guarantee that the alloca of
2319 // dalvik register are continuous, we can't perform such optimization yet.
2320 for (uint32_t i = 0; i < length; ++i) {
2321 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2322
2323 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2324
2325 data_field_addr =
2326 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2327 }
2328 }
2329
2330 return object_addr;
2331}
2332
2333void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002334 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2335 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2336 LV2SInt(call_inst.getArgOperand(0));
2337 llvm::Value* array_addr = call_inst.getArgOperand(1);
2338
TDYa127920be7c2012-09-10 17:13:22 -07002339 const art::Instruction::ArrayDataPayload* payload =
2340 reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
Ian Rogers89756f22013-03-04 16:40:02 -08002341 dex_compilation_unit_->GetCodeItem()->insns_ + payload_offset);
TDYa127f71bf5a2012-07-29 20:09:52 -07002342
2343 if (payload->element_count == 0) {
2344 // When the number of the elements in the payload is zero, we don't have
2345 // to copy any numbers. However, we should check whether the array object
2346 // address is equal to null or not.
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002347 EmitGuard_NullPointerException(dex_pc, array_addr, 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002348 } else {
2349 // To save the code size, we are going to call the runtime function to
2350 // copy the content from DexFile.
2351
2352 // NOTE: We will check for the NullPointerException in the runtime.
2353
2354 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
2355
2356 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2357
2358 EmitUpdateDexPC(dex_pc);
2359
2360 irb_.CreateCall4(runtime_func,
2361 method_object_addr, irb_.getInt32(dex_pc),
2362 array_addr, irb_.getInt32(payload_offset));
2363
2364 EmitGuard_ExceptionLandingPad(dex_pc);
2365 }
2366
2367 return;
2368}
2369
2370llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2371 llvm::Value* array_length_value,
2372 uint32_t type_idx,
2373 bool is_filled_new_array) {
2374 llvm::Function* runtime_func;
2375
2376 bool skip_access_check =
Ian Rogers89756f22013-03-04 16:40:02 -08002377 driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
2378 *dex_compilation_unit_->GetDexFile(), type_idx);
TDYa127f71bf5a2012-07-29 20:09:52 -07002379
2380
2381 if (is_filled_new_array) {
2382 runtime_func = skip_access_check ?
2383 irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
2384 irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
2385 } else {
2386 runtime_func = skip_access_check ?
2387 irb_.GetRuntime(runtime_support::AllocArray) :
2388 irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
2389 }
2390
2391 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2392
2393 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2394
2395 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2396
2397 EmitUpdateDexPC(dex_pc);
2398
2399 llvm::Value* object_addr =
2400 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2401 array_length_value, thread_object_addr);
2402
2403 EmitGuard_ExceptionLandingPad(dex_pc);
2404
2405 return object_addr;
2406}
2407
2408llvm::Value* GBCExpanderPass::
2409EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -07002410 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -07002411 llvm::Value* this_addr,
2412 uint32_t dex_pc,
2413 bool is_fast_path) {
2414
2415 llvm::Function* runtime_func = NULL;
2416
2417 switch (invoke_type) {
TDYa127920be7c2012-09-10 17:13:22 -07002418 case art::kStatic:
TDYa127f71bf5a2012-07-29 20:09:52 -07002419 runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
2420 break;
2421
TDYa127920be7c2012-09-10 17:13:22 -07002422 case art::kDirect:
TDYa127f71bf5a2012-07-29 20:09:52 -07002423 runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
2424 break;
2425
TDYa127920be7c2012-09-10 17:13:22 -07002426 case art::kVirtual:
TDYa127f71bf5a2012-07-29 20:09:52 -07002427 runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
2428 break;
2429
TDYa127920be7c2012-09-10 17:13:22 -07002430 case art::kSuper:
TDYa127f71bf5a2012-07-29 20:09:52 -07002431 runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
2432 break;
2433
TDYa127920be7c2012-09-10 17:13:22 -07002434 case art::kInterface:
TDYa127f71bf5a2012-07-29 20:09:52 -07002435 if (is_fast_path) {
2436 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
2437 } else {
2438 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
2439 }
2440 break;
2441 }
2442
2443 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2444
2445 if (this_addr == NULL) {
TDYa127920be7c2012-09-10 17:13:22 -07002446 DCHECK_EQ(invoke_type, art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002447 this_addr = irb_.getJNull();
2448 }
2449
2450 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2451
2452 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2453
2454 EmitUpdateDexPC(dex_pc);
2455
2456 llvm::Value* callee_method_object_addr =
2457 irb_.CreateCall4(runtime_func,
2458 callee_method_idx_value,
2459 this_addr,
2460 caller_method_object_addr,
2461 thread_object_addr);
2462
2463 EmitGuard_ExceptionLandingPad(dex_pc);
2464
2465 return callee_method_object_addr;
2466}
2467
TDYa1275e869b62012-07-25 00:45:39 -07002468void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2469 // Using runtime support, let the target can override by InlineAssembly.
2470 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2471}
2472
2473void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002474 if (shadow_frame_ == NULL) {
2475 return;
2476 }
TDYa1275e869b62012-07-25 00:45:39 -07002477 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07002478 art::ShadowFrame::DexPCOffset(),
TDYa1275e869b62012-07-25 00:45:39 -07002479 irb_.getInt32(dex_pc),
2480 kTBAAShadowFrame);
2481}
2482
2483void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2484 llvm::Value* denominator,
2485 JType op_jty) {
2486 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2487
2488 llvm::Constant* zero = irb_.getJZero(op_jty);
2489
2490 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2491
2492 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2493
2494 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2495
2496 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2497
2498 irb_.SetInsertPoint(block_exception);
2499 EmitUpdateDexPC(dex_pc);
2500 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
2501 EmitBranchExceptionLandingPad(dex_pc);
2502
2503 irb_.SetInsertPoint(block_continue);
2504}
2505
2506void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002507 llvm::Value* object,
2508 int opt_flags) {
2509 bool ignore_null_check = ((opt_flags & MIR_IGNORE_NULL_CHECK) != 0);
2510 if (ignore_null_check) {
2511 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2512 if (lpad) {
2513 // There is at least one catch: create a "fake" conditional branch to
2514 // keep the exception edge to the catch block.
2515 landing_pad_phi_mapping_[lpad].push_back(
2516 std::make_pair(current_bb_->getUniquePredecessor(),
2517 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002518
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002519 llvm::BasicBlock* block_continue =
2520 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002521
Ian Rogers8e696052013-03-04 09:00:40 -08002522 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002523
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002524 irb_.SetInsertPoint(block_continue);
2525 }
2526 } else {
2527 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
TDYa1275e869b62012-07-25 00:45:39 -07002528
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002529 llvm::BasicBlock* block_exception =
2530 CreateBasicBlockWithDexPC(dex_pc, "nullp");
TDYa1275e869b62012-07-25 00:45:39 -07002531
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002532 llvm::BasicBlock* block_continue =
2533 CreateBasicBlockWithDexPC(dex_pc, "cont");
2534
2535 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2536
2537 irb_.SetInsertPoint(block_exception);
2538 EmitUpdateDexPC(dex_pc);
2539 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
2540 irb_.getInt32(dex_pc));
2541 EmitBranchExceptionLandingPad(dex_pc);
2542
2543 irb_.SetInsertPoint(block_continue);
2544 }
TDYa1275e869b62012-07-25 00:45:39 -07002545}
2546
2547void
2548GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2549 llvm::Value* array,
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002550 llvm::Value* index,
2551 int opt_flags) {
2552 bool ignore_range_check = ((opt_flags & MIR_IGNORE_RANGE_CHECK) != 0);
2553 if (ignore_range_check) {
2554 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2555 if (lpad) {
2556 // There is at least one catch: create a "fake" conditional branch to
2557 // keep the exception edge to the catch block.
2558 landing_pad_phi_mapping_[lpad].push_back(
2559 std::make_pair(current_bb_->getUniquePredecessor(),
2560 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002561
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002562 llvm::BasicBlock* block_continue =
2563 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002564
Ian Rogers8e696052013-03-04 09:00:40 -08002565 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002566
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002567 irb_.SetInsertPoint(block_continue);
2568 }
2569 } else {
2570 llvm::Value* array_len = EmitLoadArrayLength(array);
TDYa1275e869b62012-07-25 00:45:39 -07002571
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002572 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
TDYa1275e869b62012-07-25 00:45:39 -07002573
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002574 llvm::BasicBlock* block_exception =
2575 CreateBasicBlockWithDexPC(dex_pc, "overflow");
TDYa1275e869b62012-07-25 00:45:39 -07002576
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002577 llvm::BasicBlock* block_continue =
2578 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002579
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002580 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2581
2582 irb_.SetInsertPoint(block_exception);
2583
2584 EmitUpdateDexPC(dex_pc);
2585 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
2586 EmitBranchExceptionLandingPad(dex_pc);
2587
2588 irb_.SetInsertPoint(block_continue);
2589 }
TDYa1275e869b62012-07-25 00:45:39 -07002590}
2591
Ian Rogers8e696052013-03-04 09:00:40 -08002592llvm::FunctionType* GBCExpanderPass::GetFunctionType(llvm::Type* ret_type, uint32_t method_idx,
TDYa1275e869b62012-07-25 00:45:39 -07002593 bool is_static) {
2594 // Get method signature
Ian Rogers8e696052013-03-04 09:00:40 -08002595 art::DexFile::MethodId const& method_id =
Ian Rogers89756f22013-03-04 16:40:02 -08002596 dex_compilation_unit_->GetDexFile()->GetMethodId(method_idx);
TDYa1275e869b62012-07-25 00:45:39 -07002597
2598 uint32_t shorty_size;
Ian Rogers89756f22013-03-04 16:40:02 -08002599 const char* shorty = dex_compilation_unit_->GetDexFile()->GetMethodShorty(method_id, &shorty_size);
TDYa1275e869b62012-07-25 00:45:39 -07002600 CHECK_GE(shorty_size, 1u);
2601
TDYa1275e869b62012-07-25 00:45:39 -07002602 // Get argument type
2603 std::vector<llvm::Type*> args_type;
2604
2605 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2606
2607 if (!is_static) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002608 args_type.push_back(irb_.getJType('L')); // "this" object pointer
TDYa1275e869b62012-07-25 00:45:39 -07002609 }
2610
2611 for (uint32_t i = 1; i < shorty_size; ++i) {
buzbee26f10ee2012-12-21 11:16:29 -08002612 char shorty_type = art::RemapShorty(shorty[i]);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002613 args_type.push_back(irb_.getJType(shorty_type));
TDYa1275e869b62012-07-25 00:45:39 -07002614 }
2615
2616 return llvm::FunctionType::get(ret_type, args_type, false);
2617}
2618
2619
2620llvm::BasicBlock* GBCExpanderPass::
2621CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2622 std::string name;
2623
2624#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002625 art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
TDYa1275e869b62012-07-25 00:45:39 -07002626#endif
2627
2628 return llvm::BasicBlock::Create(context_, name, func_);
2629}
2630
2631llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
Ian Rogers89756f22013-03-04 16:40:02 -08002632 DCHECK(dex_pc < dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002633 CHECK(basic_blocks_[dex_pc] != NULL);
TDYa1275e869b62012-07-25 00:45:39 -07002634 return basic_blocks_[dex_pc];
2635}
2636
2637int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2638 int32_t min = 0;
Ian Rogers89756f22013-03-04 16:40:02 -08002639 int32_t max = dex_compilation_unit_->GetCodeItem()->tries_size_ - 1;
TDYa1275e869b62012-07-25 00:45:39 -07002640
2641 while (min <= max) {
2642 int32_t mid = min + (max - min) / 2;
2643
Ian Rogers89756f22013-03-04 16:40:02 -08002644 const art::DexFile::TryItem* ti =
2645 art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(), mid);
TDYa1275e869b62012-07-25 00:45:39 -07002646 uint32_t start = ti->start_addr_;
2647 uint32_t end = start + ti->insn_count_;
2648
2649 if (dex_pc < start) {
2650 max = mid - 1;
2651 } else if (dex_pc >= end) {
2652 min = mid + 1;
2653 } else {
2654 return mid; // found
2655 }
2656 }
2657
2658 return -1; // not found
2659}
2660
2661llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2662 // Find the try item for this address in this method
2663 int32_t ti_offset = GetTryItemOffset(dex_pc);
2664
2665 if (ti_offset == -1) {
2666 return NULL; // No landing pad is available for this address.
2667 }
2668
2669 // Check for the existing landing pad basic block
2670 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2671 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2672
2673 if (block_lpad) {
2674 // We have generated landing pad for this try item already. Return the
2675 // same basic block.
2676 return block_lpad;
2677 }
2678
2679 // Get try item from code item
Ian Rogers89756f22013-03-04 16:40:02 -08002680 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(),
Ian Rogers8e696052013-03-04 09:00:40 -08002681 ti_offset);
TDYa1275e869b62012-07-25 00:45:39 -07002682
2683 std::string lpadname;
2684
2685#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002686 art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
TDYa1275e869b62012-07-25 00:45:39 -07002687#endif
2688
2689 // Create landing pad basic block
2690 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2691
2692 // Change IRBuilder insert point
2693 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2694 irb_.SetInsertPoint(block_lpad);
2695
2696 // Find catch block with matching type
2697 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2698
2699 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2700
2701 llvm::Value* catch_handler_index_value =
2702 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
2703 method_object_addr, ti_offset_value);
2704
2705 // Switch instruction (Go to unwind basic block by default)
2706 llvm::SwitchInst* sw =
2707 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2708
2709 // Cases with matched catch block
Ian Rogers89756f22013-03-04 16:40:02 -08002710 art::CatchHandlerIterator iter(*dex_compilation_unit_->GetCodeItem(), ti->start_addr_);
TDYa1275e869b62012-07-25 00:45:39 -07002711
2712 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2713 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2714 }
2715
2716 // Restore the orignal insert point for IRBuilder
2717 irb_.restoreIP(irb_ip_original);
2718
2719 // Cache this landing pad
2720 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2721 basic_block_landing_pads_[ti_offset] = block_lpad;
2722
2723 return block_lpad;
2724}
2725
2726llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2727 // Check the existing unwinding baisc block block
2728 if (basic_block_unwind_ != NULL) {
2729 return basic_block_unwind_;
2730 }
2731
2732 // Create new basic block for unwinding
2733 basic_block_unwind_ =
2734 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2735
2736 // Change IRBuilder insert point
2737 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2738 irb_.SetInsertPoint(basic_block_unwind_);
2739
2740 // Pop the shadow frame
2741 Expand_PopShadowFrame();
2742
2743 // Emit the code to return default value (zero) for the given return type.
Ian Rogers89756f22013-03-04 16:40:02 -08002744 char ret_shorty = dex_compilation_unit_->GetShorty()[0];
buzbee26f10ee2012-12-21 11:16:29 -08002745 ret_shorty = art::RemapShorty(ret_shorty);
TDYa1275e869b62012-07-25 00:45:39 -07002746 if (ret_shorty == 'V') {
2747 irb_.CreateRetVoid();
2748 } else {
2749 irb_.CreateRet(irb_.getJZero(ret_shorty));
2750 }
2751
2752 // Restore the orignal insert point for IRBuilder
2753 irb_.restoreIP(irb_ip_original);
2754
2755 return basic_block_unwind_;
2756}
2757
2758void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2759 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002760 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002761 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002762 irb_.CreateBr(lpad);
2763 } else {
2764 irb_.CreateBr(GetUnwindBasicBlock());
2765 }
2766}
2767
2768void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
Jeff Hao9a142652013-01-17 23:10:19 +00002769 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2770
TDYa1275e869b62012-07-25 00:45:39 -07002771 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2772
2773 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002774 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002775 irb_.GetInsertBlock()));
Jeff Hao9a142652013-01-17 23:10:19 +00002776 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002777 } else {
Jeff Hao9a142652013-01-17 23:10:19 +00002778 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002779 }
2780
2781 irb_.SetInsertPoint(block_cont);
2782}
2783
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002784llvm::Value*
2785GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2786 llvm::CallInst& call_inst) {
2787 switch (intr_id) {
2788 //==- Thread -----------------------------------------------------------==//
2789 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07002790 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002791 }
Logan Chien75e4b602012-07-23 14:24:12 -07002792 case IntrinsicHelper::CheckSuspend: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08002793 Expand_TestSuspend(call_inst);
TDYa127890ea892012-08-22 10:49:42 -07002794 return NULL;
2795 }
2796 case IntrinsicHelper::TestSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002797 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002798 return NULL;
2799 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002800 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07002801 Expand_MarkGCCard(call_inst);
2802 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002803 }
Logan Chien75e4b602012-07-23 14:24:12 -07002804
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002805 //==- Exception --------------------------------------------------------==//
2806 case IntrinsicHelper::ThrowException: {
2807 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
2808 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002809 case IntrinsicHelper::HLThrowException: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002810 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2811
2812 EmitUpdateDexPC(dex_pc);
2813
2814 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
2815 call_inst.getArgOperand(0));
2816
2817 EmitGuard_ExceptionLandingPad(dex_pc);
2818 return NULL;
2819 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002820 case IntrinsicHelper::GetException: {
TDYa127823433d2012-09-26 16:03:51 -07002821 return irb_.Runtime().EmitGetAndClearException();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002822 }
2823 case IntrinsicHelper::IsExceptionPending: {
2824 return irb_.Runtime().EmitIsExceptionPending();
2825 }
2826 case IntrinsicHelper::FindCatchBlock: {
2827 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
2828 }
2829 case IntrinsicHelper::ThrowDivZeroException: {
2830 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
2831 }
2832 case IntrinsicHelper::ThrowNullPointerException: {
2833 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
2834 }
2835 case IntrinsicHelper::ThrowIndexOutOfBounds: {
2836 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
2837 }
Logan Chien75e4b602012-07-23 14:24:12 -07002838
2839 //==- Const String -----------------------------------------------------==//
2840 case IntrinsicHelper::ConstString: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002841 return Expand_ConstString(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002842 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002843 case IntrinsicHelper::LoadStringFromDexCache: {
2844 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2845 }
2846 case IntrinsicHelper::ResolveString: {
2847 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
2848 }
Logan Chien75e4b602012-07-23 14:24:12 -07002849
2850 //==- Const Class ------------------------------------------------------==//
2851 case IntrinsicHelper::ConstClass: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002852 return Expand_ConstClass(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002853 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002854 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
2855 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
2856 }
2857 case IntrinsicHelper::LoadTypeFromDexCache: {
2858 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2859 }
2860 case IntrinsicHelper::InitializeType: {
2861 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
2862 }
Logan Chien75e4b602012-07-23 14:24:12 -07002863
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002864 //==- Lock -------------------------------------------------------------==//
2865 case IntrinsicHelper::LockObject: {
2866 Expand_LockObject(call_inst.getArgOperand(0));
2867 return NULL;
2868 }
2869 case IntrinsicHelper::UnlockObject: {
2870 Expand_UnlockObject(call_inst.getArgOperand(0));
2871 return NULL;
2872 }
Logan Chien75e4b602012-07-23 14:24:12 -07002873
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002874 //==- Cast -------------------------------------------------------------==//
2875 case IntrinsicHelper::CheckCast: {
2876 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
2877 }
Logan Chien75e4b602012-07-23 14:24:12 -07002878 case IntrinsicHelper::HLCheckCast: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002879 Expand_HLCheckCast(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002880 return NULL;
2881 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002882 case IntrinsicHelper::IsAssignable: {
2883 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
2884 }
Logan Chien75e4b602012-07-23 14:24:12 -07002885
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002886 //==- Alloc ------------------------------------------------------------==//
2887 case IntrinsicHelper::AllocObject: {
2888 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
2889 }
2890 case IntrinsicHelper::AllocObjectWithAccessCheck: {
2891 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
2892 }
Logan Chien75e4b602012-07-23 14:24:12 -07002893
2894 //==- Instance ---------------------------------------------------------==//
2895 case IntrinsicHelper::NewInstance: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002896 return Expand_NewInstance(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002897 }
2898 case IntrinsicHelper::InstanceOf: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002899 return Expand_InstanceOf(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002900 }
2901
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002902 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07002903 case IntrinsicHelper::NewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002904 return Expand_NewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002905 }
2906 case IntrinsicHelper::OptArrayLength: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002907 return Expand_OptArrayLength(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002908 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002909 case IntrinsicHelper::ArrayLength: {
2910 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2911 }
2912 case IntrinsicHelper::AllocArray: {
2913 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
2914 }
2915 case IntrinsicHelper::AllocArrayWithAccessCheck: {
2916 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
2917 call_inst);
2918 }
2919 case IntrinsicHelper::CheckAndAllocArray: {
2920 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
2921 }
2922 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
2923 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
2924 call_inst);
2925 }
2926 case IntrinsicHelper::ArrayGet: {
2927 return Expand_ArrayGet(call_inst.getArgOperand(0),
2928 call_inst.getArgOperand(1),
2929 kInt);
2930 }
2931 case IntrinsicHelper::ArrayGetWide: {
2932 return Expand_ArrayGet(call_inst.getArgOperand(0),
2933 call_inst.getArgOperand(1),
2934 kLong);
2935 }
2936 case IntrinsicHelper::ArrayGetObject: {
2937 return Expand_ArrayGet(call_inst.getArgOperand(0),
2938 call_inst.getArgOperand(1),
2939 kObject);
2940 }
2941 case IntrinsicHelper::ArrayGetBoolean: {
2942 return Expand_ArrayGet(call_inst.getArgOperand(0),
2943 call_inst.getArgOperand(1),
2944 kBoolean);
2945 }
2946 case IntrinsicHelper::ArrayGetByte: {
2947 return Expand_ArrayGet(call_inst.getArgOperand(0),
2948 call_inst.getArgOperand(1),
2949 kByte);
2950 }
2951 case IntrinsicHelper::ArrayGetChar: {
2952 return Expand_ArrayGet(call_inst.getArgOperand(0),
2953 call_inst.getArgOperand(1),
2954 kChar);
2955 }
2956 case IntrinsicHelper::ArrayGetShort: {
2957 return Expand_ArrayGet(call_inst.getArgOperand(0),
2958 call_inst.getArgOperand(1),
2959 kShort);
2960 }
2961 case IntrinsicHelper::ArrayPut: {
2962 Expand_ArrayPut(call_inst.getArgOperand(0),
2963 call_inst.getArgOperand(1),
2964 call_inst.getArgOperand(2),
2965 kInt);
2966 return NULL;
2967 }
2968 case IntrinsicHelper::ArrayPutWide: {
2969 Expand_ArrayPut(call_inst.getArgOperand(0),
2970 call_inst.getArgOperand(1),
2971 call_inst.getArgOperand(2),
2972 kLong);
2973 return NULL;
2974 }
2975 case IntrinsicHelper::ArrayPutObject: {
2976 Expand_ArrayPut(call_inst.getArgOperand(0),
2977 call_inst.getArgOperand(1),
2978 call_inst.getArgOperand(2),
2979 kObject);
2980 return NULL;
2981 }
2982 case IntrinsicHelper::ArrayPutBoolean: {
2983 Expand_ArrayPut(call_inst.getArgOperand(0),
2984 call_inst.getArgOperand(1),
2985 call_inst.getArgOperand(2),
2986 kBoolean);
2987 return NULL;
2988 }
2989 case IntrinsicHelper::ArrayPutByte: {
2990 Expand_ArrayPut(call_inst.getArgOperand(0),
2991 call_inst.getArgOperand(1),
2992 call_inst.getArgOperand(2),
2993 kByte);
2994 return NULL;
2995 }
2996 case IntrinsicHelper::ArrayPutChar: {
2997 Expand_ArrayPut(call_inst.getArgOperand(0),
2998 call_inst.getArgOperand(1),
2999 call_inst.getArgOperand(2),
3000 kChar);
3001 return NULL;
3002 }
3003 case IntrinsicHelper::ArrayPutShort: {
3004 Expand_ArrayPut(call_inst.getArgOperand(0),
3005 call_inst.getArgOperand(1),
3006 call_inst.getArgOperand(2),
3007 kShort);
3008 return NULL;
3009 }
3010 case IntrinsicHelper::CheckPutArrayElement: {
3011 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
3012 }
3013 case IntrinsicHelper::FilledNewArray: {
3014 Expand_FilledNewArray(call_inst);
3015 return NULL;
3016 }
3017 case IntrinsicHelper::FillArrayData: {
3018 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
3019 }
Logan Chien75e4b602012-07-23 14:24:12 -07003020 case IntrinsicHelper::HLFillArrayData: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003021 Expand_HLFillArrayData(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003022 return NULL;
3023 }
3024 case IntrinsicHelper::HLFilledNewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003025 return Expand_HLFilledNewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003026 }
3027
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003028 //==- Instance Field ---------------------------------------------------==//
3029 case IntrinsicHelper::InstanceFieldGet:
3030 case IntrinsicHelper::InstanceFieldGetBoolean:
3031 case IntrinsicHelper::InstanceFieldGetByte:
3032 case IntrinsicHelper::InstanceFieldGetChar:
3033 case IntrinsicHelper::InstanceFieldGetShort: {
3034 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
3035 }
3036 case IntrinsicHelper::InstanceFieldGetWide: {
3037 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
3038 }
3039 case IntrinsicHelper::InstanceFieldGetObject: {
3040 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
3041 }
3042 case IntrinsicHelper::InstanceFieldGetFast: {
3043 return Expand_IGetFast(call_inst.getArgOperand(0),
3044 call_inst.getArgOperand(1),
3045 call_inst.getArgOperand(2),
3046 kInt);
3047 }
3048 case IntrinsicHelper::InstanceFieldGetWideFast: {
3049 return Expand_IGetFast(call_inst.getArgOperand(0),
3050 call_inst.getArgOperand(1),
3051 call_inst.getArgOperand(2),
3052 kLong);
3053 }
3054 case IntrinsicHelper::InstanceFieldGetObjectFast: {
3055 return Expand_IGetFast(call_inst.getArgOperand(0),
3056 call_inst.getArgOperand(1),
3057 call_inst.getArgOperand(2),
3058 kObject);
3059 }
3060 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
3061 return Expand_IGetFast(call_inst.getArgOperand(0),
3062 call_inst.getArgOperand(1),
3063 call_inst.getArgOperand(2),
3064 kBoolean);
3065 }
3066 case IntrinsicHelper::InstanceFieldGetByteFast: {
3067 return Expand_IGetFast(call_inst.getArgOperand(0),
3068 call_inst.getArgOperand(1),
3069 call_inst.getArgOperand(2),
3070 kByte);
3071 }
3072 case IntrinsicHelper::InstanceFieldGetCharFast: {
3073 return Expand_IGetFast(call_inst.getArgOperand(0),
3074 call_inst.getArgOperand(1),
3075 call_inst.getArgOperand(2),
3076 kChar);
3077 }
3078 case IntrinsicHelper::InstanceFieldGetShortFast: {
3079 return Expand_IGetFast(call_inst.getArgOperand(0),
3080 call_inst.getArgOperand(1),
3081 call_inst.getArgOperand(2),
3082 kShort);
3083 }
3084 case IntrinsicHelper::InstanceFieldPut:
3085 case IntrinsicHelper::InstanceFieldPutBoolean:
3086 case IntrinsicHelper::InstanceFieldPutByte:
3087 case IntrinsicHelper::InstanceFieldPutChar:
3088 case IntrinsicHelper::InstanceFieldPutShort: {
3089 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
3090 }
3091 case IntrinsicHelper::InstanceFieldPutWide: {
3092 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
3093 }
3094 case IntrinsicHelper::InstanceFieldPutObject: {
3095 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
3096 }
3097 case IntrinsicHelper::InstanceFieldPutFast: {
3098 Expand_IPutFast(call_inst.getArgOperand(0),
3099 call_inst.getArgOperand(1),
3100 call_inst.getArgOperand(2),
3101 call_inst.getArgOperand(3),
3102 kInt);
3103 return NULL;
3104 }
3105 case IntrinsicHelper::InstanceFieldPutWideFast: {
3106 Expand_IPutFast(call_inst.getArgOperand(0),
3107 call_inst.getArgOperand(1),
3108 call_inst.getArgOperand(2),
3109 call_inst.getArgOperand(3),
3110 kLong);
3111 return NULL;
3112 }
3113 case IntrinsicHelper::InstanceFieldPutObjectFast: {
3114 Expand_IPutFast(call_inst.getArgOperand(0),
3115 call_inst.getArgOperand(1),
3116 call_inst.getArgOperand(2),
3117 call_inst.getArgOperand(3),
3118 kObject);
3119 return NULL;
3120 }
3121 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
3122 Expand_IPutFast(call_inst.getArgOperand(0),
3123 call_inst.getArgOperand(1),
3124 call_inst.getArgOperand(2),
3125 call_inst.getArgOperand(3),
3126 kBoolean);
3127 return NULL;
3128 }
3129 case IntrinsicHelper::InstanceFieldPutByteFast: {
3130 Expand_IPutFast(call_inst.getArgOperand(0),
3131 call_inst.getArgOperand(1),
3132 call_inst.getArgOperand(2),
3133 call_inst.getArgOperand(3),
3134 kByte);
3135 return NULL;
3136 }
3137 case IntrinsicHelper::InstanceFieldPutCharFast: {
3138 Expand_IPutFast(call_inst.getArgOperand(0),
3139 call_inst.getArgOperand(1),
3140 call_inst.getArgOperand(2),
3141 call_inst.getArgOperand(3),
3142 kChar);
3143 return NULL;
3144 }
3145 case IntrinsicHelper::InstanceFieldPutShortFast: {
3146 Expand_IPutFast(call_inst.getArgOperand(0),
3147 call_inst.getArgOperand(1),
3148 call_inst.getArgOperand(2),
3149 call_inst.getArgOperand(3),
3150 kShort);
3151 return NULL;
3152 }
Logan Chien75e4b602012-07-23 14:24:12 -07003153
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003154 //==- Static Field -----------------------------------------------------==//
3155 case IntrinsicHelper::StaticFieldGet:
3156 case IntrinsicHelper::StaticFieldGetBoolean:
3157 case IntrinsicHelper::StaticFieldGetByte:
3158 case IntrinsicHelper::StaticFieldGetChar:
3159 case IntrinsicHelper::StaticFieldGetShort: {
3160 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
3161 }
3162 case IntrinsicHelper::StaticFieldGetWide: {
3163 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
3164 }
3165 case IntrinsicHelper::StaticFieldGetObject: {
3166 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
3167 }
3168 case IntrinsicHelper::StaticFieldGetFast: {
3169 return Expand_SGetFast(call_inst.getArgOperand(0),
3170 call_inst.getArgOperand(1),
3171 call_inst.getArgOperand(2),
3172 kInt);
3173 }
3174 case IntrinsicHelper::StaticFieldGetWideFast: {
3175 return Expand_SGetFast(call_inst.getArgOperand(0),
3176 call_inst.getArgOperand(1),
3177 call_inst.getArgOperand(2),
3178 kLong);
3179 }
3180 case IntrinsicHelper::StaticFieldGetObjectFast: {
3181 return Expand_SGetFast(call_inst.getArgOperand(0),
3182 call_inst.getArgOperand(1),
3183 call_inst.getArgOperand(2),
3184 kObject);
3185 }
3186 case IntrinsicHelper::StaticFieldGetBooleanFast: {
3187 return Expand_SGetFast(call_inst.getArgOperand(0),
3188 call_inst.getArgOperand(1),
3189 call_inst.getArgOperand(2),
3190 kBoolean);
3191 }
3192 case IntrinsicHelper::StaticFieldGetByteFast: {
3193 return Expand_SGetFast(call_inst.getArgOperand(0),
3194 call_inst.getArgOperand(1),
3195 call_inst.getArgOperand(2),
3196 kByte);
3197 }
3198 case IntrinsicHelper::StaticFieldGetCharFast: {
3199 return Expand_SGetFast(call_inst.getArgOperand(0),
3200 call_inst.getArgOperand(1),
3201 call_inst.getArgOperand(2),
3202 kChar);
3203 }
3204 case IntrinsicHelper::StaticFieldGetShortFast: {
3205 return Expand_SGetFast(call_inst.getArgOperand(0),
3206 call_inst.getArgOperand(1),
3207 call_inst.getArgOperand(2),
3208 kShort);
3209 }
3210 case IntrinsicHelper::StaticFieldPut:
3211 case IntrinsicHelper::StaticFieldPutBoolean:
3212 case IntrinsicHelper::StaticFieldPutByte:
3213 case IntrinsicHelper::StaticFieldPutChar:
3214 case IntrinsicHelper::StaticFieldPutShort: {
3215 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
3216 }
3217 case IntrinsicHelper::StaticFieldPutWide: {
3218 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
3219 }
3220 case IntrinsicHelper::StaticFieldPutObject: {
3221 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
3222 }
3223 case IntrinsicHelper::StaticFieldPutFast: {
3224 Expand_SPutFast(call_inst.getArgOperand(0),
3225 call_inst.getArgOperand(1),
3226 call_inst.getArgOperand(2),
3227 call_inst.getArgOperand(3),
3228 kInt);
3229 return NULL;
3230 }
3231 case IntrinsicHelper::StaticFieldPutWideFast: {
3232 Expand_SPutFast(call_inst.getArgOperand(0),
3233 call_inst.getArgOperand(1),
3234 call_inst.getArgOperand(2),
3235 call_inst.getArgOperand(3),
3236 kLong);
3237 return NULL;
3238 }
3239 case IntrinsicHelper::StaticFieldPutObjectFast: {
3240 Expand_SPutFast(call_inst.getArgOperand(0),
3241 call_inst.getArgOperand(1),
3242 call_inst.getArgOperand(2),
3243 call_inst.getArgOperand(3),
3244 kObject);
3245 return NULL;
3246 }
3247 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3248 Expand_SPutFast(call_inst.getArgOperand(0),
3249 call_inst.getArgOperand(1),
3250 call_inst.getArgOperand(2),
3251 call_inst.getArgOperand(3),
3252 kBoolean);
3253 return NULL;
3254 }
3255 case IntrinsicHelper::StaticFieldPutByteFast: {
3256 Expand_SPutFast(call_inst.getArgOperand(0),
3257 call_inst.getArgOperand(1),
3258 call_inst.getArgOperand(2),
3259 call_inst.getArgOperand(3),
3260 kByte);
3261 return NULL;
3262 }
3263 case IntrinsicHelper::StaticFieldPutCharFast: {
3264 Expand_SPutFast(call_inst.getArgOperand(0),
3265 call_inst.getArgOperand(1),
3266 call_inst.getArgOperand(2),
3267 call_inst.getArgOperand(3),
3268 kChar);
3269 return NULL;
3270 }
3271 case IntrinsicHelper::StaticFieldPutShortFast: {
3272 Expand_SPutFast(call_inst.getArgOperand(0),
3273 call_inst.getArgOperand(1),
3274 call_inst.getArgOperand(2),
3275 call_inst.getArgOperand(3),
3276 kShort);
3277 return NULL;
3278 }
3279 case IntrinsicHelper::LoadDeclaringClassSSB: {
3280 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3281 }
3282 case IntrinsicHelper::LoadClassSSBFromDexCache: {
3283 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
3284 }
3285 case IntrinsicHelper::InitializeAndLoadClassSSB: {
3286 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
3287 }
Logan Chien75e4b602012-07-23 14:24:12 -07003288
3289 //==- High-level Array -------------------------------------------------==//
3290 case IntrinsicHelper::HLArrayGet: {
TDYa1275a26d442012-07-26 18:58:38 -07003291 return Expand_HLArrayGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003292 }
3293 case IntrinsicHelper::HLArrayGetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003294 return Expand_HLArrayGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003295 }
3296 case IntrinsicHelper::HLArrayGetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003297 return Expand_HLArrayGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003298 }
3299 case IntrinsicHelper::HLArrayGetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003300 return Expand_HLArrayGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003301 }
3302 case IntrinsicHelper::HLArrayGetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003303 return Expand_HLArrayGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003304 }
3305 case IntrinsicHelper::HLArrayGetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003306 return Expand_HLArrayGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003307 }
3308 case IntrinsicHelper::HLArrayGetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003309 return Expand_HLArrayGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003310 }
3311 case IntrinsicHelper::HLArrayGetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003312 return Expand_HLArrayGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003313 }
3314 case IntrinsicHelper::HLArrayGetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003315 return Expand_HLArrayGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003316 }
3317 case IntrinsicHelper::HLArrayPut: {
TDYa1275a26d442012-07-26 18:58:38 -07003318 Expand_HLArrayPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003319 return NULL;
3320 }
3321 case IntrinsicHelper::HLArrayPutBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003322 Expand_HLArrayPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003323 return NULL;
3324 }
3325 case IntrinsicHelper::HLArrayPutByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003326 Expand_HLArrayPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003327 return NULL;
3328 }
3329 case IntrinsicHelper::HLArrayPutChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003330 Expand_HLArrayPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003331 return NULL;
3332 }
3333 case IntrinsicHelper::HLArrayPutShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003334 Expand_HLArrayPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003335 return NULL;
3336 }
3337 case IntrinsicHelper::HLArrayPutFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003338 Expand_HLArrayPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003339 return NULL;
3340 }
3341 case IntrinsicHelper::HLArrayPutWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003342 Expand_HLArrayPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003343 return NULL;
3344 }
3345 case IntrinsicHelper::HLArrayPutDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003346 Expand_HLArrayPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003347 return NULL;
3348 }
3349 case IntrinsicHelper::HLArrayPutObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003350 Expand_HLArrayPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003351 return NULL;
3352 }
3353
3354 //==- High-level Instance ----------------------------------------------==//
3355 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07003356 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003357 }
3358 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003359 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003360 }
3361 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003362 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003363 }
3364 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003365 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003366 }
3367 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003368 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003369 }
3370 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003371 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003372 }
3373 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003374 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003375 }
3376 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003377 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003378 }
3379 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003380 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003381 }
3382 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07003383 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003384 return NULL;
3385 }
3386 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003387 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003388 return NULL;
3389 }
3390 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003391 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003392 return NULL;
3393 }
3394 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003395 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003396 return NULL;
3397 }
3398 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003399 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003400 return NULL;
3401 }
3402 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003403 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003404 return NULL;
3405 }
3406 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003407 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003408 return NULL;
3409 }
3410 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003411 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003412 return NULL;
3413 }
3414 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003415 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003416 return NULL;
3417 }
3418
3419 //==- High-level Invoke ------------------------------------------------==//
TDYa127f71bf5a2012-07-29 20:09:52 -07003420 case IntrinsicHelper::HLInvokeVoid:
3421 case IntrinsicHelper::HLInvokeObj:
3422 case IntrinsicHelper::HLInvokeInt:
3423 case IntrinsicHelper::HLInvokeFloat:
3424 case IntrinsicHelper::HLInvokeLong:
Logan Chien75e4b602012-07-23 14:24:12 -07003425 case IntrinsicHelper::HLInvokeDouble: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003426 return Expand_HLInvoke(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003427 }
3428
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003429 //==- Invoke -----------------------------------------------------------==//
3430 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
3431 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
3432 }
3433 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
3434 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
3435 }
3436 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
3437 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
3438 }
3439 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
3440 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
3441 }
3442 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
3443 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
3444 }
3445 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3446 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3447 }
3448 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3449 return Expand_GetVirtualCalleeMethodObjAddrFast(
3450 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3451 }
3452 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
3453 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
3454 }
3455 case IntrinsicHelper::InvokeRetVoid:
3456 case IntrinsicHelper::InvokeRetBoolean:
3457 case IntrinsicHelper::InvokeRetByte:
3458 case IntrinsicHelper::InvokeRetChar:
3459 case IntrinsicHelper::InvokeRetShort:
3460 case IntrinsicHelper::InvokeRetInt:
3461 case IntrinsicHelper::InvokeRetLong:
3462 case IntrinsicHelper::InvokeRetFloat:
3463 case IntrinsicHelper::InvokeRetDouble:
3464 case IntrinsicHelper::InvokeRetObject: {
3465 return Expand_Invoke(call_inst);
3466 }
Logan Chien75e4b602012-07-23 14:24:12 -07003467
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003468 //==- Math -------------------------------------------------------------==//
3469 case IntrinsicHelper::DivInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003470 return Expand_DivRem(call_inst, /* is_div */true, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003471 }
3472 case IntrinsicHelper::RemInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003473 return Expand_DivRem(call_inst, /* is_div */false, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003474 }
3475 case IntrinsicHelper::DivLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003476 return Expand_DivRem(call_inst, /* is_div */true, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003477 }
3478 case IntrinsicHelper::RemLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003479 return Expand_DivRem(call_inst, /* is_div */false, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003480 }
3481 case IntrinsicHelper::D2L: {
3482 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
3483 }
3484 case IntrinsicHelper::D2I: {
3485 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
3486 }
3487 case IntrinsicHelper::F2L: {
3488 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
3489 }
3490 case IntrinsicHelper::F2I: {
3491 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
3492 }
Logan Chien75e4b602012-07-23 14:24:12 -07003493
3494 //==- High-level Static ------------------------------------------------==//
3495 case IntrinsicHelper::HLSget: {
TDYa1275a26d442012-07-26 18:58:38 -07003496 return Expand_HLSget(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003497 }
3498 case IntrinsicHelper::HLSgetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003499 return Expand_HLSget(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003500 }
3501 case IntrinsicHelper::HLSgetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003502 return Expand_HLSget(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003503 }
3504 case IntrinsicHelper::HLSgetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003505 return Expand_HLSget(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003506 }
3507 case IntrinsicHelper::HLSgetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003508 return Expand_HLSget(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003509 }
3510 case IntrinsicHelper::HLSgetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003511 return Expand_HLSget(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003512 }
3513 case IntrinsicHelper::HLSgetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003514 return Expand_HLSget(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003515 }
3516 case IntrinsicHelper::HLSgetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003517 return Expand_HLSget(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003518 }
3519 case IntrinsicHelper::HLSgetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003520 return Expand_HLSget(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003521 }
3522 case IntrinsicHelper::HLSput: {
TDYa1275a26d442012-07-26 18:58:38 -07003523 Expand_HLSput(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003524 return NULL;
3525 }
3526 case IntrinsicHelper::HLSputBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003527 Expand_HLSput(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003528 return NULL;
3529 }
3530 case IntrinsicHelper::HLSputByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003531 Expand_HLSput(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003532 return NULL;
3533 }
3534 case IntrinsicHelper::HLSputChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003535 Expand_HLSput(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003536 return NULL;
3537 }
3538 case IntrinsicHelper::HLSputShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003539 Expand_HLSput(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003540 return NULL;
3541 }
3542 case IntrinsicHelper::HLSputFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003543 Expand_HLSput(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003544 return NULL;
3545 }
3546 case IntrinsicHelper::HLSputWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003547 Expand_HLSput(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003548 return NULL;
3549 }
3550 case IntrinsicHelper::HLSputDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003551 Expand_HLSput(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003552 return NULL;
3553 }
3554 case IntrinsicHelper::HLSputObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003555 Expand_HLSput(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003556 return NULL;
3557 }
3558
3559 //==- High-level Monitor -----------------------------------------------==//
3560 case IntrinsicHelper::MonitorEnter: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003561 Expand_MonitorEnter(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003562 return NULL;
3563 }
3564 case IntrinsicHelper::MonitorExit: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003565 Expand_MonitorExit(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003566 return NULL;
3567 }
3568
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003569 //==- Shadow Frame -----------------------------------------------------==//
3570 case IntrinsicHelper::AllocaShadowFrame: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08003571 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003572 return NULL;
3573 }
TDYa1278e950c12012-11-02 09:58:19 -07003574 case IntrinsicHelper::SetVReg: {
3575 Expand_SetVReg(call_inst.getArgOperand(0),
3576 call_inst.getArgOperand(1));
3577 return NULL;
3578 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003579 case IntrinsicHelper::PopShadowFrame: {
3580 Expand_PopShadowFrame();
3581 return NULL;
3582 }
3583 case IntrinsicHelper::UpdateDexPC: {
3584 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3585 return NULL;
3586 }
TDYa127a1b21852012-07-23 03:20:39 -07003587
Logan Chien75e4b602012-07-23 14:24:12 -07003588 //==- Comparison -------------------------------------------------------==//
3589 case IntrinsicHelper::CmplFloat:
3590 case IntrinsicHelper::CmplDouble: {
3591 return Expand_FPCompare(call_inst.getArgOperand(0),
3592 call_inst.getArgOperand(1),
3593 false);
3594 }
3595 case IntrinsicHelper::CmpgFloat:
3596 case IntrinsicHelper::CmpgDouble: {
3597 return Expand_FPCompare(call_inst.getArgOperand(0),
3598 call_inst.getArgOperand(1),
3599 true);
3600 }
3601 case IntrinsicHelper::CmpLong: {
3602 return Expand_LongCompare(call_inst.getArgOperand(0),
3603 call_inst.getArgOperand(1));
3604 }
TDYa127a1b21852012-07-23 03:20:39 -07003605
Logan Chien75e4b602012-07-23 14:24:12 -07003606 //==- Const ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003607 case IntrinsicHelper::ConstInt:
3608 case IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003609 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003610 }
TDYa127920be7c2012-09-10 17:13:22 -07003611 case IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003612 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3613 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07003614 }
TDYa127920be7c2012-09-10 17:13:22 -07003615 case IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003616 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3617 irb_.getJDoubleTy());
3618 }
TDYa127920be7c2012-09-10 17:13:22 -07003619 case IntrinsicHelper::ConstObj: {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003620 CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
3621 return irb_.getJNull();
Logan Chien75e4b602012-07-23 14:24:12 -07003622 }
3623
3624 //==- Method Info ------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003625 case IntrinsicHelper::MethodInfo: {
Shih-wei Liaob2596522012-09-14 16:36:11 -07003626 // Nothing to be done, because MethodInfo carries optional hints that are
3627 // not needed by the portable path.
Logan Chien75e4b602012-07-23 14:24:12 -07003628 return NULL;
3629 }
3630
3631 //==- Copy -------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003632 case IntrinsicHelper::CopyInt:
3633 case IntrinsicHelper::CopyFloat:
3634 case IntrinsicHelper::CopyLong:
3635 case IntrinsicHelper::CopyDouble:
3636 case IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003637 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003638 }
3639
3640 //==- Shift ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003641 case IntrinsicHelper::SHLLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003642 return Expand_IntegerShift(call_inst.getArgOperand(0),
3643 call_inst.getArgOperand(1),
3644 kIntegerSHL, kLong);
3645 }
TDYa127920be7c2012-09-10 17:13:22 -07003646 case IntrinsicHelper::SHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003647 return Expand_IntegerShift(call_inst.getArgOperand(0),
3648 call_inst.getArgOperand(1),
3649 kIntegerSHR, kLong);
3650 }
TDYa127920be7c2012-09-10 17:13:22 -07003651 case IntrinsicHelper::USHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003652 return Expand_IntegerShift(call_inst.getArgOperand(0),
3653 call_inst.getArgOperand(1),
3654 kIntegerUSHR, kLong);
3655 }
TDYa127920be7c2012-09-10 17:13:22 -07003656 case IntrinsicHelper::SHLInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003657 return Expand_IntegerShift(call_inst.getArgOperand(0),
3658 call_inst.getArgOperand(1),
3659 kIntegerSHL, kInt);
3660 }
TDYa127920be7c2012-09-10 17:13:22 -07003661 case IntrinsicHelper::SHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003662 return Expand_IntegerShift(call_inst.getArgOperand(0),
3663 call_inst.getArgOperand(1),
3664 kIntegerSHR, kInt);
3665 }
TDYa127920be7c2012-09-10 17:13:22 -07003666 case IntrinsicHelper::USHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003667 return Expand_IntegerShift(call_inst.getArgOperand(0),
3668 call_inst.getArgOperand(1),
3669 kIntegerUSHR, kInt);
3670 }
3671
3672 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07003673 case IntrinsicHelper::IntToChar: {
3674 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3675 irb_.getJIntTy());
3676 }
3677 case IntrinsicHelper::IntToShort: {
3678 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3679 irb_.getJIntTy());
3680 }
3681 case IntrinsicHelper::IntToByte: {
3682 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3683 irb_.getJIntTy());
3684 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003685
TDYa12787caa7e2012-08-25 23:23:27 -07003686 //==- Exception --------------------------------------------------------==//
3687 case IntrinsicHelper::CatchTargets: {
TDYa12755e5e6c2012-09-11 15:14:42 -07003688 UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
TDYa12787caa7e2012-08-25 23:23:27 -07003689 llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
3690 CHECK(si != NULL);
3691 irb_.CreateBr(si->getDefaultDest());
3692 si->eraseFromParent();
3693 return call_inst.getArgOperand(0);
3694 }
3695
Sebastien Hertz0d43d542013-02-27 19:02:16 +01003696 //==- Constructor barrier-----------------------------------------------==//
3697 case IntrinsicHelper::ConstructorBarrier: {
3698 irb_.CreateMemoryBarrier(art::kStoreStore);
3699 return NULL;
3700 }
3701
Logan Chien75e4b602012-07-23 14:24:12 -07003702 //==- Unknown Cases ----------------------------------------------------==//
3703 case IntrinsicHelper::MaxIntrinsicId:
3704 case IntrinsicHelper::UnknownId:
3705 //default:
3706 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3707 // give some warning on unmatched cases.
3708 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003709 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003710 }
Logan Chien75e4b602012-07-23 14:24:12 -07003711 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003712 return NULL;
3713}
3714
3715} // anonymous namespace
3716
3717namespace art {
Ian Rogers4c1c2832013-03-04 18:30:13 -08003718namespace llvm {
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003719
Ian Rogers4c1c2832013-03-04 18:30:13 -08003720::llvm::FunctionPass*
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003721CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
Brian Carlstrom265091e2013-01-30 14:08:26 -08003722 CompilerDriver* driver, const DexCompilationUnit* dex_compilation_unit) {
Ian Rogers89756f22013-03-04 16:40:02 -08003723 return new GBCExpanderPass(intrinsic_helper, irb, driver, dex_compilation_unit);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003724}
3725
Ian Rogers4c1c2832013-03-04 18:30:13 -08003726} // namespace llvm
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003727} // namespace art