Adding implementation to outline C++ catch handlers for native Windows 64 exception handling.

Differential Revision: http://reviews.llvm.org/D7363



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229715 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Kaylor
2015-02-18 18:31:51 +00:00
parent 94da968134
commit a4976167c4
5 changed files with 704 additions and 127 deletions

View File

@ -260,21 +260,26 @@ namespace {
const char *NameSuffix;
ClonedCodeInfo *CodeInfo;
const DataLayout *DL;
CloningDirector *Director;
public:
PruningFunctionCloner(Function *newFunc, const Function *oldFunc,
ValueToValueMapTy &valueMap,
bool moduleLevelChanges,
const char *nameSuffix,
ClonedCodeInfo *codeInfo,
const DataLayout *DL)
const DataLayout *DL,
CloningDirector *Director)
: NewFunc(newFunc), OldFunc(oldFunc),
VMap(valueMap), ModuleLevelChanges(moduleLevelChanges),
NameSuffix(nameSuffix), CodeInfo(codeInfo), DL(DL) {
NameSuffix(nameSuffix), CodeInfo(codeInfo), DL(DL),
Director(Director) {
}
/// CloneBlock - The specified block is found to be reachable, clone it and
/// anything that it can reach.
void CloneBlock(const BasicBlock *BB,
void CloneBlock(const BasicBlock *BB,
BasicBlock::const_iterator StartingInst,
std::vector<const BasicBlock*> &ToClone);
};
}
@ -282,6 +287,7 @@ namespace {
/// CloneBlock - The specified block is found to be reachable, clone it and
/// anything that it can reach.
void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
BasicBlock::const_iterator StartingInst,
std::vector<const BasicBlock*> &ToClone){
WeakVH &BBEntry = VMap[BB];
@ -307,14 +313,31 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
const_cast<BasicBlock*>(BB));
VMap[OldBBAddr] = BlockAddress::get(NewFunc, NewBB);
}
bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;
// Loop over all instructions, and copy them over, DCE'ing as we go. This
// loop doesn't include the terminator.
for (BasicBlock::const_iterator II = BB->begin(), IE = --BB->end();
for (BasicBlock::const_iterator II = StartingInst, IE = --BB->end();
II != IE; ++II) {
// If the "Director" remaps the instruction, don't clone it.
if (Director) {
CloningDirector::CloningAction Action
= Director->handleInstruction(VMap, II, NewBB);
// If the cloning director says stop, we want to stop everything, not
// just break out of the loop (which would cause the terminator to be
// cloned). The cloning director is responsible for inserting a proper
// terminator into the new basic block in this case.
if (Action == CloningDirector::StopCloningBB)
return;
// If the cloning director says skip, continue to the next instruction.
// In this case, the cloning director is responsible for mapping the
// skipped instruction to some value that is defined in the new
// basic block.
if (Action == CloningDirector::SkipInstruction)
continue;
}
Instruction *NewInst = II->clone();
// Eagerly remap operands to the newly cloned instruction, except for PHI
@ -354,6 +377,18 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
// Finally, clone over the terminator.
const TerminatorInst *OldTI = BB->getTerminator();
bool TerminatorDone = false;
if (Director) {
CloningDirector::CloningAction Action
= Director->handleInstruction(VMap, OldTI, NewBB);
// If the cloning director says stop, we want to stop everything, not
// just break out of the loop (which would cause the terminator to be
// cloned). The cloning director is responsible for inserting a proper
// terminator into the new basic block in this case.
if (Action == CloningDirector::StopCloningBB)
return;
assert(Action != CloningDirector::SkipInstruction &&
"SkipInstruction is not valid for terminators.");
}
if (const BranchInst *BI = dyn_cast<BranchInst>(OldTI)) {
if (BI->isConditional()) {
// If the condition was a known constant in the callee...
@ -409,39 +444,47 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
}
}
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
/// except that it does some simple constant prop and DCE on the fly. The
/// effect of this is to copy significantly less code in cases where (for
/// example) a function call with constant arguments is inlined, and those
/// constant arguments cause a significant amount of code in the callee to be
/// dead. Since this doesn't produce an exact copy of the input, it can't be
/// used for things like CloneFunction or CloneModule.
void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
/// CloneAndPruneIntoFromInst - This works like CloneAndPruneFunctionInto, except
/// that it does not clone the entire function. Instead it starts at an
/// instruction provided by the caller and copies (and prunes) only the code
/// reachable from that instruction.
void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
const Instruction *StartingInst,
ValueToValueMapTy &VMap,
bool ModuleLevelChanges,
SmallVectorImpl<ReturnInst*> &Returns,
SmallVectorImpl<ReturnInst *> &Returns,
const char *NameSuffix,
ClonedCodeInfo *CodeInfo,
const DataLayout *DL,
Instruction *TheCall) {
CloningDirector *Director) {
assert(NameSuffix && "NameSuffix cannot be null!");
#ifndef NDEBUG
for (Function::const_arg_iterator II = OldFunc->arg_begin(),
E = OldFunc->arg_end(); II != E; ++II)
assert(VMap.count(II) && "No mapping from source argument specified!");
// If the cloning starts at the begining of the function, verify that
// the function arguments are mapped.
if (!StartingInst)
for (Function::const_arg_iterator II = OldFunc->arg_begin(),
E = OldFunc->arg_end(); II != E; ++II)
assert(VMap.count(II) && "No mapping from source argument specified!");
#endif
PruningFunctionCloner PFC(NewFunc, OldFunc, VMap, ModuleLevelChanges,
NameSuffix, CodeInfo, DL);
NameSuffix, CodeInfo, DL, Director);
const BasicBlock *StartingBB;
if (StartingInst)
StartingBB = StartingInst->getParent();
else {
StartingBB = &OldFunc->getEntryBlock();
StartingInst = StartingBB->begin();
}
// Clone the entry block, and anything recursively reachable from it.
std::vector<const BasicBlock*> CloneWorklist;
CloneWorklist.push_back(&OldFunc->getEntryBlock());
PFC.CloneBlock(StartingBB, StartingInst, CloneWorklist);
while (!CloneWorklist.empty()) {
const BasicBlock *BB = CloneWorklist.back();
CloneWorklist.pop_back();
PFC.CloneBlock(BB, CloneWorklist);
PFC.CloneBlock(BB, BB->begin(), CloneWorklist);
}
// Loop over all of the basic blocks in the old function. If the block was
@ -569,7 +612,7 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
// and zap unconditional fall-through branches. This happen all the time when
// specializing code: code specialization turns conditional branches into
// uncond branches, and this code folds them.
Function::iterator Begin = cast<BasicBlock>(VMap[&OldFunc->getEntryBlock()]);
Function::iterator Begin = cast<BasicBlock>(VMap[StartingBB]);
Function::iterator I = Begin;
while (I != NewFunc->end()) {
// Check if this block has become dead during inlining or other
@ -620,9 +663,30 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
// Make a final pass over the basic blocks from theh old function to gather
// any return instructions which survived folding. We have to do this here
// because we can iteratively remove and merge returns above.
for (Function::iterator I = cast<BasicBlock>(VMap[&OldFunc->getEntryBlock()]),
for (Function::iterator I = cast<BasicBlock>(VMap[StartingBB]),
E = NewFunc->end();
I != E; ++I)
if (ReturnInst *RI = dyn_cast<ReturnInst>(I->getTerminator()))
Returns.push_back(RI);
}
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
/// except that it does some simple constant prop and DCE on the fly. The
/// effect of this is to copy significantly less code in cases where (for
/// example) a function call with constant arguments is inlined, and those
/// constant arguments cause a significant amount of code in the callee to be
/// dead. Since this doesn't produce an exact copy of the input, it can't be
/// used for things like CloneFunction or CloneModule.
void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
ValueToValueMapTy &VMap,
bool ModuleLevelChanges,
SmallVectorImpl<ReturnInst*> &Returns,
const char *NameSuffix,
ClonedCodeInfo *CodeInfo,
const DataLayout *DL,
Instruction *TheCall) {
CloneAndPruneIntoFromInst(NewFunc, OldFunc, OldFunc->front().begin(),
VMap, ModuleLevelChanges, Returns, NameSuffix,
CodeInfo, DL, nullptr);
}