blob: c25ab83466bfe4251ba3366453a9fa7dc83f99b1 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Handle the content in each basic block */
static bool methodBlockCodeGen(CompilationUnit *cUnit, BasicBlock *bb)
{
MIR *mir;
ArmLIR *labelList = (ArmLIR *) cUnit->blockLabelList;
int blockId = bb->id;
cUnit->curBlock = bb;
labelList[blockId].operands[0] = bb->startOffset;
/* Insert the block label */
labelList[blockId].opcode = kArmPseudoNormalBlockLabel;
dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
dvmCompilerClobberAllRegs(cUnit);
dvmCompilerResetNullCheck(cUnit);
ArmLIR *headLIR = NULL;
if (bb->blockType == kMethodEntryBlock) {
opImm(cUnit, kOpPush, (1 << rlr | 1 << rFP));
opRegImm(cUnit, kOpSub, rFP,
sizeof(StackSaveArea) + cUnit->method->registersSize * 4);
} else if (bb->blockType == kMethodExitBlock) {
opImm(cUnit, kOpPop, (1 << rpc | 1 << rFP));
}
for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
dvmCompilerResetRegPool(cUnit);
if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) {
dvmCompilerClobberAllRegs(cUnit);
}
if (gDvmJit.disableOpt & (1 << kSuppressLoads)) {
dvmCompilerResetDefTracking(cUnit);
}
Opcode dalvikOpcode = mir->dalvikInsn.opcode;
InstructionFormat dalvikFormat =
dexGetFormatFromOpcode(dalvikOpcode);
ArmLIR *boundaryLIR;
/*
* Don't generate the boundary LIR unless we are debugging this
* trace or we need a scheduling barrier.
*/
if (headLIR == NULL || cUnit->printMe == true) {
boundaryLIR =
newLIR2(cUnit, kArmPseudoDalvikByteCodeBoundary,
mir->offset,
(int) dvmCompilerGetDalvikDisassembly(
&mir->dalvikInsn, ""));
/* Remember the first LIR for this block */
if (headLIR == NULL) {
headLIR = boundaryLIR;
/* Set the first boundaryLIR as a scheduling barrier */
headLIR->defMask = ENCODE_ALL;
}
}
/* Don't generate the SSA annotation unless verbose mode is on */
if (cUnit->printMe && mir->ssaRep) {
char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
}
bool notHandled;
switch (dalvikFormat) {
case kFmt10t:
case kFmt20t:
case kFmt30t:
notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
mir, bb, labelList);
break;
case kFmt10x:
notHandled = handleFmt10x(cUnit, mir);
break;
case kFmt11n:
case kFmt31i:
notHandled = handleFmt11n_Fmt31i(cUnit, mir);
break;
case kFmt11x:
notHandled = handleFmt11x(cUnit, mir);
break;
case kFmt12x:
notHandled = handleFmt12x(cUnit, mir);
break;
case kFmt20bc:
case kFmt40sc:
notHandled = handleFmt20bc_Fmt40sc(cUnit, mir);
break;
case kFmt21c:
case kFmt31c:
case kFmt41c:
notHandled = handleFmt21c_Fmt31c_Fmt41c(cUnit, mir);
break;
case kFmt21h:
notHandled = handleFmt21h(cUnit, mir);
break;
case kFmt21s:
notHandled = handleFmt21s(cUnit, mir);
break;
case kFmt21t:
notHandled = handleFmt21t(cUnit, mir, bb, labelList);
break;
case kFmt22b:
case kFmt22s:
notHandled = handleFmt22b_Fmt22s(cUnit, mir);
break;
case kFmt22c:
case kFmt52c:
notHandled = handleFmt22c_Fmt52c(cUnit, mir);
break;
case kFmt22cs:
notHandled = handleFmt22cs(cUnit, mir);
break;
case kFmt22t:
notHandled = handleFmt22t(cUnit, mir, bb, labelList);
break;
case kFmt22x:
case kFmt32x:
notHandled = handleFmt22x_Fmt32x(cUnit, mir);
break;
case kFmt23x:
notHandled = handleFmt23x(cUnit, mir);
break;
case kFmt31t:
notHandled = handleFmt31t(cUnit, mir);
break;
case kFmt3rc:
case kFmt35c:
case kFmt5rc:
notHandled = handleFmt35c_3rc_5rc(cUnit, mir, bb,
labelList);
break;
case kFmt3rms:
case kFmt35ms:
notHandled = handleFmt35ms_3rms(cUnit, mir, bb,
labelList);
break;
case kFmt35mi:
case kFmt3rmi:
notHandled = handleExecuteInline(cUnit, mir);
break;
case kFmt51l:
notHandled = handleFmt51l(cUnit, mir);
break;
default:
notHandled = true;
break;
}
/* FIXME - to be implemented */
if (notHandled == true && dalvikOpcode >= kNumPackedOpcodes) {
notHandled = false;
}
if (notHandled) {
LOGE("%#06x: Opcode 0x%x (%s) / Fmt %d not handled\n",
mir->offset,
dalvikOpcode, dexGetOpcodeName(dalvikOpcode),
dalvikFormat);
dvmCompilerAbort(cUnit);
break;
}
}
if (headLIR) {
/*
* Eliminate redundant loads/stores and delay stores into later
* slots
*/
dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
cUnit->lastLIRInsn);
/*
* Generate an unconditional branch to the fallthrough block.
*/
if (bb->fallThrough) {
genUnconditionalBranch(cUnit,
&labelList[bb->fallThrough->id]);
}
}
return false;
}
void dvmCompilerMethodMIR2LIR(CompilationUnit *cUnit)
{
// FIXME - enable method compilation for selected routines here
if (strcmp(cUnit->method->name, "add")) return;
/* Used to hold the labels of each block */
cUnit->blockLabelList =
(void *) dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
dvmCompilerDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
kPreOrderDFSTraversal,
false /* isIterative */);
dvmCompilerApplyGlobalOptimizations(cUnit);
// FIXME - temporarily enable verbose printing for all methods
cUnit->printMe = true;
#if defined(WITH_SELF_VERIFICATION)
selfVerificationBranchInsertPass(cUnit);
#endif
}