1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "object_utils.h"
18
19 #include <llvm/ADT/DepthFirstIterator.h>
20 #include <llvm/Analysis/Verifier.h>
21 #include <llvm/Bitcode/ReaderWriter.h>
22 #include <llvm/IR/Instruction.h>
23 #include <llvm/IR/Instructions.h>
24 #include <llvm/IR/Metadata.h>
25 #include <llvm/IR/Type.h>
26 #include <llvm/Support/Casting.h>
27 #include <llvm/Support/InstIterator.h>
28 #include <llvm/Support/ToolOutputFile.h>
29
30 #include "dex/compiler_internals.h"
31 #include "dex/dataflow_iterator-inl.h"
32 #include "dex/frontend.h"
33 #include "mir_to_gbc.h"
34
35 #include "llvm/llvm_compilation_unit.h"
36 #include "llvm/utils_llvm.h"
37
38 const char* kLabelFormat = "%c0x%x_%d";
39 const char kInvalidBlock = 0xff;
40 const char kNormalBlock = 'L';
41 const char kCatchBlock = 'C';
42
43 namespace art {
44
GetLLVMBlock(int id)45 ::llvm::BasicBlock* MirConverter::GetLLVMBlock(int id) {
46 return id_to_block_map_.Get(id);
47 }
48
GetLLVMValue(int s_reg)49 ::llvm::Value* MirConverter::GetLLVMValue(int s_reg) {
50 return llvm_values_.Get(s_reg);
51 }
52
SetVregOnValue(::llvm::Value * val,int s_reg)53 void MirConverter::SetVregOnValue(::llvm::Value* val, int s_reg) {
54 // Set vreg for debugging
55 art::llvm::IntrinsicHelper::IntrinsicId id = art::llvm::IntrinsicHelper::SetVReg;
56 ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id);
57 int v_reg = mir_graph_->SRegToVReg(s_reg);
58 ::llvm::Value* table_slot = irb_->getInt32(v_reg);
59 ::llvm::Value* args[] = { table_slot, val };
60 irb_->CreateCall(func, args);
61 }
62
63 // Replace the placeholder value with the real definition
DefineValueOnly(::llvm::Value * val,int s_reg)64 void MirConverter::DefineValueOnly(::llvm::Value* val, int s_reg) {
65 ::llvm::Value* placeholder = GetLLVMValue(s_reg);
66 if (placeholder == NULL) {
67 // This can happen on instruction rewrite on verification failure
68 LOG(WARNING) << "Null placeholder";
69 return;
70 }
71 placeholder->replaceAllUsesWith(val);
72 val->takeName(placeholder);
73 llvm_values_.Put(s_reg, val);
74 ::llvm::Instruction* inst = ::llvm::dyn_cast< ::llvm::Instruction>(placeholder);
75 DCHECK(inst != NULL);
76 inst->eraseFromParent();
77 }
78
DefineValue(::llvm::Value * val,int s_reg)79 void MirConverter::DefineValue(::llvm::Value* val, int s_reg) {
80 DefineValueOnly(val, s_reg);
81 SetVregOnValue(val, s_reg);
82 }
83
LlvmTypeFromLocRec(RegLocation loc)84 ::llvm::Type* MirConverter::LlvmTypeFromLocRec(RegLocation loc) {
85 ::llvm::Type* res = NULL;
86 if (loc.wide) {
87 if (loc.fp)
88 res = irb_->getDoubleTy();
89 else
90 res = irb_->getInt64Ty();
91 } else {
92 if (loc.fp) {
93 res = irb_->getFloatTy();
94 } else {
95 if (loc.ref)
96 res = irb_->getJObjectTy();
97 else
98 res = irb_->getInt32Ty();
99 }
100 }
101 return res;
102 }
103
InitIR()104 void MirConverter::InitIR() {
105 if (llvm_info_ == NULL) {
106 CompilerTls* tls = cu_->compiler_driver->GetTls();
107 CHECK(tls != NULL);
108 llvm_info_ = static_cast<LLVMInfo*>(tls->GetLLVMInfo());
109 if (llvm_info_ == NULL) {
110 llvm_info_ = new LLVMInfo();
111 tls->SetLLVMInfo(llvm_info_);
112 }
113 }
114 context_ = llvm_info_->GetLLVMContext();
115 module_ = llvm_info_->GetLLVMModule();
116 intrinsic_helper_ = llvm_info_->GetIntrinsicHelper();
117 irb_ = llvm_info_->GetIRBuilder();
118 }
119
FindCaseTarget(uint32_t vaddr)120 ::llvm::BasicBlock* MirConverter::FindCaseTarget(uint32_t vaddr) {
121 BasicBlock* bb = mir_graph_->FindBlock(vaddr);
122 DCHECK(bb != NULL);
123 return GetLLVMBlock(bb->id);
124 }
125
ConvertPackedSwitch(BasicBlock * bb,int32_t table_offset,RegLocation rl_src)126 void MirConverter::ConvertPackedSwitch(BasicBlock* bb,
127 int32_t table_offset, RegLocation rl_src) {
128 const Instruction::PackedSwitchPayload* payload =
129 reinterpret_cast<const Instruction::PackedSwitchPayload*>(
130 cu_->insns + current_dalvik_offset_ + table_offset);
131
132 ::llvm::Value* value = GetLLVMValue(rl_src.orig_sreg);
133
134 ::llvm::SwitchInst* sw =
135 irb_->CreateSwitch(value, GetLLVMBlock(bb->fall_through->id),
136 payload->case_count);
137
138 for (uint16_t i = 0; i < payload->case_count; ++i) {
139 ::llvm::BasicBlock* llvm_bb =
140 FindCaseTarget(current_dalvik_offset_ + payload->targets[i]);
141 sw->addCase(irb_->getInt32(payload->first_key + i), llvm_bb);
142 }
143 ::llvm::MDNode* switch_node =
144 ::llvm::MDNode::get(*context_, irb_->getInt32(table_offset));
145 sw->setMetadata("SwitchTable", switch_node);
146 bb->taken = NULL;
147 bb->fall_through = NULL;
148 }
149
ConvertSparseSwitch(BasicBlock * bb,int32_t table_offset,RegLocation rl_src)150 void MirConverter::ConvertSparseSwitch(BasicBlock* bb,
151 int32_t table_offset, RegLocation rl_src) {
152 const Instruction::SparseSwitchPayload* payload =
153 reinterpret_cast<const Instruction::SparseSwitchPayload*>(
154 cu_->insns + current_dalvik_offset_ + table_offset);
155
156 const int32_t* keys = payload->GetKeys();
157 const int32_t* targets = payload->GetTargets();
158
159 ::llvm::Value* value = GetLLVMValue(rl_src.orig_sreg);
160
161 ::llvm::SwitchInst* sw =
162 irb_->CreateSwitch(value, GetLLVMBlock(bb->fall_through->id),
163 payload->case_count);
164
165 for (size_t i = 0; i < payload->case_count; ++i) {
166 ::llvm::BasicBlock* llvm_bb =
167 FindCaseTarget(current_dalvik_offset_ + targets[i]);
168 sw->addCase(irb_->getInt32(keys[i]), llvm_bb);
169 }
170 ::llvm::MDNode* switch_node =
171 ::llvm::MDNode::get(*context_, irb_->getInt32(table_offset));
172 sw->setMetadata("SwitchTable", switch_node);
173 bb->taken = NULL;
174 bb->fall_through = NULL;
175 }
176
ConvertSget(int32_t field_index,art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_dest)177 void MirConverter::ConvertSget(int32_t field_index,
178 art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest) {
179 ::llvm::Constant* field_idx = irb_->getInt32(field_index);
180 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
181 ::llvm::Value* res = irb_->CreateCall(intr, field_idx);
182 DefineValue(res, rl_dest.orig_sreg);
183 }
184
ConvertSput(int32_t field_index,art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_src)185 void MirConverter::ConvertSput(int32_t field_index,
186 art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src) {
187 ::llvm::SmallVector< ::llvm::Value*, 2> args;
188 args.push_back(irb_->getInt32(field_index));
189 args.push_back(GetLLVMValue(rl_src.orig_sreg));
190 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
191 irb_->CreateCall(intr, args);
192 }
193
ConvertFillArrayData(int32_t offset,RegLocation rl_array)194 void MirConverter::ConvertFillArrayData(int32_t offset, RegLocation rl_array) {
195 art::llvm::IntrinsicHelper::IntrinsicId id;
196 id = art::llvm::IntrinsicHelper::HLFillArrayData;
197 ::llvm::SmallVector< ::llvm::Value*, 2> args;
198 args.push_back(irb_->getInt32(offset));
199 args.push_back(GetLLVMValue(rl_array.orig_sreg));
200 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
201 irb_->CreateCall(intr, args);
202 }
203
EmitConst(::llvm::ArrayRef<::llvm::Value * > src,RegLocation loc)204 ::llvm::Value* MirConverter::EmitConst(::llvm::ArrayRef< ::llvm::Value*> src,
205 RegLocation loc) {
206 art::llvm::IntrinsicHelper::IntrinsicId id;
207 if (loc.wide) {
208 if (loc.fp) {
209 id = art::llvm::IntrinsicHelper::ConstDouble;
210 } else {
211 id = art::llvm::IntrinsicHelper::ConstLong;
212 }
213 } else {
214 if (loc.fp) {
215 id = art::llvm::IntrinsicHelper::ConstFloat;
216 } else if (loc.ref) {
217 id = art::llvm::IntrinsicHelper::ConstObj;
218 } else {
219 id = art::llvm::IntrinsicHelper::ConstInt;
220 }
221 }
222 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
223 return irb_->CreateCall(intr, src);
224 }
225
EmitPopShadowFrame()226 void MirConverter::EmitPopShadowFrame() {
227 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(
228 art::llvm::IntrinsicHelper::PopShadowFrame);
229 irb_->CreateCall(intr);
230 }
231
EmitCopy(::llvm::ArrayRef<::llvm::Value * > src,RegLocation loc)232 ::llvm::Value* MirConverter::EmitCopy(::llvm::ArrayRef< ::llvm::Value*> src,
233 RegLocation loc) {
234 art::llvm::IntrinsicHelper::IntrinsicId id;
235 if (loc.wide) {
236 if (loc.fp) {
237 id = art::llvm::IntrinsicHelper::CopyDouble;
238 } else {
239 id = art::llvm::IntrinsicHelper::CopyLong;
240 }
241 } else {
242 if (loc.fp) {
243 id = art::llvm::IntrinsicHelper::CopyFloat;
244 } else if (loc.ref) {
245 id = art::llvm::IntrinsicHelper::CopyObj;
246 } else {
247 id = art::llvm::IntrinsicHelper::CopyInt;
248 }
249 }
250 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
251 return irb_->CreateCall(intr, src);
252 }
253
ConvertMoveException(RegLocation rl_dest)254 void MirConverter::ConvertMoveException(RegLocation rl_dest) {
255 ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(
256 art::llvm::IntrinsicHelper::GetException);
257 ::llvm::Value* res = irb_->CreateCall(func);
258 DefineValue(res, rl_dest.orig_sreg);
259 }
260
ConvertThrow(RegLocation rl_src)261 void MirConverter::ConvertThrow(RegLocation rl_src) {
262 ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
263 ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(
264 art::llvm::IntrinsicHelper::HLThrowException);
265 irb_->CreateCall(func, src);
266 }
267
ConvertMonitorEnterExit(int opt_flags,art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_src)268 void MirConverter::ConvertMonitorEnterExit(int opt_flags,
269 art::llvm::IntrinsicHelper::IntrinsicId id,
270 RegLocation rl_src) {
271 ::llvm::SmallVector< ::llvm::Value*, 2> args;
272 args.push_back(irb_->getInt32(opt_flags));
273 args.push_back(GetLLVMValue(rl_src.orig_sreg));
274 ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id);
275 irb_->CreateCall(func, args);
276 }
277
ConvertArrayLength(int opt_flags,RegLocation rl_dest,RegLocation rl_src)278 void MirConverter::ConvertArrayLength(int opt_flags,
279 RegLocation rl_dest, RegLocation rl_src) {
280 ::llvm::SmallVector< ::llvm::Value*, 2> args;
281 args.push_back(irb_->getInt32(opt_flags));
282 args.push_back(GetLLVMValue(rl_src.orig_sreg));
283 ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(
284 art::llvm::IntrinsicHelper::OptArrayLength);
285 ::llvm::Value* res = irb_->CreateCall(func, args);
286 DefineValue(res, rl_dest.orig_sreg);
287 }
288
EmitSuspendCheck()289 void MirConverter::EmitSuspendCheck() {
290 art::llvm::IntrinsicHelper::IntrinsicId id =
291 art::llvm::IntrinsicHelper::CheckSuspend;
292 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
293 irb_->CreateCall(intr);
294 }
295
ConvertCompare(ConditionCode cc,::llvm::Value * src1,::llvm::Value * src2)296 ::llvm::Value* MirConverter::ConvertCompare(ConditionCode cc,
297 ::llvm::Value* src1, ::llvm::Value* src2) {
298 ::llvm::Value* res = NULL;
299 DCHECK_EQ(src1->getType(), src2->getType());
300 switch (cc) {
301 case kCondEq: res = irb_->CreateICmpEQ(src1, src2); break;
302 case kCondNe: res = irb_->CreateICmpNE(src1, src2); break;
303 case kCondLt: res = irb_->CreateICmpSLT(src1, src2); break;
304 case kCondGe: res = irb_->CreateICmpSGE(src1, src2); break;
305 case kCondGt: res = irb_->CreateICmpSGT(src1, src2); break;
306 case kCondLe: res = irb_->CreateICmpSLE(src1, src2); break;
307 default: LOG(FATAL) << "Unexpected cc value " << cc;
308 }
309 return res;
310 }
311
ConvertCompareAndBranch(BasicBlock * bb,MIR * mir,ConditionCode cc,RegLocation rl_src1,RegLocation rl_src2)312 void MirConverter::ConvertCompareAndBranch(BasicBlock* bb, MIR* mir,
313 ConditionCode cc, RegLocation rl_src1, RegLocation rl_src2) {
314 if (bb->taken->start_offset <= mir->offset) {
315 EmitSuspendCheck();
316 }
317 ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
318 ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg);
319 ::llvm::Value* cond_value = ConvertCompare(cc, src1, src2);
320 cond_value->setName(StringPrintf("t%d", temp_name_++));
321 irb_->CreateCondBr(cond_value, GetLLVMBlock(bb->taken->id),
322 GetLLVMBlock(bb->fall_through->id));
323 // Don't redo the fallthrough branch in the BB driver
324 bb->fall_through = NULL;
325 }
326
ConvertCompareZeroAndBranch(BasicBlock * bb,MIR * mir,ConditionCode cc,RegLocation rl_src1)327 void MirConverter::ConvertCompareZeroAndBranch(BasicBlock* bb,
328 MIR* mir, ConditionCode cc, RegLocation rl_src1) {
329 if (bb->taken->start_offset <= mir->offset) {
330 EmitSuspendCheck();
331 }
332 ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
333 ::llvm::Value* src2;
334 if (rl_src1.ref) {
335 src2 = irb_->getJNull();
336 } else {
337 src2 = irb_->getInt32(0);
338 }
339 ::llvm::Value* cond_value = ConvertCompare(cc, src1, src2);
340 irb_->CreateCondBr(cond_value, GetLLVMBlock(bb->taken->id),
341 GetLLVMBlock(bb->fall_through->id));
342 // Don't redo the fallthrough branch in the BB driver
343 bb->fall_through = NULL;
344 }
345
GenDivModOp(bool is_div,bool is_long,::llvm::Value * src1,::llvm::Value * src2)346 ::llvm::Value* MirConverter::GenDivModOp(bool is_div, bool is_long,
347 ::llvm::Value* src1, ::llvm::Value* src2) {
348 art::llvm::IntrinsicHelper::IntrinsicId id;
349 if (is_long) {
350 if (is_div) {
351 id = art::llvm::IntrinsicHelper::DivLong;
352 } else {
353 id = art::llvm::IntrinsicHelper::RemLong;
354 }
355 } else {
356 if (is_div) {
357 id = art::llvm::IntrinsicHelper::DivInt;
358 } else {
359 id = art::llvm::IntrinsicHelper::RemInt;
360 }
361 }
362 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
363 ::llvm::SmallVector< ::llvm::Value*, 2>args;
364 args.push_back(src1);
365 args.push_back(src2);
366 return irb_->CreateCall(intr, args);
367 }
368
GenArithOp(OpKind op,bool is_long,::llvm::Value * src1,::llvm::Value * src2)369 ::llvm::Value* MirConverter::GenArithOp(OpKind op, bool is_long,
370 ::llvm::Value* src1, ::llvm::Value* src2) {
371 ::llvm::Value* res = NULL;
372 switch (op) {
373 case kOpAdd: res = irb_->CreateAdd(src1, src2); break;
374 case kOpSub: res = irb_->CreateSub(src1, src2); break;
375 case kOpRsub: res = irb_->CreateSub(src2, src1); break;
376 case kOpMul: res = irb_->CreateMul(src1, src2); break;
377 case kOpOr: res = irb_->CreateOr(src1, src2); break;
378 case kOpAnd: res = irb_->CreateAnd(src1, src2); break;
379 case kOpXor: res = irb_->CreateXor(src1, src2); break;
380 case kOpDiv: res = GenDivModOp(true, is_long, src1, src2); break;
381 case kOpRem: res = GenDivModOp(false, is_long, src1, src2); break;
382 case kOpLsl: res = irb_->CreateShl(src1, src2); break;
383 case kOpLsr: res = irb_->CreateLShr(src1, src2); break;
384 case kOpAsr: res = irb_->CreateAShr(src1, src2); break;
385 default:
386 LOG(FATAL) << "Invalid op " << op;
387 }
388 return res;
389 }
390
ConvertFPArithOp(OpKind op,RegLocation rl_dest,RegLocation rl_src1,RegLocation rl_src2)391 void MirConverter::ConvertFPArithOp(OpKind op, RegLocation rl_dest,
392 RegLocation rl_src1, RegLocation rl_src2) {
393 ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
394 ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg);
395 ::llvm::Value* res = NULL;
396 switch (op) {
397 case kOpAdd: res = irb_->CreateFAdd(src1, src2); break;
398 case kOpSub: res = irb_->CreateFSub(src1, src2); break;
399 case kOpMul: res = irb_->CreateFMul(src1, src2); break;
400 case kOpDiv: res = irb_->CreateFDiv(src1, src2); break;
401 case kOpRem: res = irb_->CreateFRem(src1, src2); break;
402 default:
403 LOG(FATAL) << "Invalid op " << op;
404 }
405 DefineValue(res, rl_dest.orig_sreg);
406 }
407
ConvertShift(art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_dest,RegLocation rl_src1,RegLocation rl_src2)408 void MirConverter::ConvertShift(art::llvm::IntrinsicHelper::IntrinsicId id,
409 RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
410 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
411 ::llvm::SmallVector< ::llvm::Value*, 2>args;
412 args.push_back(GetLLVMValue(rl_src1.orig_sreg));
413 args.push_back(GetLLVMValue(rl_src2.orig_sreg));
414 ::llvm::Value* res = irb_->CreateCall(intr, args);
415 DefineValue(res, rl_dest.orig_sreg);
416 }
417
ConvertShiftLit(art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_dest,RegLocation rl_src,int shift_amount)418 void MirConverter::ConvertShiftLit(art::llvm::IntrinsicHelper::IntrinsicId id,
419 RegLocation rl_dest, RegLocation rl_src, int shift_amount) {
420 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
421 ::llvm::SmallVector< ::llvm::Value*, 2>args;
422 args.push_back(GetLLVMValue(rl_src.orig_sreg));
423 args.push_back(irb_->getInt32(shift_amount));
424 ::llvm::Value* res = irb_->CreateCall(intr, args);
425 DefineValue(res, rl_dest.orig_sreg);
426 }
427
ConvertArithOp(OpKind op,RegLocation rl_dest,RegLocation rl_src1,RegLocation rl_src2)428 void MirConverter::ConvertArithOp(OpKind op, RegLocation rl_dest,
429 RegLocation rl_src1, RegLocation rl_src2) {
430 ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
431 ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg);
432 DCHECK_EQ(src1->getType(), src2->getType());
433 ::llvm::Value* res = GenArithOp(op, rl_dest.wide, src1, src2);
434 DefineValue(res, rl_dest.orig_sreg);
435 }
436
ConvertArithOpLit(OpKind op,RegLocation rl_dest,RegLocation rl_src1,int32_t imm)437 void MirConverter::ConvertArithOpLit(OpKind op, RegLocation rl_dest,
438 RegLocation rl_src1, int32_t imm) {
439 ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
440 ::llvm::Value* src2 = irb_->getInt32(imm);
441 ::llvm::Value* res = GenArithOp(op, rl_dest.wide, src1, src2);
442 DefineValue(res, rl_dest.orig_sreg);
443 }
444
445 /*
446 * Process arguments for invoke. Note: this code is also used to
447 * collect and process arguments for NEW_FILLED_ARRAY and NEW_FILLED_ARRAY_RANGE.
448 * The requirements are similar.
449 */
ConvertInvoke(BasicBlock * bb,MIR * mir,InvokeType invoke_type,bool is_range,bool is_filled_new_array)450 void MirConverter::ConvertInvoke(BasicBlock* bb, MIR* mir,
451 InvokeType invoke_type, bool is_range, bool is_filled_new_array) {
452 CallInfo* info = mir_graph_->NewMemCallInfo(bb, mir, invoke_type, is_range);
453 ::llvm::SmallVector< ::llvm::Value*, 10> args;
454 // Insert the invoke_type
455 args.push_back(irb_->getInt32(static_cast<int>(invoke_type)));
456 // Insert the method_idx
457 args.push_back(irb_->getInt32(info->index));
458 // Insert the optimization flags
459 args.push_back(irb_->getInt32(info->opt_flags));
460 // Now, insert the actual arguments
461 for (int i = 0; i < info->num_arg_words;) {
462 ::llvm::Value* val = GetLLVMValue(info->args[i].orig_sreg);
463 args.push_back(val);
464 i += info->args[i].wide ? 2 : 1;
465 }
466 /*
467 * Choose the invoke return type based on actual usage. Note: may
468 * be different than shorty. For example, if a function return value
469 * is not used, we'll treat this as a void invoke.
470 */
471 art::llvm::IntrinsicHelper::IntrinsicId id;
472 if (is_filled_new_array) {
473 id = art::llvm::IntrinsicHelper::HLFilledNewArray;
474 } else if (info->result.location == kLocInvalid) {
475 id = art::llvm::IntrinsicHelper::HLInvokeVoid;
476 } else {
477 if (info->result.wide) {
478 if (info->result.fp) {
479 id = art::llvm::IntrinsicHelper::HLInvokeDouble;
480 } else {
481 id = art::llvm::IntrinsicHelper::HLInvokeLong;
482 }
483 } else if (info->result.ref) {
484 id = art::llvm::IntrinsicHelper::HLInvokeObj;
485 } else if (info->result.fp) {
486 id = art::llvm::IntrinsicHelper::HLInvokeFloat;
487 } else {
488 id = art::llvm::IntrinsicHelper::HLInvokeInt;
489 }
490 }
491 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
492 ::llvm::Value* res = irb_->CreateCall(intr, args);
493 if (info->result.location != kLocInvalid) {
494 DefineValue(res, info->result.orig_sreg);
495 }
496 }
497
ConvertConstObject(uint32_t idx,art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_dest)498 void MirConverter::ConvertConstObject(uint32_t idx,
499 art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest) {
500 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
501 ::llvm::Value* index = irb_->getInt32(idx);
502 ::llvm::Value* res = irb_->CreateCall(intr, index);
503 DefineValue(res, rl_dest.orig_sreg);
504 }
505
ConvertCheckCast(uint32_t type_idx,RegLocation rl_src)506 void MirConverter::ConvertCheckCast(uint32_t type_idx, RegLocation rl_src) {
507 art::llvm::IntrinsicHelper::IntrinsicId id;
508 id = art::llvm::IntrinsicHelper::HLCheckCast;
509 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
510 ::llvm::SmallVector< ::llvm::Value*, 2> args;
511 args.push_back(irb_->getInt32(type_idx));
512 args.push_back(GetLLVMValue(rl_src.orig_sreg));
513 irb_->CreateCall(intr, args);
514 }
515
ConvertNewInstance(uint32_t type_idx,RegLocation rl_dest)516 void MirConverter::ConvertNewInstance(uint32_t type_idx, RegLocation rl_dest) {
517 art::llvm::IntrinsicHelper::IntrinsicId id;
518 id = art::llvm::IntrinsicHelper::NewInstance;
519 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
520 ::llvm::Value* index = irb_->getInt32(type_idx);
521 ::llvm::Value* res = irb_->CreateCall(intr, index);
522 DefineValue(res, rl_dest.orig_sreg);
523 }
524
ConvertNewArray(uint32_t type_idx,RegLocation rl_dest,RegLocation rl_src)525 void MirConverter::ConvertNewArray(uint32_t type_idx,
526 RegLocation rl_dest, RegLocation rl_src) {
527 art::llvm::IntrinsicHelper::IntrinsicId id;
528 id = art::llvm::IntrinsicHelper::NewArray;
529 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
530 ::llvm::SmallVector< ::llvm::Value*, 2> args;
531 args.push_back(irb_->getInt32(type_idx));
532 args.push_back(GetLLVMValue(rl_src.orig_sreg));
533 ::llvm::Value* res = irb_->CreateCall(intr, args);
534 DefineValue(res, rl_dest.orig_sreg);
535 }
536
ConvertAget(int opt_flags,art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_dest,RegLocation rl_array,RegLocation rl_index)537 void MirConverter::ConvertAget(int opt_flags,
538 art::llvm::IntrinsicHelper::IntrinsicId id,
539 RegLocation rl_dest, RegLocation rl_array, RegLocation rl_index) {
540 ::llvm::SmallVector< ::llvm::Value*, 3> args;
541 args.push_back(irb_->getInt32(opt_flags));
542 args.push_back(GetLLVMValue(rl_array.orig_sreg));
543 args.push_back(GetLLVMValue(rl_index.orig_sreg));
544 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
545 ::llvm::Value* res = irb_->CreateCall(intr, args);
546 DefineValue(res, rl_dest.orig_sreg);
547 }
548
ConvertAput(int opt_flags,art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_src,RegLocation rl_array,RegLocation rl_index)549 void MirConverter::ConvertAput(int opt_flags,
550 art::llvm::IntrinsicHelper::IntrinsicId id,
551 RegLocation rl_src, RegLocation rl_array, RegLocation rl_index) {
552 ::llvm::SmallVector< ::llvm::Value*, 4> args;
553 args.push_back(irb_->getInt32(opt_flags));
554 args.push_back(GetLLVMValue(rl_src.orig_sreg));
555 args.push_back(GetLLVMValue(rl_array.orig_sreg));
556 args.push_back(GetLLVMValue(rl_index.orig_sreg));
557 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
558 irb_->CreateCall(intr, args);
559 }
560
ConvertIget(int opt_flags,art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_dest,RegLocation rl_obj,int field_index)561 void MirConverter::ConvertIget(int opt_flags,
562 art::llvm::IntrinsicHelper::IntrinsicId id,
563 RegLocation rl_dest, RegLocation rl_obj, int field_index) {
564 ::llvm::SmallVector< ::llvm::Value*, 3> args;
565 args.push_back(irb_->getInt32(opt_flags));
566 args.push_back(GetLLVMValue(rl_obj.orig_sreg));
567 args.push_back(irb_->getInt32(field_index));
568 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
569 ::llvm::Value* res = irb_->CreateCall(intr, args);
570 DefineValue(res, rl_dest.orig_sreg);
571 }
572
ConvertIput(int opt_flags,art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_src,RegLocation rl_obj,int field_index)573 void MirConverter::ConvertIput(int opt_flags,
574 art::llvm::IntrinsicHelper::IntrinsicId id,
575 RegLocation rl_src, RegLocation rl_obj, int field_index) {
576 ::llvm::SmallVector< ::llvm::Value*, 4> args;
577 args.push_back(irb_->getInt32(opt_flags));
578 args.push_back(GetLLVMValue(rl_src.orig_sreg));
579 args.push_back(GetLLVMValue(rl_obj.orig_sreg));
580 args.push_back(irb_->getInt32(field_index));
581 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
582 irb_->CreateCall(intr, args);
583 }
584
ConvertInstanceOf(uint32_t type_idx,RegLocation rl_dest,RegLocation rl_src)585 void MirConverter::ConvertInstanceOf(uint32_t type_idx,
586 RegLocation rl_dest, RegLocation rl_src) {
587 art::llvm::IntrinsicHelper::IntrinsicId id;
588 id = art::llvm::IntrinsicHelper::InstanceOf;
589 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
590 ::llvm::SmallVector< ::llvm::Value*, 2> args;
591 args.push_back(irb_->getInt32(type_idx));
592 args.push_back(GetLLVMValue(rl_src.orig_sreg));
593 ::llvm::Value* res = irb_->CreateCall(intr, args);
594 DefineValue(res, rl_dest.orig_sreg);
595 }
596
ConvertIntToLong(RegLocation rl_dest,RegLocation rl_src)597 void MirConverter::ConvertIntToLong(RegLocation rl_dest, RegLocation rl_src) {
598 ::llvm::Value* res = irb_->CreateSExt(GetLLVMValue(rl_src.orig_sreg),
599 irb_->getInt64Ty());
600 DefineValue(res, rl_dest.orig_sreg);
601 }
602
ConvertLongToInt(RegLocation rl_dest,RegLocation rl_src)603 void MirConverter::ConvertLongToInt(RegLocation rl_dest, RegLocation rl_src) {
604 ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
605 ::llvm::Value* res = irb_->CreateTrunc(src, irb_->getInt32Ty());
606 DefineValue(res, rl_dest.orig_sreg);
607 }
608
ConvertFloatToDouble(RegLocation rl_dest,RegLocation rl_src)609 void MirConverter::ConvertFloatToDouble(RegLocation rl_dest, RegLocation rl_src) {
610 ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
611 ::llvm::Value* res = irb_->CreateFPExt(src, irb_->getDoubleTy());
612 DefineValue(res, rl_dest.orig_sreg);
613 }
614
ConvertDoubleToFloat(RegLocation rl_dest,RegLocation rl_src)615 void MirConverter::ConvertDoubleToFloat(RegLocation rl_dest, RegLocation rl_src) {
616 ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
617 ::llvm::Value* res = irb_->CreateFPTrunc(src, irb_->getFloatTy());
618 DefineValue(res, rl_dest.orig_sreg);
619 }
620
ConvertWideComparison(art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_dest,RegLocation rl_src1,RegLocation rl_src2)621 void MirConverter::ConvertWideComparison(art::llvm::IntrinsicHelper::IntrinsicId id,
622 RegLocation rl_dest, RegLocation rl_src1,
623 RegLocation rl_src2) {
624 DCHECK_EQ(rl_src1.fp, rl_src2.fp);
625 DCHECK_EQ(rl_src1.wide, rl_src2.wide);
626 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
627 ::llvm::SmallVector< ::llvm::Value*, 2> args;
628 args.push_back(GetLLVMValue(rl_src1.orig_sreg));
629 args.push_back(GetLLVMValue(rl_src2.orig_sreg));
630 ::llvm::Value* res = irb_->CreateCall(intr, args);
631 DefineValue(res, rl_dest.orig_sreg);
632 }
633
ConvertIntNarrowing(RegLocation rl_dest,RegLocation rl_src,art::llvm::IntrinsicHelper::IntrinsicId id)634 void MirConverter::ConvertIntNarrowing(RegLocation rl_dest, RegLocation rl_src,
635 art::llvm::IntrinsicHelper::IntrinsicId id) {
636 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
637 ::llvm::Value* res =
638 irb_->CreateCall(intr, GetLLVMValue(rl_src.orig_sreg));
639 DefineValue(res, rl_dest.orig_sreg);
640 }
641
ConvertNeg(RegLocation rl_dest,RegLocation rl_src)642 void MirConverter::ConvertNeg(RegLocation rl_dest, RegLocation rl_src) {
643 ::llvm::Value* res = irb_->CreateNeg(GetLLVMValue(rl_src.orig_sreg));
644 DefineValue(res, rl_dest.orig_sreg);
645 }
646
ConvertIntToFP(::llvm::Type * ty,RegLocation rl_dest,RegLocation rl_src)647 void MirConverter::ConvertIntToFP(::llvm::Type* ty, RegLocation rl_dest,
648 RegLocation rl_src) {
649 ::llvm::Value* res =
650 irb_->CreateSIToFP(GetLLVMValue(rl_src.orig_sreg), ty);
651 DefineValue(res, rl_dest.orig_sreg);
652 }
653
ConvertFPToInt(art::llvm::IntrinsicHelper::IntrinsicId id,RegLocation rl_dest,RegLocation rl_src)654 void MirConverter::ConvertFPToInt(art::llvm::IntrinsicHelper::IntrinsicId id,
655 RegLocation rl_dest,
656 RegLocation rl_src) {
657 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
658 ::llvm::Value* res = irb_->CreateCall(intr, GetLLVMValue(rl_src.orig_sreg));
659 DefineValue(res, rl_dest.orig_sreg);
660 }
661
662
ConvertNegFP(RegLocation rl_dest,RegLocation rl_src)663 void MirConverter::ConvertNegFP(RegLocation rl_dest, RegLocation rl_src) {
664 ::llvm::Value* res =
665 irb_->CreateFNeg(GetLLVMValue(rl_src.orig_sreg));
666 DefineValue(res, rl_dest.orig_sreg);
667 }
668
ConvertNot(RegLocation rl_dest,RegLocation rl_src)669 void MirConverter::ConvertNot(RegLocation rl_dest, RegLocation rl_src) {
670 ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
671 ::llvm::Value* res = irb_->CreateXor(src, static_cast<uint64_t>(-1));
672 DefineValue(res, rl_dest.orig_sreg);
673 }
674
EmitConstructorBarrier()675 void MirConverter::EmitConstructorBarrier() {
676 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(
677 art::llvm::IntrinsicHelper::ConstructorBarrier);
678 irb_->CreateCall(intr);
679 }
680
681 /*
682 * Target-independent code generation. Use only high-level
683 * load/store utilities here, or target-dependent genXX() handlers
684 * when necessary.
685 */
ConvertMIRNode(MIR * mir,BasicBlock * bb,::llvm::BasicBlock * llvm_bb)686 bool MirConverter::ConvertMIRNode(MIR* mir, BasicBlock* bb,
687 ::llvm::BasicBlock* llvm_bb) {
688 bool res = false; // Assume success
689 RegLocation rl_src[3];
690 RegLocation rl_dest = mir_graph_->GetBadLoc();
691 Instruction::Code opcode = mir->dalvikInsn.opcode;
692 int op_val = opcode;
693 uint32_t vB = mir->dalvikInsn.vB;
694 uint32_t vC = mir->dalvikInsn.vC;
695 int opt_flags = mir->optimization_flags;
696
697 if (cu_->verbose) {
698 if (op_val < kMirOpFirst) {
699 LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x" << std::hex << op_val;
700 } else {
701 LOG(INFO) << mir_graph_->extended_mir_op_names_[op_val - kMirOpFirst] << " 0x" << std::hex << op_val;
702 }
703 }
704
705 /* Prep Src and Dest locations */
706 int next_sreg = 0;
707 int next_loc = 0;
708 int attrs = mir_graph_->oat_data_flow_attributes_[opcode];
709 rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
710 if (attrs & DF_UA) {
711 if (attrs & DF_A_WIDE) {
712 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
713 next_sreg+= 2;
714 } else {
715 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
716 next_sreg++;
717 }
718 }
719 if (attrs & DF_UB) {
720 if (attrs & DF_B_WIDE) {
721 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
722 next_sreg+= 2;
723 } else {
724 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
725 next_sreg++;
726 }
727 }
728 if (attrs & DF_UC) {
729 if (attrs & DF_C_WIDE) {
730 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
731 } else {
732 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
733 }
734 }
735 if (attrs & DF_DA) {
736 if (attrs & DF_A_WIDE) {
737 rl_dest = mir_graph_->GetDestWide(mir);
738 } else {
739 rl_dest = mir_graph_->GetDest(mir);
740 }
741 }
742
743 switch (opcode) {
744 case Instruction::NOP:
745 break;
746
747 case Instruction::MOVE:
748 case Instruction::MOVE_OBJECT:
749 case Instruction::MOVE_16:
750 case Instruction::MOVE_OBJECT_16:
751 case Instruction::MOVE_OBJECT_FROM16:
752 case Instruction::MOVE_FROM16:
753 case Instruction::MOVE_WIDE:
754 case Instruction::MOVE_WIDE_16:
755 case Instruction::MOVE_WIDE_FROM16: {
756 /*
757 * Moves/copies are meaningless in pure SSA register form,
758 * but we need to preserve them for the conversion back into
759 * MIR (at least until we stop using the Dalvik register maps).
760 * Insert a dummy intrinsic copy call, which will be recognized
761 * by the quick path and removed by the portable path.
762 */
763 ::llvm::Value* src = GetLLVMValue(rl_src[0].orig_sreg);
764 ::llvm::Value* res = EmitCopy(src, rl_dest);
765 DefineValue(res, rl_dest.orig_sreg);
766 }
767 break;
768
769 case Instruction::CONST:
770 case Instruction::CONST_4:
771 case Instruction::CONST_16: {
772 ::llvm::Constant* imm_value = irb_->getJInt(vB);
773 ::llvm::Value* res = EmitConst(imm_value, rl_dest);
774 DefineValue(res, rl_dest.orig_sreg);
775 }
776 break;
777
778 case Instruction::CONST_WIDE_16:
779 case Instruction::CONST_WIDE_32: {
780 // Sign extend to 64 bits
781 int64_t imm = static_cast<int32_t>(vB);
782 ::llvm::Constant* imm_value = irb_->getJLong(imm);
783 ::llvm::Value* res = EmitConst(imm_value, rl_dest);
784 DefineValue(res, rl_dest.orig_sreg);
785 }
786 break;
787
788 case Instruction::CONST_HIGH16: {
789 ::llvm::Constant* imm_value = irb_->getJInt(vB << 16);
790 ::llvm::Value* res = EmitConst(imm_value, rl_dest);
791 DefineValue(res, rl_dest.orig_sreg);
792 }
793 break;
794
795 case Instruction::CONST_WIDE: {
796 ::llvm::Constant* imm_value =
797 irb_->getJLong(mir->dalvikInsn.vB_wide);
798 ::llvm::Value* res = EmitConst(imm_value, rl_dest);
799 DefineValue(res, rl_dest.orig_sreg);
800 }
801 break;
802 case Instruction::CONST_WIDE_HIGH16: {
803 int64_t imm = static_cast<int64_t>(vB) << 48;
804 ::llvm::Constant* imm_value = irb_->getJLong(imm);
805 ::llvm::Value* res = EmitConst(imm_value, rl_dest);
806 DefineValue(res, rl_dest.orig_sreg);
807 }
808 break;
809
810 case Instruction::SPUT_OBJECT:
811 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputObject,
812 rl_src[0]);
813 break;
814 case Instruction::SPUT:
815 if (rl_src[0].fp) {
816 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputFloat,
817 rl_src[0]);
818 } else {
819 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSput, rl_src[0]);
820 }
821 break;
822 case Instruction::SPUT_BOOLEAN:
823 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputBoolean,
824 rl_src[0]);
825 break;
826 case Instruction::SPUT_BYTE:
827 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputByte, rl_src[0]);
828 break;
829 case Instruction::SPUT_CHAR:
830 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputChar, rl_src[0]);
831 break;
832 case Instruction::SPUT_SHORT:
833 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputShort, rl_src[0]);
834 break;
835 case Instruction::SPUT_WIDE:
836 if (rl_src[0].fp) {
837 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputDouble,
838 rl_src[0]);
839 } else {
840 ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputWide,
841 rl_src[0]);
842 }
843 break;
844
845 case Instruction::SGET_OBJECT:
846 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetObject, rl_dest);
847 break;
848 case Instruction::SGET:
849 if (rl_dest.fp) {
850 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetFloat, rl_dest);
851 } else {
852 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSget, rl_dest);
853 }
854 break;
855 case Instruction::SGET_BOOLEAN:
856 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetBoolean, rl_dest);
857 break;
858 case Instruction::SGET_BYTE:
859 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetByte, rl_dest);
860 break;
861 case Instruction::SGET_CHAR:
862 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetChar, rl_dest);
863 break;
864 case Instruction::SGET_SHORT:
865 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetShort, rl_dest);
866 break;
867 case Instruction::SGET_WIDE:
868 if (rl_dest.fp) {
869 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetDouble,
870 rl_dest);
871 } else {
872 ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetWide, rl_dest);
873 }
874 break;
875
876 case Instruction::RETURN_WIDE:
877 case Instruction::RETURN:
878 case Instruction::RETURN_OBJECT: {
879 if (!mir_graph_->MethodIsLeaf()) {
880 EmitSuspendCheck();
881 }
882 EmitPopShadowFrame();
883 irb_->CreateRet(GetLLVMValue(rl_src[0].orig_sreg));
884 DCHECK(bb->terminated_by_return);
885 }
886 break;
887
888 case Instruction::RETURN_VOID: {
889 if (((cu_->access_flags & kAccConstructor) != 0) &&
890 cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(),
891 cu_->dex_file,
892 cu_->class_def_idx)) {
893 EmitConstructorBarrier();
894 }
895 if (!mir_graph_->MethodIsLeaf()) {
896 EmitSuspendCheck();
897 }
898 EmitPopShadowFrame();
899 irb_->CreateRetVoid();
900 DCHECK(bb->terminated_by_return);
901 }
902 break;
903
904 case Instruction::IF_EQ:
905 ConvertCompareAndBranch(bb, mir, kCondEq, rl_src[0], rl_src[1]);
906 break;
907 case Instruction::IF_NE:
908 ConvertCompareAndBranch(bb, mir, kCondNe, rl_src[0], rl_src[1]);
909 break;
910 case Instruction::IF_LT:
911 ConvertCompareAndBranch(bb, mir, kCondLt, rl_src[0], rl_src[1]);
912 break;
913 case Instruction::IF_GE:
914 ConvertCompareAndBranch(bb, mir, kCondGe, rl_src[0], rl_src[1]);
915 break;
916 case Instruction::IF_GT:
917 ConvertCompareAndBranch(bb, mir, kCondGt, rl_src[0], rl_src[1]);
918 break;
919 case Instruction::IF_LE:
920 ConvertCompareAndBranch(bb, mir, kCondLe, rl_src[0], rl_src[1]);
921 break;
922 case Instruction::IF_EQZ:
923 ConvertCompareZeroAndBranch(bb, mir, kCondEq, rl_src[0]);
924 break;
925 case Instruction::IF_NEZ:
926 ConvertCompareZeroAndBranch(bb, mir, kCondNe, rl_src[0]);
927 break;
928 case Instruction::IF_LTZ:
929 ConvertCompareZeroAndBranch(bb, mir, kCondLt, rl_src[0]);
930 break;
931 case Instruction::IF_GEZ:
932 ConvertCompareZeroAndBranch(bb, mir, kCondGe, rl_src[0]);
933 break;
934 case Instruction::IF_GTZ:
935 ConvertCompareZeroAndBranch(bb, mir, kCondGt, rl_src[0]);
936 break;
937 case Instruction::IF_LEZ:
938 ConvertCompareZeroAndBranch(bb, mir, kCondLe, rl_src[0]);
939 break;
940
941 case Instruction::GOTO:
942 case Instruction::GOTO_16:
943 case Instruction::GOTO_32: {
944 if (bb->taken->start_offset <= bb->start_offset) {
945 EmitSuspendCheck();
946 }
947 irb_->CreateBr(GetLLVMBlock(bb->taken->id));
948 }
949 break;
950
951 case Instruction::ADD_LONG:
952 case Instruction::ADD_LONG_2ADDR:
953 case Instruction::ADD_INT:
954 case Instruction::ADD_INT_2ADDR:
955 ConvertArithOp(kOpAdd, rl_dest, rl_src[0], rl_src[1]);
956 break;
957 case Instruction::SUB_LONG:
958 case Instruction::SUB_LONG_2ADDR:
959 case Instruction::SUB_INT:
960 case Instruction::SUB_INT_2ADDR:
961 ConvertArithOp(kOpSub, rl_dest, rl_src[0], rl_src[1]);
962 break;
963 case Instruction::MUL_LONG:
964 case Instruction::MUL_LONG_2ADDR:
965 case Instruction::MUL_INT:
966 case Instruction::MUL_INT_2ADDR:
967 ConvertArithOp(kOpMul, rl_dest, rl_src[0], rl_src[1]);
968 break;
969 case Instruction::DIV_LONG:
970 case Instruction::DIV_LONG_2ADDR:
971 case Instruction::DIV_INT:
972 case Instruction::DIV_INT_2ADDR:
973 ConvertArithOp(kOpDiv, rl_dest, rl_src[0], rl_src[1]);
974 break;
975 case Instruction::REM_LONG:
976 case Instruction::REM_LONG_2ADDR:
977 case Instruction::REM_INT:
978 case Instruction::REM_INT_2ADDR:
979 ConvertArithOp(kOpRem, rl_dest, rl_src[0], rl_src[1]);
980 break;
981 case Instruction::AND_LONG:
982 case Instruction::AND_LONG_2ADDR:
983 case Instruction::AND_INT:
984 case Instruction::AND_INT_2ADDR:
985 ConvertArithOp(kOpAnd, rl_dest, rl_src[0], rl_src[1]);
986 break;
987 case Instruction::OR_LONG:
988 case Instruction::OR_LONG_2ADDR:
989 case Instruction::OR_INT:
990 case Instruction::OR_INT_2ADDR:
991 ConvertArithOp(kOpOr, rl_dest, rl_src[0], rl_src[1]);
992 break;
993 case Instruction::XOR_LONG:
994 case Instruction::XOR_LONG_2ADDR:
995 case Instruction::XOR_INT:
996 case Instruction::XOR_INT_2ADDR:
997 ConvertArithOp(kOpXor, rl_dest, rl_src[0], rl_src[1]);
998 break;
999 case Instruction::SHL_LONG:
1000 case Instruction::SHL_LONG_2ADDR:
1001 ConvertShift(art::llvm::IntrinsicHelper::SHLLong,
1002 rl_dest, rl_src[0], rl_src[1]);
1003 break;
1004 case Instruction::SHL_INT:
1005 case Instruction::SHL_INT_2ADDR:
1006 ConvertShift(art::llvm::IntrinsicHelper::SHLInt,
1007 rl_dest, rl_src[0], rl_src[1]);
1008 break;
1009 case Instruction::SHR_LONG:
1010 case Instruction::SHR_LONG_2ADDR:
1011 ConvertShift(art::llvm::IntrinsicHelper::SHRLong,
1012 rl_dest, rl_src[0], rl_src[1]);
1013 break;
1014 case Instruction::SHR_INT:
1015 case Instruction::SHR_INT_2ADDR:
1016 ConvertShift(art::llvm::IntrinsicHelper::SHRInt,
1017 rl_dest, rl_src[0], rl_src[1]);
1018 break;
1019 case Instruction::USHR_LONG:
1020 case Instruction::USHR_LONG_2ADDR:
1021 ConvertShift(art::llvm::IntrinsicHelper::USHRLong,
1022 rl_dest, rl_src[0], rl_src[1]);
1023 break;
1024 case Instruction::USHR_INT:
1025 case Instruction::USHR_INT_2ADDR:
1026 ConvertShift(art::llvm::IntrinsicHelper::USHRInt,
1027 rl_dest, rl_src[0], rl_src[1]);
1028 break;
1029
1030 case Instruction::ADD_INT_LIT16:
1031 case Instruction::ADD_INT_LIT8:
1032 ConvertArithOpLit(kOpAdd, rl_dest, rl_src[0], vC);
1033 break;
1034 case Instruction::RSUB_INT:
1035 case Instruction::RSUB_INT_LIT8:
1036 ConvertArithOpLit(kOpRsub, rl_dest, rl_src[0], vC);
1037 break;
1038 case Instruction::MUL_INT_LIT16:
1039 case Instruction::MUL_INT_LIT8:
1040 ConvertArithOpLit(kOpMul, rl_dest, rl_src[0], vC);
1041 break;
1042 case Instruction::DIV_INT_LIT16:
1043 case Instruction::DIV_INT_LIT8:
1044 ConvertArithOpLit(kOpDiv, rl_dest, rl_src[0], vC);
1045 break;
1046 case Instruction::REM_INT_LIT16:
1047 case Instruction::REM_INT_LIT8:
1048 ConvertArithOpLit(kOpRem, rl_dest, rl_src[0], vC);
1049 break;
1050 case Instruction::AND_INT_LIT16:
1051 case Instruction::AND_INT_LIT8:
1052 ConvertArithOpLit(kOpAnd, rl_dest, rl_src[0], vC);
1053 break;
1054 case Instruction::OR_INT_LIT16:
1055 case Instruction::OR_INT_LIT8:
1056 ConvertArithOpLit(kOpOr, rl_dest, rl_src[0], vC);
1057 break;
1058 case Instruction::XOR_INT_LIT16:
1059 case Instruction::XOR_INT_LIT8:
1060 ConvertArithOpLit(kOpXor, rl_dest, rl_src[0], vC);
1061 break;
1062 case Instruction::SHL_INT_LIT8:
1063 ConvertShiftLit(art::llvm::IntrinsicHelper::SHLInt,
1064 rl_dest, rl_src[0], vC & 0x1f);
1065 break;
1066 case Instruction::SHR_INT_LIT8:
1067 ConvertShiftLit(art::llvm::IntrinsicHelper::SHRInt,
1068 rl_dest, rl_src[0], vC & 0x1f);
1069 break;
1070 case Instruction::USHR_INT_LIT8:
1071 ConvertShiftLit(art::llvm::IntrinsicHelper::USHRInt,
1072 rl_dest, rl_src[0], vC & 0x1f);
1073 break;
1074
1075 case Instruction::ADD_FLOAT:
1076 case Instruction::ADD_FLOAT_2ADDR:
1077 case Instruction::ADD_DOUBLE:
1078 case Instruction::ADD_DOUBLE_2ADDR:
1079 ConvertFPArithOp(kOpAdd, rl_dest, rl_src[0], rl_src[1]);
1080 break;
1081
1082 case Instruction::SUB_FLOAT:
1083 case Instruction::SUB_FLOAT_2ADDR:
1084 case Instruction::SUB_DOUBLE:
1085 case Instruction::SUB_DOUBLE_2ADDR:
1086 ConvertFPArithOp(kOpSub, rl_dest, rl_src[0], rl_src[1]);
1087 break;
1088
1089 case Instruction::MUL_FLOAT:
1090 case Instruction::MUL_FLOAT_2ADDR:
1091 case Instruction::MUL_DOUBLE:
1092 case Instruction::MUL_DOUBLE_2ADDR:
1093 ConvertFPArithOp(kOpMul, rl_dest, rl_src[0], rl_src[1]);
1094 break;
1095
1096 case Instruction::DIV_FLOAT:
1097 case Instruction::DIV_FLOAT_2ADDR:
1098 case Instruction::DIV_DOUBLE:
1099 case Instruction::DIV_DOUBLE_2ADDR:
1100 ConvertFPArithOp(kOpDiv, rl_dest, rl_src[0], rl_src[1]);
1101 break;
1102
1103 case Instruction::REM_FLOAT:
1104 case Instruction::REM_FLOAT_2ADDR:
1105 case Instruction::REM_DOUBLE:
1106 case Instruction::REM_DOUBLE_2ADDR:
1107 ConvertFPArithOp(kOpRem, rl_dest, rl_src[0], rl_src[1]);
1108 break;
1109
1110 case Instruction::INVOKE_STATIC:
1111 ConvertInvoke(bb, mir, kStatic, false /*range*/,
1112 false /* NewFilledArray */);
1113 break;
1114 case Instruction::INVOKE_STATIC_RANGE:
1115 ConvertInvoke(bb, mir, kStatic, true /*range*/,
1116 false /* NewFilledArray */);
1117 break;
1118
1119 case Instruction::INVOKE_DIRECT:
1120 ConvertInvoke(bb, mir, kDirect, false /*range*/,
1121 false /* NewFilledArray */);
1122 break;
1123 case Instruction::INVOKE_DIRECT_RANGE:
1124 ConvertInvoke(bb, mir, kDirect, true /*range*/,
1125 false /* NewFilledArray */);
1126 break;
1127
1128 case Instruction::INVOKE_VIRTUAL:
1129 ConvertInvoke(bb, mir, kVirtual, false /*range*/,
1130 false /* NewFilledArray */);
1131 break;
1132 case Instruction::INVOKE_VIRTUAL_RANGE:
1133 ConvertInvoke(bb, mir, kVirtual, true /*range*/,
1134 false /* NewFilledArray */);
1135 break;
1136
1137 case Instruction::INVOKE_SUPER:
1138 ConvertInvoke(bb, mir, kSuper, false /*range*/,
1139 false /* NewFilledArray */);
1140 break;
1141 case Instruction::INVOKE_SUPER_RANGE:
1142 ConvertInvoke(bb, mir, kSuper, true /*range*/,
1143 false /* NewFilledArray */);
1144 break;
1145
1146 case Instruction::INVOKE_INTERFACE:
1147 ConvertInvoke(bb, mir, kInterface, false /*range*/,
1148 false /* NewFilledArray */);
1149 break;
1150 case Instruction::INVOKE_INTERFACE_RANGE:
1151 ConvertInvoke(bb, mir, kInterface, true /*range*/,
1152 false /* NewFilledArray */);
1153 break;
1154 case Instruction::FILLED_NEW_ARRAY:
1155 ConvertInvoke(bb, mir, kInterface, false /*range*/,
1156 true /* NewFilledArray */);
1157 break;
1158 case Instruction::FILLED_NEW_ARRAY_RANGE:
1159 ConvertInvoke(bb, mir, kInterface, true /*range*/,
1160 true /* NewFilledArray */);
1161 break;
1162
1163 case Instruction::CONST_STRING:
1164 case Instruction::CONST_STRING_JUMBO:
1165 ConvertConstObject(vB, art::llvm::IntrinsicHelper::ConstString,
1166 rl_dest);
1167 break;
1168
1169 case Instruction::CONST_CLASS:
1170 ConvertConstObject(vB, art::llvm::IntrinsicHelper::ConstClass,
1171 rl_dest);
1172 break;
1173
1174 case Instruction::CHECK_CAST:
1175 ConvertCheckCast(vB, rl_src[0]);
1176 break;
1177
1178 case Instruction::NEW_INSTANCE:
1179 ConvertNewInstance(vB, rl_dest);
1180 break;
1181
1182 case Instruction::MOVE_EXCEPTION:
1183 ConvertMoveException(rl_dest);
1184 break;
1185
1186 case Instruction::THROW:
1187 ConvertThrow(rl_src[0]);
1188 /*
1189 * If this throw is standalone, terminate.
1190 * If it might rethrow, force termination
1191 * of the following block.
1192 */
1193 if (bb->fall_through == NULL) {
1194 irb_->CreateUnreachable();
1195 } else {
1196 bb->fall_through->fall_through = NULL;
1197 bb->fall_through->taken = NULL;
1198 }
1199 break;
1200
1201 case Instruction::MOVE_RESULT_WIDE:
1202 case Instruction::MOVE_RESULT:
1203 case Instruction::MOVE_RESULT_OBJECT:
1204 /*
1205 * All move_results should have been folded into the preceeding invoke.
1206 */
1207 LOG(FATAL) << "Unexpected move_result";
1208 break;
1209
1210 case Instruction::MONITOR_ENTER:
1211 ConvertMonitorEnterExit(opt_flags,
1212 art::llvm::IntrinsicHelper::MonitorEnter,
1213 rl_src[0]);
1214 break;
1215
1216 case Instruction::MONITOR_EXIT:
1217 ConvertMonitorEnterExit(opt_flags,
1218 art::llvm::IntrinsicHelper::MonitorExit,
1219 rl_src[0]);
1220 break;
1221
1222 case Instruction::ARRAY_LENGTH:
1223 ConvertArrayLength(opt_flags, rl_dest, rl_src[0]);
1224 break;
1225
1226 case Instruction::NEW_ARRAY:
1227 ConvertNewArray(vC, rl_dest, rl_src[0]);
1228 break;
1229
1230 case Instruction::INSTANCE_OF:
1231 ConvertInstanceOf(vC, rl_dest, rl_src[0]);
1232 break;
1233
1234 case Instruction::AGET:
1235 if (rl_dest.fp) {
1236 ConvertAget(opt_flags,
1237 art::llvm::IntrinsicHelper::HLArrayGetFloat,
1238 rl_dest, rl_src[0], rl_src[1]);
1239 } else {
1240 ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGet,
1241 rl_dest, rl_src[0], rl_src[1]);
1242 }
1243 break;
1244 case Instruction::AGET_OBJECT:
1245 ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetObject,
1246 rl_dest, rl_src[0], rl_src[1]);
1247 break;
1248 case Instruction::AGET_BOOLEAN:
1249 ConvertAget(opt_flags,
1250 art::llvm::IntrinsicHelper::HLArrayGetBoolean,
1251 rl_dest, rl_src[0], rl_src[1]);
1252 break;
1253 case Instruction::AGET_BYTE:
1254 ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetByte,
1255 rl_dest, rl_src[0], rl_src[1]);
1256 break;
1257 case Instruction::AGET_CHAR:
1258 ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetChar,
1259 rl_dest, rl_src[0], rl_src[1]);
1260 break;
1261 case Instruction::AGET_SHORT:
1262 ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetShort,
1263 rl_dest, rl_src[0], rl_src[1]);
1264 break;
1265 case Instruction::AGET_WIDE:
1266 if (rl_dest.fp) {
1267 ConvertAget(opt_flags,
1268 art::llvm::IntrinsicHelper::HLArrayGetDouble,
1269 rl_dest, rl_src[0], rl_src[1]);
1270 } else {
1271 ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetWide,
1272 rl_dest, rl_src[0], rl_src[1]);
1273 }
1274 break;
1275
1276 case Instruction::APUT:
1277 if (rl_src[0].fp) {
1278 ConvertAput(opt_flags,
1279 art::llvm::IntrinsicHelper::HLArrayPutFloat,
1280 rl_src[0], rl_src[1], rl_src[2]);
1281 } else {
1282 ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPut,
1283 rl_src[0], rl_src[1], rl_src[2]);
1284 }
1285 break;
1286 case Instruction::APUT_OBJECT:
1287 ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutObject,
1288 rl_src[0], rl_src[1], rl_src[2]);
1289 break;
1290 case Instruction::APUT_BOOLEAN:
1291 ConvertAput(opt_flags,
1292 art::llvm::IntrinsicHelper::HLArrayPutBoolean,
1293 rl_src[0], rl_src[1], rl_src[2]);
1294 break;
1295 case Instruction::APUT_BYTE:
1296 ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutByte,
1297 rl_src[0], rl_src[1], rl_src[2]);
1298 break;
1299 case Instruction::APUT_CHAR:
1300 ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutChar,
1301 rl_src[0], rl_src[1], rl_src[2]);
1302 break;
1303 case Instruction::APUT_SHORT:
1304 ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutShort,
1305 rl_src[0], rl_src[1], rl_src[2]);
1306 break;
1307 case Instruction::APUT_WIDE:
1308 if (rl_src[0].fp) {
1309 ConvertAput(opt_flags,
1310 art::llvm::IntrinsicHelper::HLArrayPutDouble,
1311 rl_src[0], rl_src[1], rl_src[2]);
1312 } else {
1313 ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutWide,
1314 rl_src[0], rl_src[1], rl_src[2]);
1315 }
1316 break;
1317
1318 case Instruction::IGET:
1319 if (rl_dest.fp) {
1320 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetFloat,
1321 rl_dest, rl_src[0], vC);
1322 } else {
1323 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGet,
1324 rl_dest, rl_src[0], vC);
1325 }
1326 break;
1327 case Instruction::IGET_OBJECT:
1328 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetObject,
1329 rl_dest, rl_src[0], vC);
1330 break;
1331 case Instruction::IGET_BOOLEAN:
1332 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetBoolean,
1333 rl_dest, rl_src[0], vC);
1334 break;
1335 case Instruction::IGET_BYTE:
1336 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetByte,
1337 rl_dest, rl_src[0], vC);
1338 break;
1339 case Instruction::IGET_CHAR:
1340 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetChar,
1341 rl_dest, rl_src[0], vC);
1342 break;
1343 case Instruction::IGET_SHORT:
1344 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetShort,
1345 rl_dest, rl_src[0], vC);
1346 break;
1347 case Instruction::IGET_WIDE:
1348 if (rl_dest.fp) {
1349 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetDouble,
1350 rl_dest, rl_src[0], vC);
1351 } else {
1352 ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetWide,
1353 rl_dest, rl_src[0], vC);
1354 }
1355 break;
1356 case Instruction::IPUT:
1357 if (rl_src[0].fp) {
1358 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutFloat,
1359 rl_src[0], rl_src[1], vC);
1360 } else {
1361 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPut,
1362 rl_src[0], rl_src[1], vC);
1363 }
1364 break;
1365 case Instruction::IPUT_OBJECT:
1366 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutObject,
1367 rl_src[0], rl_src[1], vC);
1368 break;
1369 case Instruction::IPUT_BOOLEAN:
1370 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutBoolean,
1371 rl_src[0], rl_src[1], vC);
1372 break;
1373 case Instruction::IPUT_BYTE:
1374 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutByte,
1375 rl_src[0], rl_src[1], vC);
1376 break;
1377 case Instruction::IPUT_CHAR:
1378 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutChar,
1379 rl_src[0], rl_src[1], vC);
1380 break;
1381 case Instruction::IPUT_SHORT:
1382 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutShort,
1383 rl_src[0], rl_src[1], vC);
1384 break;
1385 case Instruction::IPUT_WIDE:
1386 if (rl_src[0].fp) {
1387 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutDouble,
1388 rl_src[0], rl_src[1], vC);
1389 } else {
1390 ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutWide,
1391 rl_src[0], rl_src[1], vC);
1392 }
1393 break;
1394
1395 case Instruction::FILL_ARRAY_DATA:
1396 ConvertFillArrayData(vB, rl_src[0]);
1397 break;
1398
1399 case Instruction::LONG_TO_INT:
1400 ConvertLongToInt(rl_dest, rl_src[0]);
1401 break;
1402
1403 case Instruction::INT_TO_LONG:
1404 ConvertIntToLong(rl_dest, rl_src[0]);
1405 break;
1406
1407 case Instruction::INT_TO_CHAR:
1408 ConvertIntNarrowing(rl_dest, rl_src[0],
1409 art::llvm::IntrinsicHelper::IntToChar);
1410 break;
1411 case Instruction::INT_TO_BYTE:
1412 ConvertIntNarrowing(rl_dest, rl_src[0],
1413 art::llvm::IntrinsicHelper::IntToByte);
1414 break;
1415 case Instruction::INT_TO_SHORT:
1416 ConvertIntNarrowing(rl_dest, rl_src[0],
1417 art::llvm::IntrinsicHelper::IntToShort);
1418 break;
1419
1420 case Instruction::INT_TO_FLOAT:
1421 case Instruction::LONG_TO_FLOAT:
1422 ConvertIntToFP(irb_->getFloatTy(), rl_dest, rl_src[0]);
1423 break;
1424
1425 case Instruction::INT_TO_DOUBLE:
1426 case Instruction::LONG_TO_DOUBLE:
1427 ConvertIntToFP(irb_->getDoubleTy(), rl_dest, rl_src[0]);
1428 break;
1429
1430 case Instruction::FLOAT_TO_DOUBLE:
1431 ConvertFloatToDouble(rl_dest, rl_src[0]);
1432 break;
1433
1434 case Instruction::DOUBLE_TO_FLOAT:
1435 ConvertDoubleToFloat(rl_dest, rl_src[0]);
1436 break;
1437
1438 case Instruction::NEG_LONG:
1439 case Instruction::NEG_INT:
1440 ConvertNeg(rl_dest, rl_src[0]);
1441 break;
1442
1443 case Instruction::NEG_FLOAT:
1444 case Instruction::NEG_DOUBLE:
1445 ConvertNegFP(rl_dest, rl_src[0]);
1446 break;
1447
1448 case Instruction::NOT_LONG:
1449 case Instruction::NOT_INT:
1450 ConvertNot(rl_dest, rl_src[0]);
1451 break;
1452
1453 case Instruction::FLOAT_TO_INT:
1454 ConvertFPToInt(art::llvm::IntrinsicHelper::F2I, rl_dest, rl_src[0]);
1455 break;
1456
1457 case Instruction::DOUBLE_TO_INT:
1458 ConvertFPToInt(art::llvm::IntrinsicHelper::D2I, rl_dest, rl_src[0]);
1459 break;
1460
1461 case Instruction::FLOAT_TO_LONG:
1462 ConvertFPToInt(art::llvm::IntrinsicHelper::F2L, rl_dest, rl_src[0]);
1463 break;
1464
1465 case Instruction::DOUBLE_TO_LONG:
1466 ConvertFPToInt(art::llvm::IntrinsicHelper::D2L, rl_dest, rl_src[0]);
1467 break;
1468
1469 case Instruction::CMPL_FLOAT:
1470 ConvertWideComparison(art::llvm::IntrinsicHelper::CmplFloat,
1471 rl_dest, rl_src[0], rl_src[1]);
1472 break;
1473 case Instruction::CMPG_FLOAT:
1474 ConvertWideComparison(art::llvm::IntrinsicHelper::CmpgFloat,
1475 rl_dest, rl_src[0], rl_src[1]);
1476 break;
1477 case Instruction::CMPL_DOUBLE:
1478 ConvertWideComparison(art::llvm::IntrinsicHelper::CmplDouble,
1479 rl_dest, rl_src[0], rl_src[1]);
1480 break;
1481 case Instruction::CMPG_DOUBLE:
1482 ConvertWideComparison(art::llvm::IntrinsicHelper::CmpgDouble,
1483 rl_dest, rl_src[0], rl_src[1]);
1484 break;
1485 case Instruction::CMP_LONG:
1486 ConvertWideComparison(art::llvm::IntrinsicHelper::CmpLong,
1487 rl_dest, rl_src[0], rl_src[1]);
1488 break;
1489
1490 case Instruction::PACKED_SWITCH:
1491 ConvertPackedSwitch(bb, vB, rl_src[0]);
1492 break;
1493
1494 case Instruction::SPARSE_SWITCH:
1495 ConvertSparseSwitch(bb, vB, rl_src[0]);
1496 break;
1497
1498 default:
1499 UNIMPLEMENTED(FATAL) << "Unsupported Dex opcode 0x" << std::hex << opcode;
1500 res = true;
1501 }
1502 return res;
1503 } // NOLINT(readability/fn_size)
1504
SetDexOffset(int32_t offset)1505 void MirConverter::SetDexOffset(int32_t offset) {
1506 current_dalvik_offset_ = offset;
1507 ::llvm::SmallVector< ::llvm::Value*, 1> array_ref;
1508 array_ref.push_back(irb_->getInt32(offset));
1509 ::llvm::MDNode* node = ::llvm::MDNode::get(*context_, array_ref);
1510 irb_->SetDexOffset(node);
1511 }
1512
1513 // Attach method info as metadata to special intrinsic
SetMethodInfo()1514 void MirConverter::SetMethodInfo() {
1515 // We don't want dex offset on this
1516 irb_->SetDexOffset(NULL);
1517 art::llvm::IntrinsicHelper::IntrinsicId id;
1518 id = art::llvm::IntrinsicHelper::MethodInfo;
1519 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
1520 ::llvm::Instruction* inst = irb_->CreateCall(intr);
1521 ::llvm::SmallVector< ::llvm::Value*, 2> reg_info;
1522 reg_info.push_back(irb_->getInt32(cu_->num_ins));
1523 reg_info.push_back(irb_->getInt32(cu_->num_regs));
1524 reg_info.push_back(irb_->getInt32(cu_->num_outs));
1525 reg_info.push_back(irb_->getInt32(cu_->num_compiler_temps));
1526 reg_info.push_back(irb_->getInt32(mir_graph_->GetNumSSARegs()));
1527 ::llvm::MDNode* reg_info_node = ::llvm::MDNode::get(*context_, reg_info);
1528 inst->setMetadata("RegInfo", reg_info_node);
1529 SetDexOffset(current_dalvik_offset_);
1530 }
1531
HandlePhiNodes(BasicBlock * bb,::llvm::BasicBlock * llvm_bb)1532 void MirConverter::HandlePhiNodes(BasicBlock* bb, ::llvm::BasicBlock* llvm_bb) {
1533 SetDexOffset(bb->start_offset);
1534 for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
1535 int opcode = mir->dalvikInsn.opcode;
1536 if (opcode < kMirOpFirst) {
1537 // Stop after first non-pseudo MIR op.
1538 continue;
1539 }
1540 if (opcode != kMirOpPhi) {
1541 // Skip other mir Pseudos.
1542 continue;
1543 }
1544 RegLocation rl_dest = mir_graph_->reg_location_[mir->ssa_rep->defs[0]];
1545 /*
1546 * The Art compiler's Phi nodes only handle 32-bit operands,
1547 * representing wide values using a matched set of Phi nodes
1548 * for the lower and upper halves. In the llvm world, we only
1549 * want a single Phi for wides. Here we will simply discard
1550 * the Phi node representing the high word.
1551 */
1552 if (rl_dest.high_word) {
1553 continue; // No Phi node - handled via low word
1554 }
1555 int* incoming = reinterpret_cast<int*>(mir->dalvikInsn.vB);
1556 ::llvm::Type* phi_type =
1557 LlvmTypeFromLocRec(rl_dest);
1558 ::llvm::PHINode* phi = irb_->CreatePHI(phi_type, mir->ssa_rep->num_uses);
1559 for (int i = 0; i < mir->ssa_rep->num_uses; i++) {
1560 RegLocation loc;
1561 // Don't check width here.
1562 loc = mir_graph_->GetRawSrc(mir, i);
1563 DCHECK_EQ(rl_dest.wide, loc.wide);
1564 DCHECK_EQ(rl_dest.wide & rl_dest.high_word, loc.wide & loc.high_word);
1565 DCHECK_EQ(rl_dest.fp, loc.fp);
1566 DCHECK_EQ(rl_dest.core, loc.core);
1567 DCHECK_EQ(rl_dest.ref, loc.ref);
1568 SafeMap<unsigned int, unsigned int>::iterator it;
1569 it = mir_graph_->block_id_map_.find(incoming[i]);
1570 DCHECK(it != mir_graph_->block_id_map_.end());
1571 DCHECK(GetLLVMValue(loc.orig_sreg) != NULL);
1572 DCHECK(GetLLVMBlock(it->second) != NULL);
1573 phi->addIncoming(GetLLVMValue(loc.orig_sreg),
1574 GetLLVMBlock(it->second));
1575 }
1576 DefineValueOnly(phi, rl_dest.orig_sreg);
1577 }
1578 }
1579
1580 /* Extended MIR instructions like PHI */
ConvertExtendedMIR(BasicBlock * bb,MIR * mir,::llvm::BasicBlock * llvm_bb)1581 void MirConverter::ConvertExtendedMIR(BasicBlock* bb, MIR* mir,
1582 ::llvm::BasicBlock* llvm_bb) {
1583 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
1584 case kMirOpPhi: {
1585 // The llvm Phi node already emitted - just DefineValue() here.
1586 RegLocation rl_dest = mir_graph_->reg_location_[mir->ssa_rep->defs[0]];
1587 if (!rl_dest.high_word) {
1588 // Only consider low word of pairs.
1589 DCHECK(GetLLVMValue(rl_dest.orig_sreg) != NULL);
1590 ::llvm::Value* phi = GetLLVMValue(rl_dest.orig_sreg);
1591 if (1) SetVregOnValue(phi, rl_dest.orig_sreg);
1592 }
1593 break;
1594 }
1595 case kMirOpCopy: {
1596 UNIMPLEMENTED(WARNING) << "unimp kMirOpPhi";
1597 break;
1598 }
1599 case kMirOpNop:
1600 if ((mir == bb->last_mir_insn) && (bb->taken == NULL) &&
1601 (bb->fall_through == NULL)) {
1602 irb_->CreateUnreachable();
1603 }
1604 break;
1605
1606 // TODO: need GBC intrinsic to take advantage of fused operations
1607 case kMirOpFusedCmplFloat:
1608 UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpFloat unsupported";
1609 break;
1610 case kMirOpFusedCmpgFloat:
1611 UNIMPLEMENTED(FATAL) << "kMirOpFusedCmgFloat unsupported";
1612 break;
1613 case kMirOpFusedCmplDouble:
1614 UNIMPLEMENTED(FATAL) << "kMirOpFusedCmplDouble unsupported";
1615 break;
1616 case kMirOpFusedCmpgDouble:
1617 UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpgDouble unsupported";
1618 break;
1619 case kMirOpFusedCmpLong:
1620 UNIMPLEMENTED(FATAL) << "kMirOpLongCmpBranch unsupported";
1621 break;
1622 default:
1623 break;
1624 }
1625 }
1626
1627 /* Handle the content in each basic block */
BlockBitcodeConversion(BasicBlock * bb)1628 bool MirConverter::BlockBitcodeConversion(BasicBlock* bb) {
1629 if (bb->block_type == kDead) return false;
1630 ::llvm::BasicBlock* llvm_bb = GetLLVMBlock(bb->id);
1631 if (llvm_bb == NULL) {
1632 CHECK(bb->block_type == kExitBlock);
1633 } else {
1634 irb_->SetInsertPoint(llvm_bb);
1635 SetDexOffset(bb->start_offset);
1636 }
1637
1638 if (cu_->verbose) {
1639 LOG(INFO) << "................................";
1640 LOG(INFO) << "Block id " << bb->id;
1641 if (llvm_bb != NULL) {
1642 LOG(INFO) << "label " << llvm_bb->getName().str().c_str();
1643 } else {
1644 LOG(INFO) << "llvm_bb is NULL";
1645 }
1646 }
1647
1648 if (bb->block_type == kEntryBlock) {
1649 SetMethodInfo();
1650
1651 { // Allocate shadowframe.
1652 art::llvm::IntrinsicHelper::IntrinsicId id =
1653 art::llvm::IntrinsicHelper::AllocaShadowFrame;
1654 ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id);
1655 ::llvm::Value* entries = irb_->getInt32(cu_->num_dalvik_registers);
1656 irb_->CreateCall(func, entries);
1657 }
1658
1659 { // Store arguments to vregs.
1660 uint16_t arg_reg = cu_->num_regs;
1661
1662 ::llvm::Function::arg_iterator arg_iter(func_->arg_begin());
1663 ::llvm::Function::arg_iterator arg_end(func_->arg_end());
1664
1665 const char* shorty = cu_->shorty;
1666 uint32_t shorty_size = strlen(shorty);
1667 CHECK_GE(shorty_size, 1u);
1668
1669 ++arg_iter; // skip method object
1670
1671 if ((cu_->access_flags & kAccStatic) == 0) {
1672 SetVregOnValue(arg_iter, arg_reg);
1673 ++arg_iter;
1674 ++arg_reg;
1675 }
1676
1677 for (uint32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
1678 SetVregOnValue(arg_iter, arg_reg);
1679
1680 ++arg_reg;
1681 if (shorty[i] == 'J' || shorty[i] == 'D') {
1682 // Wide types, such as long and double, are using a pair of registers
1683 // to store the value, so we have to increase arg_reg again.
1684 ++arg_reg;
1685 }
1686 }
1687 }
1688 } else if (bb->block_type == kExitBlock) {
1689 /*
1690 * Because of the differences between how MIR/LIR and llvm handle exit
1691 * blocks, we won't explicitly covert them. On the llvm-to-lir
1692 * path, it will need to be regenereated.
1693 */
1694 return false;
1695 } else if (bb->block_type == kExceptionHandling) {
1696 /*
1697 * Because we're deferring null checking, delete the associated empty
1698 * exception block.
1699 */
1700 llvm_bb->eraseFromParent();
1701 return false;
1702 }
1703
1704 HandlePhiNodes(bb, llvm_bb);
1705
1706 for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
1707 SetDexOffset(mir->offset);
1708
1709 int opcode = mir->dalvikInsn.opcode;
1710 Instruction::Format dalvik_format =
1711 Instruction::FormatOf(mir->dalvikInsn.opcode);
1712
1713 if (opcode == kMirOpCheck) {
1714 // Combine check and work halves of throwing instruction.
1715 MIR* work_half = mir->meta.throw_insn;
1716 mir->dalvikInsn.opcode = work_half->dalvikInsn.opcode;
1717 opcode = mir->dalvikInsn.opcode;
1718 SSARepresentation* ssa_rep = work_half->ssa_rep;
1719 work_half->ssa_rep = mir->ssa_rep;
1720 mir->ssa_rep = ssa_rep;
1721 work_half->meta.original_opcode = work_half->dalvikInsn.opcode;
1722 work_half->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
1723 if (bb->successor_block_list.block_list_type == kCatch) {
1724 ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(
1725 art::llvm::IntrinsicHelper::CatchTargets);
1726 ::llvm::Value* switch_key =
1727 irb_->CreateCall(intr, irb_->getInt32(mir->offset));
1728 GrowableArray<SuccessorBlockInfo*>::Iterator iter(bb->successor_block_list.blocks);
1729 // New basic block to use for work half
1730 ::llvm::BasicBlock* work_bb =
1731 ::llvm::BasicBlock::Create(*context_, "", func_);
1732 ::llvm::SwitchInst* sw =
1733 irb_->CreateSwitch(switch_key, work_bb,
1734 bb->successor_block_list.blocks->Size());
1735 while (true) {
1736 SuccessorBlockInfo *successor_block_info = iter.Next();
1737 if (successor_block_info == NULL) break;
1738 ::llvm::BasicBlock *target =
1739 GetLLVMBlock(successor_block_info->block->id);
1740 int type_index = successor_block_info->key;
1741 sw->addCase(irb_->getInt32(type_index), target);
1742 }
1743 llvm_bb = work_bb;
1744 irb_->SetInsertPoint(llvm_bb);
1745 }
1746 }
1747
1748 if (opcode >= kMirOpFirst) {
1749 ConvertExtendedMIR(bb, mir, llvm_bb);
1750 continue;
1751 }
1752
1753 bool not_handled = ConvertMIRNode(mir, bb, llvm_bb);
1754 if (not_handled) {
1755 Instruction::Code dalvik_opcode = static_cast<Instruction::Code>(opcode);
1756 LOG(WARNING) << StringPrintf("%#06x: Op %#x (%s) / Fmt %d not handled",
1757 mir->offset, opcode,
1758 Instruction::Name(dalvik_opcode),
1759 dalvik_format);
1760 }
1761 }
1762
1763 if (bb->block_type == kEntryBlock) {
1764 entry_target_bb_ = GetLLVMBlock(bb->fall_through->id);
1765 } else if ((bb->fall_through != NULL) && !bb->terminated_by_return) {
1766 irb_->CreateBr(GetLLVMBlock(bb->fall_through->id));
1767 }
1768
1769 return false;
1770 }
1771
RemapShorty(char shorty_type)1772 char RemapShorty(char shorty_type) {
1773 /*
1774 * TODO: might want to revisit this. Dalvik registers are 32-bits wide,
1775 * and longs/doubles are represented as a pair of registers. When sub-word
1776 * arguments (and method results) are passed, they are extended to Dalvik
1777 * virtual register containers. Because llvm is picky about type consistency,
1778 * we must either cast the "real" type to 32-bit container multiple Dalvik
1779 * register types, or always use the expanded values.
1780 * Here, we're doing the latter. We map the shorty signature to container
1781 * types (which is valid so long as we always do a real expansion of passed
1782 * arguments and field loads).
1783 */
1784 switch (shorty_type) {
1785 case 'Z' : shorty_type = 'I'; break;
1786 case 'B' : shorty_type = 'I'; break;
1787 case 'S' : shorty_type = 'I'; break;
1788 case 'C' : shorty_type = 'I'; break;
1789 default: break;
1790 }
1791 return shorty_type;
1792 }
1793
GetFunctionType()1794 ::llvm::FunctionType* MirConverter::GetFunctionType() {
1795 // Get return type
1796 ::llvm::Type* ret_type = irb_->getJType(RemapShorty(cu_->shorty[0]));
1797
1798 // Get argument type
1799 std::vector< ::llvm::Type*> args_type;
1800
1801 // method object
1802 args_type.push_back(irb_->getJMethodTy());
1803
1804 // Do we have a "this"?
1805 if ((cu_->access_flags & kAccStatic) == 0) {
1806 args_type.push_back(irb_->getJObjectTy());
1807 }
1808
1809 for (uint32_t i = 1; i < strlen(cu_->shorty); ++i) {
1810 args_type.push_back(irb_->getJType(RemapShorty(cu_->shorty[i])));
1811 }
1812
1813 return ::llvm::FunctionType::get(ret_type, args_type, false);
1814 }
1815
CreateFunction()1816 bool MirConverter::CreateFunction() {
1817 ::llvm::FunctionType* func_type = GetFunctionType();
1818 if (func_type == NULL) {
1819 return false;
1820 }
1821
1822 func_ = ::llvm::Function::Create(func_type,
1823 ::llvm::Function::InternalLinkage,
1824 symbol_, module_);
1825
1826 ::llvm::Function::arg_iterator arg_iter(func_->arg_begin());
1827 ::llvm::Function::arg_iterator arg_end(func_->arg_end());
1828
1829 arg_iter->setName("method");
1830 ++arg_iter;
1831
1832 int start_sreg = cu_->num_regs;
1833
1834 for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
1835 arg_iter->setName(StringPrintf("v%i_0", start_sreg));
1836 start_sreg += mir_graph_->reg_location_[start_sreg].wide ? 2 : 1;
1837 }
1838
1839 return true;
1840 }
1841
CreateLLVMBasicBlock(BasicBlock * bb)1842 bool MirConverter::CreateLLVMBasicBlock(BasicBlock* bb) {
1843 // Skip the exit block
1844 if ((bb->block_type == kDead) ||(bb->block_type == kExitBlock)) {
1845 id_to_block_map_.Put(bb->id, NULL);
1846 } else {
1847 int offset = bb->start_offset;
1848 bool entry_block = (bb->block_type == kEntryBlock);
1849 ::llvm::BasicBlock* llvm_bb =
1850 ::llvm::BasicBlock::Create(*context_, entry_block ? "entry" :
1851 StringPrintf(kLabelFormat, bb->catch_entry ? kCatchBlock :
1852 kNormalBlock, offset, bb->id), func_);
1853 if (entry_block) {
1854 entry_bb_ = llvm_bb;
1855 placeholder_bb_ =
1856 ::llvm::BasicBlock::Create(*context_, "placeholder",
1857 func_);
1858 }
1859 id_to_block_map_.Put(bb->id, llvm_bb);
1860 }
1861 return false;
1862 }
1863
1864
1865 /*
1866 * Convert MIR to LLVM_IR
1867 * o For each ssa name, create LLVM named value. Type these
1868 * appropriately, and ignore high half of wide and double operands.
1869 * o For each MIR basic block, create an LLVM basic block.
1870 * o Iterate through the MIR a basic block at a time, setting arguments
1871 * to recovered ssa name.
1872 */
MethodMIR2Bitcode()1873 void MirConverter::MethodMIR2Bitcode() {
1874 InitIR();
1875
1876 // Create the function
1877 CreateFunction();
1878
1879 // Create an LLVM basic block for each MIR block in dfs preorder
1880 PreOrderDfsIterator iter(mir_graph_, false /* not iterative */);
1881 for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
1882 CreateLLVMBasicBlock(bb);
1883 }
1884
1885 /*
1886 * Create an llvm named value for each MIR SSA name. Note: we'll use
1887 * placeholders for all non-argument values (because we haven't seen
1888 * the definition yet).
1889 */
1890 irb_->SetInsertPoint(placeholder_bb_);
1891 ::llvm::Function::arg_iterator arg_iter(func_->arg_begin());
1892 arg_iter++; /* Skip path method */
1893 for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) {
1894 ::llvm::Value* val;
1895 RegLocation rl_temp = mir_graph_->reg_location_[i];
1896 if ((mir_graph_->SRegToVReg(i) < 0) || rl_temp.high_word) {
1897 llvm_values_.Insert(0);
1898 } else if ((i < cu_->num_regs) ||
1899 (i >= (cu_->num_regs + cu_->num_ins))) {
1900 ::llvm::Constant* imm_value = mir_graph_->reg_location_[i].wide ?
1901 irb_->getJLong(0) : irb_->getJInt(0);
1902 val = EmitConst(imm_value, mir_graph_->reg_location_[i]);
1903 val->setName(mir_graph_->GetSSAName(i));
1904 llvm_values_.Insert(val);
1905 } else {
1906 // Recover previously-created argument values
1907 ::llvm::Value* arg_val = arg_iter++;
1908 llvm_values_.Insert(arg_val);
1909 }
1910 }
1911
1912 PreOrderDfsIterator iter2(mir_graph_, false /* not iterative */);
1913 for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
1914 BlockBitcodeConversion(bb);
1915 }
1916
1917 /*
1918 * In a few rare cases of verification failure, the verifier will
1919 * replace one or more Dalvik opcodes with the special
1920 * throw-verification-failure opcode. This can leave the SSA graph
1921 * in an invalid state, as definitions may be lost, while uses retained.
1922 * To work around this problem, we insert placeholder definitions for
1923 * all Dalvik SSA regs in the "placeholder" block. Here, after
1924 * bitcode conversion is complete, we examine those placeholder definitions
1925 * and delete any with no references (which normally is all of them).
1926 *
1927 * If any definitions remain, we link the placeholder block into the
1928 * CFG. Otherwise, it is deleted.
1929 */
1930 for (::llvm::BasicBlock::iterator it = placeholder_bb_->begin(),
1931 it_end = placeholder_bb_->end(); it != it_end;) {
1932 ::llvm::Instruction* inst = ::llvm::dyn_cast< ::llvm::Instruction>(it++);
1933 DCHECK(inst != NULL);
1934 ::llvm::Value* val = ::llvm::dyn_cast< ::llvm::Value>(inst);
1935 DCHECK(val != NULL);
1936 if (val->getNumUses() == 0) {
1937 inst->eraseFromParent();
1938 }
1939 }
1940 SetDexOffset(0);
1941 if (placeholder_bb_->empty()) {
1942 placeholder_bb_->eraseFromParent();
1943 } else {
1944 irb_->SetInsertPoint(placeholder_bb_);
1945 irb_->CreateBr(entry_target_bb_);
1946 entry_target_bb_ = placeholder_bb_;
1947 }
1948 irb_->SetInsertPoint(entry_bb_);
1949 irb_->CreateBr(entry_target_bb_);
1950
1951 if (cu_->enable_debug & (1 << kDebugVerifyBitcode)) {
1952 if (::llvm::verifyFunction(*func_, ::llvm::PrintMessageAction)) {
1953 LOG(INFO) << "Bitcode verification FAILED for "
1954 << PrettyMethod(cu_->method_idx, *cu_->dex_file)
1955 << " of size " << cu_->code_item->insns_size_in_code_units_;
1956 cu_->enable_debug |= (1 << kDebugDumpBitcodeFile);
1957 }
1958 }
1959
1960 if (cu_->enable_debug & (1 << kDebugDumpBitcodeFile)) {
1961 // Write bitcode to file
1962 std::string errmsg;
1963 std::string fname(PrettyMethod(cu_->method_idx, *cu_->dex_file));
1964 mir_graph_->ReplaceSpecialChars(fname);
1965 // TODO: make configurable change naming mechanism to avoid fname length issues.
1966 fname = StringPrintf("/sdcard/Bitcode/%s.bc", fname.c_str());
1967
1968 if (fname.size() > 240) {
1969 LOG(INFO) << "Warning: bitcode filename too long. Truncated.";
1970 fname.resize(240);
1971 }
1972
1973 ::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
1974 new ::llvm::tool_output_file(fname.c_str(), errmsg,
1975 ::llvm::sys::fs::F_Binary));
1976
1977 if (!errmsg.empty()) {
1978 LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
1979 }
1980
1981 ::llvm::WriteBitcodeToFile(module_, out_file->os());
1982 out_file->keep();
1983 }
1984 }
1985
PortableCodeGenerator(CompilationUnit * const cu,MIRGraph * const mir_graph,ArenaAllocator * const arena,llvm::LlvmCompilationUnit * const llvm_compilation_unit)1986 Backend* PortableCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
1987 ArenaAllocator* const arena,
1988 llvm::LlvmCompilationUnit* const llvm_compilation_unit) {
1989 return new MirConverter(cu, mir_graph, arena, llvm_compilation_unit);
1990 }
1991
1992 } // namespace art
1993