-/// FindSelectorAndURoR - Find the eh.selector call associated with the
-/// eh.exception call. And indicate if there is a URoR "invoke" associated with
-/// the eh.exception call. This recursively looks past instructions which don't
-/// change the EH pointer value, like casts or PHI nodes.
-bool
-DwarfEHPrepare::FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke,
- SmallPtrSet<IntrinsicInst*, 8> &SelCalls) {
- SmallPtrSet<PHINode*, 32> SeenPHIs;
- bool Changed = false;
-
- restart:
- for (Value::use_iterator
- I = Inst->use_begin(), E = Inst->use_end(); I != E; ++I) {
- Instruction *II = dyn_cast<Instruction>(I);
- if (!II || II->getParent()->getParent() != F) continue;
-
- if (IntrinsicInst *Sel = dyn_cast<IntrinsicInst>(II)) {
- if (Sel->getIntrinsicID() == Intrinsic::eh_selector)
- SelCalls.insert(Sel);
- } else if (InvokeInst *Invoke = dyn_cast<InvokeInst>(II)) {
- if (Invoke->getCalledFunction() == URoR)
- URoRInvoke = true;
- } else if (CastInst *CI = dyn_cast<CastInst>(II)) {
- Changed |= FindSelectorAndURoR(CI, URoRInvoke, SelCalls);
- } else if (StoreInst *SI = dyn_cast<StoreInst>(II)) {
- if (!PromoteStoreInst(SI)) continue;
- Changed = true;
- SeenPHIs.clear();
- goto restart; // Uses may have changed, restart loop.
- } else if (PHINode *PN = dyn_cast<PHINode>(II)) {
- if (SeenPHIs.insert(PN))
- // Don't process a PHI node more than once.
- Changed |= FindSelectorAndURoR(PN, URoRInvoke, SelCalls);
- }
- }
-
- return Changed;
-}
-
-/// CleanupSelectors - Any remaining eh.selector intrinsic calls which still use
-/// the ".llvm.eh.catch.all.value" call need to convert to using it's
-/// initializer instead.
-bool DwarfEHPrepare::CleanupSelectors() {
- bool Changed = false;
- for (Value::use_iterator
- I = SelectorIntrinsic->use_begin(),
- E = SelectorIntrinsic->use_end(); I != E; ++I) {
- IntrinsicInst *Sel = dyn_cast<IntrinsicInst>(I);
- if (!Sel || Sel->getParent()->getParent() != F) continue;
-
- // Index of the ".llvm.eh.catch.all.value" variable.
- unsigned OpIdx = Sel->getNumOperands() - 1;
- GlobalVariable *GV = dyn_cast<GlobalVariable>(Sel->getOperand(OpIdx));
- if (GV != EHCatchAllValue) continue;
- Sel->setOperand(OpIdx, EHCatchAllValue->getInitializer());
- Changed = true;
- }
-
- return Changed;
-}
-
-/// HandleURoRInvokes - Handle invokes of "_Unwind_Resume_or_Rethrow" calls. The
-/// "unwind" part of these invokes jump to a landing pad within the current
-/// function. This is a candidate to merge the selector associated with the URoR
-/// invoke with the one from the URoR's landing pad.
-bool DwarfEHPrepare::HandleURoRInvokes() {
- if (!EHCatchAllValue) {
- EHCatchAllValue =
- F->getParent()->getNamedGlobal(".llvm.eh.catch.all.value");
- if (!EHCatchAllValue) return false;
- }
-
- if (!SelectorIntrinsic) {
- SelectorIntrinsic =
- Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_selector);
- if (!SelectorIntrinsic) return false;
- }
-
- if (!URoR) {
- URoR = F->getParent()->getFunction("_Unwind_Resume_or_Rethrow");
- if (!URoR) return CleanupSelectors();
- }
-
- if (!ExceptionValueIntrinsic) {
- ExceptionValueIntrinsic =
- Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_exception);
- if (!ExceptionValueIntrinsic) return CleanupSelectors();
- }
-
- bool Changed = false;
- SmallPtrSet<IntrinsicInst*, 32> SelsToConvert;
-
- for (Value::use_iterator
- I = ExceptionValueIntrinsic->use_begin(),
- E = ExceptionValueIntrinsic->use_end(); I != E; ++I) {
- IntrinsicInst *EHPtr = dyn_cast<IntrinsicInst>(I);
- if (!EHPtr || EHPtr->getParent()->getParent() != F) continue;
-
- Changed |= PromoteEHPtrStore(EHPtr);
-
- bool URoRInvoke = false;
- SmallPtrSet<IntrinsicInst*, 8> SelCalls;
- Changed |= FindSelectorAndURoR(EHPtr, URoRInvoke, SelCalls);
-
- if (URoRInvoke) {
- // This EH pointer is being used by an invoke of an URoR instruction and
- // an eh.selector intrinsic call. If the eh.selector is a 'clean-up', we
- // need to convert it to a 'catch-all'.
- for (SmallPtrSet<IntrinsicInst*, 8>::iterator
- SI = SelCalls.begin(), SE = SelCalls.end(); SI != SE; ++SI) {
- IntrinsicInst *II = *SI;
- unsigned NumOps = II->getNumOperands();
-
- if (NumOps <= 4) {
- bool IsCleanUp = (NumOps == 3);
-
- if (!IsCleanUp)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(II->getOperand(3)))
- IsCleanUp = (CI->getZExtValue() == 0);
-
- if (IsCleanUp)
- SelsToConvert.insert(II);
- }
+/// GetExceptionObject - Return the exception object from the value passed into
+/// the 'resume' instruction (typically an aggregate). Clean up any dead
+/// instructions, including the 'resume' instruction.
+Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
+ Value *V = RI->getOperand(0);
+ Value *ExnObj = nullptr;
+ InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
+ LoadInst *SelLoad = nullptr;
+ InsertValueInst *ExcIVI = nullptr;
+ bool EraseIVIs = false;
+
+ if (SelIVI) {
+ if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
+ ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
+ if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
+ ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
+ ExnObj = ExcIVI->getOperand(1);
+ SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
+ EraseIVIs = true;