blob: 15dbeddca61f4365c7c6c40b6443ee7a4c29c87a [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
buzbee2cfc6392012-05-07 14:51:40 -070024const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
25 INVALID_REG, INVALID_REG, INVALID_SREG,
26 INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080027
28/* Mark register usage state and return long retloc */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070029RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080030{
Bill Buzbeea114add2012-05-03 15:00:40 -070031 RegLocation gpr_res = LOC_C_RETURN_WIDE;
32 RegLocation fpr_res = LOC_C_RETURN_WIDE_DOUBLE;
33 RegLocation res = isDouble ? fpr_res : gpr_res;
34 oatClobber(cUnit, res.lowReg);
35 oatClobber(cUnit, res.highReg);
36 oatLockTemp(cUnit, res.lowReg);
37 oatLockTemp(cUnit, res.highReg);
38 oatMarkPair(cUnit, res.lowReg, res.highReg);
39 return res;
buzbeee3acd072012-02-25 17:03:10 -080040}
41
Ian Rogersf7d9ad32012-03-13 18:45:39 -070042RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
buzbeee3acd072012-02-25 17:03:10 -080043{
Ian Rogersf7d9ad32012-03-13 18:45:39 -070044 RegLocation gpr_res = LOC_C_RETURN;
45 RegLocation fpr_res = LOC_C_RETURN_FLOAT;
46 RegLocation res = isFloat ? fpr_res : gpr_res;
Bill Buzbeea114add2012-05-03 15:00:40 -070047 oatClobber(cUnit, res.lowReg);
48 if (cUnit->instructionSet == kMips) {
49 oatMarkInUse(cUnit, res.lowReg);
50 } else {
51 oatLockTemp(cUnit, res.lowReg);
52 }
53 return res;
buzbeee3acd072012-02-25 17:03:10 -080054}
55
buzbeefc9e6fa2012-03-23 15:14:29 -070056void genInvoke(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
57 InvokeType type, bool isRange)
buzbeee3acd072012-02-25 17:03:10 -080058{
Bill Buzbeea114add2012-05-03 15:00:40 -070059 if (genIntrinsic(cUnit, bb, mir, type, isRange)) {
60 return;
61 }
62 DecodedInstruction* dInsn = &mir->dalvikInsn;
63 InvokeType originalType = type; // avoiding mutation by ComputeInvokeInfo
64 int callState = 0;
65 LIR* nullCk;
66 LIR** pNullCk = NULL;
67 NextCallInsn nextCallInsn;
68 oatFlushAllRegs(cUnit); /* Everything to home location */
69 // Explicit register usage
70 oatLockCallTemps(cUnit);
buzbeee3acd072012-02-25 17:03:10 -080071
Bill Buzbeea114add2012-05-03 15:00:40 -070072 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
73 *cUnit->dex_file, *cUnit->dex_cache,
74 cUnit->code_item, cUnit->method_idx,
75 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080076
Bill Buzbeea114add2012-05-03 15:00:40 -070077 uint32_t dexMethodIdx = dInsn->vB;
78 int vtableIdx;
79 uintptr_t directCode;
80 uintptr_t directMethod;
81 bool skipThis;
82 bool fastPath =
83 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, type,
84 vtableIdx, directCode,
85 directMethod)
86 && !SLOW_INVOKE_PATH;
87 if (type == kInterface) {
88 nextCallInsn = fastPath ? nextInterfaceCallInsn
89 : nextInterfaceCallInsnWithAccessCheck;
90 skipThis = false;
91 } else if (type == kDirect) {
92 if (fastPath) {
93 pNullCk = &nullCk;
buzbeee3acd072012-02-25 17:03:10 -080094 }
Bill Buzbeea114add2012-05-03 15:00:40 -070095 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
96 skipThis = false;
97 } else if (type == kStatic) {
98 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
99 skipThis = false;
100 } else if (type == kSuper) {
101 DCHECK(!fastPath); // Fast path is a direct call.
102 nextCallInsn = nextSuperCallInsnSP;
103 skipThis = false;
104 } else {
105 DCHECK_EQ(type, kVirtual);
106 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
107 skipThis = fastPath;
108 }
109 if (!isRange) {
110 callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk,
111 nextCallInsn, dexMethodIdx,
112 vtableIdx, directCode, directMethod,
113 originalType, skipThis);
114 } else {
115 callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
116 nextCallInsn, dexMethodIdx, vtableIdx,
117 directCode, directMethod, originalType,
118 skipThis);
119 }
120 // Finish up any of the call sequence not interleaved in arg loading
121 while (callState >= 0) {
122 callState = nextCallInsn(cUnit, mir, callState, dexMethodIdx,
123 vtableIdx, directCode, directMethod,
124 originalType);
125 }
126 if (DISPLAY_MISSING_TARGETS) {
127 genShowTarget(cUnit);
128 }
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700129#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 opReg(cUnit, kOpBlx, rINVOKE_TGT);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700131#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 if (fastPath && type != kInterface) {
133 opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
134 } else {
135 int trampoline = 0;
136 switch (type) {
137 case kInterface:
138 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
139 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
140 break;
141 case kDirect:
142 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
143 break;
144 case kStatic:
145 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
146 break;
147 case kSuper:
148 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
149 break;
150 case kVirtual:
151 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
152 break;
153 default:
154 LOG(FATAL) << "Unexpected invoke type";
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700155 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 opThreadMem(cUnit, kOpBlx, trampoline);
157 }
buzbeea7678db2012-03-05 15:35:46 -0800158#endif
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700159
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 oatClobberCalleeSave(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800161}
162
163/*
164 * Target-independent code generation. Use only high-level
165 * load/store utilities here, or target-dependent genXX() handlers
166 * when necessary.
167 */
buzbee31a4a6f2012-02-28 15:36:15 -0800168bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
169 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800170{
Bill Buzbeea114add2012-05-03 15:00:40 -0700171 bool res = false; // Assume success
172 RegLocation rlSrc[3];
173 RegLocation rlDest = badLoc;
174 RegLocation rlResult = badLoc;
175 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee408ad162012-06-06 16:45:18 -0700176 int optFlags = mir->optimizationFlags;
177 uint32_t vA = mir->dalvikInsn.vA;
178 uint32_t vB = mir->dalvikInsn.vB;
179 uint32_t vC = mir->dalvikInsn.vC;
buzbeee3acd072012-02-25 17:03:10 -0800180
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 /* Prep Src and Dest locations */
182 int nextSreg = 0;
183 int nextLoc = 0;
184 int attrs = oatDataFlowAttributes[opcode];
185 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
186 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700187 if (attrs & DF_A_WIDE) {
188 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
189 nextSreg+= 2;
190 } else {
191 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
192 nextSreg++;
193 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700194 }
195 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700196 if (attrs & DF_B_WIDE) {
197 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
198 nextSreg+= 2;
199 } else {
200 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
201 nextSreg++;
202 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700203 }
204 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700205 if (attrs & DF_C_WIDE) {
206 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
207 } else {
208 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
209 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 }
211 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700212 if (attrs & DF_A_WIDE) {
213 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
214 } else {
215 rlDest = oatGetDest(cUnit, mir, 0);
216 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 switch (opcode) {
219 case Instruction::NOP:
220 break;
buzbeee3acd072012-02-25 17:03:10 -0800221
Bill Buzbeea114add2012-05-03 15:00:40 -0700222 case Instruction::MOVE_EXCEPTION: {
223 int exOffset = Thread::ExceptionOffset().Int32Value();
224 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700225#if defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset);
227 newLIR2(cUnit, kX86Mov32TI, exOffset, 0);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700228#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 int resetReg = oatAllocTemp(cUnit);
230 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
231 loadConstant(cUnit, resetReg, 0);
232 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 oatFreeTemp(cUnit, resetReg);
buzbeea7678db2012-03-05 15:35:46 -0800234#endif
jeffhao41005dd2012-05-09 17:58:52 -0700235 storeValue(cUnit, rlDest, rlResult);
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 break;
buzbeee3acd072012-02-25 17:03:10 -0800237 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 case Instruction::RETURN_VOID:
239 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700240 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 }
242 break;
243
244 case Instruction::RETURN:
245 case Instruction::RETURN_OBJECT:
246 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700247 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700248 }
249 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
250 break;
251
252 case Instruction::RETURN_WIDE:
253 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700254 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 }
256 storeValueWide(cUnit, oatGetReturnWide(cUnit,
257 cUnit->shorty[0] == 'D'), rlSrc[0]);
258 break;
259
260 case Instruction::MOVE_RESULT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700261 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 break; // Nop - combined w/ previous invoke
263 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
264 break;
265
266 case Instruction::MOVE_RESULT:
267 case Instruction::MOVE_RESULT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700268 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 break; // Nop - combined w/ previous invoke
270 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
271 break;
272
273 case Instruction::MOVE:
274 case Instruction::MOVE_OBJECT:
275 case Instruction::MOVE_16:
276 case Instruction::MOVE_OBJECT_16:
277 case Instruction::MOVE_FROM16:
278 case Instruction::MOVE_OBJECT_FROM16:
279 storeValue(cUnit, rlDest, rlSrc[0]);
280 break;
281
282 case Instruction::MOVE_WIDE:
283 case Instruction::MOVE_WIDE_16:
284 case Instruction::MOVE_WIDE_FROM16:
285 storeValueWide(cUnit, rlDest, rlSrc[0]);
286 break;
287
288 case Instruction::CONST:
289 case Instruction::CONST_4:
290 case Instruction::CONST_16:
291 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700292 loadConstantNoClobber(cUnit, rlResult.lowReg, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 storeValue(cUnit, rlDest, rlResult);
294 break;
295
296 case Instruction::CONST_HIGH16:
297 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700298 loadConstantNoClobber(cUnit, rlResult.lowReg, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700299 storeValue(cUnit, rlDest, rlResult);
300 break;
301
302 case Instruction::CONST_WIDE_16:
303 case Instruction::CONST_WIDE_32:
304 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700305 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg, vB,
306 (vB & 0x80000000) ? -1 : 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 storeValueWide(cUnit, rlDest, rlResult);
308 break;
309
310 case Instruction::CONST_WIDE:
311 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
312 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
313 mir->dalvikInsn.vB_wide & 0xffffffff,
314 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
315 storeValueWide(cUnit, rlDest, rlResult);
316 break;
317
318 case Instruction::CONST_WIDE_HIGH16:
319 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
320 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
buzbee408ad162012-06-06 16:45:18 -0700321 0, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 storeValueWide(cUnit, rlDest, rlResult);
323 break;
324
325 case Instruction::MONITOR_ENTER:
buzbee408ad162012-06-06 16:45:18 -0700326 genMonitorEnter(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700327 break;
328
329 case Instruction::MONITOR_EXIT:
buzbee408ad162012-06-06 16:45:18 -0700330 genMonitorExit(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 break;
332
333 case Instruction::CHECK_CAST:
buzbee408ad162012-06-06 16:45:18 -0700334 genCheckCast(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700335 break;
336
337 case Instruction::INSTANCE_OF:
buzbee408ad162012-06-06 16:45:18 -0700338 genInstanceof(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 break;
340
341 case Instruction::NEW_INSTANCE:
buzbee408ad162012-06-06 16:45:18 -0700342 genNewInstance(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700343 break;
344
345 case Instruction::THROW:
buzbee408ad162012-06-06 16:45:18 -0700346 genThrow(cUnit, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 break;
348
349 case Instruction::THROW_VERIFICATION_ERROR:
buzbee408ad162012-06-06 16:45:18 -0700350 genThrowVerificationError(cUnit, vA, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700351 break;
352
353 case Instruction::ARRAY_LENGTH:
354 int lenOffset;
355 lenOffset = Array::LengthOffset().Int32Value();
356 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
buzbee408ad162012-06-06 16:45:18 -0700357 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
359 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
360 storeValue(cUnit, rlDest, rlResult);
361 break;
362
363 case Instruction::CONST_STRING:
364 case Instruction::CONST_STRING_JUMBO:
buzbee408ad162012-06-06 16:45:18 -0700365 genConstString(cUnit, vB, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700366 break;
367
368 case Instruction::CONST_CLASS:
buzbee408ad162012-06-06 16:45:18 -0700369 genConstClass(cUnit, vB, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 break;
371
372 case Instruction::FILL_ARRAY_DATA:
buzbee408ad162012-06-06 16:45:18 -0700373 genFillArrayData(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 break;
375
376 case Instruction::FILLED_NEW_ARRAY:
377 genFilledNewArray(cUnit, mir, false /* not range */);
378 break;
379
380 case Instruction::FILLED_NEW_ARRAY_RANGE:
381 genFilledNewArray(cUnit, mir, true /* range */);
382 break;
383
384 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700385 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700386 break;
387
388 case Instruction::GOTO:
389 case Instruction::GOTO_16:
390 case Instruction::GOTO_32:
391 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700392 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700393 } else {
394 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
395 }
396 break;
397
398 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700399 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700400 break;
401
402 case Instruction::SPARSE_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700403 genSparseSwitch(cUnit, vB, rlSrc[0], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700404 break;
405
406 case Instruction::CMPL_FLOAT:
407 case Instruction::CMPG_FLOAT:
408 case Instruction::CMPL_DOUBLE:
409 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700410 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 break;
412
413 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700414 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 break;
416
417 case Instruction::IF_EQ:
418 case Instruction::IF_NE:
419 case Instruction::IF_LT:
420 case Instruction::IF_GE:
421 case Instruction::IF_GT:
422 case Instruction::IF_LE: {
423 bool backwardBranch;
424 backwardBranch = (bb->taken->startOffset <= mir->offset);
425 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700426 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 }
buzbee408ad162012-06-06 16:45:18 -0700428 genCompareAndBranch(cUnit, bb, opcode, rlSrc[0], rlSrc[1], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 break;
430 }
431
432 case Instruction::IF_EQZ:
433 case Instruction::IF_NEZ:
434 case Instruction::IF_LTZ:
435 case Instruction::IF_GEZ:
436 case Instruction::IF_GTZ:
437 case Instruction::IF_LEZ: {
438 bool backwardBranch;
439 backwardBranch = (bb->taken->startOffset <= mir->offset);
440 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700441 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 }
buzbee408ad162012-06-06 16:45:18 -0700443 genCompareZeroAndBranch(cUnit, bb, opcode, rlSrc[0], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 break;
445 }
446
447 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700448 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 break;
450 case Instruction::AGET:
451 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700452 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 break;
454 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700455 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700456 break;
457 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700458 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 break;
460 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700461 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 break;
463 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700464 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 break;
466 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700467 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 break;
469 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700470 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 break;
472 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700473 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 break;
475 case Instruction::APUT_SHORT:
476 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700477 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 break;
479 case Instruction::APUT_BYTE:
480 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700481 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 rlSrc[0], 0);
483 break;
484
485 case Instruction::IGET_OBJECT:
486 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700487 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 break;
489
490 case Instruction::IGET_WIDE:
491 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700492 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700493 break;
494
495 case Instruction::IGET:
496 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700497 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 break;
499
500 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700501 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 break;
503
504 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700505 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 break;
507
508 case Instruction::IGET_BOOLEAN:
509 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700510 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700511 break;
512
513 case Instruction::IPUT_WIDE:
514 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700515 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700516 break;
517
518 case Instruction::IPUT_OBJECT:
519 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700520 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700521 break;
522
523 case Instruction::IPUT:
524 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700525 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 break;
527
528 case Instruction::IPUT_BOOLEAN:
529 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700530 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700531 break;
532
533 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700534 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700535 break;
536
537 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700538 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700539 break;
540
541 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700542 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700543 break;
544 case Instruction::SGET:
545 case Instruction::SGET_BOOLEAN:
546 case Instruction::SGET_BYTE:
547 case Instruction::SGET_CHAR:
548 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700549 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 break;
551
552 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700553 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700554 break;
555
556 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700557 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700558 break;
559
560 case Instruction::SPUT:
561 case Instruction::SPUT_BOOLEAN:
562 case Instruction::SPUT_BYTE:
563 case Instruction::SPUT_CHAR:
564 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700565 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 break;
567
568 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700569 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 break;
571
572 case Instruction::INVOKE_STATIC_RANGE:
573 genInvoke(cUnit, bb, mir, kStatic, true /*range*/);
574 break;
575 case Instruction::INVOKE_STATIC:
576 genInvoke(cUnit, bb, mir, kStatic, false /*range*/);
577 break;
578
579 case Instruction::INVOKE_DIRECT:
580 genInvoke(cUnit, bb, mir, kDirect, false /*range*/);
581 break;
582 case Instruction::INVOKE_DIRECT_RANGE:
583 genInvoke(cUnit, bb, mir, kDirect, true /*range*/);
584 break;
585
586 case Instruction::INVOKE_VIRTUAL:
587 genInvoke(cUnit, bb, mir, kVirtual, false /*range*/);
588 break;
589 case Instruction::INVOKE_VIRTUAL_RANGE:
590 genInvoke(cUnit, bb, mir, kVirtual, true /*range*/);
591 break;
592
593 case Instruction::INVOKE_SUPER:
594 genInvoke(cUnit, bb, mir, kSuper, false /*range*/);
595 break;
596 case Instruction::INVOKE_SUPER_RANGE:
597 genInvoke(cUnit, bb, mir, kSuper, true /*range*/);
598 break;
599
600 case Instruction::INVOKE_INTERFACE:
601 genInvoke(cUnit, bb, mir, kInterface, false /*range*/);
602 break;
603 case Instruction::INVOKE_INTERFACE_RANGE:
604 genInvoke(cUnit, bb, mir, kInterface, true /*range*/);
605 break;
606
607 case Instruction::NEG_INT:
608 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700609 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 break;
611
612 case Instruction::NEG_LONG:
613 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700614 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700615 break;
616
617 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700618 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700619 break;
620
621 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700622 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 break;
624
625 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700626 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 break;
628
629 case Instruction::LONG_TO_INT:
630 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
631 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
632 storeValue(cUnit, rlDest, rlSrc[0]);
633 break;
634
635 case Instruction::INT_TO_BYTE:
636 case Instruction::INT_TO_SHORT:
637 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700638 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700639 break;
640
641 case Instruction::INT_TO_FLOAT:
642 case Instruction::INT_TO_DOUBLE:
643 case Instruction::LONG_TO_FLOAT:
644 case Instruction::LONG_TO_DOUBLE:
645 case Instruction::FLOAT_TO_INT:
646 case Instruction::FLOAT_TO_LONG:
647 case Instruction::FLOAT_TO_DOUBLE:
648 case Instruction::DOUBLE_TO_INT:
649 case Instruction::DOUBLE_TO_LONG:
650 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700651 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700652 break;
653
654 case Instruction::ADD_INT:
655 case Instruction::SUB_INT:
656 case Instruction::MUL_INT:
657 case Instruction::DIV_INT:
658 case Instruction::REM_INT:
659 case Instruction::AND_INT:
660 case Instruction::OR_INT:
661 case Instruction::XOR_INT:
662 case Instruction::SHL_INT:
663 case Instruction::SHR_INT:
664 case Instruction::USHR_INT:
665 case Instruction::ADD_INT_2ADDR:
666 case Instruction::SUB_INT_2ADDR:
667 case Instruction::MUL_INT_2ADDR:
668 case Instruction::DIV_INT_2ADDR:
669 case Instruction::REM_INT_2ADDR:
670 case Instruction::AND_INT_2ADDR:
671 case Instruction::OR_INT_2ADDR:
672 case Instruction::XOR_INT_2ADDR:
673 case Instruction::SHL_INT_2ADDR:
674 case Instruction::SHR_INT_2ADDR:
675 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700676 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700677 break;
678
679 case Instruction::ADD_LONG:
680 case Instruction::SUB_LONG:
681 case Instruction::MUL_LONG:
682 case Instruction::DIV_LONG:
683 case Instruction::REM_LONG:
684 case Instruction::AND_LONG:
685 case Instruction::OR_LONG:
686 case Instruction::XOR_LONG:
687 case Instruction::ADD_LONG_2ADDR:
688 case Instruction::SUB_LONG_2ADDR:
689 case Instruction::MUL_LONG_2ADDR:
690 case Instruction::DIV_LONG_2ADDR:
691 case Instruction::REM_LONG_2ADDR:
692 case Instruction::AND_LONG_2ADDR:
693 case Instruction::OR_LONG_2ADDR:
694 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700695 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 break;
697
698 case Instruction::SHL_LONG:
699 case Instruction::SHR_LONG:
700 case Instruction::USHR_LONG:
701 case Instruction::SHL_LONG_2ADDR:
702 case Instruction::SHR_LONG_2ADDR:
703 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700704 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700705 break;
706
707 case Instruction::ADD_FLOAT:
708 case Instruction::SUB_FLOAT:
709 case Instruction::MUL_FLOAT:
710 case Instruction::DIV_FLOAT:
711 case Instruction::REM_FLOAT:
712 case Instruction::ADD_FLOAT_2ADDR:
713 case Instruction::SUB_FLOAT_2ADDR:
714 case Instruction::MUL_FLOAT_2ADDR:
715 case Instruction::DIV_FLOAT_2ADDR:
716 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700717 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700718 break;
719
720 case Instruction::ADD_DOUBLE:
721 case Instruction::SUB_DOUBLE:
722 case Instruction::MUL_DOUBLE:
723 case Instruction::DIV_DOUBLE:
724 case Instruction::REM_DOUBLE:
725 case Instruction::ADD_DOUBLE_2ADDR:
726 case Instruction::SUB_DOUBLE_2ADDR:
727 case Instruction::MUL_DOUBLE_2ADDR:
728 case Instruction::DIV_DOUBLE_2ADDR:
729 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700730 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 break;
732
733 case Instruction::RSUB_INT:
734 case Instruction::ADD_INT_LIT16:
735 case Instruction::MUL_INT_LIT16:
736 case Instruction::DIV_INT_LIT16:
737 case Instruction::REM_INT_LIT16:
738 case Instruction::AND_INT_LIT16:
739 case Instruction::OR_INT_LIT16:
740 case Instruction::XOR_INT_LIT16:
741 case Instruction::ADD_INT_LIT8:
742 case Instruction::RSUB_INT_LIT8:
743 case Instruction::MUL_INT_LIT8:
744 case Instruction::DIV_INT_LIT8:
745 case Instruction::REM_INT_LIT8:
746 case Instruction::AND_INT_LIT8:
747 case Instruction::OR_INT_LIT8:
748 case Instruction::XOR_INT_LIT8:
749 case Instruction::SHL_INT_LIT8:
750 case Instruction::SHR_INT_LIT8:
751 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700752 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700753 break;
754
755 default:
756 res = true;
757 }
758 return res;
buzbeee3acd072012-02-25 17:03:10 -0800759}
760
buzbee31a4a6f2012-02-28 15:36:15 -0800761const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700762 "kMirOpPhi",
763 "kMirOpCopy",
764 "kMirFusedCmplFloat",
765 "kMirFusedCmpgFloat",
766 "kMirFusedCmplDouble",
767 "kMirFusedCmpgDouble",
768 "kMirFusedCmpLong",
769 "kMirNop",
770 "kMirOpNullNRangeUpCheck",
771 "kMirOpNullNRangeDownCheck",
772 "kMirOpLowerBound",
buzbeee3acd072012-02-25 17:03:10 -0800773};
774
775/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700776void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800777{
Bill Buzbeea114add2012-05-03 15:00:40 -0700778 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
779 char* msg = NULL;
780 if (cUnit->printMe) {
781 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
782 false, kAllocDebugInfo);
783 strcpy(msg, extendedMIROpNames[opOffset]);
784 }
785 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800786
Bill Buzbeea114add2012-05-03 15:00:40 -0700787 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
788 case kMirOpPhi: {
789 char* ssaString = NULL;
790 if (cUnit->printMe) {
791 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
792 }
793 op->flags.isNop = true;
794 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
795 break;
buzbeee3acd072012-02-25 17:03:10 -0800796 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700797 case kMirOpCopy: {
798 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
799 RegLocation rlDest = oatGetDest(cUnit, mir, 0);
800 storeValue(cUnit, rlDest, rlSrc);
801 break;
802 }
803#if defined(TARGET_ARM)
804 case kMirOpFusedCmplFloat:
805 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
806 break;
807 case kMirOpFusedCmpgFloat:
808 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
809 break;
810 case kMirOpFusedCmplDouble:
811 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
812 break;
813 case kMirOpFusedCmpgDouble:
814 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
815 break;
816 case kMirOpFusedCmpLong:
817 genFusedLongCmpBranch(cUnit, bb, mir);
818 break;
819#endif
820 default:
821 break;
822 }
buzbeee3acd072012-02-25 17:03:10 -0800823}
824
825/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800826bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800827{
Bill Buzbeea114add2012-05-03 15:00:40 -0700828 MIR* mir;
829 LIR* labelList = (LIR*) cUnit->blockLabelList;
830 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800831
Bill Buzbeea114add2012-05-03 15:00:40 -0700832 cUnit->curBlock = bb;
833 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800834
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 /* Insert the block label */
836 labelList[blockId].opcode = kPseudoNormalBlockLabel;
837 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800838
Bill Buzbeea114add2012-05-03 15:00:40 -0700839 /* Free temp registers and reset redundant store tracking */
840 oatResetRegPool(cUnit);
841 oatResetDefTracking(cUnit);
842
843 /*
844 * If control reached us from our immediate predecessor via
845 * fallthrough and we have no other incoming arcs we can
846 * reuse existing liveness. Otherwise, reset.
847 */
848 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
849 oatClobberAllRegs(cUnit);
850 }
851
852 LIR* headLIR = NULL;
853
854 if (bb->blockType == kEntryBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700855 genEntrySequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700856 } else if (bb->blockType == kExitBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700857 genExitSequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700858 }
859
860 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
861
buzbeee3acd072012-02-25 17:03:10 -0800862 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
864 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700865 }
866
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
868 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800869 }
870
buzbee3d661942012-03-14 17:37:27 -0700871#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 /* Reset temp tracking sanity check */
873 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700874#endif
875
Bill Buzbeea114add2012-05-03 15:00:40 -0700876 cUnit->currentDalvikOffset = mir->offset;
buzbeee3acd072012-02-25 17:03:10 -0800877
Bill Buzbeea114add2012-05-03 15:00:40 -0700878 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
879 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800880
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800882
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 /* Mark the beginning of a Dalvik instruction for line tracking */
884 char* instStr = cUnit->printMe ?
885 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
886 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
887 (intptr_t) instStr);
888 cUnit->boundaryMap.Overwrite(mir->offset, boundaryLIR);
889 /* Remember the first LIR for this block */
890 if (headLIR == NULL) {
891 headLIR = boundaryLIR;
892 /* Set the first boundaryLIR as a scheduling barrier */
893 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800894 }
895
Bill Buzbeea114add2012-05-03 15:00:40 -0700896 /* If we're compiling for the debugger, generate an update callout */
897 if (cUnit->genDebugger) {
898 genDebuggerUpdate(cUnit, mir->offset);
buzbeee3acd072012-02-25 17:03:10 -0800899 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700900
901 /* Don't generate the SSA annotation unless verbose mode is on */
902 if (cUnit->printMe && mir->ssaRep) {
903 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
904 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
905 }
906
907 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
908 handleExtendedMethodMIR(cUnit, bb, mir);
909 continue;
910 }
911
912 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
913 if (notHandled) {
914 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
915 mir->offset, dalvikOpcode,
916 Instruction::Name(dalvikOpcode), dalvikFormat);
917
918 }
919 }
920
921 if (headLIR) {
922 /*
923 * Eliminate redundant loads/stores and delay stores into later
924 * slots
925 */
926 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
927
928 /*
929 * Generate an unconditional branch to the fallthrough block.
930 */
931 if (bb->fallThrough) {
932 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
933 }
934 }
935 return false;
buzbeee3acd072012-02-25 17:03:10 -0800936}
937
buzbee16da88c2012-03-20 10:38:17 -0700938/* Set basic block labels */
939bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
940{
Bill Buzbeea114add2012-05-03 15:00:40 -0700941 LIR* labelList = (LIR*) cUnit->blockLabelList;
942 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700943
Bill Buzbeea114add2012-05-03 15:00:40 -0700944 cUnit->curBlock = bb;
945 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700946
Bill Buzbeea114add2012-05-03 15:00:40 -0700947 /* Insert the block label */
948 labelList[blockId].opcode = kPseudoNormalBlockLabel;
949 return false;
buzbee16da88c2012-03-20 10:38:17 -0700950}
951
952void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
953{
Bill Buzbeea114add2012-05-03 15:00:40 -0700954 /* 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;
buzbee16da88c2012-03-20 10:38:17 -0700963 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700964 }
965 if (bb == NULL) {
966 return;
967 }
968 DCHECK_EQ(bb->startOffset, 0);
969 DCHECK(bb->firstMIRInsn != 0);
buzbee16da88c2012-03-20 10:38:17 -0700970
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 /* Get the first instruction */
972 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -0700973
Bill Buzbeea114add2012-05-03 15:00:40 -0700974 /* Free temp registers and reset redundant store tracking */
975 oatResetRegPool(cUnit);
976 oatResetDefTracking(cUnit);
977 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -0700978
Bill Buzbeea114add2012-05-03 15:00:40 -0700979 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -0700980}
981
buzbeee3acd072012-02-25 17:03:10 -0800982void oatMethodMIR2LIR(CompilationUnit* cUnit)
983{
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 /* Used to hold the labels of each block */
985 cUnit->blockLabelList =
986 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -0800987
Bill Buzbeea114add2012-05-03 15:00:40 -0700988 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
989 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -0700990
Bill Buzbeea114add2012-05-03 15:00:40 -0700991 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800992
Bill Buzbeea114add2012-05-03 15:00:40 -0700993 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800994
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -0700996
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
998 removeRedundantBranches(cUnit);
999 }
buzbeee3acd072012-02-25 17:03:10 -08001000}
1001
1002/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -08001003LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -08001004{
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001006}
1007
1008/* Needed by the register allocator */
1009void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
1010{
Bill Buzbeea114add2012-05-03 15:00:40 -07001011 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001012}
1013
1014/* Needed by the register allocator */
1015void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -07001016 int srcLo, int srcHi)
buzbeee3acd072012-02-25 17:03:10 -08001017{
Bill Buzbeea114add2012-05-03 15:00:40 -07001018 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001019}
1020
1021void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001022 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -08001023{
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
buzbeee3acd072012-02-25 17:03:10 -08001025}
1026
1027void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001028 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -08001029{
Bill Buzbeea114add2012-05-03 15:00:40 -07001030 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
buzbeee3acd072012-02-25 17:03:10 -08001031}
1032
1033} // namespace art