summaryrefslogtreecommitdiff
path: root/src/compiler/codegen/MethodBitcode.cc
diff options
context:
space:
mode:
author buzbee <buzbee@google.com> 2012-08-01 10:01:59 -0700
committer Android Git Automerger <android-git-automerger@android.com> 2012-08-01 10:01:59 -0700
commitf2ba9cbe81b0762a7c8c659cdb86ba79b2dbbc40 (patch)
tree3a7944e695c65fb25ebdcd27bc640b84e6f4fd38 /src/compiler/codegen/MethodBitcode.cc
parent573b42936ba7fbf296452875cdcadedc619418ef (diff)
parent8b503db0432981c6b0b2271723f9bcf9448a554a (diff)
am 8b503db0: CFG rework for explicit exception edges
* commit '8b503db0432981c6b0b2271723f9bcf9448a554a': CFG rework for explicit exception edges
Diffstat (limited to 'src/compiler/codegen/MethodBitcode.cc')
-rw-r--r--src/compiler/codegen/MethodBitcode.cc121
1 files changed, 111 insertions, 10 deletions
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index 864372a544..b2cbc699bb 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -51,7 +51,7 @@ void defineValue(CompilationUnit* cUnit, llvm::Value* val, int sReg)
llvm::Value* placeholder = getLLVMValue(cUnit, sReg);
if (placeholder == NULL) {
// This can happen on instruction rewrite on verification failure
- LOG(WARNING) << "Null placeholder - invalid CFG";
+ LOG(WARNING) << "Null placeholder";
return;
}
placeholder->replaceAllUsesWith(val);
@@ -307,7 +307,6 @@ void convertThrow(CompilationUnit* cUnit, RegLocation rlSrc)
llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(
greenland::IntrinsicHelper::Throw);
cUnit->irb->CreateCall(func, src);
- cUnit->irb->CreateUnreachable();
}
void convertMonitorEnterExit(CompilationUnit* cUnit, int optFlags,
@@ -812,6 +811,15 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,
bool objectDefinition = false;
+ if (cUnit->printMe) {
+ if ((int)opcode < kMirOpFirst) {
+ LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x"
+ << std::hex << (int)opcode;
+ } else {
+ LOG(INFO) << ".. opcode 0x" << std::hex << (int)opcode;
+ }
+ }
+
/* Prep Src and Dest locations */
int nextSreg = 0;
int nextLoc = 0;
@@ -1292,10 +1300,24 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,
case Instruction::THROW:
convertThrow(cUnit, rlSrc[0]);
+ /*
+ * If this throw is standalone, terminate.
+ * If it might rethrow, force termination
+ * of the following block.
+ */
+ if (bb->fallThrough == NULL) {
+ cUnit->irb->CreateUnreachable();
+ } else {
+ bb->fallThrough->fallThrough = NULL;
+ bb->fallThrough->taken = NULL;
+ }
break;
case Instruction::THROW_VERIFICATION_ERROR:
convertThrowVerificationError(cUnit, vA, vB);
+ UNIMPLEMENTED(WARNING) << "Need dead code elimination pass"
+ << " - disabling bitcode verification";
+ cUnit->enableDebug &= ~(1 << kDebugVerifyBitcode);
break;
case Instruction::MOVE_RESULT_WIDE:
@@ -1306,7 +1328,8 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,
* Instruction rewriting on verification failure can eliminate
* the invoke that feeds this move0result. It won't ever be reached,
* so we can ignore it.
- * TODO: verify that previous instruction if THROW_VERIFICATION_ERROR
+ * TODO: verify that previous instruction is THROW_VERIFICATION_ERROR,
+ * or better, add dead-code elimination.
*/
UNIMPLEMENTED(WARNING) << "Need to verify previous inst was rewritten";
#else
@@ -1649,6 +1672,13 @@ void convertExtendedMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
UNIMPLEMENTED(WARNING) << "unimp kMirOpPhi";
break;
}
+ case kMirOpNop:
+ if ((mir == bb->lastMIRInsn) && (bb->taken == NULL) &&
+ (bb->fallThrough == NULL)) {
+ cUnit->irb->CreateUnreachable();
+ }
+ break;
+
#if defined(TARGET_ARM)
case kMirOpFusedCmplFloat:
UNIMPLEMENTED(WARNING) << "unimp kMirOpFusedCmpFloat";
@@ -1720,6 +1750,16 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb)
cUnit->irb->SetInsertPoint(llvmBB);
setDexOffset(cUnit, bb->startOffset);
+ if (cUnit->printMe) {
+ LOG(INFO) << "................................";
+ LOG(INFO) << "Block id " << bb->id;
+ if (llvmBB != NULL) {
+ LOG(INFO) << "label " << llvmBB->getName().str().c_str();
+ } else {
+ LOG(INFO) << "llvmBB is NULL";
+ }
+ }
+
if (bb->blockType == kEntryBlock) {
setMethodInfo(cUnit);
bool *canBeRef = (bool*) oatNew(cUnit, sizeof(bool) *
@@ -1759,8 +1799,6 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb)
/*
* Because we're deferring null checking, delete the associated empty
* exception block.
- * TODO: add new block type for exception blocks that we generate
- * greenland code for.
*/
llvmBB->eraseFromParent();
return false;
@@ -1770,8 +1808,9 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb)
setDexOffset(cUnit, mir->offset);
- Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
- Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
+ int opcode = mir->dalvikInsn.opcode;
+ Instruction::Format dalvikFormat =
+ Instruction::FormatOf(mir->dalvikInsn.opcode);
/* If we're compiling for the debugger, generate an update callout */
if (cUnit->genDebugger) {
@@ -1779,7 +1818,43 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb)
//genDebuggerUpdate(cUnit, mir->offset);
}
- if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
+ if (opcode == kMirOpCheck) {
+ // Combine check and work halves of throwing instruction.
+ MIR* workHalf = mir->meta.throwInsn;
+ mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode;
+ opcode = mir->dalvikInsn.opcode;
+ SSARepresentation* ssaRep = workHalf->ssaRep;
+ workHalf->ssaRep = mir->ssaRep;
+ mir->ssaRep = ssaRep;
+ workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
+ if (bb->successorBlockList.blockListType == kCatch) {
+ llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(
+ greenland::IntrinsicHelper::CatchTargets);
+ llvm::Value* switchKey =
+ cUnit->irb->CreateCall(intr, cUnit->irb->getInt32(mir->offset));
+ GrowableListIterator iter;
+ oatGrowableListIteratorInit(&bb->successorBlockList.blocks, &iter);
+ // New basic block to use for work half
+ llvm::BasicBlock* workBB =
+ llvm::BasicBlock::Create(*cUnit->context, "", cUnit->func);
+ llvm::SwitchInst* sw =
+ cUnit->irb->CreateSwitch(switchKey, workBB,
+ bb->successorBlockList.blocks.numUsed);
+ while (true) {
+ SuccessorBlockInfo *successorBlockInfo =
+ (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iter);
+ if (successorBlockInfo == NULL) break;
+ llvm::BasicBlock *target =
+ getLLVMBlock(cUnit, successorBlockInfo->block->id);
+ int typeIndex = successorBlockInfo->key;
+ sw->addCase(cUnit->irb->getInt32(typeIndex), target);
+ }
+ llvmBB = workBB;
+ cUnit->irb->SetInsertPoint(llvmBB);
+ }
+ }
+
+ if (opcode >= kMirOpFirst) {
convertExtendedMIR(cUnit, bb, mir, llvmBB);
continue;
}
@@ -1787,8 +1862,9 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb)
bool notHandled = convertMIRNode(cUnit, mir, bb, llvmBB,
NULL /* labelList */);
if (notHandled) {
+ Instruction::Code dalvikOpcode = static_cast<Instruction::Code>(opcode);
LOG(WARNING) << StringPrintf("%#06x: Op %#x (%s) / Fmt %d not handled",
- mir->offset, dalvikOpcode,
+ mir->offset, opcode,
Instruction::Name(dalvikOpcode),
dalvikFormat);
}
@@ -1986,7 +2062,14 @@ void oatMethodMIR2Bitcode(CompilationUnit* cUnit)
cUnit->irb->SetInsertPoint(cUnit->entryBB);
cUnit->irb->CreateBr(cUnit->entryTargetBB);
- //llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction);
+ if (cUnit->enableDebug & (1 << kDebugVerifyBitcode)) {
+ if (llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction)) {
+ LOG(INFO) << "Bitcode verification FAILED for "
+ << PrettyMethod(cUnit->method_idx, *cUnit->dex_file)
+ << " of size " << cUnit->insnsSize;
+ cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile);
+ }
+ }
if (cUnit->enableDebug & (1 << kDebugDumpBitcodeFile)) {
// Write bitcode to file
@@ -3131,6 +3214,24 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb)
cvtShiftOp(cUnit, Instruction::USHR_INT, callInst);
break;
+ case greenland::IntrinsicHelper::CatchTargets: {
+ llvm::SwitchInst* swInst =
+ llvm::dyn_cast<llvm::SwitchInst>(nextIt);
+ DCHECK(swInst != NULL);
+ /*
+ * Discard the edges and the following conditional branch.
+ * Do a direct branch to the default target (which is the
+ * "work" portion of the pair.
+ * TODO: awful code layout - rework
+ */
+ llvm::BasicBlock* targetBB = swInst->getDefaultDest();
+ DCHECK(targetBB != NULL);
+ opUnconditionalBranch(cUnit,
+ cUnit->blockToLabelMap.Get(targetBB));
+ ++it;
+ }
+ break;
+
default:
LOG(FATAL) << "Unexpected intrinsic " << (int)id << ", "
<< cUnit->intrinsic_helper->GetName(id);