blob: b75b9a88b964dee31fbcef28da43cfa86a41ad8a [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 & \
Bill Buzbeea114add2012-05-03 15:00:40 -070022 (1 << kDebugDisplayMissingTargets))
buzbeee3acd072012-02-25 17:03:10 -080023
buzbeebff24652012-05-06 16:22:05 -070024const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0,
buzbee31a4a6f2012-02-28 15:36:15 -080025 INVALID_REG, INVALID_REG, INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080026
27/* Mark register usage state and return long retloc */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070028RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080029{
Bill Buzbeea114add2012-05-03 15:00:40 -070030 RegLocation gpr_res = LOC_C_RETURN_WIDE;
31 RegLocation fpr_res = LOC_C_RETURN_WIDE_DOUBLE;
32 RegLocation res = isDouble ? fpr_res : gpr_res;
33 oatClobber(cUnit, res.lowReg);
34 oatClobber(cUnit, res.highReg);
35 oatLockTemp(cUnit, res.lowReg);
36 oatLockTemp(cUnit, res.highReg);
37 oatMarkPair(cUnit, res.lowReg, res.highReg);
38 return res;
buzbeee3acd072012-02-25 17:03:10 -080039}
40
Ian Rogersf7d9ad32012-03-13 18:45:39 -070041RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
buzbeee3acd072012-02-25 17:03:10 -080042{
Ian Rogersf7d9ad32012-03-13 18:45:39 -070043 RegLocation gpr_res = LOC_C_RETURN;
44 RegLocation fpr_res = LOC_C_RETURN_FLOAT;
45 RegLocation res = isFloat ? fpr_res : gpr_res;
Bill Buzbeea114add2012-05-03 15:00:40 -070046 oatClobber(cUnit, res.lowReg);
47 if (cUnit->instructionSet == kMips) {
48 oatMarkInUse(cUnit, res.lowReg);
49 } else {
50 oatLockTemp(cUnit, res.lowReg);
51 }
52 return res;
buzbeee3acd072012-02-25 17:03:10 -080053}
54
buzbeefc9e6fa2012-03-23 15:14:29 -070055void genInvoke(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
56 InvokeType type, bool isRange)
buzbeee3acd072012-02-25 17:03:10 -080057{
Bill Buzbeea114add2012-05-03 15:00:40 -070058 if (genIntrinsic(cUnit, bb, mir, type, isRange)) {
59 return;
60 }
61 DecodedInstruction* dInsn = &mir->dalvikInsn;
62 InvokeType originalType = type; // avoiding mutation by ComputeInvokeInfo
63 int callState = 0;
64 LIR* nullCk;
65 LIR** pNullCk = NULL;
66 NextCallInsn nextCallInsn;
67 oatFlushAllRegs(cUnit); /* Everything to home location */
68 // Explicit register usage
69 oatLockCallTemps(cUnit);
buzbeee3acd072012-02-25 17:03:10 -080070
Bill Buzbeea114add2012-05-03 15:00:40 -070071 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
72 *cUnit->dex_file, *cUnit->dex_cache,
73 cUnit->code_item, cUnit->method_idx,
74 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080075
Bill Buzbeea114add2012-05-03 15:00:40 -070076 uint32_t dexMethodIdx = dInsn->vB;
77 int vtableIdx;
78 uintptr_t directCode;
79 uintptr_t directMethod;
80 bool skipThis;
81 bool fastPath =
82 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, type,
83 vtableIdx, directCode,
84 directMethod)
85 && !SLOW_INVOKE_PATH;
86 if (type == kInterface) {
87 nextCallInsn = fastPath ? nextInterfaceCallInsn
88 : nextInterfaceCallInsnWithAccessCheck;
89 skipThis = false;
90 } else if (type == kDirect) {
91 if (fastPath) {
92 pNullCk = &nullCk;
buzbeee3acd072012-02-25 17:03:10 -080093 }
Bill Buzbeea114add2012-05-03 15:00:40 -070094 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
95 skipThis = false;
96 } else if (type == kStatic) {
97 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
98 skipThis = false;
99 } else if (type == kSuper) {
100 DCHECK(!fastPath); // Fast path is a direct call.
101 nextCallInsn = nextSuperCallInsnSP;
102 skipThis = false;
103 } else {
104 DCHECK_EQ(type, kVirtual);
105 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
106 skipThis = fastPath;
107 }
108 if (!isRange) {
109 callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk,
110 nextCallInsn, dexMethodIdx,
111 vtableIdx, directCode, directMethod,
112 originalType, skipThis);
113 } else {
114 callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
115 nextCallInsn, dexMethodIdx, vtableIdx,
116 directCode, directMethod, originalType,
117 skipThis);
118 }
119 // Finish up any of the call sequence not interleaved in arg loading
120 while (callState >= 0) {
121 callState = nextCallInsn(cUnit, mir, callState, dexMethodIdx,
122 vtableIdx, directCode, directMethod,
123 originalType);
124 }
125 if (DISPLAY_MISSING_TARGETS) {
126 genShowTarget(cUnit);
127 }
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700128#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 opReg(cUnit, kOpBlx, rINVOKE_TGT);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700130#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 if (fastPath && type != kInterface) {
132 opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
133 } else {
134 int trampoline = 0;
135 switch (type) {
136 case kInterface:
137 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
138 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
139 break;
140 case kDirect:
141 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
142 break;
143 case kStatic:
144 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
145 break;
146 case kSuper:
147 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
148 break;
149 case kVirtual:
150 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
151 break;
152 default:
153 LOG(FATAL) << "Unexpected invoke type";
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700154 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 opThreadMem(cUnit, kOpBlx, trampoline);
156 }
buzbeea7678db2012-03-05 15:35:46 -0800157#endif
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700158
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 oatClobberCalleeSave(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800160}
161
162/*
163 * Target-independent code generation. Use only high-level
164 * load/store utilities here, or target-dependent genXX() handlers
165 * when necessary.
166 */
buzbee31a4a6f2012-02-28 15:36:15 -0800167bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
168 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800169{
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 bool res = false; // Assume success
171 RegLocation rlSrc[3];
172 RegLocation rlDest = badLoc;
173 RegLocation rlResult = badLoc;
174 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbeee3acd072012-02-25 17:03:10 -0800175
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 /* Prep Src and Dest locations */
177 int nextSreg = 0;
178 int nextLoc = 0;
179 int attrs = oatDataFlowAttributes[opcode];
180 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
181 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700182 if (attrs & DF_A_WIDE) {
183 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
184 nextSreg+= 2;
185 } else {
186 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
187 nextSreg++;
188 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700189 }
190 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700191 if (attrs & DF_B_WIDE) {
192 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
193 nextSreg+= 2;
194 } else {
195 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
196 nextSreg++;
197 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700198 }
199 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700200 if (attrs & DF_C_WIDE) {
201 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
202 } else {
203 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
204 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 }
206 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700207 if (attrs & DF_A_WIDE) {
208 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
209 } else {
210 rlDest = oatGetDest(cUnit, mir, 0);
211 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700213 switch (opcode) {
214 case Instruction::NOP:
215 break;
buzbeee3acd072012-02-25 17:03:10 -0800216
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 case Instruction::MOVE_EXCEPTION: {
218 int exOffset = Thread::ExceptionOffset().Int32Value();
219 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700220#if defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700221 newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset);
222 newLIR2(cUnit, kX86Mov32TI, exOffset, 0);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700223#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 int resetReg = oatAllocTemp(cUnit);
225 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
226 loadConstant(cUnit, resetReg, 0);
227 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
228 storeValue(cUnit, rlDest, rlResult);
229 oatFreeTemp(cUnit, resetReg);
buzbeea7678db2012-03-05 15:35:46 -0800230#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 break;
buzbeee3acd072012-02-25 17:03:10 -0800232 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 case Instruction::RETURN_VOID:
234 if (!cUnit->attrs & METHOD_IS_LEAF) {
235 genSuspendTest(cUnit, mir);
236 }
237 break;
238
239 case Instruction::RETURN:
240 case Instruction::RETURN_OBJECT:
241 if (!cUnit->attrs & METHOD_IS_LEAF) {
242 genSuspendTest(cUnit, mir);
243 }
244 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
245 break;
246
247 case Instruction::RETURN_WIDE:
248 if (!cUnit->attrs & METHOD_IS_LEAF) {
249 genSuspendTest(cUnit, mir);
250 }
251 storeValueWide(cUnit, oatGetReturnWide(cUnit,
252 cUnit->shorty[0] == 'D'), rlSrc[0]);
253 break;
254
255 case Instruction::MOVE_RESULT_WIDE:
256 if (mir->optimizationFlags & MIR_INLINED)
257 break; // Nop - combined w/ previous invoke
258 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
259 break;
260
261 case Instruction::MOVE_RESULT:
262 case Instruction::MOVE_RESULT_OBJECT:
263 if (mir->optimizationFlags & MIR_INLINED)
264 break; // Nop - combined w/ previous invoke
265 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
266 break;
267
268 case Instruction::MOVE:
269 case Instruction::MOVE_OBJECT:
270 case Instruction::MOVE_16:
271 case Instruction::MOVE_OBJECT_16:
272 case Instruction::MOVE_FROM16:
273 case Instruction::MOVE_OBJECT_FROM16:
274 storeValue(cUnit, rlDest, rlSrc[0]);
275 break;
276
277 case Instruction::MOVE_WIDE:
278 case Instruction::MOVE_WIDE_16:
279 case Instruction::MOVE_WIDE_FROM16:
280 storeValueWide(cUnit, rlDest, rlSrc[0]);
281 break;
282
283 case Instruction::CONST:
284 case Instruction::CONST_4:
285 case Instruction::CONST_16:
286 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
287 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
288 storeValue(cUnit, rlDest, rlResult);
289 break;
290
291 case Instruction::CONST_HIGH16:
292 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
293 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB << 16);
294 storeValue(cUnit, rlDest, rlResult);
295 break;
296
297 case Instruction::CONST_WIDE_16:
298 case Instruction::CONST_WIDE_32:
299 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
300 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
301 mir->dalvikInsn.vB,
302 (mir->dalvikInsn.vB & 0x80000000) ? -1 : 0);
303 storeValueWide(cUnit, rlDest, rlResult);
304 break;
305
306 case Instruction::CONST_WIDE:
307 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
308 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
309 mir->dalvikInsn.vB_wide & 0xffffffff,
310 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
311 storeValueWide(cUnit, rlDest, rlResult);
312 break;
313
314 case Instruction::CONST_WIDE_HIGH16:
315 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
316 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
317 0, mir->dalvikInsn.vB << 16);
318 storeValueWide(cUnit, rlDest, rlResult);
319 break;
320
321 case Instruction::MONITOR_ENTER:
322 genMonitorEnter(cUnit, mir, rlSrc[0]);
323 break;
324
325 case Instruction::MONITOR_EXIT:
326 genMonitorExit(cUnit, mir, rlSrc[0]);
327 break;
328
329 case Instruction::CHECK_CAST:
330 genCheckCast(cUnit, mir, rlSrc[0]);
331 break;
332
333 case Instruction::INSTANCE_OF:
334 genInstanceof(cUnit, mir, rlDest, rlSrc[0]);
335 break;
336
337 case Instruction::NEW_INSTANCE:
338 genNewInstance(cUnit, mir, rlDest);
339 break;
340
341 case Instruction::THROW:
342 genThrow(cUnit, mir, rlSrc[0]);
343 break;
344
345 case Instruction::THROW_VERIFICATION_ERROR:
346 genThrowVerificationError(cUnit, mir);
347 break;
348
349 case Instruction::ARRAY_LENGTH:
350 int lenOffset;
351 lenOffset = Array::LengthOffset().Int32Value();
352 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
353 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, mir);
354 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
355 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
356 storeValue(cUnit, rlDest, rlResult);
357 break;
358
359 case Instruction::CONST_STRING:
360 case Instruction::CONST_STRING_JUMBO:
361 genConstString(cUnit, mir, rlDest, rlSrc[0]);
362 break;
363
364 case Instruction::CONST_CLASS:
365 genConstClass(cUnit, mir, rlDest, rlSrc[0]);
366 break;
367
368 case Instruction::FILL_ARRAY_DATA:
369 genFillArrayData(cUnit, mir, rlSrc[0]);
370 break;
371
372 case Instruction::FILLED_NEW_ARRAY:
373 genFilledNewArray(cUnit, mir, false /* not range */);
374 break;
375
376 case Instruction::FILLED_NEW_ARRAY_RANGE:
377 genFilledNewArray(cUnit, mir, true /* range */);
378 break;
379
380 case Instruction::NEW_ARRAY:
381 genNewArray(cUnit, mir, rlDest, rlSrc[0]);
382 break;
383
384 case Instruction::GOTO:
385 case Instruction::GOTO_16:
386 case Instruction::GOTO_32:
387 if (bb->taken->startOffset <= mir->offset) {
388 genSuspendTestAndBranch(cUnit, mir, &labelList[bb->taken->id]);
389 } else {
390 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
391 }
392 break;
393
394 case Instruction::PACKED_SWITCH:
395 genPackedSwitch(cUnit, mir, rlSrc[0]);
396 break;
397
398 case Instruction::SPARSE_SWITCH:
399 genSparseSwitch(cUnit, mir, rlSrc[0], labelList);
400 break;
401
402 case Instruction::CMPL_FLOAT:
403 case Instruction::CMPG_FLOAT:
404 case Instruction::CMPL_DOUBLE:
405 case Instruction::CMPG_DOUBLE:
406 res = genCmpFP(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
407 break;
408
409 case Instruction::CMP_LONG:
410 genCmpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
411 break;
412
413 case Instruction::IF_EQ:
414 case Instruction::IF_NE:
415 case Instruction::IF_LT:
416 case Instruction::IF_GE:
417 case Instruction::IF_GT:
418 case Instruction::IF_LE: {
419 bool backwardBranch;
420 backwardBranch = (bb->taken->startOffset <= mir->offset);
421 if (backwardBranch) {
422 genSuspendTest(cUnit, mir);
423 }
424 genCompareAndBranch(cUnit, bb, mir, rlSrc[0], rlSrc[1], labelList);
425 break;
426 }
427
428 case Instruction::IF_EQZ:
429 case Instruction::IF_NEZ:
430 case Instruction::IF_LTZ:
431 case Instruction::IF_GEZ:
432 case Instruction::IF_GTZ:
433 case Instruction::IF_LEZ: {
434 bool backwardBranch;
435 backwardBranch = (bb->taken->startOffset <= mir->offset);
436 if (backwardBranch) {
437 genSuspendTest(cUnit, mir);
438 }
439 genCompareZeroAndBranch(cUnit, bb, mir, rlSrc[0], labelList);
440 break;
441 }
442
443 case Instruction::AGET_WIDE:
444 genArrayGet(cUnit, mir, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
445 break;
446 case Instruction::AGET:
447 case Instruction::AGET_OBJECT:
448 genArrayGet(cUnit, mir, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
449 break;
450 case Instruction::AGET_BOOLEAN:
451 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
452 break;
453 case Instruction::AGET_BYTE:
454 genArrayGet(cUnit, mir, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
455 break;
456 case Instruction::AGET_CHAR:
457 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
458 break;
459 case Instruction::AGET_SHORT:
460 genArrayGet(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
461 break;
462 case Instruction::APUT_WIDE:
463 genArrayPut(cUnit, mir, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
464 break;
465 case Instruction::APUT:
466 genArrayPut(cUnit, mir, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
467 break;
468 case Instruction::APUT_OBJECT:
469 genArrayObjPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2);
470 break;
471 case Instruction::APUT_SHORT:
472 case Instruction::APUT_CHAR:
473 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
474 break;
475 case Instruction::APUT_BYTE:
476 case Instruction::APUT_BOOLEAN:
477 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc[1], rlSrc[2],
478 rlSrc[0], 0);
479 break;
480
481 case Instruction::IGET_OBJECT:
482 //case Instruction::IGET_OBJECT_VOLATILE:
483 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, true);
484 break;
485
486 case Instruction::IGET_WIDE:
487 //case Instruction::IGET_WIDE_VOLATILE:
488 genIGet(cUnit, mir, kLong, rlDest, rlSrc[0], true, false);
489 break;
490
491 case Instruction::IGET:
492 //case Instruction::IGET_VOLATILE:
493 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, false);
494 break;
495
496 case Instruction::IGET_CHAR:
497 genIGet(cUnit, mir, kUnsignedHalf, rlDest, rlSrc[0], false, false);
498 break;
499
500 case Instruction::IGET_SHORT:
501 genIGet(cUnit, mir, kSignedHalf, rlDest, rlSrc[0], false, false);
502 break;
503
504 case Instruction::IGET_BOOLEAN:
505 case Instruction::IGET_BYTE:
506 genIGet(cUnit, mir, kUnsignedByte, rlDest, rlSrc[0], false, false);
507 break;
508
509 case Instruction::IPUT_WIDE:
510 //case Instruction::IPUT_WIDE_VOLATILE:
511 genIPut(cUnit, mir, kLong, rlSrc[0], rlSrc[1], true, false);
512 break;
513
514 case Instruction::IPUT_OBJECT:
515 //case Instruction::IPUT_OBJECT_VOLATILE:
516 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, true);
517 break;
518
519 case Instruction::IPUT:
520 //case Instruction::IPUT_VOLATILE:
521 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, false);
522 break;
523
524 case Instruction::IPUT_BOOLEAN:
525 case Instruction::IPUT_BYTE:
526 genIPut(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
527 break;
528
529 case Instruction::IPUT_CHAR:
530 genIPut(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
531 break;
532
533 case Instruction::IPUT_SHORT:
534 genIPut(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
535 break;
536
537 case Instruction::SGET_OBJECT:
538 genSget(cUnit, mir, rlDest, false, true);
539 break;
540 case Instruction::SGET:
541 case Instruction::SGET_BOOLEAN:
542 case Instruction::SGET_BYTE:
543 case Instruction::SGET_CHAR:
544 case Instruction::SGET_SHORT:
545 genSget(cUnit, mir, rlDest, false, false);
546 break;
547
548 case Instruction::SGET_WIDE:
549 genSget(cUnit, mir, rlDest, true, false);
550 break;
551
552 case Instruction::SPUT_OBJECT:
553 genSput(cUnit, mir, rlSrc[0], false, true);
554 break;
555
556 case Instruction::SPUT:
557 case Instruction::SPUT_BOOLEAN:
558 case Instruction::SPUT_BYTE:
559 case Instruction::SPUT_CHAR:
560 case Instruction::SPUT_SHORT:
561 genSput(cUnit, mir, rlSrc[0], false, false);
562 break;
563
564 case Instruction::SPUT_WIDE:
565 genSput(cUnit, mir, rlSrc[0], true, false);
566 break;
567
568 case Instruction::INVOKE_STATIC_RANGE:
569 genInvoke(cUnit, bb, mir, kStatic, true /*range*/);
570 break;
571 case Instruction::INVOKE_STATIC:
572 genInvoke(cUnit, bb, mir, kStatic, false /*range*/);
573 break;
574
575 case Instruction::INVOKE_DIRECT:
576 genInvoke(cUnit, bb, mir, kDirect, false /*range*/);
577 break;
578 case Instruction::INVOKE_DIRECT_RANGE:
579 genInvoke(cUnit, bb, mir, kDirect, true /*range*/);
580 break;
581
582 case Instruction::INVOKE_VIRTUAL:
583 genInvoke(cUnit, bb, mir, kVirtual, false /*range*/);
584 break;
585 case Instruction::INVOKE_VIRTUAL_RANGE:
586 genInvoke(cUnit, bb, mir, kVirtual, true /*range*/);
587 break;
588
589 case Instruction::INVOKE_SUPER:
590 genInvoke(cUnit, bb, mir, kSuper, false /*range*/);
591 break;
592 case Instruction::INVOKE_SUPER_RANGE:
593 genInvoke(cUnit, bb, mir, kSuper, true /*range*/);
594 break;
595
596 case Instruction::INVOKE_INTERFACE:
597 genInvoke(cUnit, bb, mir, kInterface, false /*range*/);
598 break;
599 case Instruction::INVOKE_INTERFACE_RANGE:
600 genInvoke(cUnit, bb, mir, kInterface, true /*range*/);
601 break;
602
603 case Instruction::NEG_INT:
604 case Instruction::NOT_INT:
605 res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
606 break;
607
608 case Instruction::NEG_LONG:
609 case Instruction::NOT_LONG:
610 res = genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
611 break;
612
613 case Instruction::NEG_FLOAT:
614 res = genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
615 break;
616
617 case Instruction::NEG_DOUBLE:
618 res = genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
619 break;
620
621 case Instruction::INT_TO_LONG:
622 genIntToLong(cUnit, mir, rlDest, rlSrc[0]);
623 break;
624
625 case Instruction::LONG_TO_INT:
626 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
627 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
628 storeValue(cUnit, rlDest, rlSrc[0]);
629 break;
630
631 case Instruction::INT_TO_BYTE:
632 case Instruction::INT_TO_SHORT:
633 case Instruction::INT_TO_CHAR:
634 genIntNarrowing(cUnit, mir, rlDest, rlSrc[0]);
635 break;
636
637 case Instruction::INT_TO_FLOAT:
638 case Instruction::INT_TO_DOUBLE:
639 case Instruction::LONG_TO_FLOAT:
640 case Instruction::LONG_TO_DOUBLE:
641 case Instruction::FLOAT_TO_INT:
642 case Instruction::FLOAT_TO_LONG:
643 case Instruction::FLOAT_TO_DOUBLE:
644 case Instruction::DOUBLE_TO_INT:
645 case Instruction::DOUBLE_TO_LONG:
646 case Instruction::DOUBLE_TO_FLOAT:
647 genConversion(cUnit, mir);
648 break;
649
650 case Instruction::ADD_INT:
651 case Instruction::SUB_INT:
652 case Instruction::MUL_INT:
653 case Instruction::DIV_INT:
654 case Instruction::REM_INT:
655 case Instruction::AND_INT:
656 case Instruction::OR_INT:
657 case Instruction::XOR_INT:
658 case Instruction::SHL_INT:
659 case Instruction::SHR_INT:
660 case Instruction::USHR_INT:
661 case Instruction::ADD_INT_2ADDR:
662 case Instruction::SUB_INT_2ADDR:
663 case Instruction::MUL_INT_2ADDR:
664 case Instruction::DIV_INT_2ADDR:
665 case Instruction::REM_INT_2ADDR:
666 case Instruction::AND_INT_2ADDR:
667 case Instruction::OR_INT_2ADDR:
668 case Instruction::XOR_INT_2ADDR:
669 case Instruction::SHL_INT_2ADDR:
670 case Instruction::SHR_INT_2ADDR:
671 case Instruction::USHR_INT_2ADDR:
672 genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
673 break;
674
675 case Instruction::ADD_LONG:
676 case Instruction::SUB_LONG:
677 case Instruction::MUL_LONG:
678 case Instruction::DIV_LONG:
679 case Instruction::REM_LONG:
680 case Instruction::AND_LONG:
681 case Instruction::OR_LONG:
682 case Instruction::XOR_LONG:
683 case Instruction::ADD_LONG_2ADDR:
684 case Instruction::SUB_LONG_2ADDR:
685 case Instruction::MUL_LONG_2ADDR:
686 case Instruction::DIV_LONG_2ADDR:
687 case Instruction::REM_LONG_2ADDR:
688 case Instruction::AND_LONG_2ADDR:
689 case Instruction::OR_LONG_2ADDR:
690 case Instruction::XOR_LONG_2ADDR:
691 genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
692 break;
693
694 case Instruction::SHL_LONG:
695 case Instruction::SHR_LONG:
696 case Instruction::USHR_LONG:
697 case Instruction::SHL_LONG_2ADDR:
698 case Instruction::SHR_LONG_2ADDR:
699 case Instruction::USHR_LONG_2ADDR:
700 genShiftOpLong(cUnit,mir, rlDest, rlSrc[0], rlSrc[1]);
701 break;
702
703 case Instruction::ADD_FLOAT:
704 case Instruction::SUB_FLOAT:
705 case Instruction::MUL_FLOAT:
706 case Instruction::DIV_FLOAT:
707 case Instruction::REM_FLOAT:
708 case Instruction::ADD_FLOAT_2ADDR:
709 case Instruction::SUB_FLOAT_2ADDR:
710 case Instruction::MUL_FLOAT_2ADDR:
711 case Instruction::DIV_FLOAT_2ADDR:
712 case Instruction::REM_FLOAT_2ADDR:
713 genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
714 break;
715
716 case Instruction::ADD_DOUBLE:
717 case Instruction::SUB_DOUBLE:
718 case Instruction::MUL_DOUBLE:
719 case Instruction::DIV_DOUBLE:
720 case Instruction::REM_DOUBLE:
721 case Instruction::ADD_DOUBLE_2ADDR:
722 case Instruction::SUB_DOUBLE_2ADDR:
723 case Instruction::MUL_DOUBLE_2ADDR:
724 case Instruction::DIV_DOUBLE_2ADDR:
725 case Instruction::REM_DOUBLE_2ADDR:
726 genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
727 break;
728
729 case Instruction::RSUB_INT:
730 case Instruction::ADD_INT_LIT16:
731 case Instruction::MUL_INT_LIT16:
732 case Instruction::DIV_INT_LIT16:
733 case Instruction::REM_INT_LIT16:
734 case Instruction::AND_INT_LIT16:
735 case Instruction::OR_INT_LIT16:
736 case Instruction::XOR_INT_LIT16:
737 case Instruction::ADD_INT_LIT8:
738 case Instruction::RSUB_INT_LIT8:
739 case Instruction::MUL_INT_LIT8:
740 case Instruction::DIV_INT_LIT8:
741 case Instruction::REM_INT_LIT8:
742 case Instruction::AND_INT_LIT8:
743 case Instruction::OR_INT_LIT8:
744 case Instruction::XOR_INT_LIT8:
745 case Instruction::SHL_INT_LIT8:
746 case Instruction::SHR_INT_LIT8:
747 case Instruction::USHR_INT_LIT8:
748 genArithOpIntLit(cUnit, mir, rlDest, rlSrc[0], mir->dalvikInsn.vC);
749 break;
750
751 default:
752 res = true;
753 }
754 return res;
buzbeee3acd072012-02-25 17:03:10 -0800755}
756
buzbee31a4a6f2012-02-28 15:36:15 -0800757const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700758 "kMirOpPhi",
759 "kMirOpCopy",
760 "kMirFusedCmplFloat",
761 "kMirFusedCmpgFloat",
762 "kMirFusedCmplDouble",
763 "kMirFusedCmpgDouble",
764 "kMirFusedCmpLong",
765 "kMirNop",
766 "kMirOpNullNRangeUpCheck",
767 "kMirOpNullNRangeDownCheck",
768 "kMirOpLowerBound",
buzbeee3acd072012-02-25 17:03:10 -0800769};
770
771/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700772void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800773{
Bill Buzbeea114add2012-05-03 15:00:40 -0700774 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
775 char* msg = NULL;
776 if (cUnit->printMe) {
777 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
778 false, kAllocDebugInfo);
779 strcpy(msg, extendedMIROpNames[opOffset]);
780 }
781 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800782
Bill Buzbeea114add2012-05-03 15:00:40 -0700783 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
784 case kMirOpPhi: {
785 char* ssaString = NULL;
786 if (cUnit->printMe) {
787 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
788 }
789 op->flags.isNop = true;
790 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
791 break;
buzbeee3acd072012-02-25 17:03:10 -0800792 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700793 case kMirOpCopy: {
794 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
795 RegLocation rlDest = oatGetDest(cUnit, mir, 0);
796 storeValue(cUnit, rlDest, rlSrc);
797 break;
798 }
799#if defined(TARGET_ARM)
800 case kMirOpFusedCmplFloat:
801 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
802 break;
803 case kMirOpFusedCmpgFloat:
804 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
805 break;
806 case kMirOpFusedCmplDouble:
807 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
808 break;
809 case kMirOpFusedCmpgDouble:
810 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
811 break;
812 case kMirOpFusedCmpLong:
813 genFusedLongCmpBranch(cUnit, bb, mir);
814 break;
815#endif
816 default:
817 break;
818 }
buzbeee3acd072012-02-25 17:03:10 -0800819}
820
821/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800822bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800823{
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 MIR* mir;
825 LIR* labelList = (LIR*) cUnit->blockLabelList;
826 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800827
Bill Buzbeea114add2012-05-03 15:00:40 -0700828 cUnit->curBlock = bb;
829 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800830
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 /* Insert the block label */
832 labelList[blockId].opcode = kPseudoNormalBlockLabel;
833 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800834
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 /* Free temp registers and reset redundant store tracking */
836 oatResetRegPool(cUnit);
837 oatResetDefTracking(cUnit);
838
839 /*
840 * If control reached us from our immediate predecessor via
841 * fallthrough and we have no other incoming arcs we can
842 * reuse existing liveness. Otherwise, reset.
843 */
844 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
845 oatClobberAllRegs(cUnit);
846 }
847
848 LIR* headLIR = NULL;
849
850 if (bb->blockType == kEntryBlock) {
851 genEntrySequence(cUnit, bb);
852 } else if (bb->blockType == kExitBlock) {
853 genExitSequence(cUnit, bb);
854 }
855
856 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
857
buzbeee3acd072012-02-25 17:03:10 -0800858 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
860 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700861 }
862
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
864 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800865 }
866
buzbee3d661942012-03-14 17:37:27 -0700867#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 /* Reset temp tracking sanity check */
869 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700870#endif
871
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 cUnit->currentDalvikOffset = mir->offset;
buzbeee3acd072012-02-25 17:03:10 -0800873
Bill Buzbeea114add2012-05-03 15:00:40 -0700874 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
875 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800876
Bill Buzbeea114add2012-05-03 15:00:40 -0700877 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800878
Bill Buzbeea114add2012-05-03 15:00:40 -0700879 /* Mark the beginning of a Dalvik instruction for line tracking */
880 char* instStr = cUnit->printMe ?
881 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
882 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
883 (intptr_t) instStr);
884 cUnit->boundaryMap.Overwrite(mir->offset, boundaryLIR);
885 /* Remember the first LIR for this block */
886 if (headLIR == NULL) {
887 headLIR = boundaryLIR;
888 /* Set the first boundaryLIR as a scheduling barrier */
889 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800890 }
891
Bill Buzbeea114add2012-05-03 15:00:40 -0700892 /* If we're compiling for the debugger, generate an update callout */
893 if (cUnit->genDebugger) {
894 genDebuggerUpdate(cUnit, mir->offset);
buzbeee3acd072012-02-25 17:03:10 -0800895 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700896
897 /* Don't generate the SSA annotation unless verbose mode is on */
898 if (cUnit->printMe && mir->ssaRep) {
899 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
900 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
901 }
902
903 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
904 handleExtendedMethodMIR(cUnit, bb, mir);
905 continue;
906 }
907
908 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
909 if (notHandled) {
910 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
911 mir->offset, dalvikOpcode,
912 Instruction::Name(dalvikOpcode), dalvikFormat);
913
914 }
915 }
916
917 if (headLIR) {
918 /*
919 * Eliminate redundant loads/stores and delay stores into later
920 * slots
921 */
922 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
923
924 /*
925 * Generate an unconditional branch to the fallthrough block.
926 */
927 if (bb->fallThrough) {
928 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
929 }
930 }
931 return false;
buzbeee3acd072012-02-25 17:03:10 -0800932}
933
buzbee16da88c2012-03-20 10:38:17 -0700934/* Set basic block labels */
935bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
936{
Bill Buzbeea114add2012-05-03 15:00:40 -0700937 LIR* labelList = (LIR*) cUnit->blockLabelList;
938 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700939
Bill Buzbeea114add2012-05-03 15:00:40 -0700940 cUnit->curBlock = bb;
941 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700942
Bill Buzbeea114add2012-05-03 15:00:40 -0700943 /* Insert the block label */
944 labelList[blockId].opcode = kPseudoNormalBlockLabel;
945 return false;
buzbee16da88c2012-03-20 10:38:17 -0700946}
947
948void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
949{
Bill Buzbeea114add2012-05-03 15:00:40 -0700950 /* Find the first DalvikByteCode block */
951 int numReachableBlocks = cUnit->numReachableBlocks;
952 const GrowableList *blockList = &cUnit->blockList;
953 BasicBlock*bb = NULL;
954 for (int idx = 0; idx < numReachableBlocks; idx++) {
955 int dfsIndex = cUnit->dfsOrder.elemList[idx];
956 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
957 if (bb->blockType == kDalvikByteCode) {
958 break;
buzbee16da88c2012-03-20 10:38:17 -0700959 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700960 }
961 if (bb == NULL) {
962 return;
963 }
964 DCHECK_EQ(bb->startOffset, 0);
965 DCHECK(bb->firstMIRInsn != 0);
buzbee16da88c2012-03-20 10:38:17 -0700966
Bill Buzbeea114add2012-05-03 15:00:40 -0700967 /* Get the first instruction */
968 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -0700969
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 /* Free temp registers and reset redundant store tracking */
971 oatResetRegPool(cUnit);
972 oatResetDefTracking(cUnit);
973 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -0700974
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -0700976}
977
buzbeee3acd072012-02-25 17:03:10 -0800978void oatMethodMIR2LIR(CompilationUnit* cUnit)
979{
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 /* Used to hold the labels of each block */
981 cUnit->blockLabelList =
982 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -0800983
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
985 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -0700986
Bill Buzbeea114add2012-05-03 15:00:40 -0700987 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800988
Bill Buzbeea114add2012-05-03 15:00:40 -0700989 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800990
Bill Buzbeea114add2012-05-03 15:00:40 -0700991 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -0700992
Bill Buzbeea114add2012-05-03 15:00:40 -0700993 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
994 removeRedundantBranches(cUnit);
995 }
buzbeee3acd072012-02-25 17:03:10 -0800996}
997
998/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -0800999LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -08001000{
Bill Buzbeea114add2012-05-03 15:00:40 -07001001 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001002}
1003
1004/* Needed by the register allocator */
1005void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
1006{
Bill Buzbeea114add2012-05-03 15:00:40 -07001007 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001008}
1009
1010/* Needed by the register allocator */
1011void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -07001012 int srcLo, int srcHi)
buzbeee3acd072012-02-25 17:03:10 -08001013{
Bill Buzbeea114add2012-05-03 15:00:40 -07001014 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001015}
1016
1017void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001018 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -08001019{
Bill Buzbeea114add2012-05-03 15:00:40 -07001020 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
buzbeee3acd072012-02-25 17:03:10 -08001021}
1022
1023void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -08001025{
Bill Buzbeea114add2012-05-03 15:00:40 -07001026 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
buzbeee3acd072012-02-25 17:03:10 -08001027}
1028
1029} // namespace art