inside a cleanup block, convert "unreachable" to a branch to "cleanupret"

This commit is contained in:
Rainer Schuetze 2015-12-30 14:33:40 +01:00 committed by Martin
parent 5dabf78c7b
commit 73ab5f4fee
2 changed files with 11 additions and 18 deletions

View file

@ -30,18 +30,6 @@ llvm::BasicBlock *getUnwindDest(llvm::Instruction *I) {
return nullptr; return nullptr;
} }
void mapFunclet(llvm::Instruction *I, llvm::ValueToValueMapTy &VMap, llvm::Value *funclet) {
if (auto II = llvm::dyn_cast<llvm::InvokeInst> (I)) {
auto bundle = II->getOperandBundle(llvm::LLVMContext::OB_funclet);
if (bundle)
VMap[bundle->Inputs[0].get()] = funclet;
} else if (auto CI = llvm::dyn_cast<llvm::CallInst> (I)) {
auto bundle = CI->getOperandBundle(llvm::LLVMContext::OB_funclet);
if (bundle)
VMap[bundle->Inputs[0].get()] = funclet;
}
}
// return all basic blocks that are reachable from bb, but don't pass through // return all basic blocks that are reachable from bb, but don't pass through
// ebb and don't follow unwinding target // ebb and don't follow unwinding target
void findSuccessors(std::vector<llvm::BasicBlock *> &blocks, void findSuccessors(std::vector<llvm::BasicBlock *> &blocks,
@ -73,8 +61,6 @@ void remapBlocks(std::vector<llvm::BasicBlock *> &blocks,
llvm::Value *funclet) { llvm::Value *funclet) {
for (llvm::BasicBlock *bb : blocks) for (llvm::BasicBlock *bb : blocks)
for (llvm::BasicBlock::iterator I = bb->begin(); I != bb->end(); ++I) { for (llvm::BasicBlock::iterator I = bb->begin(); I != bb->end(); ++I) {
//if (funclet)
// mapFunclet(&*I, VMap, funclet);
llvm::RemapInstruction(&*I, VMap, llvm::RF_IgnoreMissingEntries | llvm::RemapInstruction(&*I, VMap, llvm::RF_IgnoreMissingEntries |
llvm::RF_NoModuleLevelChanges); llvm::RF_NoModuleLevelChanges);
} }
@ -87,8 +73,11 @@ void remapBlocksValue(std::vector<llvm::BasicBlock *> &blocks,
remapBlocks(blocks, VMap, nullptr, nullptr); remapBlocks(blocks, VMap, nullptr, nullptr);
} }
// make a copy of all srcblocks, mapping values to clones and redirect srcTarget // make a copy of all blocks and instructions in srcblocks
// to continueWith // - map values to clones
// - redirect srcTarget to continueWith
// - set "funclet" attribute inside catch/cleanup pads
// - inside funclets, replace "unreachable" with "branch cleanupret"
void cloneBlocks(const std::vector<llvm::BasicBlock *> &srcblocks, void cloneBlocks(const std::vector<llvm::BasicBlock *> &srcblocks,
std::vector<llvm::BasicBlock *> &blocks, std::vector<llvm::BasicBlock *> &blocks,
llvm::BasicBlock *continueWith, llvm::BasicBlock *unwindTo, llvm::BasicBlock *continueWith, llvm::BasicBlock *unwindTo,
@ -118,6 +107,9 @@ void cloneBlocks(const std::vector<llvm::BasicBlock *> &srcblocks,
CInst, llvm::OperandBundleDef("funclet", funclet)); CInst, llvm::OperandBundleDef("funclet", funclet));
} }
} }
if (funclet && llvm::isa<llvm::UnreachableInst>(Inst)) {
newInst = llvm::BranchInst::Create(continueWith); // cleanupret
}
if (!newInst) if (!newInst)
newInst = Inst->clone(); newInst = Inst->clone();

View file

@ -251,6 +251,7 @@ void ScopeStack::runCleanupCopies(CleanupCursor sourceScope,
llvm::BasicBlock *ScopeStack::runCleanupPad(CleanupCursor scope, llvm::BasicBlock *ScopeStack::runCleanupPad(CleanupCursor scope,
llvm::BasicBlock *unwindTo) { llvm::BasicBlock *unwindTo) {
// a catch switch never needs to be cloned and is an unwind target itself
if (isCatchSwitchBlock(cleanupScopes[scope].beginBlock)) if (isCatchSwitchBlock(cleanupScopes[scope].beginBlock))
return cleanupScopes[scope].beginBlock; return cleanupScopes[scope].beginBlock;
@ -287,10 +288,10 @@ llvm::BasicBlock *ScopeStack::runCleanupPad(CleanupCursor scope,
llvm::BasicBlock *cleanupret = llvm::BasicBlock *cleanupret =
llvm::BasicBlock::Create(irs->context(), "cleanupret", irs->topfunc()); llvm::BasicBlock::Create(irs->context(), "cleanupret", irs->topfunc());
llvm::CleanupReturnInst::Create(cleanuppad, unwindTo, cleanupret); llvm::CleanupReturnInst::Create(cleanuppad, unwindTo, cleanupret);
auto copybb = executeCleanupCopying(irs, cleanupScopes[scope], cleanupbb, auto copybb = executeCleanupCopying(irs, cleanupScopes[scope], cleanupbb,
cleanupret, unwindTo, cleanuppad); cleanupret, unwindTo, cleanuppad);
llvm::BranchInst::Create(copybb, cleanupbb); llvm::BranchInst::Create(copybb, cleanupbb);
return cleanupbb; return cleanupbb;
} }