BasicBlock *EndBB);
void processSEHCatchHandler(CatchHandler *Handler, BasicBlock *StartBB);
-
+ void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot);
+ void
+ insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
+ SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist);
+ AllocaInst *insertPHILoads(PHINode *PN, Function &F);
+ void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
+ DenseMap<BasicBlock *, Value *> &Loads, Function &F);
+ void demoteNonlocalUses(Value *V, std::set<BasicBlock *> &ColorsForBB,
+ Function &F);
bool prepareExplicitEH(Function &F);
void numberFunclet(BasicBlock *InitialBB, BasicBlock *FuncletBB);
};
}
-void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) {
+static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState,
+ const Value *V) {
WinEHUnwindMapEntry UME;
UME.ToState = ToState;
- if (auto *CH = dyn_cast_or_null<CleanupHandler>(AH))
- UME.Cleanup = cast<Function>(CH->getHandlerBlockOrFunc());
- else
- UME.Cleanup = nullptr;
+ UME.Cleanup = V;
FuncInfo.UnwindMap.push_back(UME);
+ return FuncInfo.getLastStateNumber();
+}
+
+static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
+ int TryHigh, int CatchHigh,
+ ArrayRef<const CatchPadInst *> Handlers) {
+ WinEHTryBlockMapEntry TBME;
+ TBME.TryLow = TryLow;
+ TBME.TryHigh = TryHigh;
+ TBME.CatchHigh = CatchHigh;
+ assert(TBME.TryLow <= TBME.TryHigh);
+ for (const CatchPadInst *CPI : Handlers) {
+ WinEHHandlerType HT;
+ Constant *TypeInfo = cast<Constant>(CPI->getArgOperand(0));
+ if (TypeInfo->isNullValue()) {
+ HT.Adjectives = 0x40;
+ HT.TypeDescriptor = nullptr;
+ } else {
+ auto *GV = cast<GlobalVariable>(TypeInfo->stripPointerCasts());
+ // Selectors are always pointers to GlobalVariables with 'struct' type.
+ // The struct has two fields, adjectives and a type descriptor.
+ auto *CS = cast<ConstantStruct>(GV->getInitializer());
+ HT.Adjectives =
+ cast<ConstantInt>(CS->getAggregateElement(0U))->getZExtValue();
+ HT.TypeDescriptor =
+ cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts());
+ }
+ HT.Handler = CPI->getParent();
+ // FIXME: Pass CPI->getArgOperand(1).
+ HT.CatchObjRecoverIdx = -1;
+ TBME.HandlerArray.push_back(HT);
+ }
+ FuncInfo.TryBlockMap.push_back(TBME);
+}
+
+void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) {
+ Value *V = nullptr;
+ if (auto *CH = dyn_cast_or_null<CleanupHandler>(AH))
+ V = cast<Function>(CH->getHandlerBlockOrFunc());
+ addUnwindMapEntry(FuncInfo, ToState, V);
}
void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh,
continue;
processCallSite(ActionList, II);
ActionList.clear();
- FuncInfo.LandingPadStateMap[LPI] = currentEHNumber();
+ FuncInfo.EHPadStateMap[LPI] = currentEHNumber();
DEBUG(dbgs() << "Assigning state " << currentEHNumber()
<< " to landing pad at " << LPI->getParent()->getName()
<< '\n');
}
}
+static const BasicBlock *getSingleCatchPadPredecessor(const BasicBlock &BB) {
+ for (const BasicBlock *PredBlock : predecessors(&BB))
+ if (isa<CatchPadInst>(PredBlock->getFirstNonPHI()))
+ return PredBlock;
+ return nullptr;
+}
+
+// Given BB which ends in an unwind edge, return the EHPad that this BB belongs
+// to. If the unwind edge came from an invoke, return null.
+static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
+ const TerminatorInst *TI = BB->getTerminator();
+ if (isa<InvokeInst>(TI))
+ return nullptr;
+ if (isa<CatchPadInst>(TI) || isa<CatchEndPadInst>(TI) ||
+ isa<TerminatePadInst>(TI))
+ return BB;
+ return cast<CleanupPadInst>(cast<CleanupReturnInst>(TI)->getReturnValue())
+ ->getParent();
+}
+
+static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
+ const BasicBlock &BB,
+ int ParentState) {
+ assert(BB.isEHPad());
+ const Instruction *FirstNonPHI = BB.getFirstNonPHI();
+ // All catchpad instructions will be handled when we process their
+ // respective catchendpad instruction.
+ if (isa<CatchPadInst>(FirstNonPHI))
+ return;
+
+ if (isa<CatchEndPadInst>(FirstNonPHI)) {
+ const BasicBlock *TryPad = &BB;
+ const BasicBlock *LastTryPad = nullptr;
+ SmallVector<const CatchPadInst *, 2> Handlers;
+ do {
+ LastTryPad = TryPad;
+ TryPad = getSingleCatchPadPredecessor(*TryPad);
+ if (TryPad)
+ Handlers.push_back(cast<CatchPadInst>(TryPad->getFirstNonPHI()));
+ } while (TryPad);
+ // We've pushed these back into reverse source order. Reverse them to get
+ // the list back into source order.
+ std::reverse(Handlers.begin(), Handlers.end());
+ int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
+ FuncInfo.EHPadStateMap[Handlers.front()] = TryLow;
+ for (const BasicBlock *PredBlock : predecessors(LastTryPad))
+ if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+ calculateExplicitStateNumbers(FuncInfo, *PredBlock, TryLow);
+ int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
+ FuncInfo.EHPadStateMap[FirstNonPHI] = CatchLow;
+ int TryHigh = CatchLow - 1;
+ for (const BasicBlock *PredBlock : predecessors(&BB))
+ if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+ calculateExplicitStateNumbers(FuncInfo, *PredBlock, CatchLow);
+ int CatchHigh = FuncInfo.getLastStateNumber();
+ addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
+ DEBUG(dbgs() << "TryLow[" << LastTryPad->getName() << "]: " << TryLow
+ << '\n');
+ DEBUG(dbgs() << "TryHigh[" << LastTryPad->getName() << "]: " << TryHigh
+ << '\n');
+ DEBUG(dbgs() << "CatchHigh[" << LastTryPad->getName() << "]: " << CatchHigh
+ << '\n');
+ } else if (isa<CleanupPadInst>(FirstNonPHI)) {
+ int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
+ FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
+ DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
+ << BB.getName() << '\n');
+ for (const BasicBlock *PredBlock : predecessors(&BB))
+ if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+ calculateExplicitStateNumbers(FuncInfo, *PredBlock, CleanupState);
+ } else if (isa<TerminatePadInst>(FirstNonPHI)) {
+ report_fatal_error("Not yet implemented!");
+ } else {
+ llvm_unreachable("unexpected EH Pad!");
+ }
+}
+
void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn,
WinEHFuncInfo &FuncInfo) {
// Return if it's already been done.
- if (!FuncInfo.LandingPadStateMap.empty())
+ if (!FuncInfo.EHPadStateMap.empty())
+ return;
+
+ bool IsExplicit = false;
+ for (const BasicBlock &BB : *ParentFn) {
+ if (!BB.isEHPad())
+ continue;
+ // Check if the EH Pad has no exceptional successors (i.e. it unwinds to
+ // caller). Cleanups are a little bit of a special case because their
+ // control flow cannot be determined by looking at the pad but instead by
+ // the pad's users.
+ bool HasNoSuccessors = false;
+ const Instruction *FirstNonPHI = BB.getFirstNonPHI();
+ if (FirstNonPHI->mayThrow()) {
+ HasNoSuccessors = true;
+ } else if (auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI)) {
+ HasNoSuccessors =
+ CPI->use_empty() ||
+ cast<CleanupReturnInst>(CPI->user_back())->unwindsToCaller();
+ }
+
+ if (!HasNoSuccessors)
+ continue;
+ calculateExplicitStateNumbers(FuncInfo, BB, -1);
+ IsExplicit = true;
+ }
+
+ if (IsExplicit)
return;
WinEHNumbering Num(FuncInfo);
}
bool WinEHPrepare::prepareExplicitEH(Function &F) {
- LLVMContext &Context = F.getContext();
// Remove unreachable blocks. It is not valuable to assign them a color and
// their existence can trick us into thinking values are alive when they are
// not.
numberFunclet(CRI->getSuccessor(), EntryBlock);
}
- // Insert cleanuppads before EH blocks with PHI nodes.
+ // Strip PHI nodes off of EH pads.
+ SmallVector<PHINode *, 16> PHINodes;
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
BasicBlock *BB = FI++;
- // Skip any BBs which aren't EH pads.
if (!BB->isEHPad())
continue;
- // Skip any cleanuppads, they can hold non-PHI instructions.
- if (isa<CleanupPadInst>(BB->getFirstNonPHI()))
- continue;
- // Skip any EH pads without PHIs, we don't need to worry about demoting into
- // them.
- if (!isa<PHINode>(BB->begin()))
- continue;
-
- // Create our new cleanuppad BB, terminate it with a cleanupret.
- auto *NewCleanupBB = BasicBlock::Create(
- Context, Twine(BB->getName(), ".wineh.phibb"), &F, BB);
- auto *CPI = CleanupPadInst::Create(Type::getVoidTy(Context), {BB}, "",
- NewCleanupBB);
- CleanupReturnInst::Create(Context, /*RetVal=*/nullptr, BB, NewCleanupBB);
-
- // Update the funclet data structures to keep them in the loop.
- BlockColors[NewCleanupBB].insert(NewCleanupBB);
- FuncletBlocks[NewCleanupBB].insert(NewCleanupBB);
-
- // Reparent PHIs from the old EH BB into the cleanuppad.
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
Instruction *I = BI++;
auto *PN = dyn_cast<PHINode>(I);
// Stop at the first non-PHI.
if (!PN)
break;
- PN->removeFromParent();
- PN->insertBefore(CPI);
- }
- // Redirect predecessors from the old EH BB to the cleanuppad.
- std::set<BasicBlock *> Preds;
- Preds.insert(pred_begin(BB), pred_end(BB));
- for (BasicBlock *Pred : Preds) {
- // Don't redirect the new cleanuppad to itself!
- if (Pred == NewCleanupBB)
- continue;
- TerminatorInst *TI = Pred->getTerminator();
- for (unsigned TII = 0, TIE = TI->getNumSuccessors(); TII != TIE; ++TII) {
- BasicBlock *Successor = TI->getSuccessor(TII);
- if (Successor == BB)
- TI->setSuccessor(TII, NewCleanupBB);
- }
+ AllocaInst *SpillSlot = insertPHILoads(PN, F);
+ if (SpillSlot)
+ insertPHIStores(PN, SpillSlot);
+
+ PHINodes.push_back(PN);
}
}
- // Get rid of polychromatic PHI nodes.
- for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
- BasicBlock *BB = FI++;
- std::set<BasicBlock *> &ColorsForBB = BlockColors[BB];
- bool IsEHPad = BB->isEHPad();
- for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
- Instruction *I = BI++;
- auto *PN = dyn_cast<PHINode>(I);
- // Stop at the first non-PHI node.
- if (!PN)
- break;
-
- // EH pads cannot be lowered with PHI nodes prefacing them.
- if (IsEHPad) {
- // We should have removed PHIs from all non-cleanuppad blocks.
- if (!isa<CleanupPadInst>(BB->getFirstNonPHI()))
- report_fatal_error("Unexpected PHI on EH Pad");
- DemotePHIToStack(PN);
- continue;
- }
-
- // See if *all* the basic blocks involved in this PHI node are in the
- // same, lone, color. If so, demotion is not needed.
- bool SameColor = ColorsForBB.size() == 1;
- if (SameColor) {
- for (unsigned PNI = 0, PNE = PN->getNumIncomingValues(); PNI != PNE;
- ++PNI) {
- BasicBlock *IncomingBB = PN->getIncomingBlock(PNI);
- std::set<BasicBlock *> &ColorsForIncomingBB = BlockColors[IncomingBB];
- // If the colors differ, bail out early and demote.
- if (ColorsForIncomingBB != ColorsForBB) {
- SameColor = false;
- break;
- }
- }
- }
-
- if (!SameColor)
- DemotePHIToStack(PN);
- }
+ for (auto *PN : PHINodes) {
+ // There may be lingering uses on other EH PHIs being removed
+ PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
+ PN->eraseFromParent();
}
// Turn all inter-funclet uses of a Value into loads and stores.
if (AI->isStaticAlloca())
continue;
- // FIXME: Our spill-placement algorithm is incredibly naive. We should
- // try to sink+hoist as much as possible to avoid redundant stores and reloads.
- DenseMap<BasicBlock *, Value *> Loads;
- AllocaInst *SpillSlot = nullptr;
- for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
- UI != UE;) {
- Use &U = *UI++;
- auto *UsingInst = cast<Instruction>(U.getUser());
- BasicBlock *UsingBB = UsingInst->getParent();
-
- // Is the Use inside a block which is colored with a subset of the Def?
- // If so, we don't need to escape the Def because we will clone
- // ourselves our own private copy.
- std::set<BasicBlock *> &ColorsForUsingBB = BlockColors[UsingBB];
- if (std::includes(ColorsForBB.begin(), ColorsForBB.end(),
- ColorsForUsingBB.begin(), ColorsForUsingBB.end()))
- continue;
-
- // Lazilly create the spill slot. We spill immediately after the value
- // in the BasicBlock.
- // FIXME: This can be improved to spill at the block exit points.
- if (!SpillSlot)
- SpillSlot = new AllocaInst(I->getType(), nullptr,
- Twine(I->getName(), ".wineh.spillslot"),
- EntryBlock->begin());
-
- if (auto *PN = dyn_cast<PHINode>(UsingInst)) {
- // If this is a PHI node, we can't insert a load of the value before
- // the use. Instead insert the load in the predecessor block
- // corresponding to the incoming value.
- //
- // Note that if there are multiple edges from a basic block to this
- // PHI node that we cannot have multiple loads. The problem is that
- // the resulting PHI node will have multiple values (from each load)
- // coming in from the same block, which is illegal SSA form.
- // For this reason, we keep track of and reuse loads we insert.
- BasicBlock *IncomingBlock = PN->getIncomingBlock(U);
- Value *&V = Loads[IncomingBlock];
- // Insert the load into the predecessor block
- if (!V)
- V = new LoadInst(SpillSlot, Twine(I->getName(), ".wineh.reload"),
- /*Volatile=*/false,
- IncomingBlock->getTerminator());
- U.set(V);
- } else {
- // Reload right before the old use.
- // FIXME: This can be improved to reload at a block entry point.
- Value *V =
- new LoadInst(SpillSlot, Twine(I->getName(), ".wineh.reload"),
- /*Volatile=*/false, UsingInst);
- U.set(V);
- }
- }
- if (SpillSlot) {
- // Insert stores of the computed value into the stack slot.
- // We have to be careful if I is an invoke instruction,
- // because we can't insert the store AFTER the terminator instruction.
- BasicBlock::iterator InsertPt;
- if (!isa<TerminatorInst>(I)) {
- InsertPt = I;
- ++InsertPt;
- // Don't insert before PHI nodes or EH pad instrs.
- for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt)
- ;
- } else {
- auto *II = cast<InvokeInst>(I);
- // We cannot demote invoke instructions to the stack if their normal
- // edge is critical. Therefore, split the critical edge and create a
- // basic block into which the store can be inserted.
- if (!II->getNormalDest()->getSinglePredecessor()) {
- unsigned SuccNum = GetSuccessorNumber(BB, II->getNormalDest());
- assert(isCriticalEdge(II, SuccNum) && "Expected a critical edge!");
- BasicBlock *NewBlock = SplitCriticalEdge(II, SuccNum);
- assert(NewBlock && "Unable to split critical edge.");
- // Update the color mapping for the newly split edge.
- std::set<BasicBlock *> &ColorsForUsingBB =
- BlockColors[II->getParent()];
- BlockColors[NewBlock] = ColorsForUsingBB;
- for (BasicBlock *FuncletPad : ColorsForUsingBB)
- FuncletBlocks[FuncletPad].insert(NewBlock);
- }
- InsertPt = II->getNormalDest()->getFirstInsertionPt();
- }
- new StoreInst(I, SpillSlot, InsertPt);
- }
+ demoteNonlocalUses(I, ColorsForBB, F);
}
}
+ // Also demote function parameters used in funclets.
+ std::set<BasicBlock *> &ColorsForEntry = BlockColors[&F.getEntryBlock()];
+ for (Argument &Arg : F.args())
+ demoteNonlocalUses(&Arg, ColorsForEntry, F);
// We need to clone all blocks which belong to multiple funclets. Values are
// remapped throughout the funclet to propogate both the new instructions
RemapInstruction(&I, VMap, RF_IgnoreMissingEntries);
}
+ // Remove implausible terminators and replace them with UnreachableInst.
+ for (auto &Funclet : FuncletBlocks) {
+ BasicBlock *FuncletPadBB = Funclet.first;
+ std::set<BasicBlock *> &BlocksInFunclet = Funclet.second;
+ Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
+ auto *CatchPad = dyn_cast<CatchPadInst>(FirstNonPHI);
+ auto *CleanupPad = dyn_cast<CleanupPadInst>(FirstNonPHI);
+
+ for (BasicBlock *BB : BlocksInFunclet) {
+ TerminatorInst *TI = BB->getTerminator();
+ // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
+ bool IsUnreachableRet = isa<ReturnInst>(TI) && (CatchPad || CleanupPad);
+ // The token consumed by a CatchReturnInst must match the funclet token.
+ bool IsUnreachableCatchret = false;
+ if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
+ IsUnreachableCatchret = CRI->getReturnValue() != CatchPad;
+ // The token consumed by a CleanupPadInst must match the funclet token.
+ bool IsUnreachableCleanupret = false;
+ if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
+ IsUnreachableCleanupret = CRI->getReturnValue() != CleanupPad;
+ if (IsUnreachableRet || IsUnreachableCatchret || IsUnreachableCleanupret) {
+ new UnreachableInst(BB->getContext(), TI);
+ TI->eraseFromParent();
+ }
+ }
+ }
+
// Clean-up some of the mess we made by removing useles PHI nodes, trivial
// branches, etc.
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
MergeBlockIntoPredecessor(BB);
}
- // TODO: Do something about cleanupblocks which branch to implausible
- // cleanuprets.
-
// We might have some unreachable blocks after cleaning up some impossible
// control flow.
removeUnreachableBlocks(F);
BlockColors.clear();
FuncletBlocks.clear();
+
return true;
}
+
+// TODO: Share loads when one use dominates another, or when a catchpad exit
+// dominates uses (needs dominators).
+AllocaInst *WinEHPrepare::insertPHILoads(PHINode *PN, Function &F) {
+ BasicBlock *PHIBlock = PN->getParent();
+ AllocaInst *SpillSlot = nullptr;
+
+ if (isa<CleanupPadInst>(PHIBlock->getFirstNonPHI())) {
+ // Insert a load in place of the PHI and replace all uses.
+ SpillSlot = new AllocaInst(PN->getType(), nullptr,
+ Twine(PN->getName(), ".wineh.spillslot"),
+ F.getEntryBlock().begin());
+ Value *V = new LoadInst(SpillSlot, Twine(PN->getName(), ".wineh.reload"),
+ PHIBlock->getFirstInsertionPt());
+ PN->replaceAllUsesWith(V);
+ return SpillSlot;
+ }
+
+ DenseMap<BasicBlock *, Value *> Loads;
+ for (Value::use_iterator UI = PN->use_begin(), UE = PN->use_end();
+ UI != UE;) {
+ Use &U = *UI++;
+ auto *UsingInst = cast<Instruction>(U.getUser());
+ BasicBlock *UsingBB = UsingInst->getParent();
+ if (UsingBB->isEHPad()) {
+ // Use is on an EH pad phi. Leave it alone; we'll insert loads and
+ // stores for it separately.
+ assert(isa<PHINode>(UsingInst));
+ continue;
+ }
+ replaceUseWithLoad(PN, U, SpillSlot, Loads, F);
+ }
+ return SpillSlot;
+}
+
+// TODO: improve store placement. Inserting at def is probably good, but need
+// to be careful not to introduce interfering stores (needs liveness analysis).
+// TODO: identify related phi nodes that can share spill slots, and share them
+// (also needs liveness).
+void WinEHPrepare::insertPHIStores(PHINode *OriginalPHI,
+ AllocaInst *SpillSlot) {
+ // Use a worklist of (Block, Value) pairs -- the given Value needs to be
+ // stored to the spill slot by the end of the given Block.
+ SmallVector<std::pair<BasicBlock *, Value *>, 4> Worklist;
+
+ Worklist.push_back({OriginalPHI->getParent(), OriginalPHI});
+
+ while (!Worklist.empty()) {
+ BasicBlock *EHBlock;
+ Value *InVal;
+ std::tie(EHBlock, InVal) = Worklist.pop_back_val();
+
+ PHINode *PN = dyn_cast<PHINode>(InVal);
+ if (PN && PN->getParent() == EHBlock) {
+ // The value is defined by another PHI we need to remove, with no room to
+ // insert a store after the PHI, so each predecessor needs to store its
+ // incoming value.
+ for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
+ Value *PredVal = PN->getIncomingValue(i);
+
+ // Undef can safely be skipped.
+ if (isa<UndefValue>(PredVal))
+ continue;
+
+ insertPHIStore(PN->getIncomingBlock(i), PredVal, SpillSlot, Worklist);
+ }
+ } else {
+ // We need to store InVal, which dominates EHBlock, but can't put a store
+ // in EHBlock, so need to put stores in each predecessor.
+ for (BasicBlock *PredBlock : predecessors(EHBlock)) {
+ insertPHIStore(PredBlock, InVal, SpillSlot, Worklist);
+ }
+ }
+ }
+}
+
+void WinEHPrepare::insertPHIStore(
+ BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
+ SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) {
+
+ if (PredBlock->isEHPad() &&
+ !isa<CleanupPadInst>(PredBlock->getFirstNonPHI())) {
+ // Pred is unsplittable, so we need to queue it on the worklist.
+ Worklist.push_back({PredBlock, PredVal});
+ return;
+ }
+
+ // Otherwise, insert the store at the end of the basic block.
+ new StoreInst(PredVal, SpillSlot, PredBlock->getTerminator());
+}
+
+// TODO: Share loads for same-funclet uses (requires dominators if funclets
+// aren't properly nested).
+void WinEHPrepare::demoteNonlocalUses(Value *V,
+ std::set<BasicBlock *> &ColorsForBB,
+ Function &F) {
+ // Tokens can only be used non-locally due to control flow involving
+ // unreachable edges. Don't try to demote the token usage, we'll simply
+ // delete the cloned user later.
+ if (isa<CatchPadInst>(V) || isa<CleanupPadInst>(V))
+ return;
+
+ DenseMap<BasicBlock *, Value *> Loads;
+ AllocaInst *SpillSlot = nullptr;
+ for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;) {
+ Use &U = *UI++;
+ auto *UsingInst = cast<Instruction>(U.getUser());
+ BasicBlock *UsingBB = UsingInst->getParent();
+
+ // Is the Use inside a block which is colored with a subset of the Def?
+ // If so, we don't need to escape the Def because we will clone
+ // ourselves our own private copy.
+ std::set<BasicBlock *> &ColorsForUsingBB = BlockColors[UsingBB];
+ if (std::includes(ColorsForBB.begin(), ColorsForBB.end(),
+ ColorsForUsingBB.begin(), ColorsForUsingBB.end()))
+ continue;
+
+ replaceUseWithLoad(V, U, SpillSlot, Loads, F);
+ }
+ if (SpillSlot) {
+ // Insert stores of the computed value into the stack slot.
+ // We have to be careful if I is an invoke instruction,
+ // because we can't insert the store AFTER the terminator instruction.
+ BasicBlock::iterator InsertPt;
+ if (isa<Argument>(V)) {
+ InsertPt = F.getEntryBlock().getTerminator();
+ } else if (isa<TerminatorInst>(V)) {
+ auto *II = cast<InvokeInst>(V);
+ // We cannot demote invoke instructions to the stack if their normal
+ // edge is critical. Therefore, split the critical edge and create a
+ // basic block into which the store can be inserted.
+ if (!II->getNormalDest()->getSinglePredecessor()) {
+ unsigned SuccNum =
+ GetSuccessorNumber(II->getParent(), II->getNormalDest());
+ assert(isCriticalEdge(II, SuccNum) && "Expected a critical edge!");
+ BasicBlock *NewBlock = SplitCriticalEdge(II, SuccNum);
+ assert(NewBlock && "Unable to split critical edge.");
+ // Update the color mapping for the newly split edge.
+ std::set<BasicBlock *> &ColorsForUsingBB = BlockColors[II->getParent()];
+ BlockColors[NewBlock] = ColorsForUsingBB;
+ for (BasicBlock *FuncletPad : ColorsForUsingBB)
+ FuncletBlocks[FuncletPad].insert(NewBlock);
+ }
+ InsertPt = II->getNormalDest()->getFirstInsertionPt();
+ } else {
+ InsertPt = cast<Instruction>(V);
+ ++InsertPt;
+ // Don't insert before PHI nodes or EH pad instrs.
+ for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt)
+ ;
+ }
+ new StoreInst(V, SpillSlot, InsertPt);
+ }
+}
+
+void WinEHPrepare::replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
+ DenseMap<BasicBlock *, Value *> &Loads,
+ Function &F) {
+ // Lazilly create the spill slot.
+ if (!SpillSlot)
+ SpillSlot = new AllocaInst(V->getType(), nullptr,
+ Twine(V->getName(), ".wineh.spillslot"),
+ F.getEntryBlock().begin());
+
+ auto *UsingInst = cast<Instruction>(U.getUser());
+ if (auto *UsingPHI = dyn_cast<PHINode>(UsingInst)) {
+ // If this is a PHI node, we can't insert a load of the value before
+ // the use. Instead insert the load in the predecessor block
+ // corresponding to the incoming value.
+ //
+ // Note that if there are multiple edges from a basic block to this
+ // PHI node that we cannot have multiple loads. The problem is that
+ // the resulting PHI node will have multiple values (from each load)
+ // coming in from the same block, which is illegal SSA form.
+ // For this reason, we keep track of and reuse loads we insert.
+ BasicBlock *IncomingBlock = UsingPHI->getIncomingBlock(U);
+ if (auto *CatchRet =
+ dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
+ // Putting a load above a catchret and use on the phi would still leave
+ // a cross-funclet def/use. We need to split the edge, change the
+ // catchret to target the new block, and put the load there.
+ BasicBlock *PHIBlock = UsingInst->getParent();
+ BasicBlock *NewBlock = SplitEdge(IncomingBlock, PHIBlock);
+ // SplitEdge gives us:
+ // IncomingBlock:
+ // ...
+ // br label %NewBlock
+ // NewBlock:
+ // catchret label %PHIBlock
+ // But we need:
+ // IncomingBlock:
+ // ...
+ // catchret label %NewBlock
+ // NewBlock:
+ // br label %PHIBlock
+ // So move the terminators to each others' blocks and swap their
+ // successors.
+ BranchInst *Goto = cast<BranchInst>(IncomingBlock->getTerminator());
+ Goto->removeFromParent();
+ CatchRet->removeFromParent();
+ IncomingBlock->getInstList().push_back(CatchRet);
+ NewBlock->getInstList().push_back(Goto);
+ Goto->setSuccessor(0, PHIBlock);
+ CatchRet->setSuccessor(NewBlock);
+ // Update the color mapping for the newly split edge.
+ std::set<BasicBlock *> &ColorsForPHIBlock = BlockColors[PHIBlock];
+ BlockColors[NewBlock] = ColorsForPHIBlock;
+ for (BasicBlock *FuncletPad : ColorsForPHIBlock)
+ FuncletBlocks[FuncletPad].insert(NewBlock);
+ // Treat the new block as incoming for load insertion.
+ IncomingBlock = NewBlock;
+ }
+ Value *&Load = Loads[IncomingBlock];
+ // Insert the load into the predecessor block
+ if (!Load)
+ Load = new LoadInst(SpillSlot, Twine(V->getName(), ".wineh.reload"),
+ /*Volatile=*/false, IncomingBlock->getTerminator());
+
+ U.set(Load);
+ } else {
+ // Reload right before the old use.
+ auto *Load = new LoadInst(SpillSlot, Twine(V->getName(), ".wineh.reload"),
+ /*Volatile=*/false, UsingInst);
+ U.set(Load);
+ }
+}