[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:
David Majnemer 2015-12-15 21:27:59 +00:00
parent 3bb88c0210
commit 0b17d44faf
2 changed files with 37 additions and 6 deletions

View File

@ -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)

View File

@ -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();
}
}