diff options
| author | 2012-08-01 10:01:59 -0700 | |
|---|---|---|
| committer | 2012-08-01 10:01:59 -0700 | |
| commit | f2ba9cbe81b0762a7c8c659cdb86ba79b2dbbc40 (patch) | |
| tree | 3a7944e695c65fb25ebdcd27bc640b84e6f4fd38 /src/compiler/codegen/MethodBitcode.cc | |
| parent | 573b42936ba7fbf296452875cdcadedc619418ef (diff) | |
| parent | 8b503db0432981c6b0b2271723f9bcf9448a554a (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.cc | 121 |
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); |