diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -25,11 +25,13 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/CodeGenOptions.h" +#include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/CodeGen/SwiftCallingConv.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/ObjCARCInstKind.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Assumptions.h" #include "llvm/IR/Attributes.h" @@ -4465,16 +4467,37 @@ CodeGenFunction::getBundlesForFunclet(llvm::Value *Callee) { SmallVector BundleList; // There is no need for a funclet operand bundle if we aren't inside a - // funclet. + // funclet or the callee is not a function. if (!CurrentFuncletPad) return BundleList; - - // Skip intrinsics which cannot throw. auto *CalleeFn = dyn_cast(Callee->stripPointerCasts()); - if (CalleeFn && CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow()) + if (!CalleeFn) return BundleList; - BundleList.emplace_back("funclet", CurrentFuncletPad); + // Skip intrinsics which cannot throw. + bool InsertFuncletOp = true; + if (CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow()) + InsertFuncletOp = false; + + // Most ObjC ARC intrinics are lowered in PreISelIntrinsicLowering. Thus, + // WinEHPrepare will see them as regular calls. We need to set the funclet + // operand explicitly in this case to avoid accidental truncation of EH + // funclets on Windows. + if (CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow()) { + if (CGM.getTarget().getTriple().isOSWindows()) { + assert(CGM.getLangOpts().ObjCRuntime.getKind() == ObjCRuntime::GNUstep && + "Only reproduced with GNUstep so far, but likely applies to other " + "ObjC runtimes on Windows"); + using namespace llvm::objcarc; + ARCInstKind CalleeKind = GetFunctionClass(CalleeFn); + if (!IsUser(CalleeKind) && CalleeKind != ARCInstKind::None) + InsertFuncletOp = true; + } + } + + if (InsertFuncletOp) + BundleList.emplace_back("funclet", CurrentFuncletPad); + return BundleList; } diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -107,7 +107,9 @@ IRBuilder<> Builder(CI->getParent(), CI->getIterator()); SmallVector Args(CI->args()); - CallInst *NewCI = Builder.CreateCall(FCache, Args); + SmallVector BundleList; + CI->getOperandBundlesAsDefs(BundleList); + CallInst *NewCI = Builder.CreateCall(FCache, Args, BundleList); NewCI->setName(CI->getName()); // Try to set the most appropriate TailCallKind based on both the current diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -963,7 +963,7 @@ if (auto BU = CB->getOperandBundle(LLVMContext::OB_funclet)) FuncletBundleOperand = BU->Inputs.front(); - if (FuncletBundleOperand == FuncletPad) + if (!FuncletPad || FuncletBundleOperand == FuncletPad) continue; // Skip call sites which are nounwind intrinsics or inline asm.