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