shouldEmitLSDA = shouldEmitPersonality &&
LSDAEncoding != dwarf::DW_EH_PE_omit;
+
+ // If this was an outlined handler, we need to define the label corresponding
+ // to the offset of the parent frame relative to the stack pointer after the
+ // prologue.
+ const Function *F = MF->getFunction();
+ const Function *ParentF = MMI->getWinEHParent(F);
+ if (F != ParentF) {
+ WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
+ auto I = FuncInfo.CatchHandlerParentFrameObjOffset.find(F);
+ if (I != FuncInfo.CatchHandlerParentFrameObjOffset.end()) {
+ MCSymbol *HandlerTypeParentFrameOffset =
+ Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
+ GlobalValue::getRealLinkageName(F->getName()));
+
+ // Emit a symbol assignment.
+ Asm->OutStreamer.EmitAssignment(
+ HandlerTypeParentFrameOffset,
+ MCConstantExpr::Create(I->second, Asm->OutContext));
+ }
+ }
+
if (!shouldEmitPersonality && !shouldEmitMoves)
return;
const Function *F = MF->getFunction();
const Function *ParentF = MMI->getWinEHParent(F);
auto &OS = Asm->OutStreamer;
+ WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
StringRef ParentLinkageName =
GlobalValue::getRealLinkageName(ParentF->getName());
// an ordinary call) between the end of the previous try-range and now.
bool SawPotentiallyThrowing = false;
- WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
-
int LastEHState = -2;
// The parent function and the catch handlers contribute to the 'ip2state'
}
}
- if (ParentF != F)
+ // Defer emission until we've visited the parent function and all the catch
+ // handlers. Cleanups don't contribute to the ip2state table yet, so don't
+ // count them.
+ if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F))
+ return;
+ ++FuncInfo.NumIPToStateFuncsVisited;
+ if (FuncInfo.NumIPToStateFuncsVisited != FuncInfo.CatchHandlerMaxState.size())
return;
MCSymbol *UnwindMapXData = nullptr;
HandlerMaps.push_back(HandlerMapXData);
+ int CatchHigh = -1;
+ for (WinEHHandlerType &HT : TBME.HandlerArray)
+ CatchHigh =
+ std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[HT.Handler]);
+
assert(TBME.TryLow <= TBME.TryHigh);
- assert(TBME.CatchHigh > TBME.TryHigh);
+ assert(CatchHigh > TBME.TryHigh);
OS.EmitIntValue(TBME.TryLow, 4); // TryLow
OS.EmitIntValue(TBME.TryHigh, 4); // TryHigh
- OS.EmitIntValue(TBME.CatchHigh, 4); // CatchHigh
+ OS.EmitIntValue(CatchHigh, 4); // CatchHigh
OS.EmitIntValue(TBME.HandlerArray.size(), 4); // NumCatches
OS.EmitValue(createImageRel32(HandlerMapXData), 4); // HandlerArray
}
// };
OS.EmitLabel(HandlerMapXData);
for (const WinEHHandlerType &HT : TBME.HandlerArray) {
+ MCSymbol *ParentFrameOffset =
+ Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
+ GlobalValue::getRealLinkageName(HT.Handler->getName()));
+ const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::Create(
+ ParentFrameOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
+
+ // Get the frame escape label with the offset of the catch object. If
+ // the index is -1, then there is no catch object, and we should emit an
+ // offset of zero, indicating that no copy will occur.
+ const MCExpr *FrameAllocOffsetRef = nullptr;
+ if (HT.CatchObjRecoverIdx >= 0) {
+ MCSymbol *FrameAllocOffset =
+ Asm->OutContext.getOrCreateFrameAllocSymbol(
+ GlobalValue::getRealLinkageName(ParentF->getName()),
+ HT.CatchObjRecoverIdx);
+ FrameAllocOffsetRef = MCSymbolRefExpr::Create(
+ FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
+ } else {
+ FrameAllocOffsetRef = MCConstantExpr::Create(0, Asm->OutContext);
+ }
+
OS.EmitIntValue(HT.Adjectives, 4); // Adjectives
OS.EmitValue(createImageRel32(HT.TypeDescriptor), 4); // Type
- OS.EmitIntValue(0, 4); // CatchObjOffset
+ OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
OS.EmitValue(createImageRel32(HT.Handler), 4); // Handler
- OS.EmitIntValue(0, 4); // ParentFrameOffset
+ OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
}
}
}