blob: b41bd830ba93baaa1d88288ae5334d8edfadd088 [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
buzbeeeaf09bc2012-11-15 14:51:41 -080019#include "local_optimizations.h"
20
buzbeee3acd072012-02-25 17:03:10 -080021namespace art {
22
buzbee2cfc6392012-05-07 14:51:40 -070023const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
24 INVALID_REG, INVALID_REG, INVALID_SREG,
25 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{
buzbeef0504cd2012-11-13 16:31:10 -080030 RegLocation gpr_res = locCReturnWide();
31 RegLocation fpr_res = locCReturnDouble();
Bill Buzbeea114add2012-05-03 15:00:40 -070032 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{
buzbeef0504cd2012-11-13 16:31:10 -080043 RegLocation gpr_res = locCReturn();
44 RegLocation fpr_res = locCReturnFloat();
Ian Rogersf7d9ad32012-03-13 18:45:39 -070045 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
buzbeeeaf09bc2012-11-15 14:51:41 -080055// TODO: move to gen_invoke.cc
buzbee3b3dbdd2012-06-13 13:39:34 -070056void genInvoke(CompilationUnit* cUnit, CallInfo* info)
buzbeee3acd072012-02-25 17:03:10 -080057{
buzbee15bf9802012-06-12 17:49:27 -070058 if (genIntrinsic(cUnit, info)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070059 return;
60 }
buzbee15bf9802012-06-12 17:49:27 -070061 InvokeType originalType = info->type; // avoiding mutation by ComputeInvokeInfo
Bill Buzbeea114add2012-05-03 15:00:40 -070062 int callState = 0;
63 LIR* nullCk;
64 LIR** pNullCk = NULL;
65 NextCallInsn nextCallInsn;
66 oatFlushAllRegs(cUnit); /* Everything to home location */
67 // Explicit register usage
68 oatLockCallTemps(cUnit);
buzbeee3acd072012-02-25 17:03:10 -080069
Bill Buzbeea114add2012-05-03 15:00:40 -070070 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070071 *cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -070072 cUnit->code_item, cUnit->method_idx,
73 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080074
buzbee3b3dbdd2012-06-13 13:39:34 -070075 uint32_t dexMethodIdx = info->index;
Bill Buzbeea114add2012-05-03 15:00:40 -070076 int vtableIdx;
77 uintptr_t directCode;
78 uintptr_t directMethod;
79 bool skipThis;
80 bool fastPath =
buzbee15bf9802012-06-12 17:49:27 -070081 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, info->type,
Bill Buzbeea114add2012-05-03 15:00:40 -070082 vtableIdx, directCode,
83 directMethod)
84 && !SLOW_INVOKE_PATH;
buzbee15bf9802012-06-12 17:49:27 -070085 if (info->type == kInterface) {
Ian Rogers137e88f2012-10-08 17:46:47 -070086 if (fastPath) {
87 pNullCk = &nullCk;
88 }
Bill Buzbeea114add2012-05-03 15:00:40 -070089 nextCallInsn = fastPath ? nextInterfaceCallInsn
Ian Rogers137e88f2012-10-08 17:46:47 -070090 : nextInterfaceCallInsnWithAccessCheck;
Bill Buzbeea114add2012-05-03 15:00:40 -070091 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070092 } else if (info->type == kDirect) {
Bill Buzbeea114add2012-05-03 15:00:40 -070093 if (fastPath) {
94 pNullCk = &nullCk;
buzbeee3acd072012-02-25 17:03:10 -080095 }
Bill Buzbeea114add2012-05-03 15:00:40 -070096 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
97 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070098 } else if (info->type == kStatic) {
Bill Buzbeea114add2012-05-03 15:00:40 -070099 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
100 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -0700101 } else if (info->type == kSuper) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 DCHECK(!fastPath); // Fast path is a direct call.
103 nextCallInsn = nextSuperCallInsnSP;
104 skipThis = false;
105 } else {
buzbee15bf9802012-06-12 17:49:27 -0700106 DCHECK_EQ(info->type, kVirtual);
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
108 skipThis = fastPath;
109 }
buzbee15bf9802012-06-12 17:49:27 -0700110 if (!info->isRange) {
111 callState = genDalvikArgsNoRange(cUnit, info, callState, pNullCk,
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 nextCallInsn, dexMethodIdx,
113 vtableIdx, directCode, directMethod,
114 originalType, skipThis);
115 } else {
buzbee15bf9802012-06-12 17:49:27 -0700116 callState = genDalvikArgsRange(cUnit, info, callState, pNullCk,
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 nextCallInsn, dexMethodIdx, vtableIdx,
118 directCode, directMethod, originalType,
119 skipThis);
120 }
121 // Finish up any of the call sequence not interleaved in arg loading
122 while (callState >= 0) {
buzbee15bf9802012-06-12 17:49:27 -0700123 callState = nextCallInsn(cUnit, info, callState, dexMethodIdx,
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 vtableIdx, directCode, directMethod,
125 originalType);
126 }
buzbeeb046e162012-10-30 15:48:42 -0700127 if (cUnit->enableDebug & (1 << kDebugDisplayMissingTargets)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 genShowTarget(cUnit);
129 }
buzbee8320f382012-09-11 16:29:42 -0700130 LIR* callInst;
buzbeeb046e162012-10-30 15:48:42 -0700131 if (cUnit->instructionSet != kX86) {
buzbeef0504cd2012-11-13 16:31:10 -0800132 callInst = opReg(cUnit, kOpBlx, targetReg(kInvokeTgt));
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 } else {
buzbeeb046e162012-10-30 15:48:42 -0700134 if (fastPath && info->type != kInterface) {
buzbeef0504cd2012-11-13 16:31:10 -0800135 callInst = opMem(cUnit, kOpBlx, targetReg(kArg0),
136 AbstractMethod::GetCodeOffset().Int32Value());
buzbeeb046e162012-10-30 15:48:42 -0700137 } else {
138 int trampoline = 0;
139 switch (info->type) {
140 case kInterface:
141 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
142 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
143 break;
144 case kDirect:
145 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
146 break;
147 case kStatic:
148 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
149 break;
150 case kSuper:
151 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
152 break;
153 case kVirtual:
154 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
155 break;
156 default:
157 LOG(FATAL) << "Unexpected invoke type";
158 }
159 callInst = opThreadMem(cUnit, kOpBlx, trampoline);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700160 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 }
buzbee8320f382012-09-11 16:29:42 -0700162 markSafepointPC(cUnit, callInst);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700163
Bill Buzbeea114add2012-05-03 15:00:40 -0700164 oatClobberCalleeSave(cUnit);
buzbee15bf9802012-06-12 17:49:27 -0700165 if (info->result.location != kLocInvalid) {
166 // We have a following MOVE_RESULT - do it now.
167 if (info->result.wide) {
buzbee52ed7762012-06-13 23:43:14 -0700168 RegLocation retLoc = oatGetReturnWide(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700169 storeValueWide(cUnit, info->result, retLoc);
170 } else {
buzbee52ed7762012-06-13 23:43:14 -0700171 RegLocation retLoc = oatGetReturn(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700172 storeValue(cUnit, info->result, retLoc);
173 }
174 }
175}
176
177/*
178 * Build an array of location records for the incoming arguments.
179 * Note: one location record per word of arguments, with dummy
180 * high-word loc for wide arguments. Also pull up any following
181 * MOVE_RESULT and incorporate it into the invoke.
182 */
buzbeeeaf09bc2012-11-15 14:51:41 -0800183//TODO: move to gen_invoke.cc or utils
buzbee6969d502012-06-15 16:40:31 -0700184CallInfo* oatNewCallInfo(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
185 InvokeType type, bool isRange)
buzbee15bf9802012-06-12 17:49:27 -0700186{
buzbeecbd6d442012-11-17 14:11:25 -0800187 CallInfo* info = static_cast<CallInfo*>(oatNew(cUnit, sizeof(CallInfo), true, kAllocMisc));
buzbee15bf9802012-06-12 17:49:27 -0700188 MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
189 if (moveResultMIR == NULL) {
190 info->result.location = kLocInvalid;
191 } else {
192 info->result = oatGetRawDest(cUnit, moveResultMIR);
193 moveResultMIR->dalvikInsn.opcode = Instruction::NOP;
194 }
195 info->numArgWords = mir->ssaRep->numUses;
buzbeecbd6d442012-11-17 14:11:25 -0800196 info->args = (info->numArgWords == 0) ? NULL : static_cast<RegLocation*>
197 (oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc));
buzbee15bf9802012-06-12 17:49:27 -0700198 for (int i = 0; i < info->numArgWords; i++) {
199 info->args[i] = oatGetRawSrc(cUnit, mir, i);
200 }
201 info->optFlags = mir->optimizationFlags;
202 info->type = type;
203 info->isRange = isRange;
buzbee3b3dbdd2012-06-13 13:39:34 -0700204 info->index = mir->dalvikInsn.vB;
buzbee15bf9802012-06-12 17:49:27 -0700205 info->offset = mir->offset;
206 return info;
buzbeee3acd072012-02-25 17:03:10 -0800207}
208
209/*
210 * Target-independent code generation. Use only high-level
211 * load/store utilities here, or target-dependent genXX() handlers
212 * when necessary.
213 */
buzbee31a4a6f2012-02-28 15:36:15 -0800214bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
215 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800216{
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 bool res = false; // Assume success
218 RegLocation rlSrc[3];
219 RegLocation rlDest = badLoc;
220 RegLocation rlResult = badLoc;
221 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee408ad162012-06-06 16:45:18 -0700222 int optFlags = mir->optimizationFlags;
buzbee408ad162012-06-06 16:45:18 -0700223 uint32_t vB = mir->dalvikInsn.vB;
224 uint32_t vC = mir->dalvikInsn.vC;
buzbeee3acd072012-02-25 17:03:10 -0800225
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 /* Prep Src and Dest locations */
227 int nextSreg = 0;
228 int nextLoc = 0;
229 int attrs = oatDataFlowAttributes[opcode];
230 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
231 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700232 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700233 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700234 nextSreg+= 2;
235 } else {
236 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
237 nextSreg++;
238 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 }
240 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700241 if (attrs & DF_B_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700242 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700243 nextSreg+= 2;
244 } else {
245 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
246 nextSreg++;
247 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700248 }
249 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700250 if (attrs & DF_C_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700251 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700252 } else {
253 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
254 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 }
256 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700257 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700258 rlDest = oatGetDestWide(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700259 } else {
buzbee15bf9802012-06-12 17:49:27 -0700260 rlDest = oatGetDest(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700261 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 switch (opcode) {
264 case Instruction::NOP:
265 break;
buzbeee3acd072012-02-25 17:03:10 -0800266
Ian Rogers474b6da2012-09-25 00:20:38 -0700267 case Instruction::MOVE_EXCEPTION:
268 genMoveException(cUnit, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 case Instruction::RETURN_VOID:
TDYa1274f2935e2012-06-22 06:25:03 -0700271 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700272 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700273 }
274 break;
275
276 case Instruction::RETURN:
277 case Instruction::RETURN_OBJECT:
TDYa1274f2935e2012-06-22 06:25:03 -0700278 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700279 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 }
281 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
282 break;
283
284 case Instruction::RETURN_WIDE:
TDYa1274f2935e2012-06-22 06:25:03 -0700285 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700286 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700287 }
288 storeValueWide(cUnit, oatGetReturnWide(cUnit,
289 cUnit->shorty[0] == 'D'), rlSrc[0]);
290 break;
291
292 case Instruction::MOVE_RESULT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700293 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 break; // Nop - combined w/ previous invoke
295 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
296 break;
297
298 case Instruction::MOVE_RESULT:
299 case Instruction::MOVE_RESULT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700300 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700301 break; // Nop - combined w/ previous invoke
302 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
303 break;
304
305 case Instruction::MOVE:
306 case Instruction::MOVE_OBJECT:
307 case Instruction::MOVE_16:
308 case Instruction::MOVE_OBJECT_16:
309 case Instruction::MOVE_FROM16:
310 case Instruction::MOVE_OBJECT_FROM16:
311 storeValue(cUnit, rlDest, rlSrc[0]);
312 break;
313
314 case Instruction::MOVE_WIDE:
315 case Instruction::MOVE_WIDE_16:
316 case Instruction::MOVE_WIDE_FROM16:
317 storeValueWide(cUnit, rlDest, rlSrc[0]);
318 break;
319
320 case Instruction::CONST:
321 case Instruction::CONST_4:
322 case Instruction::CONST_16:
323 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700324 loadConstantNoClobber(cUnit, rlResult.lowReg, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700325 storeValue(cUnit, rlDest, rlResult);
326 break;
327
328 case Instruction::CONST_HIGH16:
329 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700330 loadConstantNoClobber(cUnit, rlResult.lowReg, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 storeValue(cUnit, rlDest, rlResult);
332 break;
333
334 case Instruction::CONST_WIDE_16:
335 case Instruction::CONST_WIDE_32:
336 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700337 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg, vB,
338 (vB & 0x80000000) ? -1 : 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 storeValueWide(cUnit, rlDest, rlResult);
340 break;
341
342 case Instruction::CONST_WIDE:
343 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
344 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
345 mir->dalvikInsn.vB_wide & 0xffffffff,
346 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
347 storeValueWide(cUnit, rlDest, rlResult);
348 break;
349
350 case Instruction::CONST_WIDE_HIGH16:
351 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
352 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
buzbee408ad162012-06-06 16:45:18 -0700353 0, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700354 storeValueWide(cUnit, rlDest, rlResult);
355 break;
356
357 case Instruction::MONITOR_ENTER:
buzbee408ad162012-06-06 16:45:18 -0700358 genMonitorEnter(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 break;
360
361 case Instruction::MONITOR_EXIT:
buzbee408ad162012-06-06 16:45:18 -0700362 genMonitorExit(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700363 break;
364
365 case Instruction::CHECK_CAST:
buzbee408ad162012-06-06 16:45:18 -0700366 genCheckCast(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 break;
368
369 case Instruction::INSTANCE_OF:
buzbee408ad162012-06-06 16:45:18 -0700370 genInstanceof(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 break;
372
373 case Instruction::NEW_INSTANCE:
buzbee408ad162012-06-06 16:45:18 -0700374 genNewInstance(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 break;
376
377 case Instruction::THROW:
buzbee408ad162012-06-06 16:45:18 -0700378 genThrow(cUnit, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 break;
380
Bill Buzbeea114add2012-05-03 15:00:40 -0700381 case Instruction::ARRAY_LENGTH:
382 int lenOffset;
383 lenOffset = Array::LengthOffset().Int32Value();
384 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
buzbee408ad162012-06-06 16:45:18 -0700385 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700386 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
387 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
388 storeValue(cUnit, rlDest, rlResult);
389 break;
390
391 case Instruction::CONST_STRING:
392 case Instruction::CONST_STRING_JUMBO:
buzbee6969d502012-06-15 16:40:31 -0700393 genConstString(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700394 break;
395
396 case Instruction::CONST_CLASS:
buzbee6969d502012-06-15 16:40:31 -0700397 genConstClass(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700398 break;
399
400 case Instruction::FILL_ARRAY_DATA:
buzbee408ad162012-06-06 16:45:18 -0700401 genFillArrayData(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 break;
403
404 case Instruction::FILLED_NEW_ARRAY:
buzbee6969d502012-06-15 16:40:31 -0700405 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700406 false /* not range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700407 break;
408
409 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700410 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700411 true /* range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700412 break;
413
414 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700415 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700416 break;
417
418 case Instruction::GOTO:
419 case Instruction::GOTO_16:
420 case Instruction::GOTO_32:
421 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700422 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 } else {
424 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
425 }
426 break;
427
428 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700429 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 break;
431
432 case Instruction::SPARSE_SWITCH:
buzbeea1da8a52012-07-09 14:00:21 -0700433 genSparseSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 break;
435
436 case Instruction::CMPL_FLOAT:
437 case Instruction::CMPG_FLOAT:
438 case Instruction::CMPL_DOUBLE:
439 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700440 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700441 break;
442
443 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700444 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700445 break;
446
447 case Instruction::IF_EQ:
448 case Instruction::IF_NE:
449 case Instruction::IF_LT:
450 case Instruction::IF_GE:
451 case Instruction::IF_GT:
452 case Instruction::IF_LE: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700453 LIR* taken = &labelList[bb->taken->id];
454 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 bool backwardBranch;
456 backwardBranch = (bb->taken->startOffset <= mir->offset);
457 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700458 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700460 genCompareAndBranch(cUnit, opcode, rlSrc[0], rlSrc[1], taken,
461 fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 break;
463 }
464
465 case Instruction::IF_EQZ:
466 case Instruction::IF_NEZ:
467 case Instruction::IF_LTZ:
468 case Instruction::IF_GEZ:
469 case Instruction::IF_GTZ:
470 case Instruction::IF_LEZ: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700471 LIR* taken = &labelList[bb->taken->id];
472 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700473 bool backwardBranch;
474 backwardBranch = (bb->taken->startOffset <= mir->offset);
475 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700476 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700477 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700478 genCompareZeroAndBranch(cUnit, opcode, rlSrc[0], taken, fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 break;
480 }
481
482 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700483 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 break;
485 case Instruction::AGET:
486 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700487 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 break;
489 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700490 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 break;
492 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700493 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 break;
495 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700496 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 break;
498 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700499 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 break;
501 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700502 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 break;
504 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700505 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 break;
507 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700508 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700509 break;
510 case Instruction::APUT_SHORT:
511 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700512 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 break;
514 case Instruction::APUT_BYTE:
515 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700516 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 rlSrc[0], 0);
518 break;
519
520 case Instruction::IGET_OBJECT:
521 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700522 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 break;
524
525 case Instruction::IGET_WIDE:
526 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700527 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700528 break;
529
530 case Instruction::IGET:
531 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700532 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 break;
534
535 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700536 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700537 break;
538
539 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700540 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700541 break;
542
543 case Instruction::IGET_BOOLEAN:
544 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700545 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700546 break;
547
548 case Instruction::IPUT_WIDE:
549 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700550 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 break;
552
553 case Instruction::IPUT_OBJECT:
554 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700555 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 break;
557
558 case Instruction::IPUT:
559 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700560 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700561 break;
562
563 case Instruction::IPUT_BOOLEAN:
564 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700565 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 break;
567
568 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700569 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 break;
571
572 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700573 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700574 break;
575
576 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700577 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700578 break;
579 case Instruction::SGET:
580 case Instruction::SGET_BOOLEAN:
581 case Instruction::SGET_BYTE:
582 case Instruction::SGET_CHAR:
583 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700584 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 break;
586
587 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700588 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700589 break;
590
591 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700592 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700593 break;
594
595 case Instruction::SPUT:
596 case Instruction::SPUT_BOOLEAN:
597 case Instruction::SPUT_BYTE:
598 case Instruction::SPUT_CHAR:
599 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700600 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 break;
602
603 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700604 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700605 break;
606
607 case Instruction::INVOKE_STATIC_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700608 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 break;
610 case Instruction::INVOKE_STATIC:
buzbee6969d502012-06-15 16:40:31 -0700611 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 break;
613
614 case Instruction::INVOKE_DIRECT:
buzbee6969d502012-06-15 16:40:31 -0700615 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700616 break;
617 case Instruction::INVOKE_DIRECT_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700618 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700619 break;
620
621 case Instruction::INVOKE_VIRTUAL:
buzbee6969d502012-06-15 16:40:31 -0700622 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 break;
624 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700625 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 break;
627
628 case Instruction::INVOKE_SUPER:
buzbee6969d502012-06-15 16:40:31 -0700629 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 break;
631 case Instruction::INVOKE_SUPER_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700632 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700633 break;
634
635 case Instruction::INVOKE_INTERFACE:
buzbee6969d502012-06-15 16:40:31 -0700636 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 break;
638 case Instruction::INVOKE_INTERFACE_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700639 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700640 break;
641
642 case Instruction::NEG_INT:
643 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700644 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 break;
646
647 case Instruction::NEG_LONG:
648 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700649 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700650 break;
651
652 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700653 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700654 break;
655
656 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700657 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700658 break;
659
660 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700661 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 break;
663
664 case Instruction::LONG_TO_INT:
665 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
666 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
667 storeValue(cUnit, rlDest, rlSrc[0]);
668 break;
669
670 case Instruction::INT_TO_BYTE:
671 case Instruction::INT_TO_SHORT:
672 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700673 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 break;
675
676 case Instruction::INT_TO_FLOAT:
677 case Instruction::INT_TO_DOUBLE:
678 case Instruction::LONG_TO_FLOAT:
679 case Instruction::LONG_TO_DOUBLE:
680 case Instruction::FLOAT_TO_INT:
681 case Instruction::FLOAT_TO_LONG:
682 case Instruction::FLOAT_TO_DOUBLE:
683 case Instruction::DOUBLE_TO_INT:
684 case Instruction::DOUBLE_TO_LONG:
685 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700686 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700687 break;
688
689 case Instruction::ADD_INT:
690 case Instruction::SUB_INT:
691 case Instruction::MUL_INT:
692 case Instruction::DIV_INT:
693 case Instruction::REM_INT:
694 case Instruction::AND_INT:
695 case Instruction::OR_INT:
696 case Instruction::XOR_INT:
697 case Instruction::SHL_INT:
698 case Instruction::SHR_INT:
699 case Instruction::USHR_INT:
700 case Instruction::ADD_INT_2ADDR:
701 case Instruction::SUB_INT_2ADDR:
702 case Instruction::MUL_INT_2ADDR:
703 case Instruction::DIV_INT_2ADDR:
704 case Instruction::REM_INT_2ADDR:
705 case Instruction::AND_INT_2ADDR:
706 case Instruction::OR_INT_2ADDR:
707 case Instruction::XOR_INT_2ADDR:
708 case Instruction::SHL_INT_2ADDR:
709 case Instruction::SHR_INT_2ADDR:
710 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700711 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700712 break;
713
714 case Instruction::ADD_LONG:
715 case Instruction::SUB_LONG:
716 case Instruction::MUL_LONG:
717 case Instruction::DIV_LONG:
718 case Instruction::REM_LONG:
719 case Instruction::AND_LONG:
720 case Instruction::OR_LONG:
721 case Instruction::XOR_LONG:
722 case Instruction::ADD_LONG_2ADDR:
723 case Instruction::SUB_LONG_2ADDR:
724 case Instruction::MUL_LONG_2ADDR:
725 case Instruction::DIV_LONG_2ADDR:
726 case Instruction::REM_LONG_2ADDR:
727 case Instruction::AND_LONG_2ADDR:
728 case Instruction::OR_LONG_2ADDR:
729 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700730 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 break;
732
733 case Instruction::SHL_LONG:
734 case Instruction::SHR_LONG:
735 case Instruction::USHR_LONG:
736 case Instruction::SHL_LONG_2ADDR:
737 case Instruction::SHR_LONG_2ADDR:
738 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700739 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700740 break;
741
742 case Instruction::ADD_FLOAT:
743 case Instruction::SUB_FLOAT:
744 case Instruction::MUL_FLOAT:
745 case Instruction::DIV_FLOAT:
746 case Instruction::REM_FLOAT:
747 case Instruction::ADD_FLOAT_2ADDR:
748 case Instruction::SUB_FLOAT_2ADDR:
749 case Instruction::MUL_FLOAT_2ADDR:
750 case Instruction::DIV_FLOAT_2ADDR:
751 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700752 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700753 break;
754
755 case Instruction::ADD_DOUBLE:
756 case Instruction::SUB_DOUBLE:
757 case Instruction::MUL_DOUBLE:
758 case Instruction::DIV_DOUBLE:
759 case Instruction::REM_DOUBLE:
760 case Instruction::ADD_DOUBLE_2ADDR:
761 case Instruction::SUB_DOUBLE_2ADDR:
762 case Instruction::MUL_DOUBLE_2ADDR:
763 case Instruction::DIV_DOUBLE_2ADDR:
764 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700765 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700766 break;
767
768 case Instruction::RSUB_INT:
769 case Instruction::ADD_INT_LIT16:
770 case Instruction::MUL_INT_LIT16:
771 case Instruction::DIV_INT_LIT16:
772 case Instruction::REM_INT_LIT16:
773 case Instruction::AND_INT_LIT16:
774 case Instruction::OR_INT_LIT16:
775 case Instruction::XOR_INT_LIT16:
776 case Instruction::ADD_INT_LIT8:
777 case Instruction::RSUB_INT_LIT8:
778 case Instruction::MUL_INT_LIT8:
779 case Instruction::DIV_INT_LIT8:
780 case Instruction::REM_INT_LIT8:
781 case Instruction::AND_INT_LIT8:
782 case Instruction::OR_INT_LIT8:
783 case Instruction::XOR_INT_LIT8:
784 case Instruction::SHL_INT_LIT8:
785 case Instruction::SHR_INT_LIT8:
786 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700787 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700788 break;
789
790 default:
791 res = true;
792 }
793 return res;
buzbeee3acd072012-02-25 17:03:10 -0800794}
795
buzbeee3acd072012-02-25 17:03:10 -0800796/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700797void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800798{
Bill Buzbeea114add2012-05-03 15:00:40 -0700799 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
800 char* msg = NULL;
801 if (cUnit->printMe) {
buzbeecbd6d442012-11-17 14:11:25 -0800802 msg = static_cast<char*>(oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
803 false, kAllocDebugInfo));
Bill Buzbeea114add2012-05-03 15:00:40 -0700804 strcpy(msg, extendedMIROpNames[opOffset]);
805 }
buzbeecbd6d442012-11-17 14:11:25 -0800806 LIR* op = newLIR1(cUnit, kPseudoExtended, reinterpret_cast<uintptr_t>(msg));
buzbeee3acd072012-02-25 17:03:10 -0800807
buzbeecbd6d442012-11-17 14:11:25 -0800808 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700809 case kMirOpPhi: {
810 char* ssaString = NULL;
811 if (cUnit->printMe) {
812 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
813 }
814 op->flags.isNop = true;
buzbeecbd6d442012-11-17 14:11:25 -0800815 newLIR1(cUnit, kPseudoSSARep, reinterpret_cast<uintptr_t>(ssaString));
Bill Buzbeea114add2012-05-03 15:00:40 -0700816 break;
buzbeee3acd072012-02-25 17:03:10 -0800817 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700818 case kMirOpCopy: {
819 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
buzbee15bf9802012-06-12 17:49:27 -0700820 RegLocation rlDest = oatGetDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700821 storeValue(cUnit, rlDest, rlSrc);
822 break;
823 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 case kMirOpFusedCmplFloat:
825 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
826 break;
827 case kMirOpFusedCmpgFloat:
828 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
829 break;
830 case kMirOpFusedCmplDouble:
831 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
832 break;
833 case kMirOpFusedCmpgDouble:
834 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
835 break;
836 case kMirOpFusedCmpLong:
837 genFusedLongCmpBranch(cUnit, bb, mir);
838 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700839 default:
840 break;
841 }
buzbeee3acd072012-02-25 17:03:10 -0800842}
843
844/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800845bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800846{
buzbee488a78c2012-09-10 15:55:34 -0700847 if (bb->blockType == kDead) return false;
buzbee8320f382012-09-11 16:29:42 -0700848 cUnit->currentDalvikOffset = bb->startOffset;
Bill Buzbeea114add2012-05-03 15:00:40 -0700849 MIR* mir;
buzbeea1da8a52012-07-09 14:00:21 -0700850 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800852
Bill Buzbeea114add2012-05-03 15:00:40 -0700853 cUnit->curBlock = bb;
854 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800855
Bill Buzbeea114add2012-05-03 15:00:40 -0700856 /* Insert the block label */
857 labelList[blockId].opcode = kPseudoNormalBlockLabel;
buzbeecbd6d442012-11-17 14:11:25 -0800858 oatAppendLIR(cUnit, &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800859
buzbee8320f382012-09-11 16:29:42 -0700860 LIR* headLIR = NULL;
861
Bill Buzbeea5b30242012-09-28 07:19:44 -0700862 /* If this is a catch block, export the start address */
buzbee8320f382012-09-11 16:29:42 -0700863 if (bb->catchEntry) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700864 headLIR = newLIR0(cUnit, kPseudoExportedPC);
buzbee8320f382012-09-11 16:29:42 -0700865 }
866
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 /* Free temp registers and reset redundant store tracking */
868 oatResetRegPool(cUnit);
869 oatResetDefTracking(cUnit);
870
buzbeed1643e42012-09-05 14:06:51 -0700871 oatClobberAllRegs(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700872
Bill Buzbeea114add2012-05-03 15:00:40 -0700873
874 if (bb->blockType == kEntryBlock) {
buzbeead8f15e2012-06-18 14:49:45 -0700875 int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
876 genEntrySequence(cUnit, &cUnit->regLocation[startVReg],
877 cUnit->regLocation[cUnit->methodSReg]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700878 } else if (bb->blockType == kExitBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700879 genExitSequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700880 }
881
882 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
buzbeee3acd072012-02-25 17:03:10 -0800883 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700884 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
885 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700886 }
887
Bill Buzbeea114add2012-05-03 15:00:40 -0700888 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
889 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800890 }
891
buzbee3d661942012-03-14 17:37:27 -0700892#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700893 /* Reset temp tracking sanity check */
894 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700895#endif
896
Bill Buzbeea114add2012-05-03 15:00:40 -0700897 cUnit->currentDalvikOffset = mir->offset;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700898 int opcode = mir->dalvikInsn.opcode;
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800900
Bill Buzbeea114add2012-05-03 15:00:40 -0700901 /* Mark the beginning of a Dalvik instruction for line tracking */
902 char* instStr = cUnit->printMe ?
903 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
buzbeed1643e42012-09-05 14:06:51 -0700904 boundaryLIR = markBoundary(cUnit, mir->offset, instStr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 /* Remember the first LIR for this block */
906 if (headLIR == NULL) {
907 headLIR = boundaryLIR;
908 /* Set the first boundaryLIR as a scheduling barrier */
909 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800910 }
911
Bill Buzbeea114add2012-05-03 15:00:40 -0700912 /* Don't generate the SSA annotation unless verbose mode is on */
913 if (cUnit->printMe && mir->ssaRep) {
914 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
buzbeecbd6d442012-11-17 14:11:25 -0800915 newLIR1(cUnit, kPseudoSSARep, reinterpret_cast<uintptr_t>(ssaString));
Bill Buzbeea114add2012-05-03 15:00:40 -0700916 }
917
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700918 if (opcode == kMirOpCheck) {
919 // Combine check and work halves of throwing instruction.
920 MIR* workHalf = mir->meta.throwInsn;
921 mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode;
922 opcode = workHalf->dalvikInsn.opcode;
923 SSARepresentation* ssaRep = workHalf->ssaRep;
924 workHalf->ssaRep = mir->ssaRep;
925 mir->ssaRep = ssaRep;
926 workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
927 }
928
929 if (opcode >= kMirOpFirst) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 handleExtendedMethodMIR(cUnit, bb, mir);
931 continue;
932 }
933
934 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
935 if (notHandled) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700936 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s)",
937 mir->offset, opcode,
938 Instruction::Name(mir->dalvikInsn.opcode));
Bill Buzbeea114add2012-05-03 15:00:40 -0700939 }
940 }
941
942 if (headLIR) {
943 /*
944 * Eliminate redundant loads/stores and delay stores into later
945 * slots
946 */
buzbeecbd6d442012-11-17 14:11:25 -0800947 oatApplyLocalOptimizations(cUnit, headLIR, cUnit->lastLIRInsn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700948
949 /*
950 * Generate an unconditional branch to the fallthrough block.
951 */
952 if (bb->fallThrough) {
953 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
954 }
955 }
956 return false;
buzbeee3acd072012-02-25 17:03:10 -0800957}
958
buzbee16da88c2012-03-20 10:38:17 -0700959/* Set basic block labels */
960bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
961{
buzbeea1da8a52012-07-09 14:00:21 -0700962 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700963 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700964
Bill Buzbeea114add2012-05-03 15:00:40 -0700965 cUnit->curBlock = bb;
966 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700967
Bill Buzbeea114add2012-05-03 15:00:40 -0700968 /* Insert the block label */
969 labelList[blockId].opcode = kPseudoNormalBlockLabel;
970 return false;
buzbee16da88c2012-03-20 10:38:17 -0700971}
972
973void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
974{
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 /* Find the first DalvikByteCode block */
976 int numReachableBlocks = cUnit->numReachableBlocks;
977 const GrowableList *blockList = &cUnit->blockList;
978 BasicBlock*bb = NULL;
979 for (int idx = 0; idx < numReachableBlocks; idx++) {
980 int dfsIndex = cUnit->dfsOrder.elemList[idx];
buzbeecbd6d442012-11-17 14:11:25 -0800981 bb = reinterpret_cast<BasicBlock*>(oatGrowableListGetElement(blockList, dfsIndex));
Bill Buzbeea114add2012-05-03 15:00:40 -0700982 if (bb->blockType == kDalvikByteCode) {
983 break;
buzbee16da88c2012-03-20 10:38:17 -0700984 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 }
986 if (bb == NULL) {
987 return;
988 }
989 DCHECK_EQ(bb->startOffset, 0);
Elliott Hughes74847412012-06-20 18:10:21 -0700990 DCHECK(bb->firstMIRInsn != NULL);
buzbee16da88c2012-03-20 10:38:17 -0700991
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 /* Get the first instruction */
993 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -0700994
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 /* Free temp registers and reset redundant store tracking */
996 oatResetRegPool(cUnit);
997 oatResetDefTracking(cUnit);
998 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -0700999
Bill Buzbeea114add2012-05-03 15:00:40 -07001000 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -07001001}
1002
buzbeee3acd072012-02-25 17:03:10 -08001003void oatMethodMIR2LIR(CompilationUnit* cUnit)
1004{
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 /* Used to hold the labels of each block */
1006 cUnit->blockLabelList =
buzbeecbd6d442012-11-17 14:11:25 -08001007 static_cast<LIR*>(oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR));
buzbeee3acd072012-02-25 17:03:10 -08001008
Bill Buzbeea114add2012-05-03 15:00:40 -07001009 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
1010 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -07001011
Bill Buzbeea114add2012-05-03 15:00:40 -07001012 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001013
Bill Buzbeea114add2012-05-03 15:00:40 -07001014 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001015
Bill Buzbeea114add2012-05-03 15:00:40 -07001016 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -07001017
Bill Buzbeea114add2012-05-03 15:00:40 -07001018 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
1019 removeRedundantBranches(cUnit);
1020 }
buzbeee3acd072012-02-25 17:03:10 -08001021}
1022
buzbeee3acd072012-02-25 17:03:10 -08001023} // namespace art