blob: 8e2d054c060f3aacd4cd8e71052848676261cede [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 Rogers89756f22013-03-04 16:40:02 -0800343 art::CompilerDriver* compiler, 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 Rogers1212a022013-03-04 10:48:41 -0800347 driver_(compiler),
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
367 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
368 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
1588 // TODO: Check is_volatile. We need to generate atomic load instruction
1589 // when is_volatile is true.
1590 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001591 field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
TDYa1275e869b62012-07-25 00:45:39 -07001592 }
1593
TDYa1275e869b62012-07-25 00:45:39 -07001594 return field_value;
1595}
1596
1597void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1598 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001599 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001600 llvm::Value* new_value = call_inst.getArgOperand(1);
1601 llvm::Value* object_addr = call_inst.getArgOperand(2);
TDYa1275e869b62012-07-25 00:45:39 -07001602 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
TDYa127920be7c2012-09-10 17:13:22 -07001603 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001604
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01001605 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa1275e869b62012-07-25 00:45:39 -07001606
1607 int field_offset;
1608 bool is_volatile;
Ian Rogers1212a022013-03-04 10:48:41 -08001609 bool is_fast_path = driver_->ComputeInstanceFieldInfo(
Ian Rogers89756f22013-03-04 16:40:02 -08001610 field_idx, dex_compilation_unit_, field_offset, is_volatile, true);
TDYa1275e869b62012-07-25 00:45:39 -07001611
1612 if (!is_fast_path) {
1613 llvm::Function* runtime_func;
1614
Ian Rogers1b2b71f2013-03-01 11:31:30 -08001615 if (field_jty == kFloat) {
1616 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
1617 } else if (field_jty == kDouble) {
1618 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
1619 }
1620
TDYa1275e869b62012-07-25 00:45:39 -07001621 if (field_jty == kObject) {
1622 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1623 } else if (field_jty == kLong || field_jty == kDouble) {
1624 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1625 } else {
1626 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1627 }
1628
1629 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1630
1631 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1632
1633 EmitUpdateDexPC(dex_pc);
1634
1635 irb_.CreateCall4(runtime_func, field_idx_value,
1636 method_object_addr, object_addr, new_value);
1637
1638 EmitGuard_ExceptionLandingPad(dex_pc);
1639
1640 } else {
1641 DCHECK_GE(field_offset, 0);
1642
1643 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001644 irb_.getJType(field_jty)->getPointerTo();
TDYa1275e869b62012-07-25 00:45:39 -07001645
1646 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1647
1648 llvm::Value* field_addr =
1649 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1650
1651 // TODO: Check is_volatile. We need to generate atomic store instruction
1652 // when is_volatile is true.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001653 new_value = TruncateCat1Types(new_value, field_jty);
TDYa1275e869b62012-07-25 00:45:39 -07001654 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1655
1656 if (field_jty == kObject) { // If put an object, mark the GC card table.
1657 EmitMarkGCCard(new_value, object_addr);
1658 }
1659 }
1660
1661 return;
1662}
1663
TDYa127f71bf5a2012-07-29 20:09:52 -07001664llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1665 uint32_t type_idx) {
Ian Rogers89756f22013-03-04 16:40:02 -08001666 if (!driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
1667 *dex_compilation_unit_->GetDexFile(), type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001668 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1669
1670 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1671
1672 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1673
1674 llvm::Function* runtime_func =
1675 irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
1676
1677 EmitUpdateDexPC(dex_pc);
1678
1679 llvm::Value* type_object_addr =
1680 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1681
1682 EmitGuard_ExceptionLandingPad(dex_pc);
1683
1684 return type_object_addr;
1685
1686 } else {
1687 // Try to load the class (type) object from the test cache.
1688 llvm::Value* type_field_addr =
1689 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1690
TDYa127ce4cc0d2012-11-18 16:59:53 -08001691 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001692
Ian Rogers89756f22013-03-04 16:40:02 -08001693 if (driver_->CanAssumeTypeIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(), type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001694 return type_object_addr;
1695 }
1696
1697 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1698
1699 // Test whether class (type) object is in the dex cache or not
1700 llvm::Value* equal_null =
1701 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1702
1703 llvm::BasicBlock* block_cont =
1704 CreateBasicBlockWithDexPC(dex_pc, "cont");
1705
1706 llvm::BasicBlock* block_load_class =
1707 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1708
1709 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1710
1711 // Failback routine to load the class object
1712 irb_.SetInsertPoint(block_load_class);
1713
1714 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
1715
1716 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1717
1718 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1719
1720 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1721
1722 EmitUpdateDexPC(dex_pc);
1723
1724 llvm::Value* loaded_type_object_addr =
1725 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1726
1727 EmitGuard_ExceptionLandingPad(dex_pc);
1728
1729 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1730
1731 irb_.CreateBr(block_cont);
1732
1733 // Now the class object must be loaded
1734 irb_.SetInsertPoint(block_cont);
1735
1736 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1737
1738 phi->addIncoming(type_object_addr, block_original);
1739 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1740
1741 return phi;
1742 }
1743}
1744
TDYa1275a26d442012-07-26 18:58:38 -07001745llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1746 uint32_t type_idx) {
1747 llvm::BasicBlock* block_load_static =
1748 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1749
1750 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1751
1752 // Load static storage from dex cache
1753 llvm::Value* storage_field_addr =
1754 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1755
TDYa127ce4cc0d2012-11-18 16:59:53 -08001756 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
TDYa1275a26d442012-07-26 18:58:38 -07001757
1758 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1759
1760 // Test: Is the static storage of this class initialized?
1761 llvm::Value* equal_null =
1762 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1763
1764 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1765
1766 // Failback routine to load the class object
1767 irb_.SetInsertPoint(block_load_static);
1768
1769 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
1770
1771 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1772
1773 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1774
1775 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1776
1777 EmitUpdateDexPC(dex_pc);
1778
1779 llvm::Value* loaded_storage_object_addr =
1780 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1781
1782 EmitGuard_ExceptionLandingPad(dex_pc);
1783
1784 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1785
1786 irb_.CreateBr(block_cont);
1787
1788 // Now the class object must be loaded
1789 irb_.SetInsertPoint(block_cont);
1790
1791 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1792
1793 phi->addIncoming(storage_object_addr, block_original);
1794 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1795
1796 return phi;
1797}
1798
1799llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1800 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001801 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1802 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1803
1804 int field_offset;
1805 int ssb_index;
1806 bool is_referrers_class;
1807 bool is_volatile;
1808
Ian Rogers1212a022013-03-04 10:48:41 -08001809 bool is_fast_path = driver_->ComputeStaticFieldInfo(
Ian Rogers89756f22013-03-04 16:40:02 -08001810 field_idx, dex_compilation_unit_, field_offset, ssb_index,
TDYa1275a26d442012-07-26 18:58:38 -07001811 is_referrers_class, is_volatile, false);
1812
1813 llvm::Value* static_field_value;
1814
1815 if (!is_fast_path) {
1816 llvm::Function* runtime_func;
1817
1818 if (field_jty == kObject) {
1819 runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
1820 } else if (field_jty == kLong || field_jty == kDouble) {
1821 runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
1822 } else {
1823 runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
1824 }
1825
1826 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1827
1828 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1829
1830 EmitUpdateDexPC(dex_pc);
1831
1832 static_field_value =
1833 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1834
1835 EmitGuard_ExceptionLandingPad(dex_pc);
1836
Ian Rogers1b2b71f2013-03-01 11:31:30 -08001837 if (field_jty == kFloat || field_jty == kDouble) {
1838 static_field_value = irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty));
1839 }
TDYa1275a26d442012-07-26 18:58:38 -07001840 } else {
1841 DCHECK_GE(field_offset, 0);
1842
1843 llvm::Value* static_storage_addr = NULL;
1844
1845 if (is_referrers_class) {
1846 // Fast path, static storage base is this method's class
1847 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1848
1849 static_storage_addr =
1850 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001851 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001852 irb_.getJObjectTy(),
1853 kTBAAConstJObject);
1854 } else {
1855 // Medium path, static storage base in a different class which
1856 // requires checks that the other class is initialized
1857 DCHECK_GE(ssb_index, 0);
1858 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1859 }
1860
1861 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1862
1863 llvm::Value* static_field_addr =
1864 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001865 irb_.getJType(field_jty)->getPointerTo());
TDYa1275a26d442012-07-26 18:58:38 -07001866
1867 // TODO: Check is_volatile. We need to generate atomic load instruction
1868 // when is_volatile is true.
1869 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001870 static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001871 }
1872
TDYa1275a26d442012-07-26 18:58:38 -07001873 return static_field_value;
1874}
1875
1876void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1877 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001878 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1879 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1880 llvm::Value* new_value = call_inst.getArgOperand(1);
1881
1882 if (field_jty == kFloat || field_jty == kDouble) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001883 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
TDYa1275a26d442012-07-26 18:58:38 -07001884 }
1885
1886 int field_offset;
1887 int ssb_index;
1888 bool is_referrers_class;
1889 bool is_volatile;
1890
Ian Rogers1212a022013-03-04 10:48:41 -08001891 bool is_fast_path = driver_->ComputeStaticFieldInfo(
Ian Rogers89756f22013-03-04 16:40:02 -08001892 field_idx, dex_compilation_unit_, field_offset, ssb_index,
TDYa1275a26d442012-07-26 18:58:38 -07001893 is_referrers_class, is_volatile, true);
1894
1895 if (!is_fast_path) {
1896 llvm::Function* runtime_func;
1897
1898 if (field_jty == kObject) {
1899 runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
1900 } else if (field_jty == kLong || field_jty == kDouble) {
1901 runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
1902 } else {
1903 runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
1904 }
1905
Ian Rogers1b2b71f2013-03-01 11:31:30 -08001906 if (field_jty == kFloat) {
1907 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
1908 } else if (field_jty == kDouble) {
1909 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
1910 }
1911
TDYa1275a26d442012-07-26 18:58:38 -07001912 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1913
1914 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1915
1916 EmitUpdateDexPC(dex_pc);
1917
1918 irb_.CreateCall3(runtime_func, field_idx_value,
1919 method_object_addr, new_value);
1920
1921 EmitGuard_ExceptionLandingPad(dex_pc);
1922
1923 } else {
1924 DCHECK_GE(field_offset, 0);
1925
1926 llvm::Value* static_storage_addr = NULL;
1927
1928 if (is_referrers_class) {
1929 // Fast path, static storage base is this method's class
1930 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1931
1932 static_storage_addr =
1933 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001934 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001935 irb_.getJObjectTy(),
1936 kTBAAConstJObject);
1937 } else {
1938 // Medium path, static storage base in a different class which
1939 // requires checks that the other class is initialized
1940 DCHECK_GE(ssb_index, 0);
1941 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1942 }
1943
1944 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1945
1946 llvm::Value* static_field_addr =
1947 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001948 irb_.getJType(field_jty)->getPointerTo());
TDYa1275a26d442012-07-26 18:58:38 -07001949
1950 // TODO: Check is_volatile. We need to generate atomic store instruction
1951 // when is_volatile is true.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001952 new_value = TruncateCat1Types(new_value, field_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001953 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1954
1955 if (field_jty == kObject) { // If put an object, mark the GC card table.
1956 EmitMarkGCCard(new_value, static_storage_addr);
1957 }
1958 }
1959
1960 return;
1961}
1962
TDYa127f71bf5a2012-07-29 20:09:52 -07001963llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001964 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1965 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
1966
1967 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1968
TDYa127ce4cc0d2012-11-18 16:59:53 -08001969 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001970
Ian Rogers89756f22013-03-04 16:40:02 -08001971 if (!driver_->CanAssumeStringIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(),
1972 string_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001973 llvm::BasicBlock* block_str_exist =
1974 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1975
1976 llvm::BasicBlock* block_str_resolve =
1977 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1978
1979 llvm::BasicBlock* block_cont =
1980 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
1981
1982 // Test: Is the string resolved and in the dex cache?
1983 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1984
1985 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
1986
1987 // String is resolved, go to next basic block.
1988 irb_.SetInsertPoint(block_str_exist);
1989 irb_.CreateBr(block_cont);
1990
1991 // String is not resolved yet, resolve it now.
1992 irb_.SetInsertPoint(block_str_resolve);
1993
1994 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
1995
1996 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1997
1998 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1999
2000 EmitUpdateDexPC(dex_pc);
2001
2002 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
2003 string_idx_value);
2004
2005 EmitGuard_ExceptionLandingPad(dex_pc);
2006
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002007 irb_.CreateBr(block_cont);
2008
2009
TDYa127f71bf5a2012-07-29 20:09:52 -07002010 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
2011
2012 irb_.SetInsertPoint(block_cont);
2013
2014 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
2015
2016 phi->addIncoming(string_addr, block_str_exist);
2017 phi->addIncoming(result, block_pre_cont);
2018
2019 string_addr = phi;
2020 }
2021
2022 return string_addr;
2023}
2024
2025llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002026 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2027 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2028
2029 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2030
2031 return type_object_addr;
2032}
2033
2034void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002035 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2036 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002037 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002038
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002039 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002040
TDYa127ce4cc0d2012-11-18 16:59:53 -08002041 EmitUpdateDexPC(dex_pc);
2042
TDYa127f71bf5a2012-07-29 20:09:52 -07002043 irb_.Runtime().EmitLockObject(object_addr);
2044
2045 return;
2046}
2047
2048void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002049 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2050 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002051 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002052
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002053 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002054
2055 EmitUpdateDexPC(dex_pc);
2056
2057 irb_.Runtime().EmitUnlockObject(object_addr);
2058
2059 EmitGuard_ExceptionLandingPad(dex_pc);
2060
2061 return;
2062}
2063
2064void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002065 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2066 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2067 llvm::Value* object_addr = call_inst.getArgOperand(1);
2068
2069 llvm::BasicBlock* block_test_class =
2070 CreateBasicBlockWithDexPC(dex_pc, "test_class");
2071
2072 llvm::BasicBlock* block_test_sub_class =
2073 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2074
2075 llvm::BasicBlock* block_cont =
2076 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
2077
2078 // Test: Is the reference equal to null? Act as no-op when it is null.
2079 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2080
Ian Rogers8e696052013-03-04 09:00:40 -08002081 irb_.CreateCondBr(equal_null, block_cont, block_test_class, kUnlikely);
TDYa127f71bf5a2012-07-29 20:09:52 -07002082
2083 // Test: Is the object instantiated from the given class?
2084 irb_.SetInsertPoint(block_test_class);
2085 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08002086 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002087
2088 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2089
2090 llvm::Value* object_type_field_addr =
2091 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2092
2093 llvm::Value* object_type_object_addr =
2094 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2095
2096 llvm::Value* equal_class =
2097 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2098
Ian Rogers8e696052013-03-04 09:00:40 -08002099 irb_.CreateCondBr(equal_class, block_cont, block_test_sub_class, kLikely);
TDYa127f71bf5a2012-07-29 20:09:52 -07002100
2101 // Test: Is the object instantiated from the subclass of the given class?
2102 irb_.SetInsertPoint(block_test_sub_class);
2103
2104 EmitUpdateDexPC(dex_pc);
2105
2106 irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
2107 type_object_addr, object_type_object_addr);
2108
2109 EmitGuard_ExceptionLandingPad(dex_pc);
2110
2111 irb_.CreateBr(block_cont);
2112
2113 irb_.SetInsertPoint(block_cont);
2114
2115 return;
2116}
2117
2118llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002119 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2120 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2121 llvm::Value* object_addr = call_inst.getArgOperand(1);
2122
2123 llvm::BasicBlock* block_nullp =
2124 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2125
2126 llvm::BasicBlock* block_test_class =
2127 CreateBasicBlockWithDexPC(dex_pc, "test_class");
2128
2129 llvm::BasicBlock* block_class_equals =
2130 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
2131
2132 llvm::BasicBlock* block_test_sub_class =
2133 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2134
2135 llvm::BasicBlock* block_cont =
2136 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
2137
2138 // Overview of the following code :
2139 // We check for null, if so, then false, otherwise check for class == . If so
2140 // then true, otherwise do callout slowpath.
2141 //
2142 // Test: Is the reference equal to null? Set 0 when it is null.
2143 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2144
Ian Rogers8e696052013-03-04 09:00:40 -08002145 irb_.CreateCondBr(equal_null, block_nullp, block_test_class, kUnlikely);
TDYa127f71bf5a2012-07-29 20:09:52 -07002146
2147 irb_.SetInsertPoint(block_nullp);
2148 irb_.CreateBr(block_cont);
2149
2150 // Test: Is the object instantiated from the given class?
2151 irb_.SetInsertPoint(block_test_class);
2152 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08002153 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002154
2155 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2156
2157 llvm::Value* object_type_field_addr =
2158 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2159
2160 llvm::Value* object_type_object_addr =
2161 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2162
2163 llvm::Value* equal_class =
2164 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2165
Ian Rogers8e696052013-03-04 09:00:40 -08002166 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class, kLikely);
TDYa127f71bf5a2012-07-29 20:09:52 -07002167
2168 irb_.SetInsertPoint(block_class_equals);
2169 irb_.CreateBr(block_cont);
2170
2171 // Test: Is the object instantiated from the subclass of the given class?
2172 irb_.SetInsertPoint(block_test_sub_class);
2173 llvm::Value* result =
2174 irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
2175 type_object_addr, object_type_object_addr);
2176 irb_.CreateBr(block_cont);
2177
2178 irb_.SetInsertPoint(block_cont);
2179
2180 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
2181
2182 phi->addIncoming(irb_.getJInt(0), block_nullp);
2183 phi->addIncoming(irb_.getJInt(1), block_class_equals);
2184 phi->addIncoming(result, block_test_sub_class);
2185
2186 return phi;
2187}
2188
2189llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002190 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2191 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2192
2193 llvm::Function* runtime_func;
Ian Rogers89756f22013-03-04 16:40:02 -08002194 if (driver_->CanAccessInstantiableTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
2195 *dex_compilation_unit_->GetDexFile(),
2196 type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002197 runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
2198 } else {
2199 runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
2200 }
2201
2202 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2203
2204 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2205
2206 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2207
2208 EmitUpdateDexPC(dex_pc);
2209
2210 llvm::Value* object_addr =
2211 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
2212
2213 EmitGuard_ExceptionLandingPad(dex_pc);
2214
2215 return object_addr;
2216}
2217
2218llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
TDYa127920be7c2012-09-10 17:13:22 -07002219 art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
2220 bool is_static = (invoke_type == art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002221
2222 if (!is_static) {
2223 // Test: Is *this* parameter equal to null?
Sebastien Hertz901d5ba2013-03-06 15:19:34 +01002224 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2225 llvm::Value* this_addr = call_inst.getArgOperand(3);
2226 int opt_flags = LV2UInt(call_inst.getArgOperand(2));
2227
2228 EmitGuard_NullPointerException(dex_pc, this_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002229 }
2230
Sebastien Hertz901d5ba2013-03-06 15:19:34 +01002231 llvm::Value* result = NULL;
2232 if (EmitIntrinsic(call_inst, &result)) {
2233 return result;
TDYa127f71bf5a2012-07-29 20:09:52 -07002234 }
2235
Sebastien Hertz901d5ba2013-03-06 15:19:34 +01002236 return EmitInvoke(call_inst);
TDYa127f71bf5a2012-07-29 20:09:52 -07002237}
2238
2239llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002240 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2241 // Get the array object address
2242 llvm::Value* array_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002243 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002244
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002245 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
TDYa127f71bf5a2012-07-29 20:09:52 -07002246
2247 // Get the array length and store it to the register
2248 return EmitLoadArrayLength(array_addr);
2249}
2250
2251llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002252 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2253 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2254 llvm::Value* length = call_inst.getArgOperand(1);
2255
2256 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2257}
2258
2259llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002260 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2261 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2262 uint32_t length = call_inst.getNumArgOperands() - 3;
2263
2264 llvm::Value* object_addr =
2265 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2266
2267 if (length > 0) {
2268 // Check for the element type
2269 uint32_t type_desc_len = 0;
2270 const char* type_desc =
Ian Rogers89756f22013-03-04 16:40:02 -08002271 dex_compilation_unit_->GetDexFile()->StringByTypeIdx(type_idx, &type_desc_len);
TDYa127f71bf5a2012-07-29 20:09:52 -07002272
2273 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2274 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2275 bool is_elem_int_ty = (type_desc[1] == 'I');
2276
2277 uint32_t alignment;
2278 llvm::Constant* elem_size;
2279 llvm::PointerType* field_type;
2280
2281 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2282 // as the element, thus we are only checking 2 cases: primitive int and
2283 // non-primitive type.
2284 if (is_elem_int_ty) {
2285 alignment = sizeof(int32_t);
2286 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2287 field_type = irb_.getJIntTy()->getPointerTo();
2288 } else {
2289 alignment = irb_.getSizeOfPtrEquivInt();
2290 elem_size = irb_.getSizeOfPtrEquivIntValue();
2291 field_type = irb_.getJObjectTy()->getPointerTo();
2292 }
2293
2294 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -08002295 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
TDYa127f71bf5a2012-07-29 20:09:52 -07002296
2297 llvm::Value* data_field_addr =
2298 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2299
2300 // TODO: Tune this code. Currently we are generating one instruction for
2301 // one element which may be very space consuming. Maybe changing to use
2302 // memcpy may help; however, since we can't guarantee that the alloca of
2303 // dalvik register are continuous, we can't perform such optimization yet.
2304 for (uint32_t i = 0; i < length; ++i) {
2305 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2306
2307 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2308
2309 data_field_addr =
2310 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2311 }
2312 }
2313
2314 return object_addr;
2315}
2316
2317void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002318 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2319 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2320 LV2SInt(call_inst.getArgOperand(0));
2321 llvm::Value* array_addr = call_inst.getArgOperand(1);
2322
TDYa127920be7c2012-09-10 17:13:22 -07002323 const art::Instruction::ArrayDataPayload* payload =
2324 reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
Ian Rogers89756f22013-03-04 16:40:02 -08002325 dex_compilation_unit_->GetCodeItem()->insns_ + payload_offset);
TDYa127f71bf5a2012-07-29 20:09:52 -07002326
2327 if (payload->element_count == 0) {
2328 // When the number of the elements in the payload is zero, we don't have
2329 // to copy any numbers. However, we should check whether the array object
2330 // address is equal to null or not.
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002331 EmitGuard_NullPointerException(dex_pc, array_addr, 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002332 } else {
2333 // To save the code size, we are going to call the runtime function to
2334 // copy the content from DexFile.
2335
2336 // NOTE: We will check for the NullPointerException in the runtime.
2337
2338 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
2339
2340 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2341
2342 EmitUpdateDexPC(dex_pc);
2343
2344 irb_.CreateCall4(runtime_func,
2345 method_object_addr, irb_.getInt32(dex_pc),
2346 array_addr, irb_.getInt32(payload_offset));
2347
2348 EmitGuard_ExceptionLandingPad(dex_pc);
2349 }
2350
2351 return;
2352}
2353
2354llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2355 llvm::Value* array_length_value,
2356 uint32_t type_idx,
2357 bool is_filled_new_array) {
2358 llvm::Function* runtime_func;
2359
2360 bool skip_access_check =
Ian Rogers89756f22013-03-04 16:40:02 -08002361 driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
2362 *dex_compilation_unit_->GetDexFile(), type_idx);
TDYa127f71bf5a2012-07-29 20:09:52 -07002363
2364
2365 if (is_filled_new_array) {
2366 runtime_func = skip_access_check ?
2367 irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
2368 irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
2369 } else {
2370 runtime_func = skip_access_check ?
2371 irb_.GetRuntime(runtime_support::AllocArray) :
2372 irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
2373 }
2374
2375 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2376
2377 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2378
2379 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2380
2381 EmitUpdateDexPC(dex_pc);
2382
2383 llvm::Value* object_addr =
2384 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2385 array_length_value, thread_object_addr);
2386
2387 EmitGuard_ExceptionLandingPad(dex_pc);
2388
2389 return object_addr;
2390}
2391
2392llvm::Value* GBCExpanderPass::
2393EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -07002394 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -07002395 llvm::Value* this_addr,
2396 uint32_t dex_pc,
2397 bool is_fast_path) {
2398
2399 llvm::Function* runtime_func = NULL;
2400
2401 switch (invoke_type) {
TDYa127920be7c2012-09-10 17:13:22 -07002402 case art::kStatic:
TDYa127f71bf5a2012-07-29 20:09:52 -07002403 runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
2404 break;
2405
TDYa127920be7c2012-09-10 17:13:22 -07002406 case art::kDirect:
TDYa127f71bf5a2012-07-29 20:09:52 -07002407 runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
2408 break;
2409
TDYa127920be7c2012-09-10 17:13:22 -07002410 case art::kVirtual:
TDYa127f71bf5a2012-07-29 20:09:52 -07002411 runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
2412 break;
2413
TDYa127920be7c2012-09-10 17:13:22 -07002414 case art::kSuper:
TDYa127f71bf5a2012-07-29 20:09:52 -07002415 runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
2416 break;
2417
TDYa127920be7c2012-09-10 17:13:22 -07002418 case art::kInterface:
TDYa127f71bf5a2012-07-29 20:09:52 -07002419 if (is_fast_path) {
2420 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
2421 } else {
2422 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
2423 }
2424 break;
2425 }
2426
2427 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2428
2429 if (this_addr == NULL) {
TDYa127920be7c2012-09-10 17:13:22 -07002430 DCHECK_EQ(invoke_type, art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002431 this_addr = irb_.getJNull();
2432 }
2433
2434 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2435
2436 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2437
2438 EmitUpdateDexPC(dex_pc);
2439
2440 llvm::Value* callee_method_object_addr =
2441 irb_.CreateCall4(runtime_func,
2442 callee_method_idx_value,
2443 this_addr,
2444 caller_method_object_addr,
2445 thread_object_addr);
2446
2447 EmitGuard_ExceptionLandingPad(dex_pc);
2448
2449 return callee_method_object_addr;
2450}
2451
TDYa1275e869b62012-07-25 00:45:39 -07002452void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2453 // Using runtime support, let the target can override by InlineAssembly.
2454 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2455}
2456
2457void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002458 if (shadow_frame_ == NULL) {
2459 return;
2460 }
TDYa1275e869b62012-07-25 00:45:39 -07002461 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07002462 art::ShadowFrame::DexPCOffset(),
TDYa1275e869b62012-07-25 00:45:39 -07002463 irb_.getInt32(dex_pc),
2464 kTBAAShadowFrame);
2465}
2466
2467void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2468 llvm::Value* denominator,
2469 JType op_jty) {
2470 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2471
2472 llvm::Constant* zero = irb_.getJZero(op_jty);
2473
2474 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2475
2476 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2477
2478 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2479
2480 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2481
2482 irb_.SetInsertPoint(block_exception);
2483 EmitUpdateDexPC(dex_pc);
2484 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
2485 EmitBranchExceptionLandingPad(dex_pc);
2486
2487 irb_.SetInsertPoint(block_continue);
2488}
2489
2490void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002491 llvm::Value* object,
2492 int opt_flags) {
2493 bool ignore_null_check = ((opt_flags & MIR_IGNORE_NULL_CHECK) != 0);
2494 if (ignore_null_check) {
2495 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2496 if (lpad) {
2497 // There is at least one catch: create a "fake" conditional branch to
2498 // keep the exception edge to the catch block.
2499 landing_pad_phi_mapping_[lpad].push_back(
2500 std::make_pair(current_bb_->getUniquePredecessor(),
2501 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002502
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002503 llvm::BasicBlock* block_continue =
2504 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002505
Ian Rogers8e696052013-03-04 09:00:40 -08002506 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002507
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002508 irb_.SetInsertPoint(block_continue);
2509 }
2510 } else {
2511 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
TDYa1275e869b62012-07-25 00:45:39 -07002512
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002513 llvm::BasicBlock* block_exception =
2514 CreateBasicBlockWithDexPC(dex_pc, "nullp");
TDYa1275e869b62012-07-25 00:45:39 -07002515
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002516 llvm::BasicBlock* block_continue =
2517 CreateBasicBlockWithDexPC(dex_pc, "cont");
2518
2519 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2520
2521 irb_.SetInsertPoint(block_exception);
2522 EmitUpdateDexPC(dex_pc);
2523 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
2524 irb_.getInt32(dex_pc));
2525 EmitBranchExceptionLandingPad(dex_pc);
2526
2527 irb_.SetInsertPoint(block_continue);
2528 }
TDYa1275e869b62012-07-25 00:45:39 -07002529}
2530
2531void
2532GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2533 llvm::Value* array,
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002534 llvm::Value* index,
2535 int opt_flags) {
2536 bool ignore_range_check = ((opt_flags & MIR_IGNORE_RANGE_CHECK) != 0);
2537 if (ignore_range_check) {
2538 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2539 if (lpad) {
2540 // There is at least one catch: create a "fake" conditional branch to
2541 // keep the exception edge to the catch block.
2542 landing_pad_phi_mapping_[lpad].push_back(
2543 std::make_pair(current_bb_->getUniquePredecessor(),
2544 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002545
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002546 llvm::BasicBlock* block_continue =
2547 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002548
Ian Rogers8e696052013-03-04 09:00:40 -08002549 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002550
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002551 irb_.SetInsertPoint(block_continue);
2552 }
2553 } else {
2554 llvm::Value* array_len = EmitLoadArrayLength(array);
TDYa1275e869b62012-07-25 00:45:39 -07002555
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002556 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
TDYa1275e869b62012-07-25 00:45:39 -07002557
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002558 llvm::BasicBlock* block_exception =
2559 CreateBasicBlockWithDexPC(dex_pc, "overflow");
TDYa1275e869b62012-07-25 00:45:39 -07002560
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002561 llvm::BasicBlock* block_continue =
2562 CreateBasicBlockWithDexPC(dex_pc, "cont");
TDYa1275e869b62012-07-25 00:45:39 -07002563
Sebastien Hertz2ffe4f12013-03-01 12:12:30 +01002564 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2565
2566 irb_.SetInsertPoint(block_exception);
2567
2568 EmitUpdateDexPC(dex_pc);
2569 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
2570 EmitBranchExceptionLandingPad(dex_pc);
2571
2572 irb_.SetInsertPoint(block_continue);
2573 }
TDYa1275e869b62012-07-25 00:45:39 -07002574}
2575
Ian Rogers8e696052013-03-04 09:00:40 -08002576llvm::FunctionType* GBCExpanderPass::GetFunctionType(llvm::Type* ret_type, uint32_t method_idx,
TDYa1275e869b62012-07-25 00:45:39 -07002577 bool is_static) {
2578 // Get method signature
Ian Rogers8e696052013-03-04 09:00:40 -08002579 art::DexFile::MethodId const& method_id =
Ian Rogers89756f22013-03-04 16:40:02 -08002580 dex_compilation_unit_->GetDexFile()->GetMethodId(method_idx);
TDYa1275e869b62012-07-25 00:45:39 -07002581
2582 uint32_t shorty_size;
Ian Rogers89756f22013-03-04 16:40:02 -08002583 const char* shorty = dex_compilation_unit_->GetDexFile()->GetMethodShorty(method_id, &shorty_size);
TDYa1275e869b62012-07-25 00:45:39 -07002584 CHECK_GE(shorty_size, 1u);
2585
TDYa1275e869b62012-07-25 00:45:39 -07002586 // Get argument type
2587 std::vector<llvm::Type*> args_type;
2588
2589 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2590
2591 if (!is_static) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002592 args_type.push_back(irb_.getJType('L')); // "this" object pointer
TDYa1275e869b62012-07-25 00:45:39 -07002593 }
2594
2595 for (uint32_t i = 1; i < shorty_size; ++i) {
buzbee26f10ee2012-12-21 11:16:29 -08002596 char shorty_type = art::RemapShorty(shorty[i]);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002597 args_type.push_back(irb_.getJType(shorty_type));
TDYa1275e869b62012-07-25 00:45:39 -07002598 }
2599
2600 return llvm::FunctionType::get(ret_type, args_type, false);
2601}
2602
2603
2604llvm::BasicBlock* GBCExpanderPass::
2605CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2606 std::string name;
2607
2608#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002609 art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
TDYa1275e869b62012-07-25 00:45:39 -07002610#endif
2611
2612 return llvm::BasicBlock::Create(context_, name, func_);
2613}
2614
2615llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
Ian Rogers89756f22013-03-04 16:40:02 -08002616 DCHECK(dex_pc < dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002617 CHECK(basic_blocks_[dex_pc] != NULL);
TDYa1275e869b62012-07-25 00:45:39 -07002618 return basic_blocks_[dex_pc];
2619}
2620
2621int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2622 int32_t min = 0;
Ian Rogers89756f22013-03-04 16:40:02 -08002623 int32_t max = dex_compilation_unit_->GetCodeItem()->tries_size_ - 1;
TDYa1275e869b62012-07-25 00:45:39 -07002624
2625 while (min <= max) {
2626 int32_t mid = min + (max - min) / 2;
2627
Ian Rogers89756f22013-03-04 16:40:02 -08002628 const art::DexFile::TryItem* ti =
2629 art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(), mid);
TDYa1275e869b62012-07-25 00:45:39 -07002630 uint32_t start = ti->start_addr_;
2631 uint32_t end = start + ti->insn_count_;
2632
2633 if (dex_pc < start) {
2634 max = mid - 1;
2635 } else if (dex_pc >= end) {
2636 min = mid + 1;
2637 } else {
2638 return mid; // found
2639 }
2640 }
2641
2642 return -1; // not found
2643}
2644
2645llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2646 // Find the try item for this address in this method
2647 int32_t ti_offset = GetTryItemOffset(dex_pc);
2648
2649 if (ti_offset == -1) {
2650 return NULL; // No landing pad is available for this address.
2651 }
2652
2653 // Check for the existing landing pad basic block
2654 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2655 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2656
2657 if (block_lpad) {
2658 // We have generated landing pad for this try item already. Return the
2659 // same basic block.
2660 return block_lpad;
2661 }
2662
2663 // Get try item from code item
Ian Rogers89756f22013-03-04 16:40:02 -08002664 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(),
Ian Rogers8e696052013-03-04 09:00:40 -08002665 ti_offset);
TDYa1275e869b62012-07-25 00:45:39 -07002666
2667 std::string lpadname;
2668
2669#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002670 art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
TDYa1275e869b62012-07-25 00:45:39 -07002671#endif
2672
2673 // Create landing pad basic block
2674 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2675
2676 // Change IRBuilder insert point
2677 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2678 irb_.SetInsertPoint(block_lpad);
2679
2680 // Find catch block with matching type
2681 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2682
2683 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2684
2685 llvm::Value* catch_handler_index_value =
2686 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
2687 method_object_addr, ti_offset_value);
2688
2689 // Switch instruction (Go to unwind basic block by default)
2690 llvm::SwitchInst* sw =
2691 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2692
2693 // Cases with matched catch block
Ian Rogers89756f22013-03-04 16:40:02 -08002694 art::CatchHandlerIterator iter(*dex_compilation_unit_->GetCodeItem(), ti->start_addr_);
TDYa1275e869b62012-07-25 00:45:39 -07002695
2696 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2697 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2698 }
2699
2700 // Restore the orignal insert point for IRBuilder
2701 irb_.restoreIP(irb_ip_original);
2702
2703 // Cache this landing pad
2704 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2705 basic_block_landing_pads_[ti_offset] = block_lpad;
2706
2707 return block_lpad;
2708}
2709
2710llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2711 // Check the existing unwinding baisc block block
2712 if (basic_block_unwind_ != NULL) {
2713 return basic_block_unwind_;
2714 }
2715
2716 // Create new basic block for unwinding
2717 basic_block_unwind_ =
2718 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2719
2720 // Change IRBuilder insert point
2721 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2722 irb_.SetInsertPoint(basic_block_unwind_);
2723
2724 // Pop the shadow frame
2725 Expand_PopShadowFrame();
2726
2727 // Emit the code to return default value (zero) for the given return type.
Ian Rogers89756f22013-03-04 16:40:02 -08002728 char ret_shorty = dex_compilation_unit_->GetShorty()[0];
buzbee26f10ee2012-12-21 11:16:29 -08002729 ret_shorty = art::RemapShorty(ret_shorty);
TDYa1275e869b62012-07-25 00:45:39 -07002730 if (ret_shorty == 'V') {
2731 irb_.CreateRetVoid();
2732 } else {
2733 irb_.CreateRet(irb_.getJZero(ret_shorty));
2734 }
2735
2736 // Restore the orignal insert point for IRBuilder
2737 irb_.restoreIP(irb_ip_original);
2738
2739 return basic_block_unwind_;
2740}
2741
2742void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2743 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002744 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002745 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002746 irb_.CreateBr(lpad);
2747 } else {
2748 irb_.CreateBr(GetUnwindBasicBlock());
2749 }
2750}
2751
2752void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
Jeff Hao9a142652013-01-17 23:10:19 +00002753 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2754
TDYa1275e869b62012-07-25 00:45:39 -07002755 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2756
2757 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002758 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002759 irb_.GetInsertBlock()));
Jeff Hao9a142652013-01-17 23:10:19 +00002760 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002761 } else {
Jeff Hao9a142652013-01-17 23:10:19 +00002762 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002763 }
2764
2765 irb_.SetInsertPoint(block_cont);
2766}
2767
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002768llvm::Value*
2769GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2770 llvm::CallInst& call_inst) {
2771 switch (intr_id) {
2772 //==- Thread -----------------------------------------------------------==//
2773 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07002774 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002775 }
Logan Chien75e4b602012-07-23 14:24:12 -07002776 case IntrinsicHelper::CheckSuspend: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08002777 Expand_TestSuspend(call_inst);
TDYa127890ea892012-08-22 10:49:42 -07002778 return NULL;
2779 }
2780 case IntrinsicHelper::TestSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002781 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002782 return NULL;
2783 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002784 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07002785 Expand_MarkGCCard(call_inst);
2786 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002787 }
Logan Chien75e4b602012-07-23 14:24:12 -07002788
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002789 //==- Exception --------------------------------------------------------==//
2790 case IntrinsicHelper::ThrowException: {
2791 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
2792 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002793 case IntrinsicHelper::HLThrowException: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002794 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2795
2796 EmitUpdateDexPC(dex_pc);
2797
2798 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
2799 call_inst.getArgOperand(0));
2800
2801 EmitGuard_ExceptionLandingPad(dex_pc);
2802 return NULL;
2803 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002804 case IntrinsicHelper::GetException: {
TDYa127823433d2012-09-26 16:03:51 -07002805 return irb_.Runtime().EmitGetAndClearException();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002806 }
2807 case IntrinsicHelper::IsExceptionPending: {
2808 return irb_.Runtime().EmitIsExceptionPending();
2809 }
2810 case IntrinsicHelper::FindCatchBlock: {
2811 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
2812 }
2813 case IntrinsicHelper::ThrowDivZeroException: {
2814 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
2815 }
2816 case IntrinsicHelper::ThrowNullPointerException: {
2817 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
2818 }
2819 case IntrinsicHelper::ThrowIndexOutOfBounds: {
2820 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
2821 }
Logan Chien75e4b602012-07-23 14:24:12 -07002822
2823 //==- Const String -----------------------------------------------------==//
2824 case IntrinsicHelper::ConstString: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002825 return Expand_ConstString(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002826 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002827 case IntrinsicHelper::LoadStringFromDexCache: {
2828 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2829 }
2830 case IntrinsicHelper::ResolveString: {
2831 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
2832 }
Logan Chien75e4b602012-07-23 14:24:12 -07002833
2834 //==- Const Class ------------------------------------------------------==//
2835 case IntrinsicHelper::ConstClass: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002836 return Expand_ConstClass(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002837 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002838 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
2839 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
2840 }
2841 case IntrinsicHelper::LoadTypeFromDexCache: {
2842 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2843 }
2844 case IntrinsicHelper::InitializeType: {
2845 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
2846 }
Logan Chien75e4b602012-07-23 14:24:12 -07002847
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002848 //==- Lock -------------------------------------------------------------==//
2849 case IntrinsicHelper::LockObject: {
2850 Expand_LockObject(call_inst.getArgOperand(0));
2851 return NULL;
2852 }
2853 case IntrinsicHelper::UnlockObject: {
2854 Expand_UnlockObject(call_inst.getArgOperand(0));
2855 return NULL;
2856 }
Logan Chien75e4b602012-07-23 14:24:12 -07002857
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002858 //==- Cast -------------------------------------------------------------==//
2859 case IntrinsicHelper::CheckCast: {
2860 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
2861 }
Logan Chien75e4b602012-07-23 14:24:12 -07002862 case IntrinsicHelper::HLCheckCast: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002863 Expand_HLCheckCast(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002864 return NULL;
2865 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002866 case IntrinsicHelper::IsAssignable: {
2867 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
2868 }
Logan Chien75e4b602012-07-23 14:24:12 -07002869
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002870 //==- Alloc ------------------------------------------------------------==//
2871 case IntrinsicHelper::AllocObject: {
2872 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
2873 }
2874 case IntrinsicHelper::AllocObjectWithAccessCheck: {
2875 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
2876 }
Logan Chien75e4b602012-07-23 14:24:12 -07002877
2878 //==- Instance ---------------------------------------------------------==//
2879 case IntrinsicHelper::NewInstance: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002880 return Expand_NewInstance(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002881 }
2882 case IntrinsicHelper::InstanceOf: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002883 return Expand_InstanceOf(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002884 }
2885
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002886 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07002887 case IntrinsicHelper::NewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002888 return Expand_NewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002889 }
2890 case IntrinsicHelper::OptArrayLength: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002891 return Expand_OptArrayLength(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002892 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002893 case IntrinsicHelper::ArrayLength: {
2894 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2895 }
2896 case IntrinsicHelper::AllocArray: {
2897 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
2898 }
2899 case IntrinsicHelper::AllocArrayWithAccessCheck: {
2900 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
2901 call_inst);
2902 }
2903 case IntrinsicHelper::CheckAndAllocArray: {
2904 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
2905 }
2906 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
2907 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
2908 call_inst);
2909 }
2910 case IntrinsicHelper::ArrayGet: {
2911 return Expand_ArrayGet(call_inst.getArgOperand(0),
2912 call_inst.getArgOperand(1),
2913 kInt);
2914 }
2915 case IntrinsicHelper::ArrayGetWide: {
2916 return Expand_ArrayGet(call_inst.getArgOperand(0),
2917 call_inst.getArgOperand(1),
2918 kLong);
2919 }
2920 case IntrinsicHelper::ArrayGetObject: {
2921 return Expand_ArrayGet(call_inst.getArgOperand(0),
2922 call_inst.getArgOperand(1),
2923 kObject);
2924 }
2925 case IntrinsicHelper::ArrayGetBoolean: {
2926 return Expand_ArrayGet(call_inst.getArgOperand(0),
2927 call_inst.getArgOperand(1),
2928 kBoolean);
2929 }
2930 case IntrinsicHelper::ArrayGetByte: {
2931 return Expand_ArrayGet(call_inst.getArgOperand(0),
2932 call_inst.getArgOperand(1),
2933 kByte);
2934 }
2935 case IntrinsicHelper::ArrayGetChar: {
2936 return Expand_ArrayGet(call_inst.getArgOperand(0),
2937 call_inst.getArgOperand(1),
2938 kChar);
2939 }
2940 case IntrinsicHelper::ArrayGetShort: {
2941 return Expand_ArrayGet(call_inst.getArgOperand(0),
2942 call_inst.getArgOperand(1),
2943 kShort);
2944 }
2945 case IntrinsicHelper::ArrayPut: {
2946 Expand_ArrayPut(call_inst.getArgOperand(0),
2947 call_inst.getArgOperand(1),
2948 call_inst.getArgOperand(2),
2949 kInt);
2950 return NULL;
2951 }
2952 case IntrinsicHelper::ArrayPutWide: {
2953 Expand_ArrayPut(call_inst.getArgOperand(0),
2954 call_inst.getArgOperand(1),
2955 call_inst.getArgOperand(2),
2956 kLong);
2957 return NULL;
2958 }
2959 case IntrinsicHelper::ArrayPutObject: {
2960 Expand_ArrayPut(call_inst.getArgOperand(0),
2961 call_inst.getArgOperand(1),
2962 call_inst.getArgOperand(2),
2963 kObject);
2964 return NULL;
2965 }
2966 case IntrinsicHelper::ArrayPutBoolean: {
2967 Expand_ArrayPut(call_inst.getArgOperand(0),
2968 call_inst.getArgOperand(1),
2969 call_inst.getArgOperand(2),
2970 kBoolean);
2971 return NULL;
2972 }
2973 case IntrinsicHelper::ArrayPutByte: {
2974 Expand_ArrayPut(call_inst.getArgOperand(0),
2975 call_inst.getArgOperand(1),
2976 call_inst.getArgOperand(2),
2977 kByte);
2978 return NULL;
2979 }
2980 case IntrinsicHelper::ArrayPutChar: {
2981 Expand_ArrayPut(call_inst.getArgOperand(0),
2982 call_inst.getArgOperand(1),
2983 call_inst.getArgOperand(2),
2984 kChar);
2985 return NULL;
2986 }
2987 case IntrinsicHelper::ArrayPutShort: {
2988 Expand_ArrayPut(call_inst.getArgOperand(0),
2989 call_inst.getArgOperand(1),
2990 call_inst.getArgOperand(2),
2991 kShort);
2992 return NULL;
2993 }
2994 case IntrinsicHelper::CheckPutArrayElement: {
2995 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
2996 }
2997 case IntrinsicHelper::FilledNewArray: {
2998 Expand_FilledNewArray(call_inst);
2999 return NULL;
3000 }
3001 case IntrinsicHelper::FillArrayData: {
3002 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
3003 }
Logan Chien75e4b602012-07-23 14:24:12 -07003004 case IntrinsicHelper::HLFillArrayData: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003005 Expand_HLFillArrayData(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003006 return NULL;
3007 }
3008 case IntrinsicHelper::HLFilledNewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003009 return Expand_HLFilledNewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003010 }
3011
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003012 //==- Instance Field ---------------------------------------------------==//
3013 case IntrinsicHelper::InstanceFieldGet:
3014 case IntrinsicHelper::InstanceFieldGetBoolean:
3015 case IntrinsicHelper::InstanceFieldGetByte:
3016 case IntrinsicHelper::InstanceFieldGetChar:
3017 case IntrinsicHelper::InstanceFieldGetShort: {
3018 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
3019 }
3020 case IntrinsicHelper::InstanceFieldGetWide: {
3021 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
3022 }
3023 case IntrinsicHelper::InstanceFieldGetObject: {
3024 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
3025 }
3026 case IntrinsicHelper::InstanceFieldGetFast: {
3027 return Expand_IGetFast(call_inst.getArgOperand(0),
3028 call_inst.getArgOperand(1),
3029 call_inst.getArgOperand(2),
3030 kInt);
3031 }
3032 case IntrinsicHelper::InstanceFieldGetWideFast: {
3033 return Expand_IGetFast(call_inst.getArgOperand(0),
3034 call_inst.getArgOperand(1),
3035 call_inst.getArgOperand(2),
3036 kLong);
3037 }
3038 case IntrinsicHelper::InstanceFieldGetObjectFast: {
3039 return Expand_IGetFast(call_inst.getArgOperand(0),
3040 call_inst.getArgOperand(1),
3041 call_inst.getArgOperand(2),
3042 kObject);
3043 }
3044 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
3045 return Expand_IGetFast(call_inst.getArgOperand(0),
3046 call_inst.getArgOperand(1),
3047 call_inst.getArgOperand(2),
3048 kBoolean);
3049 }
3050 case IntrinsicHelper::InstanceFieldGetByteFast: {
3051 return Expand_IGetFast(call_inst.getArgOperand(0),
3052 call_inst.getArgOperand(1),
3053 call_inst.getArgOperand(2),
3054 kByte);
3055 }
3056 case IntrinsicHelper::InstanceFieldGetCharFast: {
3057 return Expand_IGetFast(call_inst.getArgOperand(0),
3058 call_inst.getArgOperand(1),
3059 call_inst.getArgOperand(2),
3060 kChar);
3061 }
3062 case IntrinsicHelper::InstanceFieldGetShortFast: {
3063 return Expand_IGetFast(call_inst.getArgOperand(0),
3064 call_inst.getArgOperand(1),
3065 call_inst.getArgOperand(2),
3066 kShort);
3067 }
3068 case IntrinsicHelper::InstanceFieldPut:
3069 case IntrinsicHelper::InstanceFieldPutBoolean:
3070 case IntrinsicHelper::InstanceFieldPutByte:
3071 case IntrinsicHelper::InstanceFieldPutChar:
3072 case IntrinsicHelper::InstanceFieldPutShort: {
3073 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
3074 }
3075 case IntrinsicHelper::InstanceFieldPutWide: {
3076 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
3077 }
3078 case IntrinsicHelper::InstanceFieldPutObject: {
3079 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
3080 }
3081 case IntrinsicHelper::InstanceFieldPutFast: {
3082 Expand_IPutFast(call_inst.getArgOperand(0),
3083 call_inst.getArgOperand(1),
3084 call_inst.getArgOperand(2),
3085 call_inst.getArgOperand(3),
3086 kInt);
3087 return NULL;
3088 }
3089 case IntrinsicHelper::InstanceFieldPutWideFast: {
3090 Expand_IPutFast(call_inst.getArgOperand(0),
3091 call_inst.getArgOperand(1),
3092 call_inst.getArgOperand(2),
3093 call_inst.getArgOperand(3),
3094 kLong);
3095 return NULL;
3096 }
3097 case IntrinsicHelper::InstanceFieldPutObjectFast: {
3098 Expand_IPutFast(call_inst.getArgOperand(0),
3099 call_inst.getArgOperand(1),
3100 call_inst.getArgOperand(2),
3101 call_inst.getArgOperand(3),
3102 kObject);
3103 return NULL;
3104 }
3105 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
3106 Expand_IPutFast(call_inst.getArgOperand(0),
3107 call_inst.getArgOperand(1),
3108 call_inst.getArgOperand(2),
3109 call_inst.getArgOperand(3),
3110 kBoolean);
3111 return NULL;
3112 }
3113 case IntrinsicHelper::InstanceFieldPutByteFast: {
3114 Expand_IPutFast(call_inst.getArgOperand(0),
3115 call_inst.getArgOperand(1),
3116 call_inst.getArgOperand(2),
3117 call_inst.getArgOperand(3),
3118 kByte);
3119 return NULL;
3120 }
3121 case IntrinsicHelper::InstanceFieldPutCharFast: {
3122 Expand_IPutFast(call_inst.getArgOperand(0),
3123 call_inst.getArgOperand(1),
3124 call_inst.getArgOperand(2),
3125 call_inst.getArgOperand(3),
3126 kChar);
3127 return NULL;
3128 }
3129 case IntrinsicHelper::InstanceFieldPutShortFast: {
3130 Expand_IPutFast(call_inst.getArgOperand(0),
3131 call_inst.getArgOperand(1),
3132 call_inst.getArgOperand(2),
3133 call_inst.getArgOperand(3),
3134 kShort);
3135 return NULL;
3136 }
Logan Chien75e4b602012-07-23 14:24:12 -07003137
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003138 //==- Static Field -----------------------------------------------------==//
3139 case IntrinsicHelper::StaticFieldGet:
3140 case IntrinsicHelper::StaticFieldGetBoolean:
3141 case IntrinsicHelper::StaticFieldGetByte:
3142 case IntrinsicHelper::StaticFieldGetChar:
3143 case IntrinsicHelper::StaticFieldGetShort: {
3144 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
3145 }
3146 case IntrinsicHelper::StaticFieldGetWide: {
3147 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
3148 }
3149 case IntrinsicHelper::StaticFieldGetObject: {
3150 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
3151 }
3152 case IntrinsicHelper::StaticFieldGetFast: {
3153 return Expand_SGetFast(call_inst.getArgOperand(0),
3154 call_inst.getArgOperand(1),
3155 call_inst.getArgOperand(2),
3156 kInt);
3157 }
3158 case IntrinsicHelper::StaticFieldGetWideFast: {
3159 return Expand_SGetFast(call_inst.getArgOperand(0),
3160 call_inst.getArgOperand(1),
3161 call_inst.getArgOperand(2),
3162 kLong);
3163 }
3164 case IntrinsicHelper::StaticFieldGetObjectFast: {
3165 return Expand_SGetFast(call_inst.getArgOperand(0),
3166 call_inst.getArgOperand(1),
3167 call_inst.getArgOperand(2),
3168 kObject);
3169 }
3170 case IntrinsicHelper::StaticFieldGetBooleanFast: {
3171 return Expand_SGetFast(call_inst.getArgOperand(0),
3172 call_inst.getArgOperand(1),
3173 call_inst.getArgOperand(2),
3174 kBoolean);
3175 }
3176 case IntrinsicHelper::StaticFieldGetByteFast: {
3177 return Expand_SGetFast(call_inst.getArgOperand(0),
3178 call_inst.getArgOperand(1),
3179 call_inst.getArgOperand(2),
3180 kByte);
3181 }
3182 case IntrinsicHelper::StaticFieldGetCharFast: {
3183 return Expand_SGetFast(call_inst.getArgOperand(0),
3184 call_inst.getArgOperand(1),
3185 call_inst.getArgOperand(2),
3186 kChar);
3187 }
3188 case IntrinsicHelper::StaticFieldGetShortFast: {
3189 return Expand_SGetFast(call_inst.getArgOperand(0),
3190 call_inst.getArgOperand(1),
3191 call_inst.getArgOperand(2),
3192 kShort);
3193 }
3194 case IntrinsicHelper::StaticFieldPut:
3195 case IntrinsicHelper::StaticFieldPutBoolean:
3196 case IntrinsicHelper::StaticFieldPutByte:
3197 case IntrinsicHelper::StaticFieldPutChar:
3198 case IntrinsicHelper::StaticFieldPutShort: {
3199 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
3200 }
3201 case IntrinsicHelper::StaticFieldPutWide: {
3202 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
3203 }
3204 case IntrinsicHelper::StaticFieldPutObject: {
3205 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
3206 }
3207 case IntrinsicHelper::StaticFieldPutFast: {
3208 Expand_SPutFast(call_inst.getArgOperand(0),
3209 call_inst.getArgOperand(1),
3210 call_inst.getArgOperand(2),
3211 call_inst.getArgOperand(3),
3212 kInt);
3213 return NULL;
3214 }
3215 case IntrinsicHelper::StaticFieldPutWideFast: {
3216 Expand_SPutFast(call_inst.getArgOperand(0),
3217 call_inst.getArgOperand(1),
3218 call_inst.getArgOperand(2),
3219 call_inst.getArgOperand(3),
3220 kLong);
3221 return NULL;
3222 }
3223 case IntrinsicHelper::StaticFieldPutObjectFast: {
3224 Expand_SPutFast(call_inst.getArgOperand(0),
3225 call_inst.getArgOperand(1),
3226 call_inst.getArgOperand(2),
3227 call_inst.getArgOperand(3),
3228 kObject);
3229 return NULL;
3230 }
3231 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3232 Expand_SPutFast(call_inst.getArgOperand(0),
3233 call_inst.getArgOperand(1),
3234 call_inst.getArgOperand(2),
3235 call_inst.getArgOperand(3),
3236 kBoolean);
3237 return NULL;
3238 }
3239 case IntrinsicHelper::StaticFieldPutByteFast: {
3240 Expand_SPutFast(call_inst.getArgOperand(0),
3241 call_inst.getArgOperand(1),
3242 call_inst.getArgOperand(2),
3243 call_inst.getArgOperand(3),
3244 kByte);
3245 return NULL;
3246 }
3247 case IntrinsicHelper::StaticFieldPutCharFast: {
3248 Expand_SPutFast(call_inst.getArgOperand(0),
3249 call_inst.getArgOperand(1),
3250 call_inst.getArgOperand(2),
3251 call_inst.getArgOperand(3),
3252 kChar);
3253 return NULL;
3254 }
3255 case IntrinsicHelper::StaticFieldPutShortFast: {
3256 Expand_SPutFast(call_inst.getArgOperand(0),
3257 call_inst.getArgOperand(1),
3258 call_inst.getArgOperand(2),
3259 call_inst.getArgOperand(3),
3260 kShort);
3261 return NULL;
3262 }
3263 case IntrinsicHelper::LoadDeclaringClassSSB: {
3264 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3265 }
3266 case IntrinsicHelper::LoadClassSSBFromDexCache: {
3267 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
3268 }
3269 case IntrinsicHelper::InitializeAndLoadClassSSB: {
3270 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
3271 }
Logan Chien75e4b602012-07-23 14:24:12 -07003272
3273 //==- High-level Array -------------------------------------------------==//
3274 case IntrinsicHelper::HLArrayGet: {
TDYa1275a26d442012-07-26 18:58:38 -07003275 return Expand_HLArrayGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003276 }
3277 case IntrinsicHelper::HLArrayGetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003278 return Expand_HLArrayGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003279 }
3280 case IntrinsicHelper::HLArrayGetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003281 return Expand_HLArrayGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003282 }
3283 case IntrinsicHelper::HLArrayGetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003284 return Expand_HLArrayGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003285 }
3286 case IntrinsicHelper::HLArrayGetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003287 return Expand_HLArrayGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003288 }
3289 case IntrinsicHelper::HLArrayGetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003290 return Expand_HLArrayGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003291 }
3292 case IntrinsicHelper::HLArrayGetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003293 return Expand_HLArrayGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003294 }
3295 case IntrinsicHelper::HLArrayGetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003296 return Expand_HLArrayGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003297 }
3298 case IntrinsicHelper::HLArrayGetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003299 return Expand_HLArrayGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003300 }
3301 case IntrinsicHelper::HLArrayPut: {
TDYa1275a26d442012-07-26 18:58:38 -07003302 Expand_HLArrayPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003303 return NULL;
3304 }
3305 case IntrinsicHelper::HLArrayPutBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003306 Expand_HLArrayPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003307 return NULL;
3308 }
3309 case IntrinsicHelper::HLArrayPutByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003310 Expand_HLArrayPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003311 return NULL;
3312 }
3313 case IntrinsicHelper::HLArrayPutChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003314 Expand_HLArrayPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003315 return NULL;
3316 }
3317 case IntrinsicHelper::HLArrayPutShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003318 Expand_HLArrayPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003319 return NULL;
3320 }
3321 case IntrinsicHelper::HLArrayPutFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003322 Expand_HLArrayPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003323 return NULL;
3324 }
3325 case IntrinsicHelper::HLArrayPutWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003326 Expand_HLArrayPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003327 return NULL;
3328 }
3329 case IntrinsicHelper::HLArrayPutDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003330 Expand_HLArrayPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003331 return NULL;
3332 }
3333 case IntrinsicHelper::HLArrayPutObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003334 Expand_HLArrayPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003335 return NULL;
3336 }
3337
3338 //==- High-level Instance ----------------------------------------------==//
3339 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07003340 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003341 }
3342 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003343 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003344 }
3345 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003346 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003347 }
3348 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003349 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003350 }
3351 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003352 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003353 }
3354 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003355 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003356 }
3357 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003358 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003359 }
3360 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003361 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003362 }
3363 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003364 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003365 }
3366 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07003367 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003368 return NULL;
3369 }
3370 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003371 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003372 return NULL;
3373 }
3374 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003375 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003376 return NULL;
3377 }
3378 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003379 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003380 return NULL;
3381 }
3382 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003383 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003384 return NULL;
3385 }
3386 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003387 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003388 return NULL;
3389 }
3390 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003391 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003392 return NULL;
3393 }
3394 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003395 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003396 return NULL;
3397 }
3398 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003399 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003400 return NULL;
3401 }
3402
3403 //==- High-level Invoke ------------------------------------------------==//
TDYa127f71bf5a2012-07-29 20:09:52 -07003404 case IntrinsicHelper::HLInvokeVoid:
3405 case IntrinsicHelper::HLInvokeObj:
3406 case IntrinsicHelper::HLInvokeInt:
3407 case IntrinsicHelper::HLInvokeFloat:
3408 case IntrinsicHelper::HLInvokeLong:
Logan Chien75e4b602012-07-23 14:24:12 -07003409 case IntrinsicHelper::HLInvokeDouble: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003410 return Expand_HLInvoke(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003411 }
3412
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003413 //==- Invoke -----------------------------------------------------------==//
3414 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
3415 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
3416 }
3417 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
3418 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
3419 }
3420 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
3421 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
3422 }
3423 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
3424 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
3425 }
3426 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
3427 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
3428 }
3429 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3430 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3431 }
3432 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3433 return Expand_GetVirtualCalleeMethodObjAddrFast(
3434 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3435 }
3436 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
3437 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
3438 }
3439 case IntrinsicHelper::InvokeRetVoid:
3440 case IntrinsicHelper::InvokeRetBoolean:
3441 case IntrinsicHelper::InvokeRetByte:
3442 case IntrinsicHelper::InvokeRetChar:
3443 case IntrinsicHelper::InvokeRetShort:
3444 case IntrinsicHelper::InvokeRetInt:
3445 case IntrinsicHelper::InvokeRetLong:
3446 case IntrinsicHelper::InvokeRetFloat:
3447 case IntrinsicHelper::InvokeRetDouble:
3448 case IntrinsicHelper::InvokeRetObject: {
3449 return Expand_Invoke(call_inst);
3450 }
Logan Chien75e4b602012-07-23 14:24:12 -07003451
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003452 //==- Math -------------------------------------------------------------==//
3453 case IntrinsicHelper::DivInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003454 return Expand_DivRem(call_inst, /* is_div */true, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003455 }
3456 case IntrinsicHelper::RemInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003457 return Expand_DivRem(call_inst, /* is_div */false, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003458 }
3459 case IntrinsicHelper::DivLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003460 return Expand_DivRem(call_inst, /* is_div */true, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003461 }
3462 case IntrinsicHelper::RemLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003463 return Expand_DivRem(call_inst, /* is_div */false, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003464 }
3465 case IntrinsicHelper::D2L: {
3466 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
3467 }
3468 case IntrinsicHelper::D2I: {
3469 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
3470 }
3471 case IntrinsicHelper::F2L: {
3472 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
3473 }
3474 case IntrinsicHelper::F2I: {
3475 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
3476 }
Logan Chien75e4b602012-07-23 14:24:12 -07003477
3478 //==- High-level Static ------------------------------------------------==//
3479 case IntrinsicHelper::HLSget: {
TDYa1275a26d442012-07-26 18:58:38 -07003480 return Expand_HLSget(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003481 }
3482 case IntrinsicHelper::HLSgetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003483 return Expand_HLSget(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003484 }
3485 case IntrinsicHelper::HLSgetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003486 return Expand_HLSget(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003487 }
3488 case IntrinsicHelper::HLSgetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003489 return Expand_HLSget(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003490 }
3491 case IntrinsicHelper::HLSgetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003492 return Expand_HLSget(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003493 }
3494 case IntrinsicHelper::HLSgetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003495 return Expand_HLSget(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003496 }
3497 case IntrinsicHelper::HLSgetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003498 return Expand_HLSget(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003499 }
3500 case IntrinsicHelper::HLSgetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003501 return Expand_HLSget(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003502 }
3503 case IntrinsicHelper::HLSgetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003504 return Expand_HLSget(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003505 }
3506 case IntrinsicHelper::HLSput: {
TDYa1275a26d442012-07-26 18:58:38 -07003507 Expand_HLSput(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003508 return NULL;
3509 }
3510 case IntrinsicHelper::HLSputBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003511 Expand_HLSput(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003512 return NULL;
3513 }
3514 case IntrinsicHelper::HLSputByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003515 Expand_HLSput(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003516 return NULL;
3517 }
3518 case IntrinsicHelper::HLSputChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003519 Expand_HLSput(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003520 return NULL;
3521 }
3522 case IntrinsicHelper::HLSputShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003523 Expand_HLSput(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003524 return NULL;
3525 }
3526 case IntrinsicHelper::HLSputFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003527 Expand_HLSput(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003528 return NULL;
3529 }
3530 case IntrinsicHelper::HLSputWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003531 Expand_HLSput(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003532 return NULL;
3533 }
3534 case IntrinsicHelper::HLSputDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003535 Expand_HLSput(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003536 return NULL;
3537 }
3538 case IntrinsicHelper::HLSputObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003539 Expand_HLSput(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003540 return NULL;
3541 }
3542
3543 //==- High-level Monitor -----------------------------------------------==//
3544 case IntrinsicHelper::MonitorEnter: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003545 Expand_MonitorEnter(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003546 return NULL;
3547 }
3548 case IntrinsicHelper::MonitorExit: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003549 Expand_MonitorExit(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003550 return NULL;
3551 }
3552
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003553 //==- Shadow Frame -----------------------------------------------------==//
3554 case IntrinsicHelper::AllocaShadowFrame: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08003555 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003556 return NULL;
3557 }
TDYa1278e950c12012-11-02 09:58:19 -07003558 case IntrinsicHelper::SetVReg: {
3559 Expand_SetVReg(call_inst.getArgOperand(0),
3560 call_inst.getArgOperand(1));
3561 return NULL;
3562 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003563 case IntrinsicHelper::PopShadowFrame: {
3564 Expand_PopShadowFrame();
3565 return NULL;
3566 }
3567 case IntrinsicHelper::UpdateDexPC: {
3568 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3569 return NULL;
3570 }
TDYa127a1b21852012-07-23 03:20:39 -07003571
Logan Chien75e4b602012-07-23 14:24:12 -07003572 //==- Comparison -------------------------------------------------------==//
3573 case IntrinsicHelper::CmplFloat:
3574 case IntrinsicHelper::CmplDouble: {
3575 return Expand_FPCompare(call_inst.getArgOperand(0),
3576 call_inst.getArgOperand(1),
3577 false);
3578 }
3579 case IntrinsicHelper::CmpgFloat:
3580 case IntrinsicHelper::CmpgDouble: {
3581 return Expand_FPCompare(call_inst.getArgOperand(0),
3582 call_inst.getArgOperand(1),
3583 true);
3584 }
3585 case IntrinsicHelper::CmpLong: {
3586 return Expand_LongCompare(call_inst.getArgOperand(0),
3587 call_inst.getArgOperand(1));
3588 }
TDYa127a1b21852012-07-23 03:20:39 -07003589
Logan Chien75e4b602012-07-23 14:24:12 -07003590 //==- Const ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003591 case IntrinsicHelper::ConstInt:
3592 case IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003593 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003594 }
TDYa127920be7c2012-09-10 17:13:22 -07003595 case IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003596 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3597 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07003598 }
TDYa127920be7c2012-09-10 17:13:22 -07003599 case IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003600 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3601 irb_.getJDoubleTy());
3602 }
TDYa127920be7c2012-09-10 17:13:22 -07003603 case IntrinsicHelper::ConstObj: {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003604 CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
3605 return irb_.getJNull();
Logan Chien75e4b602012-07-23 14:24:12 -07003606 }
3607
3608 //==- Method Info ------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003609 case IntrinsicHelper::MethodInfo: {
Shih-wei Liaob2596522012-09-14 16:36:11 -07003610 // Nothing to be done, because MethodInfo carries optional hints that are
3611 // not needed by the portable path.
Logan Chien75e4b602012-07-23 14:24:12 -07003612 return NULL;
3613 }
3614
3615 //==- Copy -------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003616 case IntrinsicHelper::CopyInt:
3617 case IntrinsicHelper::CopyFloat:
3618 case IntrinsicHelper::CopyLong:
3619 case IntrinsicHelper::CopyDouble:
3620 case IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003621 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003622 }
3623
3624 //==- Shift ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003625 case IntrinsicHelper::SHLLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003626 return Expand_IntegerShift(call_inst.getArgOperand(0),
3627 call_inst.getArgOperand(1),
3628 kIntegerSHL, kLong);
3629 }
TDYa127920be7c2012-09-10 17:13:22 -07003630 case IntrinsicHelper::SHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003631 return Expand_IntegerShift(call_inst.getArgOperand(0),
3632 call_inst.getArgOperand(1),
3633 kIntegerSHR, kLong);
3634 }
TDYa127920be7c2012-09-10 17:13:22 -07003635 case IntrinsicHelper::USHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003636 return Expand_IntegerShift(call_inst.getArgOperand(0),
3637 call_inst.getArgOperand(1),
3638 kIntegerUSHR, kLong);
3639 }
TDYa127920be7c2012-09-10 17:13:22 -07003640 case IntrinsicHelper::SHLInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003641 return Expand_IntegerShift(call_inst.getArgOperand(0),
3642 call_inst.getArgOperand(1),
3643 kIntegerSHL, kInt);
3644 }
TDYa127920be7c2012-09-10 17:13:22 -07003645 case IntrinsicHelper::SHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003646 return Expand_IntegerShift(call_inst.getArgOperand(0),
3647 call_inst.getArgOperand(1),
3648 kIntegerSHR, kInt);
3649 }
TDYa127920be7c2012-09-10 17:13:22 -07003650 case IntrinsicHelper::USHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003651 return Expand_IntegerShift(call_inst.getArgOperand(0),
3652 call_inst.getArgOperand(1),
3653 kIntegerUSHR, kInt);
3654 }
3655
3656 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07003657 case IntrinsicHelper::IntToChar: {
3658 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3659 irb_.getJIntTy());
3660 }
3661 case IntrinsicHelper::IntToShort: {
3662 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3663 irb_.getJIntTy());
3664 }
3665 case IntrinsicHelper::IntToByte: {
3666 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3667 irb_.getJIntTy());
3668 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003669
TDYa12787caa7e2012-08-25 23:23:27 -07003670 //==- Exception --------------------------------------------------------==//
3671 case IntrinsicHelper::CatchTargets: {
TDYa12755e5e6c2012-09-11 15:14:42 -07003672 UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
TDYa12787caa7e2012-08-25 23:23:27 -07003673 llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
3674 CHECK(si != NULL);
3675 irb_.CreateBr(si->getDefaultDest());
3676 si->eraseFromParent();
3677 return call_inst.getArgOperand(0);
3678 }
3679
Sebastien Hertz0d43d542013-02-27 19:02:16 +01003680 //==- Constructor barrier-----------------------------------------------==//
3681 case IntrinsicHelper::ConstructorBarrier: {
3682 irb_.CreateMemoryBarrier(art::kStoreStore);
3683 return NULL;
3684 }
3685
Logan Chien75e4b602012-07-23 14:24:12 -07003686 //==- Unknown Cases ----------------------------------------------------==//
3687 case IntrinsicHelper::MaxIntrinsicId:
3688 case IntrinsicHelper::UnknownId:
3689 //default:
3690 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3691 // give some warning on unmatched cases.
3692 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003693 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003694 }
Logan Chien75e4b602012-07-23 14:24:12 -07003695 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003696 return NULL;
3697}
3698
3699} // anonymous namespace
3700
3701namespace art {
Ian Rogers4c1c2832013-03-04 18:30:13 -08003702namespace llvm {
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003703
Ian Rogers4c1c2832013-03-04 18:30:13 -08003704::llvm::FunctionPass*
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003705CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
Ian Rogers89756f22013-03-04 16:40:02 -08003706 CompilerDriver* driver, DexCompilationUnit* dex_compilation_unit) {
3707 return new GBCExpanderPass(intrinsic_helper, irb, driver, dex_compilation_unit);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003708}
3709
Ian Rogers4c1c2832013-03-04 18:30:13 -08003710} // namespace llvm
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003711} // namespace art