blob: 5ffe3e44c2bc25d51a75028abe1e038513aa5e9e [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 */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070028RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080029{
Ian Rogersf7d9ad32012-03-13 18:45:39 -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;
buzbee86a4bce2012-03-06 18:15:00 -080033 oatClobber(cUnit, res.lowReg);
34 oatClobber(cUnit, res.highReg);
buzbeee3acd072012-02-25 17:03:10 -080035 oatLockTemp(cUnit, res.lowReg);
36 oatLockTemp(cUnit, res.highReg);
37 oatMarkPair(cUnit, res.lowReg, res.highReg);
38 return res;
39}
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;
buzbee86a4bce2012-03-06 18:15:00 -080046 oatClobber(cUnit, res.lowReg);
Elliott Hughesb3cd1222012-03-09 16:00:38 -080047 if (cUnit->instructionSet == kMips) {
48 oatMarkInUse(cUnit, res.lowReg);
49 } else {
50 oatLockTemp(cUnit, res.lowReg);
51 }
buzbeee3acd072012-02-25 17:03:10 -080052 return res;
53}
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{
buzbeefc9e6fa2012-03-23 15:14:29 -070058 if (genIntrinsic(cUnit, bb, mir, type, isRange)) {
59 return;
60 }
buzbeee3acd072012-02-25 17:03:10 -080061 DecodedInstruction* dInsn = &mir->dalvikInsn;
Brian Carlstromf5822582012-03-19 22:34:31 -070062 InvokeType originalType = type; // avoiding mutation by ComputeInvokeInfo
buzbeee3acd072012-02-25 17:03:10 -080063 int callState = 0;
buzbee31a4a6f2012-02-28 15:36:15 -080064 LIR* nullCk;
65 LIR** pNullCk = NULL;
buzbeee3acd072012-02-25 17:03:10 -080066 NextCallInsn nextCallInsn;
67 oatFlushAllRegs(cUnit); /* Everything to home location */
68 // Explicit register usage
69 oatLockCallTemps(cUnit);
70
Logan Chien4dd96f52012-02-29 01:26:58 +080071 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
buzbee31a4a6f2012-02-28 15:36:15 -080072 *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
buzbeee3acd072012-02-25 17:03:10 -080076 uint32_t dexMethodIdx = dInsn->vB;
77 int vtableIdx;
Ian Rogers2ed3b952012-03-17 11:49:39 -070078 uintptr_t directCode;
79 uintptr_t directMethod;
buzbeee3acd072012-02-25 17:03:10 -080080 bool skipThis;
81 bool fastPath =
Logan Chien4dd96f52012-02-29 01:26:58 +080082 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, type,
Ian Rogers2ed3b952012-03-17 11:49:39 -070083 vtableIdx, directCode,
84 directMethod)
buzbeee3acd072012-02-25 17:03:10 -080085 && !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;
93 }
94 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) {
Ian Rogers2ed3b952012-03-17 11:49:39 -0700100 DCHECK(!fastPath); // Fast path is a direct call.
101 nextCallInsn = nextSuperCallInsnSP;
102 skipThis = false;
buzbeee3acd072012-02-25 17:03:10 -0800103 } 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,
Brian Carlstromf5822582012-03-19 22:34:31 -0700111 vtableIdx, directCode, directMethod,
112 originalType, skipThis);
buzbeee3acd072012-02-25 17:03:10 -0800113 } else {
114 callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
115 nextCallInsn, dexMethodIdx, vtableIdx,
Brian Carlstromf5822582012-03-19 22:34:31 -0700116 directCode, directMethod, originalType,
117 skipThis);
buzbeee3acd072012-02-25 17:03:10 -0800118 }
119 // Finish up any of the call sequence not interleaved in arg loading
120 while (callState >= 0) {
121 callState = nextCallInsn(cUnit, mir, callState, dexMethodIdx,
Brian Carlstromf5822582012-03-19 22:34:31 -0700122 vtableIdx, directCode, directMethod,
123 originalType);
buzbeee3acd072012-02-25 17:03:10 -0800124 }
125 if (DISPLAY_MISSING_TARGETS) {
126 genShowTarget(cUnit);
127 }
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700128#if !defined(TARGET_X86)
buzbee0398c422012-03-02 15:22:47 -0800129 opReg(cUnit, kOpBlx, rINVOKE_TGT);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700130#else
131 if (fastPath) {
132 opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
133 } else {
134 UNIMPLEMENTED(FATAL) << "compute trampoline";
135 opThreadMem(cUnit, kOpBlx, 0);
136 }
buzbeea7678db2012-03-05 15:35:46 -0800137#endif
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700138
139 oatClobberCalleeSave(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800140}
141
142/*
143 * Target-independent code generation. Use only high-level
144 * load/store utilities here, or target-dependent genXX() handlers
145 * when necessary.
146 */
buzbee31a4a6f2012-02-28 15:36:15 -0800147bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
148 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800149{
150 bool res = false; // Assume success
151 RegLocation rlSrc[3];
152 RegLocation rlDest = badLoc;
153 RegLocation rlResult = badLoc;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800154 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbeee3acd072012-02-25 17:03:10 -0800155
156 /* Prep Src and Dest locations */
157 int nextSreg = 0;
158 int nextLoc = 0;
159 int attrs = oatDataFlowAttributes[opcode];
160 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
161 if (attrs & DF_UA) {
162 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
163 nextSreg++;
164 } else if (attrs & DF_UA_WIDE) {
165 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
166 nextSreg + 1);
167 nextSreg+= 2;
168 }
169 if (attrs & DF_UB) {
170 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
171 nextSreg++;
172 } else if (attrs & DF_UB_WIDE) {
173 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
174 nextSreg + 1);
175 nextSreg+= 2;
176 }
177 if (attrs & DF_UC) {
178 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
179 } else if (attrs & DF_UC_WIDE) {
180 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
181 nextSreg + 1);
182 }
183 if (attrs & DF_DA) {
184 rlDest = oatGetDest(cUnit, mir, 0);
185 } else if (attrs & DF_DA_WIDE) {
186 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
187 }
188
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700189 switch (opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800190 case Instruction::NOP:
buzbeee3acd072012-02-25 17:03:10 -0800191 break;
192
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700193 case Instruction::MOVE_EXCEPTION: {
194 int exOffset = Thread::ExceptionOffset().Int32Value();
buzbeee3acd072012-02-25 17:03:10 -0800195 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700196#if defined(TARGET_X86)
197 newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset);
198 newLIR2(cUnit, kX86Mov32TI, exOffset, 0);
199#else
200 int resetReg = oatAllocTemp(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800201 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
202 loadConstant(cUnit, resetReg, 0);
203 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
204 storeValue(cUnit, rlDest, rlResult);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700205 oatFreeTemp(cUnit, resetReg);
buzbeea7678db2012-03-05 15:35:46 -0800206#endif
buzbeee3acd072012-02-25 17:03:10 -0800207 break;
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700208 }
Elliott Hughesadb8c672012-03-06 16:49:32 -0800209 case Instruction::RETURN_VOID:
buzbee86a4bce2012-03-06 18:15:00 -0800210 if (!cUnit->attrs & METHOD_IS_LEAF) {
211 genSuspendTest(cUnit, mir);
212 }
buzbeee3acd072012-02-25 17:03:10 -0800213 break;
214
Elliott Hughesadb8c672012-03-06 16:49:32 -0800215 case Instruction::RETURN:
216 case Instruction::RETURN_OBJECT:
buzbee86a4bce2012-03-06 18:15:00 -0800217 if (!cUnit->attrs & METHOD_IS_LEAF) {
218 genSuspendTest(cUnit, mir);
219 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700220 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'),
221 rlSrc[0]);
buzbeee3acd072012-02-25 17:03:10 -0800222 break;
223
Elliott Hughesadb8c672012-03-06 16:49:32 -0800224 case Instruction::RETURN_WIDE:
buzbee86a4bce2012-03-06 18:15:00 -0800225 if (!cUnit->attrs & METHOD_IS_LEAF) {
226 genSuspendTest(cUnit, mir);
227 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700228 storeValueWide(cUnit, oatGetReturnWide(cUnit,
229 cUnit->shorty[0] == 'D'), rlSrc[0]);
buzbeee3acd072012-02-25 17:03:10 -0800230 break;
231
Elliott Hughesadb8c672012-03-06 16:49:32 -0800232 case Instruction::MOVE_RESULT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800233 if (mir->optimizationFlags & MIR_INLINED)
234 break; // Nop - combined w/ previous invoke
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700235 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
buzbeee3acd072012-02-25 17:03:10 -0800236 break;
237
Elliott Hughesadb8c672012-03-06 16:49:32 -0800238 case Instruction::MOVE_RESULT:
239 case Instruction::MOVE_RESULT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800240 if (mir->optimizationFlags & MIR_INLINED)
241 break; // Nop - combined w/ previous invoke
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700242 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
buzbeee3acd072012-02-25 17:03:10 -0800243 break;
244
Elliott Hughesadb8c672012-03-06 16:49:32 -0800245 case Instruction::MOVE:
246 case Instruction::MOVE_OBJECT:
247 case Instruction::MOVE_16:
248 case Instruction::MOVE_OBJECT_16:
249 case Instruction::MOVE_FROM16:
250 case Instruction::MOVE_OBJECT_FROM16:
buzbeee3acd072012-02-25 17:03:10 -0800251 storeValue(cUnit, rlDest, rlSrc[0]);
252 break;
253
Elliott Hughesadb8c672012-03-06 16:49:32 -0800254 case Instruction::MOVE_WIDE:
255 case Instruction::MOVE_WIDE_16:
256 case Instruction::MOVE_WIDE_FROM16:
buzbeee3acd072012-02-25 17:03:10 -0800257 storeValueWide(cUnit, rlDest, rlSrc[0]);
258 break;
259
Elliott Hughesadb8c672012-03-06 16:49:32 -0800260 case Instruction::CONST:
261 case Instruction::CONST_4:
262 case Instruction::CONST_16:
buzbeee3acd072012-02-25 17:03:10 -0800263 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
264 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
265 storeValue(cUnit, rlDest, rlResult);
266 break;
267
Elliott Hughesadb8c672012-03-06 16:49:32 -0800268 case Instruction::CONST_HIGH16:
buzbeee3acd072012-02-25 17:03:10 -0800269 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
270 loadConstantNoClobber(cUnit, rlResult.lowReg,
271 mir->dalvikInsn.vB << 16);
272 storeValue(cUnit, rlDest, rlResult);
273 break;
274
Elliott Hughesadb8c672012-03-06 16:49:32 -0800275 case Instruction::CONST_WIDE_16:
276 case Instruction::CONST_WIDE_32:
buzbeee3acd072012-02-25 17:03:10 -0800277 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
278 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
279 mir->dalvikInsn.vB,
280 (mir->dalvikInsn.vB & 0x80000000) ? -1 : 0);
281 storeValueWide(cUnit, rlDest, rlResult);
282 break;
283
Elliott Hughesadb8c672012-03-06 16:49:32 -0800284 case Instruction::CONST_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800285 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
286 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
287 mir->dalvikInsn.vB_wide & 0xffffffff,
288 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
289 storeValueWide(cUnit, rlDest, rlResult);
290 break;
291
Elliott Hughesadb8c672012-03-06 16:49:32 -0800292 case Instruction::CONST_WIDE_HIGH16:
buzbeee3acd072012-02-25 17:03:10 -0800293 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
294 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
295 0, mir->dalvikInsn.vB << 16);
296 storeValueWide(cUnit, rlDest, rlResult);
297 break;
298
Elliott Hughesadb8c672012-03-06 16:49:32 -0800299 case Instruction::MONITOR_ENTER:
buzbeee3acd072012-02-25 17:03:10 -0800300 genMonitorEnter(cUnit, mir, rlSrc[0]);
301 break;
302
Elliott Hughesadb8c672012-03-06 16:49:32 -0800303 case Instruction::MONITOR_EXIT:
buzbeee3acd072012-02-25 17:03:10 -0800304 genMonitorExit(cUnit, mir, rlSrc[0]);
305 break;
306
Elliott Hughesadb8c672012-03-06 16:49:32 -0800307 case Instruction::CHECK_CAST:
buzbeee3acd072012-02-25 17:03:10 -0800308 genCheckCast(cUnit, mir, rlSrc[0]);
309 break;
310
Elliott Hughesadb8c672012-03-06 16:49:32 -0800311 case Instruction::INSTANCE_OF:
buzbeee3acd072012-02-25 17:03:10 -0800312 genInstanceof(cUnit, mir, rlDest, rlSrc[0]);
313 break;
314
Elliott Hughesadb8c672012-03-06 16:49:32 -0800315 case Instruction::NEW_INSTANCE:
buzbeee3acd072012-02-25 17:03:10 -0800316 genNewInstance(cUnit, mir, rlDest);
317 break;
318
Elliott Hughesadb8c672012-03-06 16:49:32 -0800319 case Instruction::THROW:
buzbeee3acd072012-02-25 17:03:10 -0800320 genThrow(cUnit, mir, rlSrc[0]);
321 break;
322
Elliott Hughesadb8c672012-03-06 16:49:32 -0800323 case Instruction::THROW_VERIFICATION_ERROR:
buzbeee3acd072012-02-25 17:03:10 -0800324 genThrowVerificationError(cUnit, mir);
325 break;
326
Elliott Hughesadb8c672012-03-06 16:49:32 -0800327 case Instruction::ARRAY_LENGTH:
buzbeee3acd072012-02-25 17:03:10 -0800328 int lenOffset;
329 lenOffset = Array::LengthOffset().Int32Value();
330 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
331 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, mir);
332 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
333 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset,
334 rlResult.lowReg);
335 storeValue(cUnit, rlDest, rlResult);
336 break;
337
Elliott Hughesadb8c672012-03-06 16:49:32 -0800338 case Instruction::CONST_STRING:
339 case Instruction::CONST_STRING_JUMBO:
buzbeee3acd072012-02-25 17:03:10 -0800340 genConstString(cUnit, mir, rlDest, rlSrc[0]);
341 break;
342
Elliott Hughesadb8c672012-03-06 16:49:32 -0800343 case Instruction::CONST_CLASS:
buzbeee3acd072012-02-25 17:03:10 -0800344 genConstClass(cUnit, mir, rlDest, rlSrc[0]);
345 break;
346
Elliott Hughesadb8c672012-03-06 16:49:32 -0800347 case Instruction::FILL_ARRAY_DATA:
buzbeee3acd072012-02-25 17:03:10 -0800348 genFillArrayData(cUnit, mir, rlSrc[0]);
349 break;
350
Elliott Hughesadb8c672012-03-06 16:49:32 -0800351 case Instruction::FILLED_NEW_ARRAY:
buzbeee3acd072012-02-25 17:03:10 -0800352 genFilledNewArray(cUnit, mir, false /* not range */);
353 break;
354
Elliott Hughesadb8c672012-03-06 16:49:32 -0800355 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbeee3acd072012-02-25 17:03:10 -0800356 genFilledNewArray(cUnit, mir, true /* range */);
357 break;
358
Elliott Hughesadb8c672012-03-06 16:49:32 -0800359 case Instruction::NEW_ARRAY:
buzbeee3acd072012-02-25 17:03:10 -0800360 genNewArray(cUnit, mir, rlDest, rlSrc[0]);
361 break;
362
Elliott Hughesadb8c672012-03-06 16:49:32 -0800363 case Instruction::GOTO:
364 case Instruction::GOTO_16:
365 case Instruction::GOTO_32:
buzbeee3acd072012-02-25 17:03:10 -0800366 if (bb->taken->startOffset <= mir->offset) {
buzbeefead2932012-03-30 14:02:01 -0700367 genSuspendTestAndBranch(cUnit, mir, &labelList[bb->taken->id]);
368 } else {
369 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
buzbeee3acd072012-02-25 17:03:10 -0800370 }
buzbeee3acd072012-02-25 17:03:10 -0800371 break;
372
Elliott Hughesadb8c672012-03-06 16:49:32 -0800373 case Instruction::PACKED_SWITCH:
buzbeee3acd072012-02-25 17:03:10 -0800374 genPackedSwitch(cUnit, mir, rlSrc[0]);
375 break;
376
Elliott Hughesadb8c672012-03-06 16:49:32 -0800377 case Instruction::SPARSE_SWITCH:
buzbeee3acd072012-02-25 17:03:10 -0800378 genSparseSwitch(cUnit, mir, rlSrc[0]);
379 break;
380
Elliott Hughesadb8c672012-03-06 16:49:32 -0800381 case Instruction::CMPL_FLOAT:
382 case Instruction::CMPG_FLOAT:
383 case Instruction::CMPL_DOUBLE:
384 case Instruction::CMPG_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800385 res = genCmpFP(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
386 break;
387
Elliott Hughesadb8c672012-03-06 16:49:32 -0800388 case Instruction::CMP_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800389 genCmpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
390 break;
391
Elliott Hughesadb8c672012-03-06 16:49:32 -0800392 case Instruction::IF_EQ:
393 case Instruction::IF_NE:
394 case Instruction::IF_LT:
395 case Instruction::IF_GE:
396 case Instruction::IF_GT:
397 case Instruction::IF_LE: {
buzbeee3acd072012-02-25 17:03:10 -0800398 bool backwardBranch;
399 backwardBranch = (bb->taken->startOffset <= mir->offset);
400 if (backwardBranch) {
401 genSuspendTest(cUnit, mir);
402 }
403 genCompareAndBranch(cUnit, bb, mir, rlSrc[0], rlSrc[1], labelList);
404 break;
405 }
406
Elliott Hughesadb8c672012-03-06 16:49:32 -0800407 case Instruction::IF_EQZ:
408 case Instruction::IF_NEZ:
409 case Instruction::IF_LTZ:
410 case Instruction::IF_GEZ:
411 case Instruction::IF_GTZ:
412 case Instruction::IF_LEZ: {
buzbeee3acd072012-02-25 17:03:10 -0800413 bool backwardBranch;
414 backwardBranch = (bb->taken->startOffset <= mir->offset);
415 if (backwardBranch) {
416 genSuspendTest(cUnit, mir);
417 }
418 genCompareZeroAndBranch(cUnit, bb, mir, rlSrc[0], labelList);
419 break;
420 }
421
Elliott Hughesadb8c672012-03-06 16:49:32 -0800422 case Instruction::AGET_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800423 genArrayGet(cUnit, mir, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
424 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800425 case Instruction::AGET:
426 case Instruction::AGET_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800427 genArrayGet(cUnit, mir, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
428 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800429 case Instruction::AGET_BOOLEAN:
buzbeee3acd072012-02-25 17:03:10 -0800430 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1],
431 rlDest, 0);
432 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800433 case Instruction::AGET_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800434 genArrayGet(cUnit, mir, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
435 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800436 case Instruction::AGET_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800437 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1],
438 rlDest, 1);
439 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800440 case Instruction::AGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800441 genArrayGet(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
442 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800443 case Instruction::APUT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800444 genArrayPut(cUnit, mir, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
445 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800446 case Instruction::APUT:
buzbeee3acd072012-02-25 17:03:10 -0800447 genArrayPut(cUnit, mir, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
448 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800449 case Instruction::APUT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800450 genArrayObjPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2);
451 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800452 case Instruction::APUT_SHORT:
453 case Instruction::APUT_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800454 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc[1], rlSrc[2],
455 rlSrc[0], 1);
456 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800457 case Instruction::APUT_BYTE:
458 case Instruction::APUT_BOOLEAN:
buzbeee3acd072012-02-25 17:03:10 -0800459 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc[1], rlSrc[2],
460 rlSrc[0], 0);
461 break;
462
Elliott Hughesadb8c672012-03-06 16:49:32 -0800463 case Instruction::IGET_OBJECT:
464 //case Instruction::IGET_OBJECT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800465 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, true);
466 break;
467
Elliott Hughesadb8c672012-03-06 16:49:32 -0800468 case Instruction::IGET_WIDE:
469 //case Instruction::IGET_WIDE_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800470 genIGet(cUnit, mir, kLong, rlDest, rlSrc[0], true, false);
471 break;
472
Elliott Hughesadb8c672012-03-06 16:49:32 -0800473 case Instruction::IGET:
474 //case Instruction::IGET_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800475 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, false);
476 break;
477
Elliott Hughesadb8c672012-03-06 16:49:32 -0800478 case Instruction::IGET_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800479 genIGet(cUnit, mir, kUnsignedHalf, rlDest, rlSrc[0], false, false);
480 break;
481
Elliott Hughesadb8c672012-03-06 16:49:32 -0800482 case Instruction::IGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800483 genIGet(cUnit, mir, kSignedHalf, rlDest, rlSrc[0], false, false);
484 break;
485
Elliott Hughesadb8c672012-03-06 16:49:32 -0800486 case Instruction::IGET_BOOLEAN:
487 case Instruction::IGET_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800488 genIGet(cUnit, mir, kUnsignedByte, rlDest, rlSrc[0], false, false);
489 break;
490
Elliott Hughesadb8c672012-03-06 16:49:32 -0800491 case Instruction::IPUT_WIDE:
492 //case Instruction::IPUT_WIDE_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800493 genIPut(cUnit, mir, kLong, rlSrc[0], rlSrc[1], true, false);
494 break;
495
Elliott Hughesadb8c672012-03-06 16:49:32 -0800496 case Instruction::IPUT_OBJECT:
497 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800498 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, true);
499 break;
500
Elliott Hughesadb8c672012-03-06 16:49:32 -0800501 case Instruction::IPUT:
502 //case Instruction::IPUT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800503 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, false);
504 break;
505
Elliott Hughesadb8c672012-03-06 16:49:32 -0800506 case Instruction::IPUT_BOOLEAN:
507 case Instruction::IPUT_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800508 genIPut(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
509 break;
510
Elliott Hughesadb8c672012-03-06 16:49:32 -0800511 case Instruction::IPUT_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800512 genIPut(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
513 break;
514
Elliott Hughesadb8c672012-03-06 16:49:32 -0800515 case Instruction::IPUT_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800516 genIPut(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
517 break;
518
Elliott Hughesadb8c672012-03-06 16:49:32 -0800519 case Instruction::SGET_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800520 genSget(cUnit, mir, rlDest, false, true);
521 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800522 case Instruction::SGET:
523 case Instruction::SGET_BOOLEAN:
524 case Instruction::SGET_BYTE:
525 case Instruction::SGET_CHAR:
526 case Instruction::SGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800527 genSget(cUnit, mir, rlDest, false, false);
528 break;
529
Elliott Hughesadb8c672012-03-06 16:49:32 -0800530 case Instruction::SGET_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800531 genSget(cUnit, mir, rlDest, true, false);
532 break;
533
Elliott Hughesadb8c672012-03-06 16:49:32 -0800534 case Instruction::SPUT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800535 genSput(cUnit, mir, rlSrc[0], false, true);
536 break;
537
Elliott Hughesadb8c672012-03-06 16:49:32 -0800538 case Instruction::SPUT:
539 case Instruction::SPUT_BOOLEAN:
540 case Instruction::SPUT_BYTE:
541 case Instruction::SPUT_CHAR:
542 case Instruction::SPUT_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800543 genSput(cUnit, mir, rlSrc[0], false, false);
544 break;
545
Elliott Hughesadb8c672012-03-06 16:49:32 -0800546 case Instruction::SPUT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800547 genSput(cUnit, mir, rlSrc[0], true, false);
548 break;
549
Elliott Hughesadb8c672012-03-06 16:49:32 -0800550 case Instruction::INVOKE_STATIC_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700551 genInvoke(cUnit, bb, mir, kStatic, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800552 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800553 case Instruction::INVOKE_STATIC:
buzbeefc9e6fa2012-03-23 15:14:29 -0700554 genInvoke(cUnit, bb, mir, kStatic, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800555 break;
556
Elliott Hughesadb8c672012-03-06 16:49:32 -0800557 case Instruction::INVOKE_DIRECT:
buzbeefc9e6fa2012-03-23 15:14:29 -0700558 genInvoke(cUnit, bb, mir, kDirect, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800559 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800560 case Instruction::INVOKE_DIRECT_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700561 genInvoke(cUnit, bb, mir, kDirect, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800562 break;
563
Elliott Hughesadb8c672012-03-06 16:49:32 -0800564 case Instruction::INVOKE_VIRTUAL:
buzbeefc9e6fa2012-03-23 15:14:29 -0700565 genInvoke(cUnit, bb, mir, kVirtual, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800566 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800567 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700568 genInvoke(cUnit, bb, mir, kVirtual, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800569 break;
570
Elliott Hughesadb8c672012-03-06 16:49:32 -0800571 case Instruction::INVOKE_SUPER:
buzbeefc9e6fa2012-03-23 15:14:29 -0700572 genInvoke(cUnit, bb, mir, kSuper, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800573 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800574 case Instruction::INVOKE_SUPER_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700575 genInvoke(cUnit, bb, mir, kSuper, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800576 break;
577
Elliott Hughesadb8c672012-03-06 16:49:32 -0800578 case Instruction::INVOKE_INTERFACE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700579 genInvoke(cUnit, bb, mir, kInterface, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800580 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800581 case Instruction::INVOKE_INTERFACE_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700582 genInvoke(cUnit, bb, mir, kInterface, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800583 break;
584
Elliott Hughesadb8c672012-03-06 16:49:32 -0800585 case Instruction::NEG_INT:
586 case Instruction::NOT_INT:
buzbeee3acd072012-02-25 17:03:10 -0800587 res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
588 break;
589
Elliott Hughesadb8c672012-03-06 16:49:32 -0800590 case Instruction::NEG_LONG:
591 case Instruction::NOT_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800592 res = genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
593 break;
594
Elliott Hughesadb8c672012-03-06 16:49:32 -0800595 case Instruction::NEG_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800596 res = genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
597 break;
598
Elliott Hughesadb8c672012-03-06 16:49:32 -0800599 case Instruction::NEG_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800600 res = genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
601 break;
602
Elliott Hughesadb8c672012-03-06 16:49:32 -0800603 case Instruction::INT_TO_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800604 genIntToLong(cUnit, mir, rlDest, rlSrc[0]);
605 break;
606
Elliott Hughesadb8c672012-03-06 16:49:32 -0800607 case Instruction::LONG_TO_INT:
buzbeee3acd072012-02-25 17:03:10 -0800608 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
609 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
610 storeValue(cUnit, rlDest, rlSrc[0]);
611 break;
612
Elliott Hughesadb8c672012-03-06 16:49:32 -0800613 case Instruction::INT_TO_BYTE:
614 case Instruction::INT_TO_SHORT:
615 case Instruction::INT_TO_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800616 genIntNarrowing(cUnit, mir, rlDest, rlSrc[0]);
617 break;
618
Elliott Hughesadb8c672012-03-06 16:49:32 -0800619 case Instruction::INT_TO_FLOAT:
620 case Instruction::INT_TO_DOUBLE:
621 case Instruction::LONG_TO_FLOAT:
622 case Instruction::LONG_TO_DOUBLE:
623 case Instruction::FLOAT_TO_INT:
624 case Instruction::FLOAT_TO_LONG:
625 case Instruction::FLOAT_TO_DOUBLE:
626 case Instruction::DOUBLE_TO_INT:
627 case Instruction::DOUBLE_TO_LONG:
628 case Instruction::DOUBLE_TO_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800629 genConversion(cUnit, mir);
630 break;
631
Elliott Hughesadb8c672012-03-06 16:49:32 -0800632 case Instruction::ADD_INT:
633 case Instruction::SUB_INT:
634 case Instruction::MUL_INT:
635 case Instruction::DIV_INT:
636 case Instruction::REM_INT:
637 case Instruction::AND_INT:
638 case Instruction::OR_INT:
639 case Instruction::XOR_INT:
640 case Instruction::SHL_INT:
641 case Instruction::SHR_INT:
642 case Instruction::USHR_INT:
643 case Instruction::ADD_INT_2ADDR:
644 case Instruction::SUB_INT_2ADDR:
645 case Instruction::MUL_INT_2ADDR:
646 case Instruction::DIV_INT_2ADDR:
647 case Instruction::REM_INT_2ADDR:
648 case Instruction::AND_INT_2ADDR:
649 case Instruction::OR_INT_2ADDR:
650 case Instruction::XOR_INT_2ADDR:
651 case Instruction::SHL_INT_2ADDR:
652 case Instruction::SHR_INT_2ADDR:
653 case Instruction::USHR_INT_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800654 genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
655 break;
656
Elliott Hughesadb8c672012-03-06 16:49:32 -0800657 case Instruction::ADD_LONG:
658 case Instruction::SUB_LONG:
659 case Instruction::MUL_LONG:
660 case Instruction::DIV_LONG:
661 case Instruction::REM_LONG:
662 case Instruction::AND_LONG:
663 case Instruction::OR_LONG:
664 case Instruction::XOR_LONG:
665 case Instruction::ADD_LONG_2ADDR:
666 case Instruction::SUB_LONG_2ADDR:
667 case Instruction::MUL_LONG_2ADDR:
668 case Instruction::DIV_LONG_2ADDR:
669 case Instruction::REM_LONG_2ADDR:
670 case Instruction::AND_LONG_2ADDR:
671 case Instruction::OR_LONG_2ADDR:
672 case Instruction::XOR_LONG_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800673 genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
674 break;
675
Elliott Hughesadb8c672012-03-06 16:49:32 -0800676 case Instruction::SHL_LONG:
677 case Instruction::SHR_LONG:
678 case Instruction::USHR_LONG:
679 case Instruction::SHL_LONG_2ADDR:
680 case Instruction::SHR_LONG_2ADDR:
681 case Instruction::USHR_LONG_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800682 genShiftOpLong(cUnit,mir, rlDest, rlSrc[0], rlSrc[1]);
683 break;
684
Elliott Hughesadb8c672012-03-06 16:49:32 -0800685 case Instruction::ADD_FLOAT:
686 case Instruction::SUB_FLOAT:
687 case Instruction::MUL_FLOAT:
688 case Instruction::DIV_FLOAT:
689 case Instruction::REM_FLOAT:
690 case Instruction::ADD_FLOAT_2ADDR:
691 case Instruction::SUB_FLOAT_2ADDR:
692 case Instruction::MUL_FLOAT_2ADDR:
693 case Instruction::DIV_FLOAT_2ADDR:
694 case Instruction::REM_FLOAT_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800695 genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
696 break;
697
Elliott Hughesadb8c672012-03-06 16:49:32 -0800698 case Instruction::ADD_DOUBLE:
699 case Instruction::SUB_DOUBLE:
700 case Instruction::MUL_DOUBLE:
701 case Instruction::DIV_DOUBLE:
702 case Instruction::REM_DOUBLE:
703 case Instruction::ADD_DOUBLE_2ADDR:
704 case Instruction::SUB_DOUBLE_2ADDR:
705 case Instruction::MUL_DOUBLE_2ADDR:
706 case Instruction::DIV_DOUBLE_2ADDR:
707 case Instruction::REM_DOUBLE_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800708 genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
709 break;
710
Elliott Hughesadb8c672012-03-06 16:49:32 -0800711 case Instruction::RSUB_INT:
712 case Instruction::ADD_INT_LIT16:
713 case Instruction::MUL_INT_LIT16:
714 case Instruction::DIV_INT_LIT16:
715 case Instruction::REM_INT_LIT16:
716 case Instruction::AND_INT_LIT16:
717 case Instruction::OR_INT_LIT16:
718 case Instruction::XOR_INT_LIT16:
719 case Instruction::ADD_INT_LIT8:
720 case Instruction::RSUB_INT_LIT8:
721 case Instruction::MUL_INT_LIT8:
722 case Instruction::DIV_INT_LIT8:
723 case Instruction::REM_INT_LIT8:
724 case Instruction::AND_INT_LIT8:
725 case Instruction::OR_INT_LIT8:
726 case Instruction::XOR_INT_LIT8:
727 case Instruction::SHL_INT_LIT8:
728 case Instruction::SHR_INT_LIT8:
729 case Instruction::USHR_INT_LIT8:
buzbeee3acd072012-02-25 17:03:10 -0800730 genArithOpIntLit(cUnit, mir, rlDest, rlSrc[0], mir->dalvikInsn.vC);
731 break;
732
733 default:
734 res = true;
735 }
736 return res;
737}
738
buzbee31a4a6f2012-02-28 15:36:15 -0800739const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
buzbeee3acd072012-02-25 17:03:10 -0800740 "kMirOpPhi",
buzbeee1965672012-03-11 18:39:19 -0700741 "kMirOpCopy",
buzbee84fd6932012-03-29 16:44:16 -0700742 "kMirFusedCmplFloat",
743 "kMirFusedCmpgFloat",
744 "kMirFusedCmplDouble",
745 "kMirFusedCmpgDouble",
746 "kMirFusedCmpLong",
747 "kMirNop",
buzbeea2e39d92012-03-30 09:11:45 -0700748 "kMirOpNullNRangeUpCheck",
749 "kMirOpNullNRangeDownCheck",
750 "kMirOpLowerBound",
buzbeee3acd072012-02-25 17:03:10 -0800751};
752
753/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700754void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800755{
756 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
757 char* msg = NULL;
758 if (cUnit->printMe) {
759 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
760 false, kAllocDebugInfo);
761 strcpy(msg, extendedMIROpNames[opOffset]);
762 }
buzbee31a4a6f2012-02-28 15:36:15 -0800763 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800764
765 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
766 case kMirOpPhi: {
767 char* ssaString = NULL;
768 if (cUnit->printMe) {
769 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
770 }
771 op->flags.isNop = true;
buzbee31a4a6f2012-02-28 15:36:15 -0800772 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
buzbeee3acd072012-02-25 17:03:10 -0800773 break;
774 }
buzbee239c4e72012-03-16 08:42:29 -0700775 case kMirOpCopy: {
776 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
777 RegLocation rlDest = oatGetDest(cUnit, mir, 0);
778 storeValue(cUnit, rlDest, rlSrc);
buzbeee1965672012-03-11 18:39:19 -0700779 break;
buzbee239c4e72012-03-16 08:42:29 -0700780 }
buzbee84fd6932012-03-29 16:44:16 -0700781#if defined(TARGET_ARM)
782 case kMirOpFusedCmplFloat:
783 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
784 break;
785 case kMirOpFusedCmpgFloat:
786 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
787 break;
788 case kMirOpFusedCmplDouble:
789 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
790 break;
791 case kMirOpFusedCmpgDouble:
792 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
793 break;
794 case kMirOpFusedCmpLong:
795 genFusedLongCmpBranch(cUnit, bb, mir);
796 break;
797#endif
buzbeee3acd072012-02-25 17:03:10 -0800798 default:
799 break;
800 }
801}
802
803/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800804bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800805{
806 MIR* mir;
buzbee31a4a6f2012-02-28 15:36:15 -0800807 LIR* labelList = (LIR*) cUnit->blockLabelList;
buzbeee3acd072012-02-25 17:03:10 -0800808 int blockId = bb->id;
809
810 cUnit->curBlock = bb;
811 labelList[blockId].operands[0] = bb->startOffset;
812
813 /* Insert the block label */
buzbee31a4a6f2012-02-28 15:36:15 -0800814 labelList[blockId].opcode = kPseudoNormalBlockLabel;
buzbeee3acd072012-02-25 17:03:10 -0800815 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
816
buzbeee1965672012-03-11 18:39:19 -0700817 /* Free temp registers and reset redundant store tracking */
buzbeee3acd072012-02-25 17:03:10 -0800818 oatResetRegPool(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800819 oatResetDefTracking(cUnit);
820
buzbeee1965672012-03-11 18:39:19 -0700821 /*
822 * If control reached us from our immediate predecessor via
823 * fallthrough and we have no other incoming arcs we can
824 * reuse existing liveness. Otherwise, reset.
825 */
826 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
827 oatClobberAllRegs(cUnit);
828 }
829
buzbee31a4a6f2012-02-28 15:36:15 -0800830 LIR* headLIR = NULL;
buzbeee3acd072012-02-25 17:03:10 -0800831
832 if (bb->blockType == kEntryBlock) {
833 genEntrySequence(cUnit, bb);
834 } else if (bb->blockType == kExitBlock) {
835 genExitSequence(cUnit, bb);
836 }
837
838 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
839
840 oatResetRegPool(cUnit);
841 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
842 oatClobberAllRegs(cUnit);
843 }
844
845 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
846 oatResetDefTracking(cUnit);
847 }
848
buzbee3d661942012-03-14 17:37:27 -0700849#ifndef NDEBUG
850 /* Reset temp tracking sanity check */
851 cUnit->liveSReg = INVALID_SREG;
852#endif
853
buzbeee3acd072012-02-25 17:03:10 -0800854 cUnit->currentDalvikOffset = mir->offset;
855
Elliott Hughesadb8c672012-03-06 16:49:32 -0800856 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
857 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800858
buzbee31a4a6f2012-02-28 15:36:15 -0800859 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800860
861 /* Mark the beginning of a Dalvik instruction for line tracking */
862 char* instStr = cUnit->printMe ?
Elliott Hughesadb8c672012-03-06 16:49:32 -0800863 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800864 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
buzbeee3acd072012-02-25 17:03:10 -0800865 (intptr_t) instStr);
866 cUnit->boundaryMap.insert(std::make_pair(mir->offset,
867 (LIR*)boundaryLIR));
868 /* Remember the first LIR for this block */
869 if (headLIR == NULL) {
870 headLIR = boundaryLIR;
871 /* Set the first boundaryLIR as a scheduling barrier */
872 headLIR->defMask = ENCODE_ALL;
873 }
874
875 /* If we're compiling for the debugger, generate an update callout */
876 if (cUnit->genDebugger) {
877 genDebuggerUpdate(cUnit, mir->offset);
878 }
879
880 /* Don't generate the SSA annotation unless verbose mode is on */
881 if (cUnit->printMe && mir->ssaRep) {
882 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
buzbee31a4a6f2012-02-28 15:36:15 -0800883 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
buzbeee3acd072012-02-25 17:03:10 -0800884 }
885
buzbee84fd6932012-03-29 16:44:16 -0700886 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
887 handleExtendedMethodMIR(cUnit, bb, mir);
888 continue;
889 }
890
buzbeee3acd072012-02-25 17:03:10 -0800891 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
buzbeee3acd072012-02-25 17:03:10 -0800892 if (notHandled) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800893 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
894 mir->offset, dalvikOpcode, Instruction::Name(dalvikOpcode), dalvikFormat);
895
buzbeee3acd072012-02-25 17:03:10 -0800896 }
897 }
898
899 if (headLIR) {
900 /*
901 * Eliminate redundant loads/stores and delay stores into later
902 * slots
903 */
904 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR,
905 cUnit->lastLIRInsn);
906
907 /*
908 * Generate an unconditional branch to the fallthrough block.
909 */
910 if (bb->fallThrough) {
buzbee82488f52012-03-02 08:20:26 -0800911 opUnconditionalBranch(cUnit,
912 &labelList[bb->fallThrough->id]);
buzbeee3acd072012-02-25 17:03:10 -0800913 }
914 }
915 return false;
916}
917
buzbee16da88c2012-03-20 10:38:17 -0700918/* Set basic block labels */
919bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
920{
921 LIR* labelList = (LIR*) cUnit->blockLabelList;
922 int blockId = bb->id;
923
924 cUnit->curBlock = bb;
925 labelList[blockId].operands[0] = bb->startOffset;
926
927 /* Insert the block label */
928 labelList[blockId].opcode = kPseudoNormalBlockLabel;
929 return false;
930}
931
932void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
933{
934 /* Find the first DalvikByteCode block */
935 int numReachableBlocks = cUnit->numReachableBlocks;
936 const GrowableList *blockList = &cUnit->blockList;
937 BasicBlock*bb = NULL;
938 for (int idx = 0; idx < numReachableBlocks; idx++) {
939 int dfsIndex = cUnit->dfsOrder.elemList[idx];
940 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
941 if (bb->blockType == kDalvikByteCode) {
942 break;
943 }
944 }
945 if (bb == NULL) {
946 return;
947 }
948 DCHECK_EQ(bb->startOffset, 0);
949 DCHECK(bb->firstMIRInsn != 0);
950
951 /* Get the first instruction */
952 MIR* mir = bb->firstMIRInsn;
953
954 /* Free temp registers and reset redundant store tracking */
955 oatResetRegPool(cUnit);
956 oatResetDefTracking(cUnit);
957 oatClobberAllRegs(cUnit);
958
959 genSpecialCase(cUnit, bb, mir, specialCase);
960}
961
buzbeee3acd072012-02-25 17:03:10 -0800962void oatMethodMIR2LIR(CompilationUnit* cUnit)
963{
964 /* Used to hold the labels of each block */
965 cUnit->blockLabelList =
buzbee31a4a6f2012-02-28 15:36:15 -0800966 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true,
buzbeee3acd072012-02-25 17:03:10 -0800967 kAllocLIR);
968
969 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
970 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -0700971
buzbeee3acd072012-02-25 17:03:10 -0800972 handleSuspendLaunchpads(cUnit);
973
974 handleThrowLaunchpads(cUnit);
975
buzbeefc9e6fa2012-03-23 15:14:29 -0700976 handleIntrinsicLaunchpads(cUnit);
977
buzbee86a4bce2012-03-06 18:15:00 -0800978 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
979 removeRedundantBranches(cUnit);
980 }
buzbeee3acd072012-02-25 17:03:10 -0800981}
982
983/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -0800984LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -0800985{
buzbee82488f52012-03-02 08:20:26 -0800986 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -0800987}
988
989/* Needed by the register allocator */
990void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
991{
buzbee82488f52012-03-02 08:20:26 -0800992 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -0800993}
994
995/* Needed by the register allocator */
996void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
997 int srcLo, int srcHi)
998{
buzbee82488f52012-03-02 08:20:26 -0800999 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001000}
1001
1002void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
1003 int displacement, int rSrc, OpSize size)
1004{
1005 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
1006}
1007
1008void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
1009 int displacement, int rSrcLo, int rSrcHi)
1010{
1011 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
1012}
1013
1014} // namespace art