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