forked from OSchip/llvm-project
[WinEH] Update clang to use operand bundles on call sites
This updates clang to use bundle operands to associate an invoke with the funclet which it is contained within. Depends on D15517. Differential Revision: http://reviews.llvm.org/D15518 llvm-svn: 255675
This commit is contained in:
parent
3bb88c0210
commit
0b17d44faf
|
@ -3058,19 +3058,41 @@ CodeGenFunction::EmitRuntimeCall(llvm::Value *callee,
|
|||
return call;
|
||||
}
|
||||
|
||||
// Calls which may throw must have operand bundles indicating which funclet
|
||||
// they are nested within.
|
||||
static void
|
||||
getBundlesForFunclet(llvm::Value *Callee,
|
||||
llvm::Instruction *CurrentFuncletPad,
|
||||
SmallVectorImpl<llvm::OperandBundleDef> &BundleList) {
|
||||
// There is no need for a funclet operand bundle if we aren't inside a funclet.
|
||||
if (!CurrentFuncletPad)
|
||||
return;
|
||||
|
||||
// Skip intrinsics which cannot throw.
|
||||
auto *CalleeFn = dyn_cast<llvm::Function>(Callee->stripPointerCasts());
|
||||
if (CalleeFn && CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow())
|
||||
return;
|
||||
|
||||
BundleList.emplace_back("funclet", CurrentFuncletPad);
|
||||
}
|
||||
|
||||
/// Emits a call or invoke to the given noreturn runtime function.
|
||||
void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
|
||||
ArrayRef<llvm::Value*> args) {
|
||||
SmallVector<llvm::OperandBundleDef, 1> BundleList;
|
||||
getBundlesForFunclet(callee, CurrentFuncletPad, BundleList);
|
||||
|
||||
if (getInvokeDest()) {
|
||||
llvm::InvokeInst *invoke =
|
||||
Builder.CreateInvoke(callee,
|
||||
getUnreachableBlock(),
|
||||
getInvokeDest(),
|
||||
args);
|
||||
args,
|
||||
BundleList);
|
||||
invoke->setDoesNotReturn();
|
||||
invoke->setCallingConv(getRuntimeCC());
|
||||
} else {
|
||||
llvm::CallInst *call = Builder.CreateCall(callee, args);
|
||||
llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList);
|
||||
call->setDoesNotReturn();
|
||||
call->setCallingConv(getRuntimeCC());
|
||||
Builder.CreateUnreachable();
|
||||
|
@ -3489,12 +3511,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
|||
}
|
||||
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
|
||||
|
||||
SmallVector<llvm::OperandBundleDef, 1> BundleList;
|
||||
getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList);
|
||||
|
||||
llvm::CallSite CS;
|
||||
if (!InvokeDest) {
|
||||
CS = Builder.CreateCall(Callee, IRCallArgs);
|
||||
CS = Builder.CreateCall(Callee, IRCallArgs, BundleList);
|
||||
} else {
|
||||
llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
|
||||
CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs);
|
||||
CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs,
|
||||
BundleList);
|
||||
EmitBlock(Cont);
|
||||
}
|
||||
if (callOrInvoke)
|
||||
|
|
|
@ -2495,6 +2495,7 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
|
|||
|
||||
llvm::Type *newRetTy = newFn->getReturnType();
|
||||
SmallVector<llvm::Value*, 4> newArgs;
|
||||
SmallVector<llvm::OperandBundleDef, 1> newBundles;
|
||||
|
||||
for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end();
|
||||
ui != ue; ) {
|
||||
|
@ -2562,16 +2563,19 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
|
|||
// over the required information.
|
||||
newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo);
|
||||
|
||||
// Copy over any operand bundles.
|
||||
callSite.getOperandBundlesAsDefs(newBundles);
|
||||
|
||||
llvm::CallSite newCall;
|
||||
if (callSite.isCall()) {
|
||||
newCall = llvm::CallInst::Create(newFn, newArgs, "",
|
||||
newCall = llvm::CallInst::Create(newFn, newArgs, newBundles, "",
|
||||
callSite.getInstruction());
|
||||
} else {
|
||||
auto *oldInvoke = cast<llvm::InvokeInst>(callSite.getInstruction());
|
||||
newCall = llvm::InvokeInst::Create(newFn,
|
||||
oldInvoke->getNormalDest(),
|
||||
oldInvoke->getUnwindDest(),
|
||||
newArgs, "",
|
||||
newArgs, newBundles, "",
|
||||
callSite.getInstruction());
|
||||
}
|
||||
newArgs.clear(); // for the next iteration
|
||||
|
@ -2589,6 +2593,7 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
|
|||
// Copy debug location attached to CI.
|
||||
if (callSite->getDebugLoc())
|
||||
newCall->setDebugLoc(callSite->getDebugLoc());
|
||||
|
||||
callSite->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue