blob: f25c7e5a224ea981ea309ac6eada06a095637a1b [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
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
19namespace art {
20
21#define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \
22 (1 << kDebugDisplayMissingTargets))
23
buzbee31a4a6f2012-02-28 15:36:15 -080024const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0,
25 INVALID_REG, INVALID_REG, INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080026
27/* Mark register usage state and return long retloc */
buzbee31a4a6f2012-02-28 15:36:15 -080028RegLocation getRetLocWide(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -080029{
30 RegLocation res = LOC_C_RETURN_WIDE;
31 oatLockTemp(cUnit, res.lowReg);
32 oatLockTemp(cUnit, res.highReg);
33 oatMarkPair(cUnit, res.lowReg, res.highReg);
34 return res;
35}
36
buzbee31a4a6f2012-02-28 15:36:15 -080037RegLocation getRetLoc(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -080038{
39 RegLocation res = LOC_C_RETURN;
40 oatLockTemp(cUnit, res.lowReg);
41 return res;
42}
43
buzbee31a4a6f2012-02-28 15:36:15 -080044void genInvoke(CompilationUnit* cUnit, MIR* mir, InvokeType type, bool isRange)
buzbeee3acd072012-02-25 17:03:10 -080045{
buzbeea7678db2012-03-05 15:35:46 -080046#if defined(TARGET_X86)
47 UNIMPLEMENTED(WARNING) << "genInvoke";
48#else
buzbeee3acd072012-02-25 17:03:10 -080049 DecodedInstruction* dInsn = &mir->dalvikInsn;
50 int callState = 0;
buzbee31a4a6f2012-02-28 15:36:15 -080051 LIR* nullCk;
52 LIR** pNullCk = NULL;
buzbeee3acd072012-02-25 17:03:10 -080053 NextCallInsn nextCallInsn;
54 oatFlushAllRegs(cUnit); /* Everything to home location */
55 // Explicit register usage
56 oatLockCallTemps(cUnit);
57
Logan Chien4dd96f52012-02-29 01:26:58 +080058 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
buzbee31a4a6f2012-02-28 15:36:15 -080059 *cUnit->dex_file, *cUnit->dex_cache,
60 cUnit->code_item, cUnit->method_idx,
61 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080062
buzbeee3acd072012-02-25 17:03:10 -080063 uint32_t dexMethodIdx = dInsn->vB;
64 int vtableIdx;
65 bool skipThis;
66 bool fastPath =
Logan Chien4dd96f52012-02-29 01:26:58 +080067 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, type,
buzbeee3acd072012-02-25 17:03:10 -080068 vtableIdx)
69 && !SLOW_INVOKE_PATH;
70 if (type == kInterface) {
71 nextCallInsn = fastPath ? nextInterfaceCallInsn
72 : nextInterfaceCallInsnWithAccessCheck;
73 skipThis = false;
74 } else if (type == kDirect) {
75 if (fastPath) {
76 pNullCk = &nullCk;
77 }
78 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
79 skipThis = false;
80 } else if (type == kStatic) {
81 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
82 skipThis = false;
83 } else if (type == kSuper) {
84 nextCallInsn = fastPath ? nextSuperCallInsn : nextSuperCallInsnSP;
85 skipThis = fastPath;
86 } else {
87 DCHECK_EQ(type, kVirtual);
88 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
89 skipThis = fastPath;
90 }
91 if (!isRange) {
92 callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk,
93 nextCallInsn, dexMethodIdx,
94 vtableIdx, skipThis);
95 } else {
96 callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
97 nextCallInsn, dexMethodIdx, vtableIdx,
98 skipThis);
99 }
100 // Finish up any of the call sequence not interleaved in arg loading
101 while (callState >= 0) {
102 callState = nextCallInsn(cUnit, mir, callState, dexMethodIdx,
103 vtableIdx);
104 }
105 if (DISPLAY_MISSING_TARGETS) {
106 genShowTarget(cUnit);
107 }
buzbee0398c422012-03-02 15:22:47 -0800108 opReg(cUnit, kOpBlx, rINVOKE_TGT);
buzbeee3acd072012-02-25 17:03:10 -0800109 oatClobberCalleeSave(cUnit);
buzbeea7678db2012-03-05 15:35:46 -0800110#endif
buzbeee3acd072012-02-25 17:03:10 -0800111}
112
113/*
114 * Target-independent code generation. Use only high-level
115 * load/store utilities here, or target-dependent genXX() handlers
116 * when necessary.
117 */
buzbee31a4a6f2012-02-28 15:36:15 -0800118bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
119 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800120{
121 bool res = false; // Assume success
122 RegLocation rlSrc[3];
123 RegLocation rlDest = badLoc;
124 RegLocation rlResult = badLoc;
125 Opcode opcode = mir->dalvikInsn.opcode;
126
127 /* Prep Src and Dest locations */
128 int nextSreg = 0;
129 int nextLoc = 0;
130 int attrs = oatDataFlowAttributes[opcode];
131 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
132 if (attrs & DF_UA) {
133 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
134 nextSreg++;
135 } else if (attrs & DF_UA_WIDE) {
136 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
137 nextSreg + 1);
138 nextSreg+= 2;
139 }
140 if (attrs & DF_UB) {
141 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
142 nextSreg++;
143 } else if (attrs & DF_UB_WIDE) {
144 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
145 nextSreg + 1);
146 nextSreg+= 2;
147 }
148 if (attrs & DF_UC) {
149 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
150 } else if (attrs & DF_UC_WIDE) {
151 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
152 nextSreg + 1);
153 }
154 if (attrs & DF_DA) {
155 rlDest = oatGetDest(cUnit, mir, 0);
156 } else if (attrs & DF_DA_WIDE) {
157 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
158 }
159
160 switch(opcode) {
161 case OP_NOP:
162 break;
163
164 case OP_MOVE_EXCEPTION:
buzbeea7678db2012-03-05 15:35:46 -0800165#if defined(TARGET_X86)
166 UNIMPLEMENTED(WARNING) << "OP_MOVE_EXCEPTION";
167#else
buzbeee3acd072012-02-25 17:03:10 -0800168 int exOffset;
169 int resetReg;
170 exOffset = Thread::ExceptionOffset().Int32Value();
171 resetReg = oatAllocTemp(cUnit);
172 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
173 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
174 loadConstant(cUnit, resetReg, 0);
175 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
176 storeValue(cUnit, rlDest, rlResult);
buzbeea7678db2012-03-05 15:35:46 -0800177#endif
buzbeee3acd072012-02-25 17:03:10 -0800178 break;
179
180 case OP_RETURN_VOID:
181 genSuspendTest(cUnit, mir);
182 break;
183
184 case OP_RETURN:
185 case OP_RETURN_OBJECT:
186 genSuspendTest(cUnit, mir);
187 storeValue(cUnit, getRetLoc(cUnit), rlSrc[0]);
188 break;
189
190 case OP_RETURN_WIDE:
191 genSuspendTest(cUnit, mir);
192 storeValueWide(cUnit, getRetLocWide(cUnit), rlSrc[0]);
193 break;
194
195 case OP_MOVE_RESULT_WIDE:
196 if (mir->optimizationFlags & MIR_INLINED)
197 break; // Nop - combined w/ previous invoke
198 storeValueWide(cUnit, rlDest, getRetLocWide(cUnit));
199 break;
200
201 case OP_MOVE_RESULT:
202 case OP_MOVE_RESULT_OBJECT:
203 if (mir->optimizationFlags & MIR_INLINED)
204 break; // Nop - combined w/ previous invoke
205 storeValue(cUnit, rlDest, getRetLoc(cUnit));
206 break;
207
208 case OP_MOVE:
209 case OP_MOVE_OBJECT:
210 case OP_MOVE_16:
211 case OP_MOVE_OBJECT_16:
212 case OP_MOVE_FROM16:
213 case OP_MOVE_OBJECT_FROM16:
214 storeValue(cUnit, rlDest, rlSrc[0]);
215 break;
216
217 case OP_MOVE_WIDE:
218 case OP_MOVE_WIDE_16:
219 case OP_MOVE_WIDE_FROM16:
220 storeValueWide(cUnit, rlDest, rlSrc[0]);
221 break;
222
223 case OP_CONST:
224 case OP_CONST_4:
225 case OP_CONST_16:
226 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
227 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
228 storeValue(cUnit, rlDest, rlResult);
229 break;
230
231 case OP_CONST_HIGH16:
232 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
233 loadConstantNoClobber(cUnit, rlResult.lowReg,
234 mir->dalvikInsn.vB << 16);
235 storeValue(cUnit, rlDest, rlResult);
236 break;
237
238 case OP_CONST_WIDE_16:
239 case OP_CONST_WIDE_32:
240 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
241 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
242 mir->dalvikInsn.vB,
243 (mir->dalvikInsn.vB & 0x80000000) ? -1 : 0);
244 storeValueWide(cUnit, rlDest, rlResult);
245 break;
246
247 case OP_CONST_WIDE:
248 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
249 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
250 mir->dalvikInsn.vB_wide & 0xffffffff,
251 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
252 storeValueWide(cUnit, rlDest, rlResult);
253 break;
254
255 case OP_CONST_WIDE_HIGH16:
256 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
257 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
258 0, mir->dalvikInsn.vB << 16);
259 storeValueWide(cUnit, rlDest, rlResult);
260 break;
261
262 case OP_MONITOR_ENTER:
263 genMonitorEnter(cUnit, mir, rlSrc[0]);
264 break;
265
266 case OP_MONITOR_EXIT:
267 genMonitorExit(cUnit, mir, rlSrc[0]);
268 break;
269
270 case OP_CHECK_CAST:
271 genCheckCast(cUnit, mir, rlSrc[0]);
272 break;
273
274 case OP_INSTANCE_OF:
275 genInstanceof(cUnit, mir, rlDest, rlSrc[0]);
276 break;
277
278 case OP_NEW_INSTANCE:
279 genNewInstance(cUnit, mir, rlDest);
280 break;
281
282 case OP_THROW:
283 genThrow(cUnit, mir, rlSrc[0]);
284 break;
285
286 case OP_THROW_VERIFICATION_ERROR:
287 genThrowVerificationError(cUnit, mir);
288 break;
289
290 case OP_ARRAY_LENGTH:
291 int lenOffset;
292 lenOffset = Array::LengthOffset().Int32Value();
293 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
294 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, mir);
295 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
296 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset,
297 rlResult.lowReg);
298 storeValue(cUnit, rlDest, rlResult);
299 break;
300
301 case OP_CONST_STRING:
302 case OP_CONST_STRING_JUMBO:
303 genConstString(cUnit, mir, rlDest, rlSrc[0]);
304 break;
305
306 case OP_CONST_CLASS:
307 genConstClass(cUnit, mir, rlDest, rlSrc[0]);
308 break;
309
310 case OP_FILL_ARRAY_DATA:
311 genFillArrayData(cUnit, mir, rlSrc[0]);
312 break;
313
314 case OP_FILLED_NEW_ARRAY:
315 genFilledNewArray(cUnit, mir, false /* not range */);
316 break;
317
318 case OP_FILLED_NEW_ARRAY_RANGE:
319 genFilledNewArray(cUnit, mir, true /* range */);
320 break;
321
322 case OP_NEW_ARRAY:
323 genNewArray(cUnit, mir, rlDest, rlSrc[0]);
324 break;
325
326 case OP_GOTO:
327 case OP_GOTO_16:
328 case OP_GOTO_32:
329 if (bb->taken->startOffset <= mir->offset) {
330 genSuspendTest(cUnit, mir);
331 }
buzbee82488f52012-03-02 08:20:26 -0800332 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
buzbeee3acd072012-02-25 17:03:10 -0800333 break;
334
335 case OP_PACKED_SWITCH:
336 genPackedSwitch(cUnit, mir, rlSrc[0]);
337 break;
338
339 case OP_SPARSE_SWITCH:
340 genSparseSwitch(cUnit, mir, rlSrc[0]);
341 break;
342
343 case OP_CMPL_FLOAT:
344 case OP_CMPG_FLOAT:
345 case OP_CMPL_DOUBLE:
346 case OP_CMPG_DOUBLE:
347 res = genCmpFP(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
348 break;
349
350 case OP_CMP_LONG:
351 genCmpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
352 break;
353
354 case OP_IF_EQ:
355 case OP_IF_NE:
356 case OP_IF_LT:
357 case OP_IF_GE:
358 case OP_IF_GT:
359 case OP_IF_LE: {
360 bool backwardBranch;
361 backwardBranch = (bb->taken->startOffset <= mir->offset);
362 if (backwardBranch) {
363 genSuspendTest(cUnit, mir);
364 }
365 genCompareAndBranch(cUnit, bb, mir, rlSrc[0], rlSrc[1], labelList);
366 break;
367 }
368
369 case OP_IF_EQZ:
370 case OP_IF_NEZ:
371 case OP_IF_LTZ:
372 case OP_IF_GEZ:
373 case OP_IF_GTZ:
374 case OP_IF_LEZ: {
375 bool backwardBranch;
376 backwardBranch = (bb->taken->startOffset <= mir->offset);
377 if (backwardBranch) {
378 genSuspendTest(cUnit, mir);
379 }
380 genCompareZeroAndBranch(cUnit, bb, mir, rlSrc[0], labelList);
381 break;
382 }
383
384 case OP_AGET_WIDE:
385 genArrayGet(cUnit, mir, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
386 break;
387 case OP_AGET:
388 case OP_AGET_OBJECT:
389 genArrayGet(cUnit, mir, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
390 break;
391 case OP_AGET_BOOLEAN:
392 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1],
393 rlDest, 0);
394 break;
395 case OP_AGET_BYTE:
396 genArrayGet(cUnit, mir, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
397 break;
398 case OP_AGET_CHAR:
399 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1],
400 rlDest, 1);
401 break;
402 case OP_AGET_SHORT:
403 genArrayGet(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
404 break;
405 case OP_APUT_WIDE:
406 genArrayPut(cUnit, mir, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
407 break;
408 case OP_APUT:
409 genArrayPut(cUnit, mir, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
410 break;
411 case OP_APUT_OBJECT:
412 genArrayObjPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2);
413 break;
414 case OP_APUT_SHORT:
415 case OP_APUT_CHAR:
416 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc[1], rlSrc[2],
417 rlSrc[0], 1);
418 break;
419 case OP_APUT_BYTE:
420 case OP_APUT_BOOLEAN:
421 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc[1], rlSrc[2],
422 rlSrc[0], 0);
423 break;
424
425 case OP_IGET_OBJECT:
426 case OP_IGET_OBJECT_VOLATILE:
427 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, true);
428 break;
429
430 case OP_IGET_WIDE:
431 case OP_IGET_WIDE_VOLATILE:
432 genIGet(cUnit, mir, kLong, rlDest, rlSrc[0], true, false);
433 break;
434
435 case OP_IGET:
436 case OP_IGET_VOLATILE:
437 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, false);
438 break;
439
440 case OP_IGET_CHAR:
441 genIGet(cUnit, mir, kUnsignedHalf, rlDest, rlSrc[0], false, false);
442 break;
443
444 case OP_IGET_SHORT:
445 genIGet(cUnit, mir, kSignedHalf, rlDest, rlSrc[0], false, false);
446 break;
447
448 case OP_IGET_BOOLEAN:
449 case OP_IGET_BYTE:
450 genIGet(cUnit, mir, kUnsignedByte, rlDest, rlSrc[0], false, false);
451 break;
452
453 case OP_IPUT_WIDE:
454 case OP_IPUT_WIDE_VOLATILE:
455 genIPut(cUnit, mir, kLong, rlSrc[0], rlSrc[1], true, false);
456 break;
457
458 case OP_IPUT_OBJECT:
459 case OP_IPUT_OBJECT_VOLATILE:
460 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, true);
461 break;
462
463 case OP_IPUT:
464 case OP_IPUT_VOLATILE:
465 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, false);
466 break;
467
468 case OP_IPUT_BOOLEAN:
469 case OP_IPUT_BYTE:
470 genIPut(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
471 break;
472
473 case OP_IPUT_CHAR:
474 genIPut(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
475 break;
476
477 case OP_IPUT_SHORT:
478 genIPut(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
479 break;
480
481 case OP_SGET_OBJECT:
482 genSget(cUnit, mir, rlDest, false, true);
483 break;
484 case OP_SGET:
485 case OP_SGET_BOOLEAN:
486 case OP_SGET_BYTE:
487 case OP_SGET_CHAR:
488 case OP_SGET_SHORT:
489 genSget(cUnit, mir, rlDest, false, false);
490 break;
491
492 case OP_SGET_WIDE:
493 genSget(cUnit, mir, rlDest, true, false);
494 break;
495
496 case OP_SPUT_OBJECT:
497 genSput(cUnit, mir, rlSrc[0], false, true);
498 break;
499
500 case OP_SPUT:
501 case OP_SPUT_BOOLEAN:
502 case OP_SPUT_BYTE:
503 case OP_SPUT_CHAR:
504 case OP_SPUT_SHORT:
505 genSput(cUnit, mir, rlSrc[0], false, false);
506 break;
507
508 case OP_SPUT_WIDE:
509 genSput(cUnit, mir, rlSrc[0], true, false);
510 break;
511
512 case OP_INVOKE_STATIC_RANGE:
513 genInvoke(cUnit, mir, kStatic, true /*range*/);
514 break;
515 case OP_INVOKE_STATIC:
516 genInvoke(cUnit, mir, kStatic, false /*range*/);
517 break;
518
519 case OP_INVOKE_DIRECT:
520 genInvoke(cUnit, mir, kDirect, false /*range*/);
521 break;
522 case OP_INVOKE_DIRECT_RANGE:
523 genInvoke(cUnit, mir, kDirect, true /*range*/);
524 break;
525
526 case OP_INVOKE_VIRTUAL:
527 genInvoke(cUnit, mir, kVirtual, false /*range*/);
528 break;
529 case OP_INVOKE_VIRTUAL_RANGE:
530 genInvoke(cUnit, mir, kVirtual, true /*range*/);
531 break;
532
533 case OP_INVOKE_SUPER:
534 genInvoke(cUnit, mir, kSuper, false /*range*/);
535 break;
536 case OP_INVOKE_SUPER_RANGE:
537 genInvoke(cUnit, mir, kSuper, true /*range*/);
538 break;
539
540 case OP_INVOKE_INTERFACE:
541 genInvoke(cUnit, mir, kInterface, false /*range*/);
542 break;
543 case OP_INVOKE_INTERFACE_RANGE:
544 genInvoke(cUnit, mir, kInterface, true /*range*/);
545 break;
546
547 case OP_NEG_INT:
548 case OP_NOT_INT:
549 res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
550 break;
551
552 case OP_NEG_LONG:
553 case OP_NOT_LONG:
554 res = genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
555 break;
556
557 case OP_NEG_FLOAT:
558 res = genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
559 break;
560
561 case OP_NEG_DOUBLE:
562 res = genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
563 break;
564
565 case OP_INT_TO_LONG:
566 genIntToLong(cUnit, mir, rlDest, rlSrc[0]);
567 break;
568
569 case OP_LONG_TO_INT:
570 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
571 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
572 storeValue(cUnit, rlDest, rlSrc[0]);
573 break;
574
575 case OP_INT_TO_BYTE:
576 case OP_INT_TO_SHORT:
577 case OP_INT_TO_CHAR:
578 genIntNarrowing(cUnit, mir, rlDest, rlSrc[0]);
579 break;
580
581 case OP_INT_TO_FLOAT:
582 case OP_INT_TO_DOUBLE:
583 case OP_LONG_TO_FLOAT:
584 case OP_LONG_TO_DOUBLE:
585 case OP_FLOAT_TO_INT:
586 case OP_FLOAT_TO_LONG:
587 case OP_FLOAT_TO_DOUBLE:
588 case OP_DOUBLE_TO_INT:
589 case OP_DOUBLE_TO_LONG:
590 case OP_DOUBLE_TO_FLOAT:
591 genConversion(cUnit, mir);
592 break;
593
594 case OP_ADD_INT:
595 case OP_SUB_INT:
596 case OP_MUL_INT:
597 case OP_DIV_INT:
598 case OP_REM_INT:
599 case OP_AND_INT:
600 case OP_OR_INT:
601 case OP_XOR_INT:
602 case OP_SHL_INT:
603 case OP_SHR_INT:
604 case OP_USHR_INT:
605 case OP_ADD_INT_2ADDR:
606 case OP_SUB_INT_2ADDR:
607 case OP_MUL_INT_2ADDR:
608 case OP_DIV_INT_2ADDR:
609 case OP_REM_INT_2ADDR:
610 case OP_AND_INT_2ADDR:
611 case OP_OR_INT_2ADDR:
612 case OP_XOR_INT_2ADDR:
613 case OP_SHL_INT_2ADDR:
614 case OP_SHR_INT_2ADDR:
615 case OP_USHR_INT_2ADDR:
616 genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
617 break;
618
619 case OP_ADD_LONG:
620 case OP_SUB_LONG:
621 case OP_MUL_LONG:
622 case OP_DIV_LONG:
623 case OP_REM_LONG:
624 case OP_AND_LONG:
625 case OP_OR_LONG:
626 case OP_XOR_LONG:
627 case OP_ADD_LONG_2ADDR:
628 case OP_SUB_LONG_2ADDR:
629 case OP_MUL_LONG_2ADDR:
630 case OP_DIV_LONG_2ADDR:
631 case OP_REM_LONG_2ADDR:
632 case OP_AND_LONG_2ADDR:
633 case OP_OR_LONG_2ADDR:
634 case OP_XOR_LONG_2ADDR:
635 genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
636 break;
637
638 case OP_SHL_LONG:
639 case OP_SHR_LONG:
640 case OP_USHR_LONG:
641 case OP_SHL_LONG_2ADDR:
642 case OP_SHR_LONG_2ADDR:
643 case OP_USHR_LONG_2ADDR:
644 genShiftOpLong(cUnit,mir, rlDest, rlSrc[0], rlSrc[1]);
645 break;
646
647 case OP_ADD_FLOAT:
648 case OP_SUB_FLOAT:
649 case OP_MUL_FLOAT:
650 case OP_DIV_FLOAT:
651 case OP_REM_FLOAT:
652 case OP_ADD_FLOAT_2ADDR:
653 case OP_SUB_FLOAT_2ADDR:
654 case OP_MUL_FLOAT_2ADDR:
655 case OP_DIV_FLOAT_2ADDR:
656 case OP_REM_FLOAT_2ADDR:
657 genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
658 break;
659
660 case OP_ADD_DOUBLE:
661 case OP_SUB_DOUBLE:
662 case OP_MUL_DOUBLE:
663 case OP_DIV_DOUBLE:
664 case OP_REM_DOUBLE:
665 case OP_ADD_DOUBLE_2ADDR:
666 case OP_SUB_DOUBLE_2ADDR:
667 case OP_MUL_DOUBLE_2ADDR:
668 case OP_DIV_DOUBLE_2ADDR:
669 case OP_REM_DOUBLE_2ADDR:
670 genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
671 break;
672
673 case OP_RSUB_INT:
674 case OP_ADD_INT_LIT16:
675 case OP_MUL_INT_LIT16:
676 case OP_DIV_INT_LIT16:
677 case OP_REM_INT_LIT16:
678 case OP_AND_INT_LIT16:
679 case OP_OR_INT_LIT16:
680 case OP_XOR_INT_LIT16:
681 case OP_ADD_INT_LIT8:
682 case OP_RSUB_INT_LIT8:
683 case OP_MUL_INT_LIT8:
684 case OP_DIV_INT_LIT8:
685 case OP_REM_INT_LIT8:
686 case OP_AND_INT_LIT8:
687 case OP_OR_INT_LIT8:
688 case OP_XOR_INT_LIT8:
689 case OP_SHL_INT_LIT8:
690 case OP_SHR_INT_LIT8:
691 case OP_USHR_INT_LIT8:
692 genArithOpIntLit(cUnit, mir, rlDest, rlSrc[0], mir->dalvikInsn.vC);
693 break;
694
695 default:
696 res = true;
697 }
698 return res;
699}
700
buzbee31a4a6f2012-02-28 15:36:15 -0800701const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
buzbeee3acd072012-02-25 17:03:10 -0800702 "kMirOpPhi",
703 "kMirOpNullNRangeUpCheck",
704 "kMirOpNullNRangeDownCheck",
705 "kMirOpLowerBound",
706 "kMirOpPunt",
707 "kMirOpCheckInlinePrediction",
708};
709
710/* Extended MIR instructions like PHI */
buzbee31a4a6f2012-02-28 15:36:15 -0800711void handleExtendedMethodMIR(CompilationUnit* cUnit, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800712{
713 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
714 char* msg = NULL;
715 if (cUnit->printMe) {
716 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
717 false, kAllocDebugInfo);
718 strcpy(msg, extendedMIROpNames[opOffset]);
719 }
buzbee31a4a6f2012-02-28 15:36:15 -0800720 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800721
722 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
723 case kMirOpPhi: {
724 char* ssaString = NULL;
725 if (cUnit->printMe) {
726 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
727 }
728 op->flags.isNop = true;
buzbee31a4a6f2012-02-28 15:36:15 -0800729 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
buzbeee3acd072012-02-25 17:03:10 -0800730 break;
731 }
732 default:
733 break;
734 }
735}
736
737/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800738bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800739{
740 MIR* mir;
buzbee31a4a6f2012-02-28 15:36:15 -0800741 LIR* labelList = (LIR*) cUnit->blockLabelList;
buzbeee3acd072012-02-25 17:03:10 -0800742 int blockId = bb->id;
743
744 cUnit->curBlock = bb;
745 labelList[blockId].operands[0] = bb->startOffset;
746
747 /* Insert the block label */
buzbee31a4a6f2012-02-28 15:36:15 -0800748 labelList[blockId].opcode = kPseudoNormalBlockLabel;
buzbeee3acd072012-02-25 17:03:10 -0800749 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
750
751 /* Reset local optimization data on block boundaries */
752 oatResetRegPool(cUnit);
753 oatClobberAllRegs(cUnit);
754 oatResetDefTracking(cUnit);
755
buzbee31a4a6f2012-02-28 15:36:15 -0800756 LIR* headLIR = NULL;
buzbeee3acd072012-02-25 17:03:10 -0800757
758 if (bb->blockType == kEntryBlock) {
759 genEntrySequence(cUnit, bb);
760 } else if (bb->blockType == kExitBlock) {
761 genExitSequence(cUnit, bb);
762 }
763
764 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
765
766 oatResetRegPool(cUnit);
767 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
768 oatClobberAllRegs(cUnit);
769 }
770
771 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
772 oatResetDefTracking(cUnit);
773 }
774
775 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
776 handleExtendedMethodMIR(cUnit, mir);
777 continue;
778 }
779
780 cUnit->currentDalvikOffset = mir->offset;
781
782 Opcode dalvikOpcode = mir->dalvikInsn.opcode;
783 InstructionFormat dalvikFormat =
784 dexGetFormatFromOpcode(dalvikOpcode);
785
buzbee31a4a6f2012-02-28 15:36:15 -0800786 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800787
788 /* Mark the beginning of a Dalvik instruction for line tracking */
789 char* instStr = cUnit->printMe ?
790 oatGetDalvikDisassembly(cUnit, &mir->dalvikInsn, "") : NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800791 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
buzbeee3acd072012-02-25 17:03:10 -0800792 (intptr_t) instStr);
793 cUnit->boundaryMap.insert(std::make_pair(mir->offset,
794 (LIR*)boundaryLIR));
795 /* Remember the first LIR for this block */
796 if (headLIR == NULL) {
797 headLIR = boundaryLIR;
798 /* Set the first boundaryLIR as a scheduling barrier */
799 headLIR->defMask = ENCODE_ALL;
800 }
801
802 /* If we're compiling for the debugger, generate an update callout */
803 if (cUnit->genDebugger) {
804 genDebuggerUpdate(cUnit, mir->offset);
805 }
806
807 /* Don't generate the SSA annotation unless verbose mode is on */
808 if (cUnit->printMe && mir->ssaRep) {
809 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
buzbee31a4a6f2012-02-28 15:36:15 -0800810 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
buzbeee3acd072012-02-25 17:03:10 -0800811 }
812
813 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
814
815 if (notHandled) {
816 char buf[100];
817 snprintf(buf, 100, "%#06x: Opcode %#x (%s) / Fmt %d not handled",
818 mir->offset,
819 dalvikOpcode, dexGetOpcodeName(dalvikOpcode),
820 dalvikFormat);
821 LOG(FATAL) << buf;
822 }
823 }
824
825 if (headLIR) {
826 /*
827 * Eliminate redundant loads/stores and delay stores into later
828 * slots
829 */
830 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR,
831 cUnit->lastLIRInsn);
832
833 /*
834 * Generate an unconditional branch to the fallthrough block.
835 */
836 if (bb->fallThrough) {
buzbee82488f52012-03-02 08:20:26 -0800837 opUnconditionalBranch(cUnit,
838 &labelList[bb->fallThrough->id]);
buzbeee3acd072012-02-25 17:03:10 -0800839 }
840 }
841 return false;
842}
843
844void oatMethodMIR2LIR(CompilationUnit* cUnit)
845{
846 /* Used to hold the labels of each block */
847 cUnit->blockLabelList =
buzbee31a4a6f2012-02-28 15:36:15 -0800848 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true,
buzbeee3acd072012-02-25 17:03:10 -0800849 kAllocLIR);
850
851 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
852 kPreOrderDFSTraversal, false /* Iterative */);
853 handleSuspendLaunchpads(cUnit);
854
855 handleThrowLaunchpads(cUnit);
856
857 removeRedundantBranches(cUnit);
858}
859
860/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -0800861LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -0800862{
buzbee82488f52012-03-02 08:20:26 -0800863 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -0800864}
865
866/* Needed by the register allocator */
867void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
868{
buzbee82488f52012-03-02 08:20:26 -0800869 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -0800870}
871
872/* Needed by the register allocator */
873void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
874 int srcLo, int srcHi)
875{
buzbee82488f52012-03-02 08:20:26 -0800876 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -0800877}
878
879void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
880 int displacement, int rSrc, OpSize size)
881{
882 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
883}
884
885void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
886 int displacement, int rSrcLo, int rSrcHi)
887{
888 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
889}
890
891} // namespace art