blob: b28df0183e89659f74c01dcd7e656dee92cbd8c1 [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
Ian Rogers7caad772012-03-30 01:07:54 -0700131 if (fastPath && type != kInterface) {
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700132 opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
133 } else {
Ian Rogers7caad772012-03-30 01:07:54 -0700134 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";
154 }
155 opThreadMem(cUnit, kOpBlx, trampoline);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700156 }
buzbeea7678db2012-03-05 15:35:46 -0800157#endif
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700158
159 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{
170 bool res = false; // Assume success
171 RegLocation rlSrc[3];
172 RegLocation rlDest = badLoc;
173 RegLocation rlResult = badLoc;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800174 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbeee3acd072012-02-25 17:03:10 -0800175
176 /* 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) {
182 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
183 nextSreg++;
184 } else if (attrs & DF_UA_WIDE) {
185 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
186 nextSreg + 1);
187 nextSreg+= 2;
188 }
189 if (attrs & DF_UB) {
190 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
191 nextSreg++;
192 } else if (attrs & DF_UB_WIDE) {
193 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
194 nextSreg + 1);
195 nextSreg+= 2;
196 }
197 if (attrs & DF_UC) {
198 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
199 } else if (attrs & DF_UC_WIDE) {
200 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
201 nextSreg + 1);
202 }
203 if (attrs & DF_DA) {
204 rlDest = oatGetDest(cUnit, mir, 0);
205 } else if (attrs & DF_DA_WIDE) {
206 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
207 }
208
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700209 switch (opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800210 case Instruction::NOP:
buzbeee3acd072012-02-25 17:03:10 -0800211 break;
212
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700213 case Instruction::MOVE_EXCEPTION: {
214 int exOffset = Thread::ExceptionOffset().Int32Value();
buzbeee3acd072012-02-25 17:03:10 -0800215 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700216#if defined(TARGET_X86)
217 newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset);
218 newLIR2(cUnit, kX86Mov32TI, exOffset, 0);
219#else
220 int resetReg = oatAllocTemp(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800221 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
222 loadConstant(cUnit, resetReg, 0);
223 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
224 storeValue(cUnit, rlDest, rlResult);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700225 oatFreeTemp(cUnit, resetReg);
buzbeea7678db2012-03-05 15:35:46 -0800226#endif
buzbeee3acd072012-02-25 17:03:10 -0800227 break;
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700228 }
Elliott Hughesadb8c672012-03-06 16:49:32 -0800229 case Instruction::RETURN_VOID:
buzbee86a4bce2012-03-06 18:15:00 -0800230 if (!cUnit->attrs & METHOD_IS_LEAF) {
231 genSuspendTest(cUnit, mir);
232 }
buzbeee3acd072012-02-25 17:03:10 -0800233 break;
234
Elliott Hughesadb8c672012-03-06 16:49:32 -0800235 case Instruction::RETURN:
236 case Instruction::RETURN_OBJECT:
buzbee86a4bce2012-03-06 18:15:00 -0800237 if (!cUnit->attrs & METHOD_IS_LEAF) {
238 genSuspendTest(cUnit, mir);
239 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700240 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'),
241 rlSrc[0]);
buzbeee3acd072012-02-25 17:03:10 -0800242 break;
243
Elliott Hughesadb8c672012-03-06 16:49:32 -0800244 case Instruction::RETURN_WIDE:
buzbee86a4bce2012-03-06 18:15:00 -0800245 if (!cUnit->attrs & METHOD_IS_LEAF) {
246 genSuspendTest(cUnit, mir);
247 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700248 storeValueWide(cUnit, oatGetReturnWide(cUnit,
249 cUnit->shorty[0] == 'D'), rlSrc[0]);
buzbeee3acd072012-02-25 17:03:10 -0800250 break;
251
Elliott Hughesadb8c672012-03-06 16:49:32 -0800252 case Instruction::MOVE_RESULT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800253 if (mir->optimizationFlags & MIR_INLINED)
254 break; // Nop - combined w/ previous invoke
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700255 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
buzbeee3acd072012-02-25 17:03:10 -0800256 break;
257
Elliott Hughesadb8c672012-03-06 16:49:32 -0800258 case Instruction::MOVE_RESULT:
259 case Instruction::MOVE_RESULT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800260 if (mir->optimizationFlags & MIR_INLINED)
261 break; // Nop - combined w/ previous invoke
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700262 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
buzbeee3acd072012-02-25 17:03:10 -0800263 break;
264
Elliott Hughesadb8c672012-03-06 16:49:32 -0800265 case Instruction::MOVE:
266 case Instruction::MOVE_OBJECT:
267 case Instruction::MOVE_16:
268 case Instruction::MOVE_OBJECT_16:
269 case Instruction::MOVE_FROM16:
270 case Instruction::MOVE_OBJECT_FROM16:
buzbeee3acd072012-02-25 17:03:10 -0800271 storeValue(cUnit, rlDest, rlSrc[0]);
272 break;
273
Elliott Hughesadb8c672012-03-06 16:49:32 -0800274 case Instruction::MOVE_WIDE:
275 case Instruction::MOVE_WIDE_16:
276 case Instruction::MOVE_WIDE_FROM16:
buzbeee3acd072012-02-25 17:03:10 -0800277 storeValueWide(cUnit, rlDest, rlSrc[0]);
278 break;
279
Elliott Hughesadb8c672012-03-06 16:49:32 -0800280 case Instruction::CONST:
281 case Instruction::CONST_4:
282 case Instruction::CONST_16:
buzbeee3acd072012-02-25 17:03:10 -0800283 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
284 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
285 storeValue(cUnit, rlDest, rlResult);
286 break;
287
Elliott Hughesadb8c672012-03-06 16:49:32 -0800288 case Instruction::CONST_HIGH16:
buzbeee3acd072012-02-25 17:03:10 -0800289 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
290 loadConstantNoClobber(cUnit, rlResult.lowReg,
291 mir->dalvikInsn.vB << 16);
292 storeValue(cUnit, rlDest, rlResult);
293 break;
294
Elliott Hughesadb8c672012-03-06 16:49:32 -0800295 case Instruction::CONST_WIDE_16:
296 case Instruction::CONST_WIDE_32:
buzbeee3acd072012-02-25 17:03:10 -0800297 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
298 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
299 mir->dalvikInsn.vB,
300 (mir->dalvikInsn.vB & 0x80000000) ? -1 : 0);
301 storeValueWide(cUnit, rlDest, rlResult);
302 break;
303
Elliott Hughesadb8c672012-03-06 16:49:32 -0800304 case Instruction::CONST_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800305 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
306 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
307 mir->dalvikInsn.vB_wide & 0xffffffff,
308 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
309 storeValueWide(cUnit, rlDest, rlResult);
310 break;
311
Elliott Hughesadb8c672012-03-06 16:49:32 -0800312 case Instruction::CONST_WIDE_HIGH16:
buzbeee3acd072012-02-25 17:03:10 -0800313 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
314 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
315 0, mir->dalvikInsn.vB << 16);
316 storeValueWide(cUnit, rlDest, rlResult);
317 break;
318
Elliott Hughesadb8c672012-03-06 16:49:32 -0800319 case Instruction::MONITOR_ENTER:
buzbeee3acd072012-02-25 17:03:10 -0800320 genMonitorEnter(cUnit, mir, rlSrc[0]);
321 break;
322
Elliott Hughesadb8c672012-03-06 16:49:32 -0800323 case Instruction::MONITOR_EXIT:
buzbeee3acd072012-02-25 17:03:10 -0800324 genMonitorExit(cUnit, mir, rlSrc[0]);
325 break;
326
Elliott Hughesadb8c672012-03-06 16:49:32 -0800327 case Instruction::CHECK_CAST:
buzbeee3acd072012-02-25 17:03:10 -0800328 genCheckCast(cUnit, mir, rlSrc[0]);
329 break;
330
Elliott Hughesadb8c672012-03-06 16:49:32 -0800331 case Instruction::INSTANCE_OF:
buzbeee3acd072012-02-25 17:03:10 -0800332 genInstanceof(cUnit, mir, rlDest, rlSrc[0]);
333 break;
334
Elliott Hughesadb8c672012-03-06 16:49:32 -0800335 case Instruction::NEW_INSTANCE:
buzbeee3acd072012-02-25 17:03:10 -0800336 genNewInstance(cUnit, mir, rlDest);
337 break;
338
Elliott Hughesadb8c672012-03-06 16:49:32 -0800339 case Instruction::THROW:
buzbeee3acd072012-02-25 17:03:10 -0800340 genThrow(cUnit, mir, rlSrc[0]);
341 break;
342
Elliott Hughesadb8c672012-03-06 16:49:32 -0800343 case Instruction::THROW_VERIFICATION_ERROR:
buzbeee3acd072012-02-25 17:03:10 -0800344 genThrowVerificationError(cUnit, mir);
345 break;
346
Elliott Hughesadb8c672012-03-06 16:49:32 -0800347 case Instruction::ARRAY_LENGTH:
buzbeee3acd072012-02-25 17:03:10 -0800348 int lenOffset;
349 lenOffset = Array::LengthOffset().Int32Value();
350 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
351 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, mir);
352 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
353 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset,
354 rlResult.lowReg);
355 storeValue(cUnit, rlDest, rlResult);
356 break;
357
Elliott Hughesadb8c672012-03-06 16:49:32 -0800358 case Instruction::CONST_STRING:
359 case Instruction::CONST_STRING_JUMBO:
buzbeee3acd072012-02-25 17:03:10 -0800360 genConstString(cUnit, mir, rlDest, rlSrc[0]);
361 break;
362
Elliott Hughesadb8c672012-03-06 16:49:32 -0800363 case Instruction::CONST_CLASS:
buzbeee3acd072012-02-25 17:03:10 -0800364 genConstClass(cUnit, mir, rlDest, rlSrc[0]);
365 break;
366
Elliott Hughesadb8c672012-03-06 16:49:32 -0800367 case Instruction::FILL_ARRAY_DATA:
buzbeee3acd072012-02-25 17:03:10 -0800368 genFillArrayData(cUnit, mir, rlSrc[0]);
369 break;
370
Elliott Hughesadb8c672012-03-06 16:49:32 -0800371 case Instruction::FILLED_NEW_ARRAY:
buzbeee3acd072012-02-25 17:03:10 -0800372 genFilledNewArray(cUnit, mir, false /* not range */);
373 break;
374
Elliott Hughesadb8c672012-03-06 16:49:32 -0800375 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbeee3acd072012-02-25 17:03:10 -0800376 genFilledNewArray(cUnit, mir, true /* range */);
377 break;
378
Elliott Hughesadb8c672012-03-06 16:49:32 -0800379 case Instruction::NEW_ARRAY:
buzbeee3acd072012-02-25 17:03:10 -0800380 genNewArray(cUnit, mir, rlDest, rlSrc[0]);
381 break;
382
Elliott Hughesadb8c672012-03-06 16:49:32 -0800383 case Instruction::GOTO:
384 case Instruction::GOTO_16:
385 case Instruction::GOTO_32:
buzbeee3acd072012-02-25 17:03:10 -0800386 if (bb->taken->startOffset <= mir->offset) {
buzbeefead2932012-03-30 14:02:01 -0700387 genSuspendTestAndBranch(cUnit, mir, &labelList[bb->taken->id]);
388 } else {
389 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
buzbeee3acd072012-02-25 17:03:10 -0800390 }
buzbeee3acd072012-02-25 17:03:10 -0800391 break;
392
Elliott Hughesadb8c672012-03-06 16:49:32 -0800393 case Instruction::PACKED_SWITCH:
buzbeee3acd072012-02-25 17:03:10 -0800394 genPackedSwitch(cUnit, mir, rlSrc[0]);
395 break;
396
Elliott Hughesadb8c672012-03-06 16:49:32 -0800397 case Instruction::SPARSE_SWITCH:
buzbeee3acd072012-02-25 17:03:10 -0800398 genSparseSwitch(cUnit, mir, rlSrc[0]);
399 break;
400
Elliott Hughesadb8c672012-03-06 16:49:32 -0800401 case Instruction::CMPL_FLOAT:
402 case Instruction::CMPG_FLOAT:
403 case Instruction::CMPL_DOUBLE:
404 case Instruction::CMPG_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800405 res = genCmpFP(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
406 break;
407
Elliott Hughesadb8c672012-03-06 16:49:32 -0800408 case Instruction::CMP_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800409 genCmpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
410 break;
411
Elliott Hughesadb8c672012-03-06 16:49:32 -0800412 case Instruction::IF_EQ:
413 case Instruction::IF_NE:
414 case Instruction::IF_LT:
415 case Instruction::IF_GE:
416 case Instruction::IF_GT:
417 case Instruction::IF_LE: {
buzbeee3acd072012-02-25 17:03:10 -0800418 bool backwardBranch;
419 backwardBranch = (bb->taken->startOffset <= mir->offset);
420 if (backwardBranch) {
421 genSuspendTest(cUnit, mir);
422 }
423 genCompareAndBranch(cUnit, bb, mir, rlSrc[0], rlSrc[1], labelList);
424 break;
425 }
426
Elliott Hughesadb8c672012-03-06 16:49:32 -0800427 case Instruction::IF_EQZ:
428 case Instruction::IF_NEZ:
429 case Instruction::IF_LTZ:
430 case Instruction::IF_GEZ:
431 case Instruction::IF_GTZ:
432 case Instruction::IF_LEZ: {
buzbeee3acd072012-02-25 17:03:10 -0800433 bool backwardBranch;
434 backwardBranch = (bb->taken->startOffset <= mir->offset);
435 if (backwardBranch) {
436 genSuspendTest(cUnit, mir);
437 }
438 genCompareZeroAndBranch(cUnit, bb, mir, rlSrc[0], labelList);
439 break;
440 }
441
Elliott Hughesadb8c672012-03-06 16:49:32 -0800442 case Instruction::AGET_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800443 genArrayGet(cUnit, mir, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
444 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800445 case Instruction::AGET:
446 case Instruction::AGET_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800447 genArrayGet(cUnit, mir, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
448 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800449 case Instruction::AGET_BOOLEAN:
buzbeee3acd072012-02-25 17:03:10 -0800450 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1],
451 rlDest, 0);
452 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800453 case Instruction::AGET_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800454 genArrayGet(cUnit, mir, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
455 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800456 case Instruction::AGET_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800457 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1],
458 rlDest, 1);
459 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800460 case Instruction::AGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800461 genArrayGet(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
462 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800463 case Instruction::APUT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800464 genArrayPut(cUnit, mir, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
465 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800466 case Instruction::APUT:
buzbeee3acd072012-02-25 17:03:10 -0800467 genArrayPut(cUnit, mir, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
468 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800469 case Instruction::APUT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800470 genArrayObjPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2);
471 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800472 case Instruction::APUT_SHORT:
473 case Instruction::APUT_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800474 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc[1], rlSrc[2],
475 rlSrc[0], 1);
476 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800477 case Instruction::APUT_BYTE:
478 case Instruction::APUT_BOOLEAN:
buzbeee3acd072012-02-25 17:03:10 -0800479 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc[1], rlSrc[2],
480 rlSrc[0], 0);
481 break;
482
Elliott Hughesadb8c672012-03-06 16:49:32 -0800483 case Instruction::IGET_OBJECT:
484 //case Instruction::IGET_OBJECT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800485 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, true);
486 break;
487
Elliott Hughesadb8c672012-03-06 16:49:32 -0800488 case Instruction::IGET_WIDE:
489 //case Instruction::IGET_WIDE_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800490 genIGet(cUnit, mir, kLong, rlDest, rlSrc[0], true, false);
491 break;
492
Elliott Hughesadb8c672012-03-06 16:49:32 -0800493 case Instruction::IGET:
494 //case Instruction::IGET_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800495 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, false);
496 break;
497
Elliott Hughesadb8c672012-03-06 16:49:32 -0800498 case Instruction::IGET_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800499 genIGet(cUnit, mir, kUnsignedHalf, rlDest, rlSrc[0], false, false);
500 break;
501
Elliott Hughesadb8c672012-03-06 16:49:32 -0800502 case Instruction::IGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800503 genIGet(cUnit, mir, kSignedHalf, rlDest, rlSrc[0], false, false);
504 break;
505
Elliott Hughesadb8c672012-03-06 16:49:32 -0800506 case Instruction::IGET_BOOLEAN:
507 case Instruction::IGET_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800508 genIGet(cUnit, mir, kUnsignedByte, rlDest, rlSrc[0], false, false);
509 break;
510
Elliott Hughesadb8c672012-03-06 16:49:32 -0800511 case Instruction::IPUT_WIDE:
512 //case Instruction::IPUT_WIDE_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800513 genIPut(cUnit, mir, kLong, rlSrc[0], rlSrc[1], true, false);
514 break;
515
Elliott Hughesadb8c672012-03-06 16:49:32 -0800516 case Instruction::IPUT_OBJECT:
517 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800518 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, true);
519 break;
520
Elliott Hughesadb8c672012-03-06 16:49:32 -0800521 case Instruction::IPUT:
522 //case Instruction::IPUT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800523 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, false);
524 break;
525
Elliott Hughesadb8c672012-03-06 16:49:32 -0800526 case Instruction::IPUT_BOOLEAN:
527 case Instruction::IPUT_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800528 genIPut(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
529 break;
530
Elliott Hughesadb8c672012-03-06 16:49:32 -0800531 case Instruction::IPUT_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800532 genIPut(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
533 break;
534
Elliott Hughesadb8c672012-03-06 16:49:32 -0800535 case Instruction::IPUT_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800536 genIPut(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
537 break;
538
Elliott Hughesadb8c672012-03-06 16:49:32 -0800539 case Instruction::SGET_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800540 genSget(cUnit, mir, rlDest, false, true);
541 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800542 case Instruction::SGET:
543 case Instruction::SGET_BOOLEAN:
544 case Instruction::SGET_BYTE:
545 case Instruction::SGET_CHAR:
546 case Instruction::SGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800547 genSget(cUnit, mir, rlDest, false, false);
548 break;
549
Elliott Hughesadb8c672012-03-06 16:49:32 -0800550 case Instruction::SGET_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800551 genSget(cUnit, mir, rlDest, true, false);
552 break;
553
Elliott Hughesadb8c672012-03-06 16:49:32 -0800554 case Instruction::SPUT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800555 genSput(cUnit, mir, rlSrc[0], false, true);
556 break;
557
Elliott Hughesadb8c672012-03-06 16:49:32 -0800558 case Instruction::SPUT:
559 case Instruction::SPUT_BOOLEAN:
560 case Instruction::SPUT_BYTE:
561 case Instruction::SPUT_CHAR:
562 case Instruction::SPUT_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800563 genSput(cUnit, mir, rlSrc[0], false, false);
564 break;
565
Elliott Hughesadb8c672012-03-06 16:49:32 -0800566 case Instruction::SPUT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800567 genSput(cUnit, mir, rlSrc[0], true, false);
568 break;
569
Elliott Hughesadb8c672012-03-06 16:49:32 -0800570 case Instruction::INVOKE_STATIC_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700571 genInvoke(cUnit, bb, mir, kStatic, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800572 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800573 case Instruction::INVOKE_STATIC:
buzbeefc9e6fa2012-03-23 15:14:29 -0700574 genInvoke(cUnit, bb, mir, kStatic, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800575 break;
576
Elliott Hughesadb8c672012-03-06 16:49:32 -0800577 case Instruction::INVOKE_DIRECT:
buzbeefc9e6fa2012-03-23 15:14:29 -0700578 genInvoke(cUnit, bb, mir, kDirect, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800579 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800580 case Instruction::INVOKE_DIRECT_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700581 genInvoke(cUnit, bb, mir, kDirect, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800582 break;
583
Elliott Hughesadb8c672012-03-06 16:49:32 -0800584 case Instruction::INVOKE_VIRTUAL:
buzbeefc9e6fa2012-03-23 15:14:29 -0700585 genInvoke(cUnit, bb, mir, kVirtual, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800586 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800587 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700588 genInvoke(cUnit, bb, mir, kVirtual, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800589 break;
590
Elliott Hughesadb8c672012-03-06 16:49:32 -0800591 case Instruction::INVOKE_SUPER:
buzbeefc9e6fa2012-03-23 15:14:29 -0700592 genInvoke(cUnit, bb, mir, kSuper, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800593 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800594 case Instruction::INVOKE_SUPER_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700595 genInvoke(cUnit, bb, mir, kSuper, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800596 break;
597
Elliott Hughesadb8c672012-03-06 16:49:32 -0800598 case Instruction::INVOKE_INTERFACE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700599 genInvoke(cUnit, bb, mir, kInterface, false /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800600 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800601 case Instruction::INVOKE_INTERFACE_RANGE:
buzbeefc9e6fa2012-03-23 15:14:29 -0700602 genInvoke(cUnit, bb, mir, kInterface, true /*range*/);
buzbeee3acd072012-02-25 17:03:10 -0800603 break;
604
Elliott Hughesadb8c672012-03-06 16:49:32 -0800605 case Instruction::NEG_INT:
606 case Instruction::NOT_INT:
buzbeee3acd072012-02-25 17:03:10 -0800607 res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
608 break;
609
Elliott Hughesadb8c672012-03-06 16:49:32 -0800610 case Instruction::NEG_LONG:
611 case Instruction::NOT_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800612 res = genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
613 break;
614
Elliott Hughesadb8c672012-03-06 16:49:32 -0800615 case Instruction::NEG_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800616 res = genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
617 break;
618
Elliott Hughesadb8c672012-03-06 16:49:32 -0800619 case Instruction::NEG_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800620 res = genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
621 break;
622
Elliott Hughesadb8c672012-03-06 16:49:32 -0800623 case Instruction::INT_TO_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800624 genIntToLong(cUnit, mir, rlDest, rlSrc[0]);
625 break;
626
Elliott Hughesadb8c672012-03-06 16:49:32 -0800627 case Instruction::LONG_TO_INT:
buzbeee3acd072012-02-25 17:03:10 -0800628 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
629 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
630 storeValue(cUnit, rlDest, rlSrc[0]);
631 break;
632
Elliott Hughesadb8c672012-03-06 16:49:32 -0800633 case Instruction::INT_TO_BYTE:
634 case Instruction::INT_TO_SHORT:
635 case Instruction::INT_TO_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800636 genIntNarrowing(cUnit, mir, rlDest, rlSrc[0]);
637 break;
638
Elliott Hughesadb8c672012-03-06 16:49:32 -0800639 case Instruction::INT_TO_FLOAT:
640 case Instruction::INT_TO_DOUBLE:
641 case Instruction::LONG_TO_FLOAT:
642 case Instruction::LONG_TO_DOUBLE:
643 case Instruction::FLOAT_TO_INT:
644 case Instruction::FLOAT_TO_LONG:
645 case Instruction::FLOAT_TO_DOUBLE:
646 case Instruction::DOUBLE_TO_INT:
647 case Instruction::DOUBLE_TO_LONG:
648 case Instruction::DOUBLE_TO_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800649 genConversion(cUnit, mir);
650 break;
651
Elliott Hughesadb8c672012-03-06 16:49:32 -0800652 case Instruction::ADD_INT:
653 case Instruction::SUB_INT:
654 case Instruction::MUL_INT:
655 case Instruction::DIV_INT:
656 case Instruction::REM_INT:
657 case Instruction::AND_INT:
658 case Instruction::OR_INT:
659 case Instruction::XOR_INT:
660 case Instruction::SHL_INT:
661 case Instruction::SHR_INT:
662 case Instruction::USHR_INT:
663 case Instruction::ADD_INT_2ADDR:
664 case Instruction::SUB_INT_2ADDR:
665 case Instruction::MUL_INT_2ADDR:
666 case Instruction::DIV_INT_2ADDR:
667 case Instruction::REM_INT_2ADDR:
668 case Instruction::AND_INT_2ADDR:
669 case Instruction::OR_INT_2ADDR:
670 case Instruction::XOR_INT_2ADDR:
671 case Instruction::SHL_INT_2ADDR:
672 case Instruction::SHR_INT_2ADDR:
673 case Instruction::USHR_INT_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800674 genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
675 break;
676
Elliott Hughesadb8c672012-03-06 16:49:32 -0800677 case Instruction::ADD_LONG:
678 case Instruction::SUB_LONG:
679 case Instruction::MUL_LONG:
680 case Instruction::DIV_LONG:
681 case Instruction::REM_LONG:
682 case Instruction::AND_LONG:
683 case Instruction::OR_LONG:
684 case Instruction::XOR_LONG:
685 case Instruction::ADD_LONG_2ADDR:
686 case Instruction::SUB_LONG_2ADDR:
687 case Instruction::MUL_LONG_2ADDR:
688 case Instruction::DIV_LONG_2ADDR:
689 case Instruction::REM_LONG_2ADDR:
690 case Instruction::AND_LONG_2ADDR:
691 case Instruction::OR_LONG_2ADDR:
692 case Instruction::XOR_LONG_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800693 genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
694 break;
695
Elliott Hughesadb8c672012-03-06 16:49:32 -0800696 case Instruction::SHL_LONG:
697 case Instruction::SHR_LONG:
698 case Instruction::USHR_LONG:
699 case Instruction::SHL_LONG_2ADDR:
700 case Instruction::SHR_LONG_2ADDR:
701 case Instruction::USHR_LONG_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800702 genShiftOpLong(cUnit,mir, rlDest, rlSrc[0], rlSrc[1]);
703 break;
704
Elliott Hughesadb8c672012-03-06 16:49:32 -0800705 case Instruction::ADD_FLOAT:
706 case Instruction::SUB_FLOAT:
707 case Instruction::MUL_FLOAT:
708 case Instruction::DIV_FLOAT:
709 case Instruction::REM_FLOAT:
710 case Instruction::ADD_FLOAT_2ADDR:
711 case Instruction::SUB_FLOAT_2ADDR:
712 case Instruction::MUL_FLOAT_2ADDR:
713 case Instruction::DIV_FLOAT_2ADDR:
714 case Instruction::REM_FLOAT_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800715 genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
716 break;
717
Elliott Hughesadb8c672012-03-06 16:49:32 -0800718 case Instruction::ADD_DOUBLE:
719 case Instruction::SUB_DOUBLE:
720 case Instruction::MUL_DOUBLE:
721 case Instruction::DIV_DOUBLE:
722 case Instruction::REM_DOUBLE:
723 case Instruction::ADD_DOUBLE_2ADDR:
724 case Instruction::SUB_DOUBLE_2ADDR:
725 case Instruction::MUL_DOUBLE_2ADDR:
726 case Instruction::DIV_DOUBLE_2ADDR:
727 case Instruction::REM_DOUBLE_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800728 genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
729 break;
730
Elliott Hughesadb8c672012-03-06 16:49:32 -0800731 case Instruction::RSUB_INT:
732 case Instruction::ADD_INT_LIT16:
733 case Instruction::MUL_INT_LIT16:
734 case Instruction::DIV_INT_LIT16:
735 case Instruction::REM_INT_LIT16:
736 case Instruction::AND_INT_LIT16:
737 case Instruction::OR_INT_LIT16:
738 case Instruction::XOR_INT_LIT16:
739 case Instruction::ADD_INT_LIT8:
740 case Instruction::RSUB_INT_LIT8:
741 case Instruction::MUL_INT_LIT8:
742 case Instruction::DIV_INT_LIT8:
743 case Instruction::REM_INT_LIT8:
744 case Instruction::AND_INT_LIT8:
745 case Instruction::OR_INT_LIT8:
746 case Instruction::XOR_INT_LIT8:
747 case Instruction::SHL_INT_LIT8:
748 case Instruction::SHR_INT_LIT8:
749 case Instruction::USHR_INT_LIT8:
buzbeee3acd072012-02-25 17:03:10 -0800750 genArithOpIntLit(cUnit, mir, rlDest, rlSrc[0], mir->dalvikInsn.vC);
751 break;
752
753 default:
754 res = true;
755 }
756 return res;
757}
758
buzbee31a4a6f2012-02-28 15:36:15 -0800759const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
buzbeee3acd072012-02-25 17:03:10 -0800760 "kMirOpPhi",
buzbeee1965672012-03-11 18:39:19 -0700761 "kMirOpCopy",
buzbee84fd6932012-03-29 16:44:16 -0700762 "kMirFusedCmplFloat",
763 "kMirFusedCmpgFloat",
764 "kMirFusedCmplDouble",
765 "kMirFusedCmpgDouble",
766 "kMirFusedCmpLong",
767 "kMirNop",
buzbeea2e39d92012-03-30 09:11:45 -0700768 "kMirOpNullNRangeUpCheck",
769 "kMirOpNullNRangeDownCheck",
770 "kMirOpLowerBound",
buzbeee3acd072012-02-25 17:03:10 -0800771};
772
773/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700774void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800775{
776 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
777 char* msg = NULL;
778 if (cUnit->printMe) {
779 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
780 false, kAllocDebugInfo);
781 strcpy(msg, extendedMIROpNames[opOffset]);
782 }
buzbee31a4a6f2012-02-28 15:36:15 -0800783 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800784
785 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
786 case kMirOpPhi: {
787 char* ssaString = NULL;
788 if (cUnit->printMe) {
789 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
790 }
791 op->flags.isNop = true;
buzbee31a4a6f2012-02-28 15:36:15 -0800792 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
buzbeee3acd072012-02-25 17:03:10 -0800793 break;
794 }
buzbee239c4e72012-03-16 08:42:29 -0700795 case kMirOpCopy: {
796 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
797 RegLocation rlDest = oatGetDest(cUnit, mir, 0);
798 storeValue(cUnit, rlDest, rlSrc);
buzbeee1965672012-03-11 18:39:19 -0700799 break;
buzbee239c4e72012-03-16 08:42:29 -0700800 }
buzbee84fd6932012-03-29 16:44:16 -0700801#if defined(TARGET_ARM)
802 case kMirOpFusedCmplFloat:
803 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
804 break;
805 case kMirOpFusedCmpgFloat:
806 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
807 break;
808 case kMirOpFusedCmplDouble:
809 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
810 break;
811 case kMirOpFusedCmpgDouble:
812 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
813 break;
814 case kMirOpFusedCmpLong:
815 genFusedLongCmpBranch(cUnit, bb, mir);
816 break;
817#endif
buzbeee3acd072012-02-25 17:03:10 -0800818 default:
819 break;
820 }
821}
822
823/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800824bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800825{
826 MIR* mir;
buzbee31a4a6f2012-02-28 15:36:15 -0800827 LIR* labelList = (LIR*) cUnit->blockLabelList;
buzbeee3acd072012-02-25 17:03:10 -0800828 int blockId = bb->id;
829
830 cUnit->curBlock = bb;
831 labelList[blockId].operands[0] = bb->startOffset;
832
833 /* Insert the block label */
buzbee31a4a6f2012-02-28 15:36:15 -0800834 labelList[blockId].opcode = kPseudoNormalBlockLabel;
buzbeee3acd072012-02-25 17:03:10 -0800835 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
836
buzbeee1965672012-03-11 18:39:19 -0700837 /* Free temp registers and reset redundant store tracking */
buzbeee3acd072012-02-25 17:03:10 -0800838 oatResetRegPool(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800839 oatResetDefTracking(cUnit);
840
buzbeee1965672012-03-11 18:39:19 -0700841 /*
842 * If control reached us from our immediate predecessor via
843 * fallthrough and we have no other incoming arcs we can
844 * reuse existing liveness. Otherwise, reset.
845 */
846 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
847 oatClobberAllRegs(cUnit);
848 }
849
buzbee31a4a6f2012-02-28 15:36:15 -0800850 LIR* headLIR = NULL;
buzbeee3acd072012-02-25 17:03:10 -0800851
852 if (bb->blockType == kEntryBlock) {
853 genEntrySequence(cUnit, bb);
854 } else if (bb->blockType == kExitBlock) {
855 genExitSequence(cUnit, bb);
856 }
857
858 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
859
860 oatResetRegPool(cUnit);
861 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
862 oatClobberAllRegs(cUnit);
863 }
864
865 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
866 oatResetDefTracking(cUnit);
867 }
868
buzbee3d661942012-03-14 17:37:27 -0700869#ifndef NDEBUG
870 /* Reset temp tracking sanity check */
871 cUnit->liveSReg = INVALID_SREG;
872#endif
873
buzbeee3acd072012-02-25 17:03:10 -0800874 cUnit->currentDalvikOffset = mir->offset;
875
Elliott Hughesadb8c672012-03-06 16:49:32 -0800876 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
877 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800878
buzbee31a4a6f2012-02-28 15:36:15 -0800879 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800880
881 /* Mark the beginning of a Dalvik instruction for line tracking */
882 char* instStr = cUnit->printMe ?
Elliott Hughesadb8c672012-03-06 16:49:32 -0800883 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800884 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
buzbeee3acd072012-02-25 17:03:10 -0800885 (intptr_t) instStr);
886 cUnit->boundaryMap.insert(std::make_pair(mir->offset,
887 (LIR*)boundaryLIR));
888 /* Remember the first LIR for this block */
889 if (headLIR == NULL) {
890 headLIR = boundaryLIR;
891 /* Set the first boundaryLIR as a scheduling barrier */
892 headLIR->defMask = ENCODE_ALL;
893 }
894
895 /* If we're compiling for the debugger, generate an update callout */
896 if (cUnit->genDebugger) {
897 genDebuggerUpdate(cUnit, mir->offset);
898 }
899
900 /* Don't generate the SSA annotation unless verbose mode is on */
901 if (cUnit->printMe && mir->ssaRep) {
902 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
buzbee31a4a6f2012-02-28 15:36:15 -0800903 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
buzbeee3acd072012-02-25 17:03:10 -0800904 }
905
buzbee84fd6932012-03-29 16:44:16 -0700906 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
907 handleExtendedMethodMIR(cUnit, bb, mir);
908 continue;
909 }
910
buzbeee3acd072012-02-25 17:03:10 -0800911 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
buzbeee3acd072012-02-25 17:03:10 -0800912 if (notHandled) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800913 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
914 mir->offset, dalvikOpcode, Instruction::Name(dalvikOpcode), dalvikFormat);
915
buzbeee3acd072012-02-25 17:03:10 -0800916 }
917 }
918
919 if (headLIR) {
920 /*
921 * Eliminate redundant loads/stores and delay stores into later
922 * slots
923 */
924 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR,
925 cUnit->lastLIRInsn);
926
927 /*
928 * Generate an unconditional branch to the fallthrough block.
929 */
930 if (bb->fallThrough) {
buzbee82488f52012-03-02 08:20:26 -0800931 opUnconditionalBranch(cUnit,
932 &labelList[bb->fallThrough->id]);
buzbeee3acd072012-02-25 17:03:10 -0800933 }
934 }
935 return false;
936}
937
buzbee16da88c2012-03-20 10:38:17 -0700938/* Set basic block labels */
939bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
940{
941 LIR* labelList = (LIR*) cUnit->blockLabelList;
942 int blockId = bb->id;
943
944 cUnit->curBlock = bb;
945 labelList[blockId].operands[0] = bb->startOffset;
946
947 /* Insert the block label */
948 labelList[blockId].opcode = kPseudoNormalBlockLabel;
949 return false;
950}
951
952void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
953{
954 /* Find the first DalvikByteCode block */
955 int numReachableBlocks = cUnit->numReachableBlocks;
956 const GrowableList *blockList = &cUnit->blockList;
957 BasicBlock*bb = NULL;
958 for (int idx = 0; idx < numReachableBlocks; idx++) {
959 int dfsIndex = cUnit->dfsOrder.elemList[idx];
960 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
961 if (bb->blockType == kDalvikByteCode) {
962 break;
963 }
964 }
965 if (bb == NULL) {
966 return;
967 }
968 DCHECK_EQ(bb->startOffset, 0);
969 DCHECK(bb->firstMIRInsn != 0);
970
971 /* Get the first instruction */
972 MIR* mir = bb->firstMIRInsn;
973
974 /* Free temp registers and reset redundant store tracking */
975 oatResetRegPool(cUnit);
976 oatResetDefTracking(cUnit);
977 oatClobberAllRegs(cUnit);
978
979 genSpecialCase(cUnit, bb, mir, specialCase);
980}
981
buzbeee3acd072012-02-25 17:03:10 -0800982void oatMethodMIR2LIR(CompilationUnit* cUnit)
983{
984 /* Used to hold the labels of each block */
985 cUnit->blockLabelList =
buzbee31a4a6f2012-02-28 15:36:15 -0800986 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true,
buzbeee3acd072012-02-25 17:03:10 -0800987 kAllocLIR);
988
989 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
990 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -0700991
buzbeee3acd072012-02-25 17:03:10 -0800992 handleSuspendLaunchpads(cUnit);
993
994 handleThrowLaunchpads(cUnit);
995
buzbeefc9e6fa2012-03-23 15:14:29 -0700996 handleIntrinsicLaunchpads(cUnit);
997
buzbee86a4bce2012-03-06 18:15:00 -0800998 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
999 removeRedundantBranches(cUnit);
1000 }
buzbeee3acd072012-02-25 17:03:10 -08001001}
1002
1003/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -08001004LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -08001005{
buzbee82488f52012-03-02 08:20:26 -08001006 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001007}
1008
1009/* Needed by the register allocator */
1010void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
1011{
buzbee82488f52012-03-02 08:20:26 -08001012 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001013}
1014
1015/* Needed by the register allocator */
1016void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
1017 int srcLo, int srcHi)
1018{
buzbee82488f52012-03-02 08:20:26 -08001019 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001020}
1021
1022void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
1023 int displacement, int rSrc, OpSize size)
1024{
1025 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
1026}
1027
1028void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
1029 int displacement, int rSrcLo, int rSrcHi)
1030{
1031 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
1032}
1033
1034} // namespace art