blob: 671eb7344cf934425ac71ffd2b694e58cc0915df [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
buzbee31a4a6f2012-02-28 15:36:15 -080055void genInvoke(CompilationUnit* cUnit, MIR* mir, InvokeType type, bool isRange)
buzbeee3acd072012-02-25 17:03:10 -080056{
57 DecodedInstruction* dInsn = &mir->dalvikInsn;
Brian Carlstromf5822582012-03-19 22:34:31 -070058 InvokeType originalType = type; // avoiding mutation by ComputeInvokeInfo
buzbeee3acd072012-02-25 17:03:10 -080059 int callState = 0;
buzbee31a4a6f2012-02-28 15:36:15 -080060 LIR* nullCk;
61 LIR** pNullCk = NULL;
buzbeee3acd072012-02-25 17:03:10 -080062 NextCallInsn nextCallInsn;
63 oatFlushAllRegs(cUnit); /* Everything to home location */
64 // Explicit register usage
65 oatLockCallTemps(cUnit);
66
Logan Chien4dd96f52012-02-29 01:26:58 +080067 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
buzbee31a4a6f2012-02-28 15:36:15 -080068 *cUnit->dex_file, *cUnit->dex_cache,
69 cUnit->code_item, cUnit->method_idx,
70 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080071
buzbeee3acd072012-02-25 17:03:10 -080072 uint32_t dexMethodIdx = dInsn->vB;
73 int vtableIdx;
Ian Rogers2ed3b952012-03-17 11:49:39 -070074 uintptr_t directCode;
75 uintptr_t directMethod;
buzbeee3acd072012-02-25 17:03:10 -080076 bool skipThis;
77 bool fastPath =
Logan Chien4dd96f52012-02-29 01:26:58 +080078 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, type,
Ian Rogers2ed3b952012-03-17 11:49:39 -070079 vtableIdx, directCode,
80 directMethod)
buzbeee3acd072012-02-25 17:03:10 -080081 && !SLOW_INVOKE_PATH;
82 if (type == kInterface) {
83 nextCallInsn = fastPath ? nextInterfaceCallInsn
84 : nextInterfaceCallInsnWithAccessCheck;
85 skipThis = false;
86 } else if (type == kDirect) {
87 if (fastPath) {
88 pNullCk = &nullCk;
89 }
90 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
91 skipThis = false;
92 } else if (type == kStatic) {
93 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
94 skipThis = false;
95 } else if (type == kSuper) {
Ian Rogers2ed3b952012-03-17 11:49:39 -070096 DCHECK(!fastPath); // Fast path is a direct call.
97 nextCallInsn = nextSuperCallInsnSP;
98 skipThis = false;
buzbeee3acd072012-02-25 17:03:10 -080099 } else {
100 DCHECK_EQ(type, kVirtual);
101 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
102 skipThis = fastPath;
103 }
104 if (!isRange) {
105 callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk,
106 nextCallInsn, dexMethodIdx,
Brian Carlstromf5822582012-03-19 22:34:31 -0700107 vtableIdx, directCode, directMethod,
108 originalType, skipThis);
buzbeee3acd072012-02-25 17:03:10 -0800109 } else {
110 callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
111 nextCallInsn, dexMethodIdx, vtableIdx,
Brian Carlstromf5822582012-03-19 22:34:31 -0700112 directCode, directMethod, originalType,
113 skipThis);
buzbeee3acd072012-02-25 17:03:10 -0800114 }
115 // Finish up any of the call sequence not interleaved in arg loading
116 while (callState >= 0) {
117 callState = nextCallInsn(cUnit, mir, callState, dexMethodIdx,
Brian Carlstromf5822582012-03-19 22:34:31 -0700118 vtableIdx, directCode, directMethod,
119 originalType);
buzbeee3acd072012-02-25 17:03:10 -0800120 }
121 if (DISPLAY_MISSING_TARGETS) {
122 genShowTarget(cUnit);
123 }
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700124#if !defined(TARGET_X86)
buzbee0398c422012-03-02 15:22:47 -0800125 opReg(cUnit, kOpBlx, rINVOKE_TGT);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700126#else
127 if (fastPath) {
128 opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
129 } else {
130 UNIMPLEMENTED(FATAL) << "compute trampoline";
131 opThreadMem(cUnit, kOpBlx, 0);
132 }
buzbeea7678db2012-03-05 15:35:46 -0800133#endif
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700134
135 oatClobberCalleeSave(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800136}
137
138/*
139 * Target-independent code generation. Use only high-level
140 * load/store utilities here, or target-dependent genXX() handlers
141 * when necessary.
142 */
buzbee31a4a6f2012-02-28 15:36:15 -0800143bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
144 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800145{
146 bool res = false; // Assume success
147 RegLocation rlSrc[3];
148 RegLocation rlDest = badLoc;
149 RegLocation rlResult = badLoc;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800150 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbeee3acd072012-02-25 17:03:10 -0800151
152 /* Prep Src and Dest locations */
153 int nextSreg = 0;
154 int nextLoc = 0;
155 int attrs = oatDataFlowAttributes[opcode];
156 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
157 if (attrs & DF_UA) {
158 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
159 nextSreg++;
160 } else if (attrs & DF_UA_WIDE) {
161 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
162 nextSreg + 1);
163 nextSreg+= 2;
164 }
165 if (attrs & DF_UB) {
166 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
167 nextSreg++;
168 } else if (attrs & DF_UB_WIDE) {
169 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
170 nextSreg + 1);
171 nextSreg+= 2;
172 }
173 if (attrs & DF_UC) {
174 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
175 } else if (attrs & DF_UC_WIDE) {
176 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg,
177 nextSreg + 1);
178 }
179 if (attrs & DF_DA) {
180 rlDest = oatGetDest(cUnit, mir, 0);
181 } else if (attrs & DF_DA_WIDE) {
182 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
183 }
184
185 switch(opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800186 case Instruction::NOP:
buzbeee3acd072012-02-25 17:03:10 -0800187 break;
188
Elliott Hughesadb8c672012-03-06 16:49:32 -0800189 case Instruction::MOVE_EXCEPTION:
buzbeea7678db2012-03-05 15:35:46 -0800190#if defined(TARGET_X86)
Elliott Hughesadb8c672012-03-06 16:49:32 -0800191 UNIMPLEMENTED(WARNING) << "Instruction::MOVE_EXCEPTION";
buzbeea7678db2012-03-05 15:35:46 -0800192#else
buzbeee3acd072012-02-25 17:03:10 -0800193 int exOffset;
194 int resetReg;
195 exOffset = Thread::ExceptionOffset().Int32Value();
196 resetReg = oatAllocTemp(cUnit);
197 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
198 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
199 loadConstant(cUnit, resetReg, 0);
200 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
201 storeValue(cUnit, rlDest, rlResult);
buzbeea7678db2012-03-05 15:35:46 -0800202#endif
buzbeee3acd072012-02-25 17:03:10 -0800203 break;
204
Elliott Hughesadb8c672012-03-06 16:49:32 -0800205 case Instruction::RETURN_VOID:
buzbee86a4bce2012-03-06 18:15:00 -0800206 if (!cUnit->attrs & METHOD_IS_LEAF) {
207 genSuspendTest(cUnit, mir);
208 }
buzbeee3acd072012-02-25 17:03:10 -0800209 break;
210
Elliott Hughesadb8c672012-03-06 16:49:32 -0800211 case Instruction::RETURN:
212 case Instruction::RETURN_OBJECT:
buzbee86a4bce2012-03-06 18:15:00 -0800213 if (!cUnit->attrs & METHOD_IS_LEAF) {
214 genSuspendTest(cUnit, mir);
215 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700216 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'),
217 rlSrc[0]);
buzbeee3acd072012-02-25 17:03:10 -0800218 break;
219
Elliott Hughesadb8c672012-03-06 16:49:32 -0800220 case Instruction::RETURN_WIDE:
buzbee86a4bce2012-03-06 18:15:00 -0800221 if (!cUnit->attrs & METHOD_IS_LEAF) {
222 genSuspendTest(cUnit, mir);
223 }
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700224 storeValueWide(cUnit, oatGetReturnWide(cUnit,
225 cUnit->shorty[0] == 'D'), rlSrc[0]);
buzbeee3acd072012-02-25 17:03:10 -0800226 break;
227
Elliott Hughesadb8c672012-03-06 16:49:32 -0800228 case Instruction::MOVE_RESULT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800229 if (mir->optimizationFlags & MIR_INLINED)
230 break; // Nop - combined w/ previous invoke
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700231 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
buzbeee3acd072012-02-25 17:03:10 -0800232 break;
233
Elliott Hughesadb8c672012-03-06 16:49:32 -0800234 case Instruction::MOVE_RESULT:
235 case Instruction::MOVE_RESULT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800236 if (mir->optimizationFlags & MIR_INLINED)
237 break; // Nop - combined w/ previous invoke
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700238 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
buzbeee3acd072012-02-25 17:03:10 -0800239 break;
240
Elliott Hughesadb8c672012-03-06 16:49:32 -0800241 case Instruction::MOVE:
242 case Instruction::MOVE_OBJECT:
243 case Instruction::MOVE_16:
244 case Instruction::MOVE_OBJECT_16:
245 case Instruction::MOVE_FROM16:
246 case Instruction::MOVE_OBJECT_FROM16:
buzbeee3acd072012-02-25 17:03:10 -0800247 storeValue(cUnit, rlDest, rlSrc[0]);
248 break;
249
Elliott Hughesadb8c672012-03-06 16:49:32 -0800250 case Instruction::MOVE_WIDE:
251 case Instruction::MOVE_WIDE_16:
252 case Instruction::MOVE_WIDE_FROM16:
buzbeee3acd072012-02-25 17:03:10 -0800253 storeValueWide(cUnit, rlDest, rlSrc[0]);
254 break;
255
Elliott Hughesadb8c672012-03-06 16:49:32 -0800256 case Instruction::CONST:
257 case Instruction::CONST_4:
258 case Instruction::CONST_16:
buzbeee3acd072012-02-25 17:03:10 -0800259 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
260 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
261 storeValue(cUnit, rlDest, rlResult);
262 break;
263
Elliott Hughesadb8c672012-03-06 16:49:32 -0800264 case Instruction::CONST_HIGH16:
buzbeee3acd072012-02-25 17:03:10 -0800265 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
266 loadConstantNoClobber(cUnit, rlResult.lowReg,
267 mir->dalvikInsn.vB << 16);
268 storeValue(cUnit, rlDest, rlResult);
269 break;
270
Elliott Hughesadb8c672012-03-06 16:49:32 -0800271 case Instruction::CONST_WIDE_16:
272 case Instruction::CONST_WIDE_32:
buzbeee3acd072012-02-25 17:03:10 -0800273 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
274 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
275 mir->dalvikInsn.vB,
276 (mir->dalvikInsn.vB & 0x80000000) ? -1 : 0);
277 storeValueWide(cUnit, rlDest, rlResult);
278 break;
279
Elliott Hughesadb8c672012-03-06 16:49:32 -0800280 case Instruction::CONST_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800281 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
282 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
283 mir->dalvikInsn.vB_wide & 0xffffffff,
284 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
285 storeValueWide(cUnit, rlDest, rlResult);
286 break;
287
Elliott Hughesadb8c672012-03-06 16:49:32 -0800288 case Instruction::CONST_WIDE_HIGH16:
buzbeee3acd072012-02-25 17:03:10 -0800289 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
290 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
291 0, mir->dalvikInsn.vB << 16);
292 storeValueWide(cUnit, rlDest, rlResult);
293 break;
294
Elliott Hughesadb8c672012-03-06 16:49:32 -0800295 case Instruction::MONITOR_ENTER:
buzbeee3acd072012-02-25 17:03:10 -0800296 genMonitorEnter(cUnit, mir, rlSrc[0]);
297 break;
298
Elliott Hughesadb8c672012-03-06 16:49:32 -0800299 case Instruction::MONITOR_EXIT:
buzbeee3acd072012-02-25 17:03:10 -0800300 genMonitorExit(cUnit, mir, rlSrc[0]);
301 break;
302
Elliott Hughesadb8c672012-03-06 16:49:32 -0800303 case Instruction::CHECK_CAST:
buzbeee3acd072012-02-25 17:03:10 -0800304 genCheckCast(cUnit, mir, rlSrc[0]);
305 break;
306
Elliott Hughesadb8c672012-03-06 16:49:32 -0800307 case Instruction::INSTANCE_OF:
buzbeee3acd072012-02-25 17:03:10 -0800308 genInstanceof(cUnit, mir, rlDest, rlSrc[0]);
309 break;
310
Elliott Hughesadb8c672012-03-06 16:49:32 -0800311 case Instruction::NEW_INSTANCE:
buzbeee3acd072012-02-25 17:03:10 -0800312 genNewInstance(cUnit, mir, rlDest);
313 break;
314
Elliott Hughesadb8c672012-03-06 16:49:32 -0800315 case Instruction::THROW:
buzbeee3acd072012-02-25 17:03:10 -0800316 genThrow(cUnit, mir, rlSrc[0]);
317 break;
318
Elliott Hughesadb8c672012-03-06 16:49:32 -0800319 case Instruction::THROW_VERIFICATION_ERROR:
buzbeee3acd072012-02-25 17:03:10 -0800320 genThrowVerificationError(cUnit, mir);
321 break;
322
Elliott Hughesadb8c672012-03-06 16:49:32 -0800323 case Instruction::ARRAY_LENGTH:
buzbeee3acd072012-02-25 17:03:10 -0800324 int lenOffset;
325 lenOffset = Array::LengthOffset().Int32Value();
326 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
327 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, mir);
328 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
329 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset,
330 rlResult.lowReg);
331 storeValue(cUnit, rlDest, rlResult);
332 break;
333
Elliott Hughesadb8c672012-03-06 16:49:32 -0800334 case Instruction::CONST_STRING:
335 case Instruction::CONST_STRING_JUMBO:
buzbeee3acd072012-02-25 17:03:10 -0800336 genConstString(cUnit, mir, rlDest, rlSrc[0]);
337 break;
338
Elliott Hughesadb8c672012-03-06 16:49:32 -0800339 case Instruction::CONST_CLASS:
buzbeee3acd072012-02-25 17:03:10 -0800340 genConstClass(cUnit, mir, rlDest, rlSrc[0]);
341 break;
342
Elliott Hughesadb8c672012-03-06 16:49:32 -0800343 case Instruction::FILL_ARRAY_DATA:
buzbeee3acd072012-02-25 17:03:10 -0800344 genFillArrayData(cUnit, mir, rlSrc[0]);
345 break;
346
Elliott Hughesadb8c672012-03-06 16:49:32 -0800347 case Instruction::FILLED_NEW_ARRAY:
buzbeee3acd072012-02-25 17:03:10 -0800348 genFilledNewArray(cUnit, mir, false /* not range */);
349 break;
350
Elliott Hughesadb8c672012-03-06 16:49:32 -0800351 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbeee3acd072012-02-25 17:03:10 -0800352 genFilledNewArray(cUnit, mir, true /* range */);
353 break;
354
Elliott Hughesadb8c672012-03-06 16:49:32 -0800355 case Instruction::NEW_ARRAY:
buzbeee3acd072012-02-25 17:03:10 -0800356 genNewArray(cUnit, mir, rlDest, rlSrc[0]);
357 break;
358
Elliott Hughesadb8c672012-03-06 16:49:32 -0800359 case Instruction::GOTO:
360 case Instruction::GOTO_16:
361 case Instruction::GOTO_32:
buzbeee3acd072012-02-25 17:03:10 -0800362 if (bb->taken->startOffset <= mir->offset) {
363 genSuspendTest(cUnit, mir);
364 }
buzbee82488f52012-03-02 08:20:26 -0800365 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
buzbeee3acd072012-02-25 17:03:10 -0800366 break;
367
Elliott Hughesadb8c672012-03-06 16:49:32 -0800368 case Instruction::PACKED_SWITCH:
buzbeee3acd072012-02-25 17:03:10 -0800369 genPackedSwitch(cUnit, mir, rlSrc[0]);
370 break;
371
Elliott Hughesadb8c672012-03-06 16:49:32 -0800372 case Instruction::SPARSE_SWITCH:
buzbeee3acd072012-02-25 17:03:10 -0800373 genSparseSwitch(cUnit, mir, rlSrc[0]);
374 break;
375
Elliott Hughesadb8c672012-03-06 16:49:32 -0800376 case Instruction::CMPL_FLOAT:
377 case Instruction::CMPG_FLOAT:
378 case Instruction::CMPL_DOUBLE:
379 case Instruction::CMPG_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800380 res = genCmpFP(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
381 break;
382
Elliott Hughesadb8c672012-03-06 16:49:32 -0800383 case Instruction::CMP_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800384 genCmpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
385 break;
386
Elliott Hughesadb8c672012-03-06 16:49:32 -0800387 case Instruction::IF_EQ:
388 case Instruction::IF_NE:
389 case Instruction::IF_LT:
390 case Instruction::IF_GE:
391 case Instruction::IF_GT:
392 case Instruction::IF_LE: {
buzbeee3acd072012-02-25 17:03:10 -0800393 bool backwardBranch;
394 backwardBranch = (bb->taken->startOffset <= mir->offset);
395 if (backwardBranch) {
396 genSuspendTest(cUnit, mir);
397 }
398 genCompareAndBranch(cUnit, bb, mir, rlSrc[0], rlSrc[1], labelList);
399 break;
400 }
401
Elliott Hughesadb8c672012-03-06 16:49:32 -0800402 case Instruction::IF_EQZ:
403 case Instruction::IF_NEZ:
404 case Instruction::IF_LTZ:
405 case Instruction::IF_GEZ:
406 case Instruction::IF_GTZ:
407 case Instruction::IF_LEZ: {
buzbeee3acd072012-02-25 17:03:10 -0800408 bool backwardBranch;
409 backwardBranch = (bb->taken->startOffset <= mir->offset);
410 if (backwardBranch) {
411 genSuspendTest(cUnit, mir);
412 }
413 genCompareZeroAndBranch(cUnit, bb, mir, rlSrc[0], labelList);
414 break;
415 }
416
Elliott Hughesadb8c672012-03-06 16:49:32 -0800417 case Instruction::AGET_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800418 genArrayGet(cUnit, mir, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
419 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800420 case Instruction::AGET:
421 case Instruction::AGET_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800422 genArrayGet(cUnit, mir, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
423 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800424 case Instruction::AGET_BOOLEAN:
buzbeee3acd072012-02-25 17:03:10 -0800425 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1],
426 rlDest, 0);
427 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800428 case Instruction::AGET_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800429 genArrayGet(cUnit, mir, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
430 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800431 case Instruction::AGET_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800432 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1],
433 rlDest, 1);
434 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800435 case Instruction::AGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800436 genArrayGet(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
437 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800438 case Instruction::APUT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800439 genArrayPut(cUnit, mir, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
440 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800441 case Instruction::APUT:
buzbeee3acd072012-02-25 17:03:10 -0800442 genArrayPut(cUnit, mir, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
443 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800444 case Instruction::APUT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800445 genArrayObjPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2);
446 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800447 case Instruction::APUT_SHORT:
448 case Instruction::APUT_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800449 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc[1], rlSrc[2],
450 rlSrc[0], 1);
451 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800452 case Instruction::APUT_BYTE:
453 case Instruction::APUT_BOOLEAN:
buzbeee3acd072012-02-25 17:03:10 -0800454 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc[1], rlSrc[2],
455 rlSrc[0], 0);
456 break;
457
Elliott Hughesadb8c672012-03-06 16:49:32 -0800458 case Instruction::IGET_OBJECT:
459 //case Instruction::IGET_OBJECT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800460 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, true);
461 break;
462
Elliott Hughesadb8c672012-03-06 16:49:32 -0800463 case Instruction::IGET_WIDE:
464 //case Instruction::IGET_WIDE_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800465 genIGet(cUnit, mir, kLong, rlDest, rlSrc[0], true, false);
466 break;
467
Elliott Hughesadb8c672012-03-06 16:49:32 -0800468 case Instruction::IGET:
469 //case Instruction::IGET_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800470 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, false);
471 break;
472
Elliott Hughesadb8c672012-03-06 16:49:32 -0800473 case Instruction::IGET_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800474 genIGet(cUnit, mir, kUnsignedHalf, rlDest, rlSrc[0], false, false);
475 break;
476
Elliott Hughesadb8c672012-03-06 16:49:32 -0800477 case Instruction::IGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800478 genIGet(cUnit, mir, kSignedHalf, rlDest, rlSrc[0], false, false);
479 break;
480
Elliott Hughesadb8c672012-03-06 16:49:32 -0800481 case Instruction::IGET_BOOLEAN:
482 case Instruction::IGET_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800483 genIGet(cUnit, mir, kUnsignedByte, rlDest, rlSrc[0], false, false);
484 break;
485
Elliott Hughesadb8c672012-03-06 16:49:32 -0800486 case Instruction::IPUT_WIDE:
487 //case Instruction::IPUT_WIDE_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800488 genIPut(cUnit, mir, kLong, rlSrc[0], rlSrc[1], true, false);
489 break;
490
Elliott Hughesadb8c672012-03-06 16:49:32 -0800491 case Instruction::IPUT_OBJECT:
492 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800493 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, true);
494 break;
495
Elliott Hughesadb8c672012-03-06 16:49:32 -0800496 case Instruction::IPUT:
497 //case Instruction::IPUT_VOLATILE:
buzbeee3acd072012-02-25 17:03:10 -0800498 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, false);
499 break;
500
Elliott Hughesadb8c672012-03-06 16:49:32 -0800501 case Instruction::IPUT_BOOLEAN:
502 case Instruction::IPUT_BYTE:
buzbeee3acd072012-02-25 17:03:10 -0800503 genIPut(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
504 break;
505
Elliott Hughesadb8c672012-03-06 16:49:32 -0800506 case Instruction::IPUT_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800507 genIPut(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
508 break;
509
Elliott Hughesadb8c672012-03-06 16:49:32 -0800510 case Instruction::IPUT_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800511 genIPut(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
512 break;
513
Elliott Hughesadb8c672012-03-06 16:49:32 -0800514 case Instruction::SGET_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800515 genSget(cUnit, mir, rlDest, false, true);
516 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800517 case Instruction::SGET:
518 case Instruction::SGET_BOOLEAN:
519 case Instruction::SGET_BYTE:
520 case Instruction::SGET_CHAR:
521 case Instruction::SGET_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800522 genSget(cUnit, mir, rlDest, false, false);
523 break;
524
Elliott Hughesadb8c672012-03-06 16:49:32 -0800525 case Instruction::SGET_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800526 genSget(cUnit, mir, rlDest, true, false);
527 break;
528
Elliott Hughesadb8c672012-03-06 16:49:32 -0800529 case Instruction::SPUT_OBJECT:
buzbeee3acd072012-02-25 17:03:10 -0800530 genSput(cUnit, mir, rlSrc[0], false, true);
531 break;
532
Elliott Hughesadb8c672012-03-06 16:49:32 -0800533 case Instruction::SPUT:
534 case Instruction::SPUT_BOOLEAN:
535 case Instruction::SPUT_BYTE:
536 case Instruction::SPUT_CHAR:
537 case Instruction::SPUT_SHORT:
buzbeee3acd072012-02-25 17:03:10 -0800538 genSput(cUnit, mir, rlSrc[0], false, false);
539 break;
540
Elliott Hughesadb8c672012-03-06 16:49:32 -0800541 case Instruction::SPUT_WIDE:
buzbeee3acd072012-02-25 17:03:10 -0800542 genSput(cUnit, mir, rlSrc[0], true, false);
543 break;
544
Elliott Hughesadb8c672012-03-06 16:49:32 -0800545 case Instruction::INVOKE_STATIC_RANGE:
buzbeee3acd072012-02-25 17:03:10 -0800546 genInvoke(cUnit, mir, kStatic, true /*range*/);
547 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800548 case Instruction::INVOKE_STATIC:
buzbeee3acd072012-02-25 17:03:10 -0800549 genInvoke(cUnit, mir, kStatic, false /*range*/);
550 break;
551
Elliott Hughesadb8c672012-03-06 16:49:32 -0800552 case Instruction::INVOKE_DIRECT:
buzbeee3acd072012-02-25 17:03:10 -0800553 genInvoke(cUnit, mir, kDirect, false /*range*/);
554 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800555 case Instruction::INVOKE_DIRECT_RANGE:
buzbeee3acd072012-02-25 17:03:10 -0800556 genInvoke(cUnit, mir, kDirect, true /*range*/);
557 break;
558
Elliott Hughesadb8c672012-03-06 16:49:32 -0800559 case Instruction::INVOKE_VIRTUAL:
buzbeee3acd072012-02-25 17:03:10 -0800560 genInvoke(cUnit, mir, kVirtual, false /*range*/);
561 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800562 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbeee3acd072012-02-25 17:03:10 -0800563 genInvoke(cUnit, mir, kVirtual, true /*range*/);
564 break;
565
Elliott Hughesadb8c672012-03-06 16:49:32 -0800566 case Instruction::INVOKE_SUPER:
buzbeee3acd072012-02-25 17:03:10 -0800567 genInvoke(cUnit, mir, kSuper, false /*range*/);
568 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800569 case Instruction::INVOKE_SUPER_RANGE:
buzbeee3acd072012-02-25 17:03:10 -0800570 genInvoke(cUnit, mir, kSuper, true /*range*/);
571 break;
572
Elliott Hughesadb8c672012-03-06 16:49:32 -0800573 case Instruction::INVOKE_INTERFACE:
buzbeee3acd072012-02-25 17:03:10 -0800574 genInvoke(cUnit, mir, kInterface, false /*range*/);
575 break;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800576 case Instruction::INVOKE_INTERFACE_RANGE:
buzbeee3acd072012-02-25 17:03:10 -0800577 genInvoke(cUnit, mir, kInterface, true /*range*/);
578 break;
579
Elliott Hughesadb8c672012-03-06 16:49:32 -0800580 case Instruction::NEG_INT:
581 case Instruction::NOT_INT:
buzbeee3acd072012-02-25 17:03:10 -0800582 res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
583 break;
584
Elliott Hughesadb8c672012-03-06 16:49:32 -0800585 case Instruction::NEG_LONG:
586 case Instruction::NOT_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800587 res = genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
588 break;
589
Elliott Hughesadb8c672012-03-06 16:49:32 -0800590 case Instruction::NEG_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800591 res = genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
592 break;
593
Elliott Hughesadb8c672012-03-06 16:49:32 -0800594 case Instruction::NEG_DOUBLE:
buzbeee3acd072012-02-25 17:03:10 -0800595 res = genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
596 break;
597
Elliott Hughesadb8c672012-03-06 16:49:32 -0800598 case Instruction::INT_TO_LONG:
buzbeee3acd072012-02-25 17:03:10 -0800599 genIntToLong(cUnit, mir, rlDest, rlSrc[0]);
600 break;
601
Elliott Hughesadb8c672012-03-06 16:49:32 -0800602 case Instruction::LONG_TO_INT:
buzbeee3acd072012-02-25 17:03:10 -0800603 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
604 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
605 storeValue(cUnit, rlDest, rlSrc[0]);
606 break;
607
Elliott Hughesadb8c672012-03-06 16:49:32 -0800608 case Instruction::INT_TO_BYTE:
609 case Instruction::INT_TO_SHORT:
610 case Instruction::INT_TO_CHAR:
buzbeee3acd072012-02-25 17:03:10 -0800611 genIntNarrowing(cUnit, mir, rlDest, rlSrc[0]);
612 break;
613
Elliott Hughesadb8c672012-03-06 16:49:32 -0800614 case Instruction::INT_TO_FLOAT:
615 case Instruction::INT_TO_DOUBLE:
616 case Instruction::LONG_TO_FLOAT:
617 case Instruction::LONG_TO_DOUBLE:
618 case Instruction::FLOAT_TO_INT:
619 case Instruction::FLOAT_TO_LONG:
620 case Instruction::FLOAT_TO_DOUBLE:
621 case Instruction::DOUBLE_TO_INT:
622 case Instruction::DOUBLE_TO_LONG:
623 case Instruction::DOUBLE_TO_FLOAT:
buzbeee3acd072012-02-25 17:03:10 -0800624 genConversion(cUnit, mir);
625 break;
626
Elliott Hughesadb8c672012-03-06 16:49:32 -0800627 case Instruction::ADD_INT:
628 case Instruction::SUB_INT:
629 case Instruction::MUL_INT:
630 case Instruction::DIV_INT:
631 case Instruction::REM_INT:
632 case Instruction::AND_INT:
633 case Instruction::OR_INT:
634 case Instruction::XOR_INT:
635 case Instruction::SHL_INT:
636 case Instruction::SHR_INT:
637 case Instruction::USHR_INT:
638 case Instruction::ADD_INT_2ADDR:
639 case Instruction::SUB_INT_2ADDR:
640 case Instruction::MUL_INT_2ADDR:
641 case Instruction::DIV_INT_2ADDR:
642 case Instruction::REM_INT_2ADDR:
643 case Instruction::AND_INT_2ADDR:
644 case Instruction::OR_INT_2ADDR:
645 case Instruction::XOR_INT_2ADDR:
646 case Instruction::SHL_INT_2ADDR:
647 case Instruction::SHR_INT_2ADDR:
648 case Instruction::USHR_INT_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800649 genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
650 break;
651
Elliott Hughesadb8c672012-03-06 16:49:32 -0800652 case Instruction::ADD_LONG:
653 case Instruction::SUB_LONG:
654 case Instruction::MUL_LONG:
655 case Instruction::DIV_LONG:
656 case Instruction::REM_LONG:
657 case Instruction::AND_LONG:
658 case Instruction::OR_LONG:
659 case Instruction::XOR_LONG:
660 case Instruction::ADD_LONG_2ADDR:
661 case Instruction::SUB_LONG_2ADDR:
662 case Instruction::MUL_LONG_2ADDR:
663 case Instruction::DIV_LONG_2ADDR:
664 case Instruction::REM_LONG_2ADDR:
665 case Instruction::AND_LONG_2ADDR:
666 case Instruction::OR_LONG_2ADDR:
667 case Instruction::XOR_LONG_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800668 genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
669 break;
670
Elliott Hughesadb8c672012-03-06 16:49:32 -0800671 case Instruction::SHL_LONG:
672 case Instruction::SHR_LONG:
673 case Instruction::USHR_LONG:
674 case Instruction::SHL_LONG_2ADDR:
675 case Instruction::SHR_LONG_2ADDR:
676 case Instruction::USHR_LONG_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800677 genShiftOpLong(cUnit,mir, rlDest, rlSrc[0], rlSrc[1]);
678 break;
679
Elliott Hughesadb8c672012-03-06 16:49:32 -0800680 case Instruction::ADD_FLOAT:
681 case Instruction::SUB_FLOAT:
682 case Instruction::MUL_FLOAT:
683 case Instruction::DIV_FLOAT:
684 case Instruction::REM_FLOAT:
685 case Instruction::ADD_FLOAT_2ADDR:
686 case Instruction::SUB_FLOAT_2ADDR:
687 case Instruction::MUL_FLOAT_2ADDR:
688 case Instruction::DIV_FLOAT_2ADDR:
689 case Instruction::REM_FLOAT_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800690 genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
691 break;
692
Elliott Hughesadb8c672012-03-06 16:49:32 -0800693 case Instruction::ADD_DOUBLE:
694 case Instruction::SUB_DOUBLE:
695 case Instruction::MUL_DOUBLE:
696 case Instruction::DIV_DOUBLE:
697 case Instruction::REM_DOUBLE:
698 case Instruction::ADD_DOUBLE_2ADDR:
699 case Instruction::SUB_DOUBLE_2ADDR:
700 case Instruction::MUL_DOUBLE_2ADDR:
701 case Instruction::DIV_DOUBLE_2ADDR:
702 case Instruction::REM_DOUBLE_2ADDR:
buzbeee3acd072012-02-25 17:03:10 -0800703 genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
704 break;
705
Elliott Hughesadb8c672012-03-06 16:49:32 -0800706 case Instruction::RSUB_INT:
707 case Instruction::ADD_INT_LIT16:
708 case Instruction::MUL_INT_LIT16:
709 case Instruction::DIV_INT_LIT16:
710 case Instruction::REM_INT_LIT16:
711 case Instruction::AND_INT_LIT16:
712 case Instruction::OR_INT_LIT16:
713 case Instruction::XOR_INT_LIT16:
714 case Instruction::ADD_INT_LIT8:
715 case Instruction::RSUB_INT_LIT8:
716 case Instruction::MUL_INT_LIT8:
717 case Instruction::DIV_INT_LIT8:
718 case Instruction::REM_INT_LIT8:
719 case Instruction::AND_INT_LIT8:
720 case Instruction::OR_INT_LIT8:
721 case Instruction::XOR_INT_LIT8:
722 case Instruction::SHL_INT_LIT8:
723 case Instruction::SHR_INT_LIT8:
724 case Instruction::USHR_INT_LIT8:
buzbeee3acd072012-02-25 17:03:10 -0800725 genArithOpIntLit(cUnit, mir, rlDest, rlSrc[0], mir->dalvikInsn.vC);
726 break;
727
728 default:
729 res = true;
730 }
731 return res;
732}
733
buzbee31a4a6f2012-02-28 15:36:15 -0800734const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
buzbeee3acd072012-02-25 17:03:10 -0800735 "kMirOpPhi",
736 "kMirOpNullNRangeUpCheck",
737 "kMirOpNullNRangeDownCheck",
738 "kMirOpLowerBound",
buzbeee1965672012-03-11 18:39:19 -0700739 "kMirOpCopy",
buzbeee3acd072012-02-25 17:03:10 -0800740};
741
742/* Extended MIR instructions like PHI */
buzbee31a4a6f2012-02-28 15:36:15 -0800743void handleExtendedMethodMIR(CompilationUnit* cUnit, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800744{
745 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
746 char* msg = NULL;
747 if (cUnit->printMe) {
748 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
749 false, kAllocDebugInfo);
750 strcpy(msg, extendedMIROpNames[opOffset]);
751 }
buzbee31a4a6f2012-02-28 15:36:15 -0800752 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800753
754 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
755 case kMirOpPhi: {
756 char* ssaString = NULL;
757 if (cUnit->printMe) {
758 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
759 }
760 op->flags.isNop = true;
buzbee31a4a6f2012-02-28 15:36:15 -0800761 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
buzbeee3acd072012-02-25 17:03:10 -0800762 break;
763 }
buzbee239c4e72012-03-16 08:42:29 -0700764 case kMirOpCopy: {
765 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
766 RegLocation rlDest = oatGetDest(cUnit, mir, 0);
767 storeValue(cUnit, rlDest, rlSrc);
buzbeee1965672012-03-11 18:39:19 -0700768 break;
buzbee239c4e72012-03-16 08:42:29 -0700769 }
buzbeee3acd072012-02-25 17:03:10 -0800770 default:
771 break;
772 }
773}
774
775/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800776bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800777{
778 MIR* mir;
buzbee31a4a6f2012-02-28 15:36:15 -0800779 LIR* labelList = (LIR*) cUnit->blockLabelList;
buzbeee3acd072012-02-25 17:03:10 -0800780 int blockId = bb->id;
781
782 cUnit->curBlock = bb;
783 labelList[blockId].operands[0] = bb->startOffset;
784
785 /* Insert the block label */
buzbee31a4a6f2012-02-28 15:36:15 -0800786 labelList[blockId].opcode = kPseudoNormalBlockLabel;
buzbeee3acd072012-02-25 17:03:10 -0800787 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
788
buzbeee1965672012-03-11 18:39:19 -0700789 /* Free temp registers and reset redundant store tracking */
buzbeee3acd072012-02-25 17:03:10 -0800790 oatResetRegPool(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800791 oatResetDefTracking(cUnit);
792
buzbeee1965672012-03-11 18:39:19 -0700793 /*
794 * If control reached us from our immediate predecessor via
795 * fallthrough and we have no other incoming arcs we can
796 * reuse existing liveness. Otherwise, reset.
797 */
798 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
799 oatClobberAllRegs(cUnit);
800 }
801
buzbee31a4a6f2012-02-28 15:36:15 -0800802 LIR* headLIR = NULL;
buzbeee3acd072012-02-25 17:03:10 -0800803
804 if (bb->blockType == kEntryBlock) {
805 genEntrySequence(cUnit, bb);
806 } else if (bb->blockType == kExitBlock) {
807 genExitSequence(cUnit, bb);
808 }
809
810 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
811
812 oatResetRegPool(cUnit);
813 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
814 oatClobberAllRegs(cUnit);
815 }
816
817 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
818 oatResetDefTracking(cUnit);
819 }
820
buzbee3d661942012-03-14 17:37:27 -0700821#ifndef NDEBUG
822 /* Reset temp tracking sanity check */
823 cUnit->liveSReg = INVALID_SREG;
824#endif
825
buzbeee3acd072012-02-25 17:03:10 -0800826 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
827 handleExtendedMethodMIR(cUnit, mir);
828 continue;
829 }
830
831 cUnit->currentDalvikOffset = mir->offset;
832
Elliott Hughesadb8c672012-03-06 16:49:32 -0800833 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
834 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800835
buzbee31a4a6f2012-02-28 15:36:15 -0800836 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800837
838 /* Mark the beginning of a Dalvik instruction for line tracking */
839 char* instStr = cUnit->printMe ?
Elliott Hughesadb8c672012-03-06 16:49:32 -0800840 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800841 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
buzbeee3acd072012-02-25 17:03:10 -0800842 (intptr_t) instStr);
843 cUnit->boundaryMap.insert(std::make_pair(mir->offset,
844 (LIR*)boundaryLIR));
845 /* Remember the first LIR for this block */
846 if (headLIR == NULL) {
847 headLIR = boundaryLIR;
848 /* Set the first boundaryLIR as a scheduling barrier */
849 headLIR->defMask = ENCODE_ALL;
850 }
851
852 /* If we're compiling for the debugger, generate an update callout */
853 if (cUnit->genDebugger) {
854 genDebuggerUpdate(cUnit, mir->offset);
855 }
856
857 /* Don't generate the SSA annotation unless verbose mode is on */
858 if (cUnit->printMe && mir->ssaRep) {
859 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
buzbee31a4a6f2012-02-28 15:36:15 -0800860 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
buzbeee3acd072012-02-25 17:03:10 -0800861 }
862
863 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
buzbeee3acd072012-02-25 17:03:10 -0800864 if (notHandled) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800865 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
866 mir->offset, dalvikOpcode, Instruction::Name(dalvikOpcode), dalvikFormat);
867
buzbeee3acd072012-02-25 17:03:10 -0800868 }
869 }
870
871 if (headLIR) {
872 /*
873 * Eliminate redundant loads/stores and delay stores into later
874 * slots
875 */
876 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR,
877 cUnit->lastLIRInsn);
878
879 /*
880 * Generate an unconditional branch to the fallthrough block.
881 */
882 if (bb->fallThrough) {
buzbee82488f52012-03-02 08:20:26 -0800883 opUnconditionalBranch(cUnit,
884 &labelList[bb->fallThrough->id]);
buzbeee3acd072012-02-25 17:03:10 -0800885 }
886 }
887 return false;
888}
889
buzbee16da88c2012-03-20 10:38:17 -0700890/* Set basic block labels */
891bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
892{
893 LIR* labelList = (LIR*) cUnit->blockLabelList;
894 int blockId = bb->id;
895
896 cUnit->curBlock = bb;
897 labelList[blockId].operands[0] = bb->startOffset;
898
899 /* Insert the block label */
900 labelList[blockId].opcode = kPseudoNormalBlockLabel;
901 return false;
902}
903
904void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
905{
906 /* Find the first DalvikByteCode block */
907 int numReachableBlocks = cUnit->numReachableBlocks;
908 const GrowableList *blockList = &cUnit->blockList;
909 BasicBlock*bb = NULL;
910 for (int idx = 0; idx < numReachableBlocks; idx++) {
911 int dfsIndex = cUnit->dfsOrder.elemList[idx];
912 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
913 if (bb->blockType == kDalvikByteCode) {
914 break;
915 }
916 }
917 if (bb == NULL) {
918 return;
919 }
920 DCHECK_EQ(bb->startOffset, 0);
921 DCHECK(bb->firstMIRInsn != 0);
922
923 /* Get the first instruction */
924 MIR* mir = bb->firstMIRInsn;
925
926 /* Free temp registers and reset redundant store tracking */
927 oatResetRegPool(cUnit);
928 oatResetDefTracking(cUnit);
929 oatClobberAllRegs(cUnit);
930
931 genSpecialCase(cUnit, bb, mir, specialCase);
932}
933
buzbeee3acd072012-02-25 17:03:10 -0800934void oatMethodMIR2LIR(CompilationUnit* cUnit)
935{
936 /* Used to hold the labels of each block */
937 cUnit->blockLabelList =
buzbee31a4a6f2012-02-28 15:36:15 -0800938 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true,
buzbeee3acd072012-02-25 17:03:10 -0800939 kAllocLIR);
940
941 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
942 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -0700943
buzbeee3acd072012-02-25 17:03:10 -0800944 handleSuspendLaunchpads(cUnit);
945
946 handleThrowLaunchpads(cUnit);
947
buzbee86a4bce2012-03-06 18:15:00 -0800948 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
949 removeRedundantBranches(cUnit);
950 }
buzbeee3acd072012-02-25 17:03:10 -0800951}
952
953/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -0800954LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -0800955{
buzbee82488f52012-03-02 08:20:26 -0800956 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -0800957}
958
959/* Needed by the register allocator */
960void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
961{
buzbee82488f52012-03-02 08:20:26 -0800962 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -0800963}
964
965/* Needed by the register allocator */
966void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
967 int srcLo, int srcHi)
968{
buzbee82488f52012-03-02 08:20:26 -0800969 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -0800970}
971
972void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
973 int displacement, int rSrc, OpSize size)
974{
975 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
976}
977
978void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
979 int displacement, int rSrcLo, int rSrcHi)
980{
981 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
982}
983
984} // namespace art