blob: 9c51f0a49e615e22be29ce530436647b7a936f1d [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "object_utils.h"
18
19namespace art {
20
21#define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \
Bill Buzbeea114add2012-05-03 15:00:40 -070022 (1 << kDebugDisplayMissingTargets))
buzbeee3acd072012-02-25 17:03:10 -080023
buzbeebff24652012-05-06 16:22:05 -070024const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0,
buzbee31a4a6f2012-02-28 15:36:15 -080025 INVALID_REG, INVALID_REG, INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080026
27/* Mark register usage state and return long retloc */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070028RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080029{
Bill Buzbeea114add2012-05-03 15:00:40 -070030 RegLocation gpr_res = LOC_C_RETURN_WIDE;
31 RegLocation fpr_res = LOC_C_RETURN_WIDE_DOUBLE;
32 RegLocation res = isDouble ? fpr_res : gpr_res;
33 oatClobber(cUnit, res.lowReg);
34 oatClobber(cUnit, res.highReg);
35 oatLockTemp(cUnit, res.lowReg);
36 oatLockTemp(cUnit, res.highReg);
37 oatMarkPair(cUnit, res.lowReg, res.highReg);
38 return res;
buzbeee3acd072012-02-25 17:03:10 -080039}
40
Ian Rogersf7d9ad32012-03-13 18:45:39 -070041RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
buzbeee3acd072012-02-25 17:03:10 -080042{
Ian Rogersf7d9ad32012-03-13 18:45:39 -070043 RegLocation gpr_res = LOC_C_RETURN;
44 RegLocation fpr_res = LOC_C_RETURN_FLOAT;
45 RegLocation res = isFloat ? fpr_res : gpr_res;
Bill Buzbeea114add2012-05-03 15:00:40 -070046 oatClobber(cUnit, res.lowReg);
47 if (cUnit->instructionSet == kMips) {
48 oatMarkInUse(cUnit, res.lowReg);
49 } else {
50 oatLockTemp(cUnit, res.lowReg);
51 }
52 return res;
buzbeee3acd072012-02-25 17:03:10 -080053}
54
buzbeefc9e6fa2012-03-23 15:14:29 -070055void genInvoke(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
56 InvokeType type, bool isRange)
buzbeee3acd072012-02-25 17:03:10 -080057{
Bill Buzbeea114add2012-05-03 15:00:40 -070058 if (genIntrinsic(cUnit, bb, mir, type, isRange)) {
59 return;
60 }
61 DecodedInstruction* dInsn = &mir->dalvikInsn;
62 InvokeType originalType = type; // avoiding mutation by ComputeInvokeInfo
63 int callState = 0;
64 LIR* nullCk;
65 LIR** pNullCk = NULL;
66 NextCallInsn nextCallInsn;
67 oatFlushAllRegs(cUnit); /* Everything to home location */
68 // Explicit register usage
69 oatLockCallTemps(cUnit);
buzbeee3acd072012-02-25 17:03:10 -080070
Bill Buzbeea114add2012-05-03 15:00:40 -070071 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
72 *cUnit->dex_file, *cUnit->dex_cache,
73 cUnit->code_item, cUnit->method_idx,
74 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080075
Bill Buzbeea114add2012-05-03 15:00:40 -070076 uint32_t dexMethodIdx = dInsn->vB;
77 int vtableIdx;
78 uintptr_t directCode;
79 uintptr_t directMethod;
80 bool skipThis;
81 bool fastPath =
82 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, type,
83 vtableIdx, directCode,
84 directMethod)
85 && !SLOW_INVOKE_PATH;
86 if (type == kInterface) {
87 nextCallInsn = fastPath ? nextInterfaceCallInsn
88 : nextInterfaceCallInsnWithAccessCheck;
89 skipThis = false;
90 } else if (type == kDirect) {
91 if (fastPath) {
92 pNullCk = &nullCk;
buzbeee3acd072012-02-25 17:03:10 -080093 }
Bill Buzbeea114add2012-05-03 15:00:40 -070094 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
95 skipThis = false;
96 } else if (type == kStatic) {
97 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
98 skipThis = false;
99 } else if (type == kSuper) {
100 DCHECK(!fastPath); // Fast path is a direct call.
101 nextCallInsn = nextSuperCallInsnSP;
102 skipThis = false;
103 } else {
104 DCHECK_EQ(type, kVirtual);
105 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
106 skipThis = fastPath;
107 }
108 if (!isRange) {
109 callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk,
110 nextCallInsn, dexMethodIdx,
111 vtableIdx, directCode, directMethod,
112 originalType, skipThis);
113 } else {
114 callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
115 nextCallInsn, dexMethodIdx, vtableIdx,
116 directCode, directMethod, originalType,
117 skipThis);
118 }
119 // Finish up any of the call sequence not interleaved in arg loading
120 while (callState >= 0) {
121 callState = nextCallInsn(cUnit, mir, callState, dexMethodIdx,
122 vtableIdx, directCode, directMethod,
123 originalType);
124 }
125 if (DISPLAY_MISSING_TARGETS) {
126 genShowTarget(cUnit);
127 }
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700128#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 opReg(cUnit, kOpBlx, rINVOKE_TGT);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700130#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 if (fastPath && type != kInterface) {
132 opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
133 } else {
134 int trampoline = 0;
135 switch (type) {
136 case kInterface:
137 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
138 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
139 break;
140 case kDirect:
141 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
142 break;
143 case kStatic:
144 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
145 break;
146 case kSuper:
147 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
148 break;
149 case kVirtual:
150 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
151 break;
152 default:
153 LOG(FATAL) << "Unexpected invoke type";
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700154 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 opThreadMem(cUnit, kOpBlx, trampoline);
156 }
buzbeea7678db2012-03-05 15:35:46 -0800157#endif
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700158
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 oatClobberCalleeSave(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800160}
161
162/*
163 * Target-independent code generation. Use only high-level
164 * load/store utilities here, or target-dependent genXX() handlers
165 * when necessary.
166 */
buzbee31a4a6f2012-02-28 15:36:15 -0800167bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
168 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800169{
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 bool res = false; // Assume success
171 RegLocation rlSrc[3];
172 RegLocation rlDest = badLoc;
173 RegLocation rlResult = badLoc;
174 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee408ad162012-06-06 16:45:18 -0700175 int optFlags = mir->optimizationFlags;
176 uint32_t vA = mir->dalvikInsn.vA;
177 uint32_t vB = mir->dalvikInsn.vB;
178 uint32_t vC = mir->dalvikInsn.vC;
buzbeee3acd072012-02-25 17:03:10 -0800179
Bill Buzbeea114add2012-05-03 15:00:40 -0700180 /* Prep Src and Dest locations */
181 int nextSreg = 0;
182 int nextLoc = 0;
183 int attrs = oatDataFlowAttributes[opcode];
184 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
185 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700186 if (attrs & DF_A_WIDE) {
187 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
188 nextSreg+= 2;
189 } else {
190 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
191 nextSreg++;
192 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 }
194 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700195 if (attrs & DF_B_WIDE) {
196 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
197 nextSreg+= 2;
198 } else {
199 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
200 nextSreg++;
201 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700202 }
203 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700204 if (attrs & DF_C_WIDE) {
205 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
206 } else {
207 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
208 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700209 }
210 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700211 if (attrs & DF_A_WIDE) {
212 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
213 } else {
214 rlDest = oatGetDest(cUnit, mir, 0);
215 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700216 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 switch (opcode) {
218 case Instruction::NOP:
219 break;
buzbeee3acd072012-02-25 17:03:10 -0800220
Bill Buzbeea114add2012-05-03 15:00:40 -0700221 case Instruction::MOVE_EXCEPTION: {
222 int exOffset = Thread::ExceptionOffset().Int32Value();
223 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700224#if defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700225 newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset);
226 newLIR2(cUnit, kX86Mov32TI, exOffset, 0);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700227#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 int resetReg = oatAllocTemp(cUnit);
229 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
230 loadConstant(cUnit, resetReg, 0);
231 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700232 oatFreeTemp(cUnit, resetReg);
buzbeea7678db2012-03-05 15:35:46 -0800233#endif
jeffhao41005dd2012-05-09 17:58:52 -0700234 storeValue(cUnit, rlDest, rlResult);
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 break;
buzbeee3acd072012-02-25 17:03:10 -0800236 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700237 case Instruction::RETURN_VOID:
238 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700239 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 }
241 break;
242
243 case Instruction::RETURN:
244 case Instruction::RETURN_OBJECT:
245 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700246 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 }
248 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
249 break;
250
251 case Instruction::RETURN_WIDE:
252 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700253 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 }
255 storeValueWide(cUnit, oatGetReturnWide(cUnit,
256 cUnit->shorty[0] == 'D'), rlSrc[0]);
257 break;
258
259 case Instruction::MOVE_RESULT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700260 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700261 break; // Nop - combined w/ previous invoke
262 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
263 break;
264
265 case Instruction::MOVE_RESULT:
266 case Instruction::MOVE_RESULT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700267 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 break; // Nop - combined w/ previous invoke
269 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
270 break;
271
272 case Instruction::MOVE:
273 case Instruction::MOVE_OBJECT:
274 case Instruction::MOVE_16:
275 case Instruction::MOVE_OBJECT_16:
276 case Instruction::MOVE_FROM16:
277 case Instruction::MOVE_OBJECT_FROM16:
278 storeValue(cUnit, rlDest, rlSrc[0]);
279 break;
280
281 case Instruction::MOVE_WIDE:
282 case Instruction::MOVE_WIDE_16:
283 case Instruction::MOVE_WIDE_FROM16:
284 storeValueWide(cUnit, rlDest, rlSrc[0]);
285 break;
286
287 case Instruction::CONST:
288 case Instruction::CONST_4:
289 case Instruction::CONST_16:
290 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700291 loadConstantNoClobber(cUnit, rlResult.lowReg, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 storeValue(cUnit, rlDest, rlResult);
293 break;
294
295 case Instruction::CONST_HIGH16:
296 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700297 loadConstantNoClobber(cUnit, rlResult.lowReg, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700298 storeValue(cUnit, rlDest, rlResult);
299 break;
300
301 case Instruction::CONST_WIDE_16:
302 case Instruction::CONST_WIDE_32:
303 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700304 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg, vB,
305 (vB & 0x80000000) ? -1 : 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700306 storeValueWide(cUnit, rlDest, rlResult);
307 break;
308
309 case Instruction::CONST_WIDE:
310 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
311 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
312 mir->dalvikInsn.vB_wide & 0xffffffff,
313 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
314 storeValueWide(cUnit, rlDest, rlResult);
315 break;
316
317 case Instruction::CONST_WIDE_HIGH16:
318 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
319 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
buzbee408ad162012-06-06 16:45:18 -0700320 0, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700321 storeValueWide(cUnit, rlDest, rlResult);
322 break;
323
324 case Instruction::MONITOR_ENTER:
buzbee408ad162012-06-06 16:45:18 -0700325 genMonitorEnter(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 break;
327
328 case Instruction::MONITOR_EXIT:
buzbee408ad162012-06-06 16:45:18 -0700329 genMonitorExit(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 break;
331
332 case Instruction::CHECK_CAST:
buzbee408ad162012-06-06 16:45:18 -0700333 genCheckCast(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 break;
335
336 case Instruction::INSTANCE_OF:
buzbee408ad162012-06-06 16:45:18 -0700337 genInstanceof(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700338 break;
339
340 case Instruction::NEW_INSTANCE:
buzbee408ad162012-06-06 16:45:18 -0700341 genNewInstance(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 break;
343
344 case Instruction::THROW:
buzbee408ad162012-06-06 16:45:18 -0700345 genThrow(cUnit, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700346 break;
347
348 case Instruction::THROW_VERIFICATION_ERROR:
buzbee408ad162012-06-06 16:45:18 -0700349 genThrowVerificationError(cUnit, vA, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700350 break;
351
352 case Instruction::ARRAY_LENGTH:
353 int lenOffset;
354 lenOffset = Array::LengthOffset().Int32Value();
355 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
buzbee408ad162012-06-06 16:45:18 -0700356 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
358 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
359 storeValue(cUnit, rlDest, rlResult);
360 break;
361
362 case Instruction::CONST_STRING:
363 case Instruction::CONST_STRING_JUMBO:
buzbee408ad162012-06-06 16:45:18 -0700364 genConstString(cUnit, vB, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700365 break;
366
367 case Instruction::CONST_CLASS:
buzbee408ad162012-06-06 16:45:18 -0700368 genConstClass(cUnit, vB, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 break;
370
371 case Instruction::FILL_ARRAY_DATA:
buzbee408ad162012-06-06 16:45:18 -0700372 genFillArrayData(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700373 break;
374
375 case Instruction::FILLED_NEW_ARRAY:
376 genFilledNewArray(cUnit, mir, false /* not range */);
377 break;
378
379 case Instruction::FILLED_NEW_ARRAY_RANGE:
380 genFilledNewArray(cUnit, mir, true /* range */);
381 break;
382
383 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700384 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 break;
386
387 case Instruction::GOTO:
388 case Instruction::GOTO_16:
389 case Instruction::GOTO_32:
390 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700391 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700392 } else {
393 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
394 }
395 break;
396
397 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700398 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 break;
400
401 case Instruction::SPARSE_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700402 genSparseSwitch(cUnit, vB, rlSrc[0], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 break;
404
405 case Instruction::CMPL_FLOAT:
406 case Instruction::CMPG_FLOAT:
407 case Instruction::CMPL_DOUBLE:
408 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700409 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700410 break;
411
412 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700413 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700414 break;
415
416 case Instruction::IF_EQ:
417 case Instruction::IF_NE:
418 case Instruction::IF_LT:
419 case Instruction::IF_GE:
420 case Instruction::IF_GT:
421 case Instruction::IF_LE: {
422 bool backwardBranch;
423 backwardBranch = (bb->taken->startOffset <= mir->offset);
424 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700425 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 }
buzbee408ad162012-06-06 16:45:18 -0700427 genCompareAndBranch(cUnit, bb, opcode, rlSrc[0], rlSrc[1], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700428 break;
429 }
430
431 case Instruction::IF_EQZ:
432 case Instruction::IF_NEZ:
433 case Instruction::IF_LTZ:
434 case Instruction::IF_GEZ:
435 case Instruction::IF_GTZ:
436 case Instruction::IF_LEZ: {
437 bool backwardBranch;
438 backwardBranch = (bb->taken->startOffset <= mir->offset);
439 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700440 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700441 }
buzbee408ad162012-06-06 16:45:18 -0700442 genCompareZeroAndBranch(cUnit, bb, opcode, rlSrc[0], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700443 break;
444 }
445
446 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700447 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700448 break;
449 case Instruction::AGET:
450 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700451 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700452 break;
453 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700454 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 break;
456 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700457 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 break;
459 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700460 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 break;
462 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700463 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 break;
465 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700466 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 break;
468 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700469 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 break;
471 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700472 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700473 break;
474 case Instruction::APUT_SHORT:
475 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700476 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700477 break;
478 case Instruction::APUT_BYTE:
479 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700480 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 rlSrc[0], 0);
482 break;
483
484 case Instruction::IGET_OBJECT:
485 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700486 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 break;
488
489 case Instruction::IGET_WIDE:
490 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700491 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700492 break;
493
494 case Instruction::IGET:
495 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700496 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 break;
498
499 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700500 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 break;
502
503 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700504 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700505 break;
506
507 case Instruction::IGET_BOOLEAN:
508 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700509 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 break;
511
512 case Instruction::IPUT_WIDE:
513 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700514 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700515 break;
516
517 case Instruction::IPUT_OBJECT:
518 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700519 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700520 break;
521
522 case Instruction::IPUT:
523 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700524 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 break;
526
527 case Instruction::IPUT_BOOLEAN:
528 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700529 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700530 break;
531
532 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700533 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 break;
535
536 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700537 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 break;
539
540 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700541 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700542 break;
543 case Instruction::SGET:
544 case Instruction::SGET_BOOLEAN:
545 case Instruction::SGET_BYTE:
546 case Instruction::SGET_CHAR:
547 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700548 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700549 break;
550
551 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700552 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 break;
554
555 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700556 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 break;
558
559 case Instruction::SPUT:
560 case Instruction::SPUT_BOOLEAN:
561 case Instruction::SPUT_BYTE:
562 case Instruction::SPUT_CHAR:
563 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700564 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 break;
566
567 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700568 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700569 break;
570
571 case Instruction::INVOKE_STATIC_RANGE:
572 genInvoke(cUnit, bb, mir, kStatic, true /*range*/);
573 break;
574 case Instruction::INVOKE_STATIC:
575 genInvoke(cUnit, bb, mir, kStatic, false /*range*/);
576 break;
577
578 case Instruction::INVOKE_DIRECT:
579 genInvoke(cUnit, bb, mir, kDirect, false /*range*/);
580 break;
581 case Instruction::INVOKE_DIRECT_RANGE:
582 genInvoke(cUnit, bb, mir, kDirect, true /*range*/);
583 break;
584
585 case Instruction::INVOKE_VIRTUAL:
586 genInvoke(cUnit, bb, mir, kVirtual, false /*range*/);
587 break;
588 case Instruction::INVOKE_VIRTUAL_RANGE:
589 genInvoke(cUnit, bb, mir, kVirtual, true /*range*/);
590 break;
591
592 case Instruction::INVOKE_SUPER:
593 genInvoke(cUnit, bb, mir, kSuper, false /*range*/);
594 break;
595 case Instruction::INVOKE_SUPER_RANGE:
596 genInvoke(cUnit, bb, mir, kSuper, true /*range*/);
597 break;
598
599 case Instruction::INVOKE_INTERFACE:
600 genInvoke(cUnit, bb, mir, kInterface, false /*range*/);
601 break;
602 case Instruction::INVOKE_INTERFACE_RANGE:
603 genInvoke(cUnit, bb, mir, kInterface, true /*range*/);
604 break;
605
606 case Instruction::NEG_INT:
607 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700608 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 break;
610
611 case Instruction::NEG_LONG:
612 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700613 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700614 break;
615
616 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700617 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 break;
619
620 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700621 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 break;
623
624 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700625 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 break;
627
628 case Instruction::LONG_TO_INT:
629 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
630 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
631 storeValue(cUnit, rlDest, rlSrc[0]);
632 break;
633
634 case Instruction::INT_TO_BYTE:
635 case Instruction::INT_TO_SHORT:
636 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700637 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 break;
639
640 case Instruction::INT_TO_FLOAT:
641 case Instruction::INT_TO_DOUBLE:
642 case Instruction::LONG_TO_FLOAT:
643 case Instruction::LONG_TO_DOUBLE:
644 case Instruction::FLOAT_TO_INT:
645 case Instruction::FLOAT_TO_LONG:
646 case Instruction::FLOAT_TO_DOUBLE:
647 case Instruction::DOUBLE_TO_INT:
648 case Instruction::DOUBLE_TO_LONG:
649 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700650 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 break;
652
653 case Instruction::ADD_INT:
654 case Instruction::SUB_INT:
655 case Instruction::MUL_INT:
656 case Instruction::DIV_INT:
657 case Instruction::REM_INT:
658 case Instruction::AND_INT:
659 case Instruction::OR_INT:
660 case Instruction::XOR_INT:
661 case Instruction::SHL_INT:
662 case Instruction::SHR_INT:
663 case Instruction::USHR_INT:
664 case Instruction::ADD_INT_2ADDR:
665 case Instruction::SUB_INT_2ADDR:
666 case Instruction::MUL_INT_2ADDR:
667 case Instruction::DIV_INT_2ADDR:
668 case Instruction::REM_INT_2ADDR:
669 case Instruction::AND_INT_2ADDR:
670 case Instruction::OR_INT_2ADDR:
671 case Instruction::XOR_INT_2ADDR:
672 case Instruction::SHL_INT_2ADDR:
673 case Instruction::SHR_INT_2ADDR:
674 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700675 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700676 break;
677
678 case Instruction::ADD_LONG:
679 case Instruction::SUB_LONG:
680 case Instruction::MUL_LONG:
681 case Instruction::DIV_LONG:
682 case Instruction::REM_LONG:
683 case Instruction::AND_LONG:
684 case Instruction::OR_LONG:
685 case Instruction::XOR_LONG:
686 case Instruction::ADD_LONG_2ADDR:
687 case Instruction::SUB_LONG_2ADDR:
688 case Instruction::MUL_LONG_2ADDR:
689 case Instruction::DIV_LONG_2ADDR:
690 case Instruction::REM_LONG_2ADDR:
691 case Instruction::AND_LONG_2ADDR:
692 case Instruction::OR_LONG_2ADDR:
693 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700694 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700695 break;
696
697 case Instruction::SHL_LONG:
698 case Instruction::SHR_LONG:
699 case Instruction::USHR_LONG:
700 case Instruction::SHL_LONG_2ADDR:
701 case Instruction::SHR_LONG_2ADDR:
702 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700703 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700704 break;
705
706 case Instruction::ADD_FLOAT:
707 case Instruction::SUB_FLOAT:
708 case Instruction::MUL_FLOAT:
709 case Instruction::DIV_FLOAT:
710 case Instruction::REM_FLOAT:
711 case Instruction::ADD_FLOAT_2ADDR:
712 case Instruction::SUB_FLOAT_2ADDR:
713 case Instruction::MUL_FLOAT_2ADDR:
714 case Instruction::DIV_FLOAT_2ADDR:
715 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700716 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700717 break;
718
719 case Instruction::ADD_DOUBLE:
720 case Instruction::SUB_DOUBLE:
721 case Instruction::MUL_DOUBLE:
722 case Instruction::DIV_DOUBLE:
723 case Instruction::REM_DOUBLE:
724 case Instruction::ADD_DOUBLE_2ADDR:
725 case Instruction::SUB_DOUBLE_2ADDR:
726 case Instruction::MUL_DOUBLE_2ADDR:
727 case Instruction::DIV_DOUBLE_2ADDR:
728 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700729 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700730 break;
731
732 case Instruction::RSUB_INT:
733 case Instruction::ADD_INT_LIT16:
734 case Instruction::MUL_INT_LIT16:
735 case Instruction::DIV_INT_LIT16:
736 case Instruction::REM_INT_LIT16:
737 case Instruction::AND_INT_LIT16:
738 case Instruction::OR_INT_LIT16:
739 case Instruction::XOR_INT_LIT16:
740 case Instruction::ADD_INT_LIT8:
741 case Instruction::RSUB_INT_LIT8:
742 case Instruction::MUL_INT_LIT8:
743 case Instruction::DIV_INT_LIT8:
744 case Instruction::REM_INT_LIT8:
745 case Instruction::AND_INT_LIT8:
746 case Instruction::OR_INT_LIT8:
747 case Instruction::XOR_INT_LIT8:
748 case Instruction::SHL_INT_LIT8:
749 case Instruction::SHR_INT_LIT8:
750 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700751 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700752 break;
753
754 default:
755 res = true;
756 }
757 return res;
buzbeee3acd072012-02-25 17:03:10 -0800758}
759
buzbee31a4a6f2012-02-28 15:36:15 -0800760const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700761 "kMirOpPhi",
762 "kMirOpCopy",
763 "kMirFusedCmplFloat",
764 "kMirFusedCmpgFloat",
765 "kMirFusedCmplDouble",
766 "kMirFusedCmpgDouble",
767 "kMirFusedCmpLong",
768 "kMirNop",
769 "kMirOpNullNRangeUpCheck",
770 "kMirOpNullNRangeDownCheck",
771 "kMirOpLowerBound",
buzbeee3acd072012-02-25 17:03:10 -0800772};
773
774/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700775void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800776{
Bill Buzbeea114add2012-05-03 15:00:40 -0700777 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
778 char* msg = NULL;
779 if (cUnit->printMe) {
780 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
781 false, kAllocDebugInfo);
782 strcpy(msg, extendedMIROpNames[opOffset]);
783 }
784 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800785
Bill Buzbeea114add2012-05-03 15:00:40 -0700786 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
787 case kMirOpPhi: {
788 char* ssaString = NULL;
789 if (cUnit->printMe) {
790 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
791 }
792 op->flags.isNop = true;
793 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
794 break;
buzbeee3acd072012-02-25 17:03:10 -0800795 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700796 case kMirOpCopy: {
797 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
798 RegLocation rlDest = oatGetDest(cUnit, mir, 0);
799 storeValue(cUnit, rlDest, rlSrc);
800 break;
801 }
802#if defined(TARGET_ARM)
803 case kMirOpFusedCmplFloat:
804 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
805 break;
806 case kMirOpFusedCmpgFloat:
807 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
808 break;
809 case kMirOpFusedCmplDouble:
810 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
811 break;
812 case kMirOpFusedCmpgDouble:
813 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
814 break;
815 case kMirOpFusedCmpLong:
816 genFusedLongCmpBranch(cUnit, bb, mir);
817 break;
818#endif
819 default:
820 break;
821 }
buzbeee3acd072012-02-25 17:03:10 -0800822}
823
824/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800825bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800826{
Bill Buzbeea114add2012-05-03 15:00:40 -0700827 MIR* mir;
828 LIR* labelList = (LIR*) cUnit->blockLabelList;
829 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800830
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 cUnit->curBlock = bb;
832 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800833
Bill Buzbeea114add2012-05-03 15:00:40 -0700834 /* Insert the block label */
835 labelList[blockId].opcode = kPseudoNormalBlockLabel;
836 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800837
Bill Buzbeea114add2012-05-03 15:00:40 -0700838 /* Free temp registers and reset redundant store tracking */
839 oatResetRegPool(cUnit);
840 oatResetDefTracking(cUnit);
841
842 /*
843 * If control reached us from our immediate predecessor via
844 * fallthrough and we have no other incoming arcs we can
845 * reuse existing liveness. Otherwise, reset.
846 */
847 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
848 oatClobberAllRegs(cUnit);
849 }
850
851 LIR* headLIR = NULL;
852
853 if (bb->blockType == kEntryBlock) {
854 genEntrySequence(cUnit, bb);
855 } else if (bb->blockType == kExitBlock) {
856 genExitSequence(cUnit, bb);
857 }
858
859 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
860
buzbeee3acd072012-02-25 17:03:10 -0800861 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
863 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700864 }
865
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
867 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800868 }
869
buzbee3d661942012-03-14 17:37:27 -0700870#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 /* Reset temp tracking sanity check */
872 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700873#endif
874
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 cUnit->currentDalvikOffset = mir->offset;
buzbeee3acd072012-02-25 17:03:10 -0800876
Bill Buzbeea114add2012-05-03 15:00:40 -0700877 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
878 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800879
Bill Buzbeea114add2012-05-03 15:00:40 -0700880 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800881
Bill Buzbeea114add2012-05-03 15:00:40 -0700882 /* Mark the beginning of a Dalvik instruction for line tracking */
883 char* instStr = cUnit->printMe ?
884 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
885 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
886 (intptr_t) instStr);
887 cUnit->boundaryMap.Overwrite(mir->offset, 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;
buzbeee3acd072012-02-25 17:03:10 -0800893 }
894
Bill Buzbeea114add2012-05-03 15:00:40 -0700895 /* If we're compiling for the debugger, generate an update callout */
896 if (cUnit->genDebugger) {
897 genDebuggerUpdate(cUnit, mir->offset);
buzbeee3acd072012-02-25 17:03:10 -0800898 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700899
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);
903 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
904 }
905
906 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
907 handleExtendedMethodMIR(cUnit, bb, mir);
908 continue;
909 }
910
911 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
912 if (notHandled) {
913 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
914 mir->offset, dalvikOpcode,
915 Instruction::Name(dalvikOpcode), dalvikFormat);
916
917 }
918 }
919
920 if (headLIR) {
921 /*
922 * Eliminate redundant loads/stores and delay stores into later
923 * slots
924 */
925 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
926
927 /*
928 * Generate an unconditional branch to the fallthrough block.
929 */
930 if (bb->fallThrough) {
931 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
932 }
933 }
934 return false;
buzbeee3acd072012-02-25 17:03:10 -0800935}
936
buzbee16da88c2012-03-20 10:38:17 -0700937/* Set basic block labels */
938bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
939{
Bill Buzbeea114add2012-05-03 15:00:40 -0700940 LIR* labelList = (LIR*) cUnit->blockLabelList;
941 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700942
Bill Buzbeea114add2012-05-03 15:00:40 -0700943 cUnit->curBlock = bb;
944 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700945
Bill Buzbeea114add2012-05-03 15:00:40 -0700946 /* Insert the block label */
947 labelList[blockId].opcode = kPseudoNormalBlockLabel;
948 return false;
buzbee16da88c2012-03-20 10:38:17 -0700949}
950
951void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
952{
Bill Buzbeea114add2012-05-03 15:00:40 -0700953 /* Find the first DalvikByteCode block */
954 int numReachableBlocks = cUnit->numReachableBlocks;
955 const GrowableList *blockList = &cUnit->blockList;
956 BasicBlock*bb = NULL;
957 for (int idx = 0; idx < numReachableBlocks; idx++) {
958 int dfsIndex = cUnit->dfsOrder.elemList[idx];
959 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
960 if (bb->blockType == kDalvikByteCode) {
961 break;
buzbee16da88c2012-03-20 10:38:17 -0700962 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700963 }
964 if (bb == NULL) {
965 return;
966 }
967 DCHECK_EQ(bb->startOffset, 0);
968 DCHECK(bb->firstMIRInsn != 0);
buzbee16da88c2012-03-20 10:38:17 -0700969
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 /* Get the first instruction */
971 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -0700972
Bill Buzbeea114add2012-05-03 15:00:40 -0700973 /* Free temp registers and reset redundant store tracking */
974 oatResetRegPool(cUnit);
975 oatResetDefTracking(cUnit);
976 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -0700977
Bill Buzbeea114add2012-05-03 15:00:40 -0700978 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -0700979}
980
buzbeee3acd072012-02-25 17:03:10 -0800981void oatMethodMIR2LIR(CompilationUnit* cUnit)
982{
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 /* Used to hold the labels of each block */
984 cUnit->blockLabelList =
985 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -0800986
Bill Buzbeea114add2012-05-03 15:00:40 -0700987 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
988 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -0700989
Bill Buzbeea114add2012-05-03 15:00:40 -0700990 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800991
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800993
Bill Buzbeea114add2012-05-03 15:00:40 -0700994 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -0700995
Bill Buzbeea114add2012-05-03 15:00:40 -0700996 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
997 removeRedundantBranches(cUnit);
998 }
buzbeee3acd072012-02-25 17:03:10 -0800999}
1000
1001/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -08001002LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -08001003{
Bill Buzbeea114add2012-05-03 15:00:40 -07001004 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001005}
1006
1007/* Needed by the register allocator */
1008void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
1009{
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001011}
1012
1013/* Needed by the register allocator */
1014void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -07001015 int srcLo, int srcHi)
buzbeee3acd072012-02-25 17:03:10 -08001016{
Bill Buzbeea114add2012-05-03 15:00:40 -07001017 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001018}
1019
1020void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001021 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -08001022{
Bill Buzbeea114add2012-05-03 15:00:40 -07001023 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
buzbeee3acd072012-02-25 17:03:10 -08001024}
1025
1026void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001027 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -08001028{
Bill Buzbeea114add2012-05-03 15:00:40 -07001029 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
buzbeee3acd072012-02-25 17:03:10 -08001030}
1031
1032} // namespace art