[WinEH] Create an llvm.x86.seh.exceptioninfo intrinsic

This intrinsic is like framerecover plus a load. It recovers the EH
registration stack allocation from the parent frame and loads the
exception information field out of it, giving back a pointer to an
EXCEPTION_POINTERS struct. It's designed for clang to use in SEH filter
expressions instead of accessing the EXCEPTION_POINTERS parameter that
is available on x64.

This required a minor change to MC to allow defining a label variable to
another absolute framerecover label variable.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239567 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Kleckner
2015-06-11 22:32:23 +00:00
parent 5e9819c5bd
commit 3e16bd3aaf
10 changed files with 176 additions and 105 deletions

View File

@ -449,7 +449,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
GlobalValue::getRealLinkageName(HT.Handler->getName()));
const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create(
ParentFrameOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
ParentFrameOffset, Asm->OutContext);
OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
}
}
@ -551,11 +551,26 @@ void WinException::extendIP2StateTable(const MachineFunction *MF,
/// functionally equivalent to the __C_specific_handler table, except it is
/// indexed by state number instead of IP.
void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
auto &OS = *Asm->OutStreamer;
MCStreamer &OS = *Asm->OutStreamer;
// Define the EH registration node offset label in terms of its frameescape
// label. The WinEHStatePass ensures that the registration node is passed to
// frameescape. This allows SEH filter functions to access the
// EXCEPTION_POINTERS field, which is filled in by the _except_handlerN.
const Function *F = MF->getFunction();
WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F);
assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX &&
"no EH reg node frameescape index");
StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
MCSymbol *ParentFrameOffset =
Asm->OutContext.getOrCreateParentFrameOffsetSymbol(FLinkageName);
MCSymbol *FrameAllocSym = Asm->OutContext.getOrCreateFrameAllocSymbol(
FLinkageName, FuncInfo.EHRegNodeEscapeIndex);
const MCSymbolRefExpr *FrameAllocSymRef =
MCSymbolRefExpr::create(FrameAllocSym, Asm->OutContext);
OS.EmitAssignment(ParentFrameOffset, FrameAllocSymRef);
// Emit the __ehtable label that we use for llvm.x86.seh.lsda.
const Function *F = MF->getFunction();
StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
OS.EmitLabel(LSDALabel);