[WinEH] Emit EH tables for __CxxFrameHandler3 on 32-bit x86
Small (really small!) C++ exception handling examples work on 32-bit x86
now.
This change disables the use of .seh_* directives in WinException when
CFI is not in use. It also uses absolute symbol references in the tables
instead of imagerel32 relocations.
Also fixes a cache invalidation bug in MMI personality classification.
llvm-svn: 238575
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index c895aa5..229082f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -268,6 +268,7 @@
default: llvm_unreachable("unsupported unwinding information encoding");
case WinEH::EncodingType::Invalid:
break;
+ case WinEH::EncodingType::X86:
case WinEH::EncodingType::Itanium:
ES = new WinException(this);
break;
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index 9c6069b..0b4bf75 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -29,6 +29,7 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCWin64EH.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
@@ -38,9 +39,11 @@
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
-WinException::WinException(AsmPrinter *A)
- : EHStreamer(A), shouldEmitPersonality(false), shouldEmitLSDA(false),
- shouldEmitMoves(false) {}
+WinException::WinException(AsmPrinter *A) : EHStreamer(A) {
+ // MSVC's EH tables are always composed of 32-bit words. All known 64-bit
+ // platforms use an imagerel32 relocation to refer to symbols.
+ useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64);
+}
WinException::~WinException() {}
@@ -55,11 +58,14 @@
// If any landing pads survive, we need an EH table.
bool hasLandingPads = !MMI->getLandingPads().empty();
+ const Function *F = MF->getFunction();
+ const Function *ParentF = MMI->getWinEHParent(F);
+
shouldEmitMoves = Asm->needsSEHMoves();
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
unsigned PerEncoding = TLOF.getPersonalityEncoding();
- const Function *Per = MF->getMMI().getPersonality();
+ const Function *Per = MMI->getPersonality();
shouldEmitPersonality = hasLandingPads &&
PerEncoding != dwarf::DW_EH_PE_omit && Per;
@@ -68,12 +74,17 @@
shouldEmitLSDA = shouldEmitPersonality &&
LSDAEncoding != dwarf::DW_EH_PE_omit;
+ // If we're not using CFI, we don't want the CFI or the personality. Emit the
+ // LSDA if this is the parent function.
+ if (!Asm->MAI->usesWindowsCFI()) {
+ shouldEmitLSDA = (hasLandingPads && F == ParentF);
+ shouldEmitPersonality = false;
+ return;
+ }
// 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);
@@ -89,23 +100,20 @@
}
}
- if (!shouldEmitPersonality && !shouldEmitMoves)
- return;
+ if (shouldEmitMoves || shouldEmitPersonality)
+ Asm->OutStreamer->EmitWinCFIStartProc(Asm->CurrentFnSym);
- Asm->OutStreamer->EmitWinCFIStartProc(Asm->CurrentFnSym);
-
- if (!shouldEmitPersonality)
- return;
-
- const MCSymbol *PersHandlerSym =
- TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
- Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true);
+ if (shouldEmitPersonality) {
+ const MCSymbol *PersHandlerSym =
+ TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
+ Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true);
+ }
}
/// endFunction - Gather and emit post-function exception information.
///
void WinException::endFunction(const MachineFunction *MF) {
- if (!shouldEmitPersonality && !shouldEmitMoves)
+ if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA)
return;
EHPersonality Per = MMI->getPersonalityType();
@@ -116,16 +124,27 @@
if (!isMSVCEHPersonality(Per))
MMI->TidyLandingPads();
- if (shouldEmitPersonality) {
+ if (shouldEmitPersonality || shouldEmitLSDA) {
Asm->OutStreamer->PushSection();
- // Emit an UNWIND_INFO struct describing the prologue.
- Asm->OutStreamer->EmitWinEHHandlerData();
+ if (shouldEmitMoves || shouldEmitPersonality) {
+ // Emit an UNWIND_INFO struct describing the prologue.
+ Asm->OutStreamer->EmitWinEHHandlerData();
+ } else {
+ // Just switch sections to the right xdata section. This use of
+ // CurrentFnSym assumes that we only emit the LSDA when ending the parent
+ // function.
+ MCSection *XData = WinEH::UnwindEmitter::getXDataSection(
+ Asm->CurrentFnSym, Asm->OutContext);
+ Asm->OutStreamer->SwitchSection(XData);
+ }
// Emit the tables appropriate to the personality function in use. If we
// don't recognize the personality, assume it uses an Itanium-style LSDA.
if (Per == EHPersonality::MSVC_Win64SEH)
emitCSpecificHandlerTable();
+ else if (Per == EHPersonality::MSVC_X86SEH)
+ emitCSpecificHandlerTable(); // FIXME
else if (Per == EHPersonality::MSVC_CXX)
emitCXXFrameHandler3Table(MF);
else
@@ -133,20 +152,24 @@
Asm->OutStreamer->PopSection();
}
- Asm->OutStreamer->EmitWinCFIEndProc();
+
+ if (shouldEmitMoves)
+ Asm->OutStreamer->EmitWinCFIEndProc();
}
-const MCExpr *WinException::createImageRel32(const MCSymbol *Value) {
+const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
if (!Value)
return MCConstantExpr::Create(0, Asm->OutContext);
- return MCSymbolRefExpr::Create(Value, MCSymbolRefExpr::VK_COFF_IMGREL32,
+ return MCSymbolRefExpr::Create(Value, useImageRel32
+ ? MCSymbolRefExpr::VK_COFF_IMGREL32
+ : MCSymbolRefExpr::VK_None,
Asm->OutContext);
}
-const MCExpr *WinException::createImageRel32(const GlobalValue *GV) {
+const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
if (!GV)
return MCConstantExpr::Create(0, Asm->OutContext);
- return createImageRel32(Asm->getSymbol(GV));
+ return create32bitRef(Asm->getSymbol(GV));
}
/// Emit the language-specific data that __C_specific_handler expects. This
@@ -227,16 +250,16 @@
// Compute the label range. We may reuse the function begin and end labels
// rather than forming new ones.
const MCExpr *Begin =
- createImageRel32(CSE.BeginLabel ? CSE.BeginLabel : EHFuncBeginSym);
+ create32bitRef(CSE.BeginLabel ? CSE.BeginLabel : EHFuncBeginSym);
const MCExpr *End;
if (CSE.EndLabel) {
// The interval is half-open, so we have to add one to include the return
// address of the last invoke in the range.
- End = MCBinaryExpr::CreateAdd(createImageRel32(CSE.EndLabel),
+ End = MCBinaryExpr::CreateAdd(create32bitRef(CSE.EndLabel),
MCConstantExpr::Create(1, Asm->OutContext),
Asm->OutContext);
} else {
- End = createImageRel32(EHFuncEndSym);
+ End = create32bitRef(EHFuncEndSym);
}
// Emit an entry for each action.
@@ -248,7 +271,7 @@
// emit '1' to indicate a catch-all.
const Function *F = Handler.FilterOrFinally;
if (F)
- Asm->OutStreamer->EmitValue(createImageRel32(Asm->getSymbol(F)), 4);
+ Asm->OutStreamer->EmitValue(create32bitRef(Asm->getSymbol(F)), 4);
else
Asm->OutStreamer->EmitIntValue(1, 4);
@@ -257,7 +280,7 @@
const BlockAddress *BA = Handler.RecoverBA;
if (BA)
Asm->OutStreamer->EmitValue(
- createImageRel32(Asm->GetBlockAddressSymbol(BA)), 4);
+ create32bitRef(Asm->GetBlockAddressSymbol(BA)), 4);
else
Asm->OutStreamer->EmitIntValue(0, 4);
}
@@ -273,9 +296,178 @@
StringRef ParentLinkageName =
GlobalValue::getRealLinkageName(ParentF->getName());
- MCSymbol *FuncInfoXData =
- Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", ParentLinkageName));
- OS.EmitValue(createImageRel32(FuncInfoXData), 4);
+ MCSymbol *FuncInfoXData = nullptr;
+ if (shouldEmitPersonality) {
+ FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
+ Twine("$cppxdata$", ParentLinkageName));
+ OS.EmitValue(create32bitRef(FuncInfoXData), 4);
+
+ extendIP2StateTable(MF, ParentF, FuncInfo);
+
+ // Defer emission until we've visited the parent function and all the catch
+ // handlers. Cleanups don't contribute to the ip2state table, so don't count
+ // them.
+ if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F))
+ return;
+ ++FuncInfo.NumIPToStateFuncsVisited;
+ if (FuncInfo.NumIPToStateFuncsVisited != FuncInfo.CatchHandlerMaxState.size())
+ return;
+ } else {
+ FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(ParentLinkageName);
+ }
+
+ MCSymbol *UnwindMapXData = nullptr;
+ MCSymbol *TryBlockMapXData = nullptr;
+ MCSymbol *IPToStateXData = nullptr;
+ if (!FuncInfo.UnwindMap.empty())
+ UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
+ Twine("$stateUnwindMap$", ParentLinkageName));
+ if (!FuncInfo.TryBlockMap.empty())
+ TryBlockMapXData = Asm->OutContext.getOrCreateSymbol(
+ Twine("$tryMap$", ParentLinkageName));
+ if (!FuncInfo.IPToStateList.empty())
+ IPToStateXData = Asm->OutContext.getOrCreateSymbol(
+ Twine("$ip2state$", ParentLinkageName));
+
+ // FuncInfo {
+ // uint32_t MagicNumber
+ // int32_t MaxState;
+ // UnwindMapEntry *UnwindMap;
+ // uint32_t NumTryBlocks;
+ // TryBlockMapEntry *TryBlockMap;
+ // uint32_t IPMapEntries; // always 0 for x86
+ // IPToStateMapEntry *IPToStateMap; // always 0 for x86
+ // uint32_t UnwindHelp; // non-x86 only
+ // ESTypeList *ESTypeList;
+ // int32_t EHFlags;
+ // }
+ // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
+ // EHFlags & 2 -> ???
+ // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
+ OS.EmitLabel(FuncInfoXData);
+ OS.EmitIntValue(0x19930522, 4); // MagicNumber
+ OS.EmitIntValue(FuncInfo.UnwindMap.size(), 4); // MaxState
+ OS.EmitValue(create32bitRef(UnwindMapXData), 4); // UnwindMap
+ OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4); // NumTryBlocks
+ OS.EmitValue(create32bitRef(TryBlockMapXData), 4); // TryBlockMap
+ OS.EmitIntValue(FuncInfo.IPToStateList.size(), 4); // IPMapEntries
+ OS.EmitValue(create32bitRef(IPToStateXData), 4); // IPToStateMap
+ if (Asm->MAI->usesWindowsCFI())
+ OS.EmitIntValue(FuncInfo.UnwindHelpFrameOffset, 4); // UnwindHelp
+ OS.EmitIntValue(0, 4); // ESTypeList
+ OS.EmitIntValue(1, 4); // EHFlags
+
+ // UnwindMapEntry {
+ // int32_t ToState;
+ // void (*Action)();
+ // };
+ if (UnwindMapXData) {
+ OS.EmitLabel(UnwindMapXData);
+ for (const WinEHUnwindMapEntry &UME : FuncInfo.UnwindMap) {
+ OS.EmitIntValue(UME.ToState, 4); // ToState
+ OS.EmitValue(create32bitRef(UME.Cleanup), 4); // Action
+ }
+ }
+
+ // TryBlockMap {
+ // int32_t TryLow;
+ // int32_t TryHigh;
+ // int32_t CatchHigh;
+ // int32_t NumCatches;
+ // HandlerType *HandlerArray;
+ // };
+ if (TryBlockMapXData) {
+ OS.EmitLabel(TryBlockMapXData);
+ SmallVector<MCSymbol *, 1> HandlerMaps;
+ for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
+ WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
+ MCSymbol *HandlerMapXData = nullptr;
+
+ if (!TBME.HandlerArray.empty())
+ HandlerMapXData =
+ Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
+ .concat(Twine(I))
+ .concat("$")
+ .concat(ParentLinkageName));
+
+ 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);
+ OS.EmitIntValue(TBME.TryLow, 4); // TryLow
+ OS.EmitIntValue(TBME.TryHigh, 4); // TryHigh
+ OS.EmitIntValue(CatchHigh, 4); // CatchHigh
+ OS.EmitIntValue(TBME.HandlerArray.size(), 4); // NumCatches
+ OS.EmitValue(create32bitRef(HandlerMapXData), 4); // HandlerArray
+ }
+
+ for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
+ WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
+ MCSymbol *HandlerMapXData = HandlerMaps[I];
+ if (!HandlerMapXData)
+ continue;
+ // HandlerType {
+ // int32_t Adjectives;
+ // TypeDescriptor *Type;
+ // int32_t CatchObjOffset;
+ // void (*Handler)();
+ // int32_t ParentFrameOffset; // x64 only
+ // };
+ OS.EmitLabel(HandlerMapXData);
+ for (const WinEHHandlerType &HT : TBME.HandlerArray) {
+ // 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(create32bitRef(HT.TypeDescriptor), 4); // Type
+ OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
+ OS.EmitValue(create32bitRef(HT.Handler), 4); // Handler
+
+ if (shouldEmitPersonality) {
+ MCSymbol *ParentFrameOffset =
+ Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
+ GlobalValue::getRealLinkageName(HT.Handler->getName()));
+ const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::Create(
+ ParentFrameOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
+ OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
+ }
+ }
+ }
+ }
+
+ // IPToStateMapEntry {
+ // void *IP;
+ // int32_t State;
+ // };
+ if (IPToStateXData) {
+ OS.EmitLabel(IPToStateXData);
+ for (auto &IPStatePair : FuncInfo.IPToStateList) {
+ OS.EmitValue(create32bitRef(IPStatePair.first), 4); // IP
+ OS.EmitIntValue(IPStatePair.second, 4); // State
+ }
+ }
+}
+
+void WinException::extendIP2StateTable(const MachineFunction *MF,
+ const Function *ParentF,
+ WinEHFuncInfo &FuncInfo) {
+ const Function *F = MF->getFunction();
// The Itanium LSDA table sorts similar landing pads together to simplify the
// actions table, but we don't need that.
@@ -306,8 +498,8 @@
FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
LastEHState = -1;
} else if (FuncInfo.HandlerBaseState.count(F)) {
- FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel,
- FuncInfo.HandlerBaseState[F]));
+ FuncInfo.IPToStateList.push_back(
+ std::make_pair(LastLabel, FuncInfo.HandlerBaseState[F]));
LastEHState = FuncInfo.HandlerBaseState[F];
}
for (const auto &MBB : *MF) {
@@ -348,157 +540,4 @@
LastLabel = LandingPad->EndLabels[P.RangeIndex];
}
}
-
- // 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;
- MCSymbol *TryBlockMapXData = nullptr;
- MCSymbol *IPToStateXData = nullptr;
- if (!FuncInfo.UnwindMap.empty())
- UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
- Twine("$stateUnwindMap$", ParentLinkageName));
- if (!FuncInfo.TryBlockMap.empty())
- TryBlockMapXData = Asm->OutContext.getOrCreateSymbol(
- Twine("$tryMap$", ParentLinkageName));
- if (!FuncInfo.IPToStateList.empty())
- IPToStateXData = Asm->OutContext.getOrCreateSymbol(
- Twine("$ip2state$", ParentLinkageName));
-
- // FuncInfo {
- // uint32_t MagicNumber
- // int32_t MaxState;
- // UnwindMapEntry *UnwindMap;
- // uint32_t NumTryBlocks;
- // TryBlockMapEntry *TryBlockMap;
- // uint32_t IPMapEntries;
- // IPToStateMapEntry *IPToStateMap;
- // uint32_t UnwindHelp; // (x64/ARM only)
- // ESTypeList *ESTypeList;
- // int32_t EHFlags;
- // }
- // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
- // EHFlags & 2 -> ???
- // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
- OS.EmitLabel(FuncInfoXData);
- OS.EmitIntValue(0x19930522, 4); // MagicNumber
- OS.EmitIntValue(FuncInfo.UnwindMap.size(), 4); // MaxState
- OS.EmitValue(createImageRel32(UnwindMapXData), 4); // UnwindMap
- OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4); // NumTryBlocks
- OS.EmitValue(createImageRel32(TryBlockMapXData), 4); // TryBlockMap
- OS.EmitIntValue(FuncInfo.IPToStateList.size(), 4); // IPMapEntries
- OS.EmitValue(createImageRel32(IPToStateXData), 4); // IPToStateMap
- OS.EmitIntValue(FuncInfo.UnwindHelpFrameOffset, 4); // UnwindHelp
- OS.EmitIntValue(0, 4); // ESTypeList
- OS.EmitIntValue(1, 4); // EHFlags
-
- // UnwindMapEntry {
- // int32_t ToState;
- // void (*Action)();
- // };
- if (UnwindMapXData) {
- OS.EmitLabel(UnwindMapXData);
- for (const WinEHUnwindMapEntry &UME : FuncInfo.UnwindMap) {
- OS.EmitIntValue(UME.ToState, 4); // ToState
- OS.EmitValue(createImageRel32(UME.Cleanup), 4); // Action
- }
- }
-
- // TryBlockMap {
- // int32_t TryLow;
- // int32_t TryHigh;
- // int32_t CatchHigh;
- // int32_t NumCatches;
- // HandlerType *HandlerArray;
- // };
- if (TryBlockMapXData) {
- OS.EmitLabel(TryBlockMapXData);
- SmallVector<MCSymbol *, 1> HandlerMaps;
- for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
- WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
- MCSymbol *HandlerMapXData = nullptr;
-
- if (!TBME.HandlerArray.empty())
- HandlerMapXData =
- Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
- .concat(Twine(I))
- .concat("$")
- .concat(ParentLinkageName));
-
- 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);
- OS.EmitIntValue(TBME.TryLow, 4); // TryLow
- OS.EmitIntValue(TBME.TryHigh, 4); // TryHigh
- OS.EmitIntValue(CatchHigh, 4); // CatchHigh
- OS.EmitIntValue(TBME.HandlerArray.size(), 4); // NumCatches
- OS.EmitValue(createImageRel32(HandlerMapXData), 4); // HandlerArray
- }
-
- for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
- WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
- MCSymbol *HandlerMapXData = HandlerMaps[I];
- if (!HandlerMapXData)
- continue;
- // HandlerType {
- // int32_t Adjectives;
- // TypeDescriptor *Type;
- // int32_t CatchObjOffset;
- // void (*Handler)();
- // int32_t ParentFrameOffset; // x64 only
- // };
- 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.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
- OS.EmitValue(createImageRel32(HT.Handler), 4); // Handler
- OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
- }
- }
- }
-
- // IPToStateMapEntry {
- // void *IP;
- // int32_t State;
- // };
- if (IPToStateXData) {
- OS.EmitLabel(IPToStateXData);
- for (auto &IPStatePair : FuncInfo.IPToStateList) {
- OS.EmitValue(createImageRel32(IPStatePair.first), 4); // IP
- OS.EmitIntValue(IPStatePair.second, 4); // State
- }
- }
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.h b/llvm/lib/CodeGen/AsmPrinter/WinException.h
index ee5f122..478899b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.h
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.h
@@ -17,26 +17,34 @@
#include "EHStreamer.h"
namespace llvm {
+class Function;
class GlobalValue;
class MachineFunction;
class MCExpr;
+struct WinEHFuncInfo;
class WinException : public EHStreamer {
/// Per-function flag to indicate if personality info should be emitted.
- bool shouldEmitPersonality;
+ bool shouldEmitPersonality = false;
/// Per-function flag to indicate if the LSDA should be emitted.
- bool shouldEmitLSDA;
+ bool shouldEmitLSDA = false;
/// Per-function flag to indicate if frame moves info should be emitted.
- bool shouldEmitMoves;
+ bool shouldEmitMoves = false;
+
+ /// True if this is a 64-bit target and we should use image relative offsets.
+ bool useImageRel32 = false;
void emitCSpecificHandlerTable();
void emitCXXFrameHandler3Table(const MachineFunction *MF);
- const MCExpr *createImageRel32(const MCSymbol *Value);
- const MCExpr *createImageRel32(const GlobalValue *GV);
+ void extendIP2StateTable(const MachineFunction *MF, const Function *ParentF,
+ WinEHFuncInfo &FuncInfo);
+
+ const MCExpr *create32bitRef(const MCSymbol *Value);
+ const MCExpr *create32bitRef(const GlobalValue *GV);
public:
//===--------------------------------------------------------------------===//
diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp
index d9da7bc..deff625 100644
--- a/llvm/lib/CodeGen/MachineModuleInfo.cpp
+++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp
@@ -308,6 +308,7 @@
// Clean up exception info.
LandingPads.clear();
+ PersonalityTypeCache = EHPersonality::Unknown;
CallSiteMap.clear();
TypeInfos.clear();
FilterIds.clear();