WinException.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. //===-- CodeGen/AsmPrinter/WinException.cpp - Dwarf Exception Impl ------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file contains support for writing Win64 exception info into asm files.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "WinException.h"
  14. #include "llvm/ADT/SmallString.h"
  15. #include "llvm/ADT/StringExtras.h"
  16. #include "llvm/ADT/Twine.h"
  17. #include "llvm/CodeGen/AsmPrinter.h"
  18. #include "llvm/CodeGen/MachineFrameInfo.h"
  19. #include "llvm/CodeGen/MachineFunction.h"
  20. #include "llvm/CodeGen/MachineModuleInfo.h"
  21. #include "llvm/CodeGen/WinEHFuncInfo.h"
  22. #include "llvm/IR/DataLayout.h"
  23. #include "llvm/IR/Mangler.h"
  24. #include "llvm/IR/Module.h"
  25. #include "llvm/MC/MCAsmInfo.h"
  26. #include "llvm/MC/MCContext.h"
  27. #include "llvm/MC/MCExpr.h"
  28. #include "llvm/MC/MCSection.h"
  29. #include "llvm/MC/MCStreamer.h"
  30. #include "llvm/MC/MCSymbol.h"
  31. #include "llvm/MC/MCWin64EH.h"
  32. #include "llvm/Support/Dwarf.h"
  33. #include "llvm/Support/ErrorHandling.h"
  34. #include "llvm/Support/FormattedStream.h"
  35. #include "llvm/Target/TargetFrameLowering.h"
  36. #include "llvm/Target/TargetLoweringObjectFile.h"
  37. #include "llvm/Target/TargetOptions.h"
  38. #include "llvm/Target/TargetRegisterInfo.h"
  39. using namespace llvm;
  40. WinException::WinException(AsmPrinter *A) : EHStreamer(A) {
  41. // MSVC's EH tables are always composed of 32-bit words. All known 64-bit
  42. // platforms use an imagerel32 relocation to refer to symbols.
  43. useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64);
  44. }
  45. WinException::~WinException() {}
  46. /// endModule - Emit all exception information that should come after the
  47. /// content.
  48. void WinException::endModule() {
  49. auto &OS = *Asm->OutStreamer;
  50. const Module *M = MMI->getModule();
  51. for (const Function &F : *M)
  52. if (F.hasFnAttribute("safeseh"))
  53. OS.EmitCOFFSafeSEH(Asm->getSymbol(&F));
  54. }
  55. void WinException::beginFunction(const MachineFunction *MF) {
  56. shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
  57. // If any landing pads survive, we need an EH table.
  58. bool hasLandingPads = !MMI->getLandingPads().empty();
  59. const Function *F = MF->getFunction();
  60. const Function *ParentF = MMI->getWinEHParent(F);
  61. shouldEmitMoves = Asm->needsSEHMoves();
  62. const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  63. unsigned PerEncoding = TLOF.getPersonalityEncoding();
  64. const Function *Per = nullptr;
  65. if (F->hasPersonalityFn())
  66. Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
  67. bool forceEmitPersonality =
  68. F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
  69. F->needsUnwindTableEntry();
  70. shouldEmitPersonality = forceEmitPersonality || (hasLandingPads &&
  71. PerEncoding != dwarf::DW_EH_PE_omit && Per);
  72. unsigned LSDAEncoding = TLOF.getLSDAEncoding();
  73. shouldEmitLSDA = shouldEmitPersonality &&
  74. LSDAEncoding != dwarf::DW_EH_PE_omit;
  75. // If we're not using CFI, we don't want the CFI or the personality. If
  76. // WinEHPrepare outlined something, we should emit the LSDA.
  77. if (!Asm->MAI->usesWindowsCFI()) {
  78. bool HasOutlinedChildren =
  79. F->hasFnAttribute("wineh-parent") && F == ParentF;
  80. shouldEmitLSDA = HasOutlinedChildren;
  81. shouldEmitPersonality = false;
  82. return;
  83. }
  84. // If this was an outlined handler, we need to define the label corresponding
  85. // to the offset of the parent frame relative to the stack pointer after the
  86. // prologue.
  87. if (F != ParentF) {
  88. WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
  89. auto I = FuncInfo.CatchHandlerParentFrameObjOffset.find(F);
  90. if (I != FuncInfo.CatchHandlerParentFrameObjOffset.end()) {
  91. MCSymbol *HandlerTypeParentFrameOffset =
  92. Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
  93. GlobalValue::getRealLinkageName(F->getName()));
  94. // Emit a symbol assignment.
  95. Asm->OutStreamer->EmitAssignment(
  96. HandlerTypeParentFrameOffset,
  97. MCConstantExpr::create(I->second, Asm->OutContext));
  98. }
  99. }
  100. if (shouldEmitMoves || shouldEmitPersonality)
  101. Asm->OutStreamer->EmitWinCFIStartProc(Asm->CurrentFnSym);
  102. if (shouldEmitPersonality) {
  103. const MCSymbol *PersHandlerSym =
  104. TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
  105. Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true);
  106. }
  107. }
  108. /// endFunction - Gather and emit post-function exception information.
  109. ///
  110. void WinException::endFunction(const MachineFunction *MF) {
  111. if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA)
  112. return;
  113. const Function *F = MF->getFunction();
  114. EHPersonality Per = EHPersonality::Unknown;
  115. if (F->hasPersonalityFn())
  116. Per = classifyEHPersonality(F->getPersonalityFn());
  117. // Get rid of any dead landing pads if we're not using a Windows EH scheme. In
  118. // Windows EH schemes, the landing pad is not actually reachable. It only
  119. // exists so that we can emit the right table data.
  120. if (!isMSVCEHPersonality(Per))
  121. MMI->TidyLandingPads();
  122. if (shouldEmitPersonality || shouldEmitLSDA) {
  123. Asm->OutStreamer->PushSection();
  124. if (shouldEmitMoves || shouldEmitPersonality) {
  125. // Emit an UNWIND_INFO struct describing the prologue.
  126. Asm->OutStreamer->EmitWinEHHandlerData();
  127. } else {
  128. // Just switch sections to the right xdata section. This use of
  129. // CurrentFnSym assumes that we only emit the LSDA when ending the parent
  130. // function.
  131. MCSection *XData = WinEH::UnwindEmitter::getXDataSection(
  132. Asm->CurrentFnSym, Asm->OutContext);
  133. Asm->OutStreamer->SwitchSection(XData);
  134. }
  135. // Emit the tables appropriate to the personality function in use. If we
  136. // don't recognize the personality, assume it uses an Itanium-style LSDA.
  137. if (Per == EHPersonality::MSVC_Win64SEH)
  138. emitCSpecificHandlerTable();
  139. else if (Per == EHPersonality::MSVC_X86SEH)
  140. emitExceptHandlerTable(MF);
  141. else if (Per == EHPersonality::MSVC_CXX)
  142. emitCXXFrameHandler3Table(MF);
  143. else
  144. emitExceptionTable();
  145. Asm->OutStreamer->PopSection();
  146. }
  147. if (shouldEmitMoves)
  148. Asm->OutStreamer->EmitWinCFIEndProc();
  149. }
  150. const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
  151. if (!Value)
  152. return MCConstantExpr::create(0, Asm->OutContext);
  153. return MCSymbolRefExpr::create(Value, useImageRel32
  154. ? MCSymbolRefExpr::VK_COFF_IMGREL32
  155. : MCSymbolRefExpr::VK_None,
  156. Asm->OutContext);
  157. }
  158. const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
  159. if (!GV)
  160. return MCConstantExpr::create(0, Asm->OutContext);
  161. return create32bitRef(Asm->getSymbol(GV));
  162. }
  163. /// Emit the language-specific data that __C_specific_handler expects. This
  164. /// handler lives in the x64 Microsoft C runtime and allows catching or cleaning
  165. /// up after faults with __try, __except, and __finally. The typeinfo values
  166. /// are not really RTTI data, but pointers to filter functions that return an
  167. /// integer (1, 0, or -1) indicating how to handle the exception. For __finally
  168. /// blocks and other cleanups, the landing pad label is zero, and the filter
  169. /// function is actually a cleanup handler with the same prototype. A catch-all
  170. /// entry is modeled with a null filter function field and a non-zero landing
  171. /// pad label.
  172. ///
  173. /// Possible filter function return values:
  174. /// EXCEPTION_EXECUTE_HANDLER (1):
  175. /// Jump to the landing pad label after cleanups.
  176. /// EXCEPTION_CONTINUE_SEARCH (0):
  177. /// Continue searching this table or continue unwinding.
  178. /// EXCEPTION_CONTINUE_EXECUTION (-1):
  179. /// Resume execution at the trapping PC.
  180. ///
  181. /// Inferred table structure:
  182. /// struct Table {
  183. /// int NumEntries;
  184. /// struct Entry {
  185. /// imagerel32 LabelStart;
  186. /// imagerel32 LabelEnd;
  187. /// imagerel32 FilterOrFinally; // One means catch-all.
  188. /// imagerel32 LabelLPad; // Zero means __finally.
  189. /// } Entries[NumEntries];
  190. /// };
  191. void WinException::emitCSpecificHandlerTable() {
  192. const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
  193. // Simplifying assumptions for first implementation:
  194. // - Cleanups are not implemented.
  195. // - Filters are not implemented.
  196. // The Itanium LSDA table sorts similar landing pads together to simplify the
  197. // actions table, but we don't need that.
  198. SmallVector<const LandingPadInfo *, 64> LandingPads;
  199. LandingPads.reserve(PadInfos.size());
  200. for (const auto &LP : PadInfos)
  201. LandingPads.push_back(&LP);
  202. // Compute label ranges for call sites as we would for the Itanium LSDA, but
  203. // use an all zero action table because we aren't using these actions.
  204. SmallVector<unsigned, 64> FirstActions;
  205. FirstActions.resize(LandingPads.size());
  206. SmallVector<CallSiteEntry, 64> CallSites;
  207. computeCallSiteTable(CallSites, LandingPads, FirstActions);
  208. MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin();
  209. MCSymbol *EHFuncEndSym = Asm->getFunctionEnd();
  210. // Emit the number of table entries.
  211. unsigned NumEntries = 0;
  212. for (const CallSiteEntry &CSE : CallSites) {
  213. if (!CSE.LPad)
  214. continue; // Ignore gaps.
  215. NumEntries += CSE.LPad->SEHHandlers.size();
  216. }
  217. Asm->OutStreamer->EmitIntValue(NumEntries, 4);
  218. // If there are no actions, we don't need to iterate again.
  219. if (NumEntries == 0)
  220. return;
  221. // Emit the four-label records for each call site entry. The table has to be
  222. // sorted in layout order, and the call sites should already be sorted.
  223. for (const CallSiteEntry &CSE : CallSites) {
  224. // Ignore gaps. Unlike the Itanium model, unwinding through a frame without
  225. // an EH table entry will propagate the exception rather than terminating
  226. // the program.
  227. if (!CSE.LPad)
  228. continue;
  229. const LandingPadInfo *LPad = CSE.LPad;
  230. // Compute the label range. We may reuse the function begin and end labels
  231. // rather than forming new ones.
  232. const MCExpr *Begin =
  233. create32bitRef(CSE.BeginLabel ? CSE.BeginLabel : EHFuncBeginSym);
  234. const MCExpr *End;
  235. if (CSE.EndLabel) {
  236. // The interval is half-open, so we have to add one to include the return
  237. // address of the last invoke in the range.
  238. End = MCBinaryExpr::createAdd(create32bitRef(CSE.EndLabel),
  239. MCConstantExpr::create(1, Asm->OutContext),
  240. Asm->OutContext);
  241. } else {
  242. End = create32bitRef(EHFuncEndSym);
  243. }
  244. // Emit an entry for each action.
  245. for (SEHHandler Handler : LPad->SEHHandlers) {
  246. Asm->OutStreamer->EmitValue(Begin, 4);
  247. Asm->OutStreamer->EmitValue(End, 4);
  248. // Emit the filter or finally function pointer, if present. Otherwise,
  249. // emit '1' to indicate a catch-all.
  250. const Function *F = Handler.FilterOrFinally;
  251. if (F)
  252. Asm->OutStreamer->EmitValue(create32bitRef(Asm->getSymbol(F)), 4);
  253. else
  254. Asm->OutStreamer->EmitIntValue(1, 4);
  255. // Emit the recovery address, if present. Otherwise, this must be a
  256. // finally.
  257. const BlockAddress *BA = Handler.RecoverBA;
  258. if (BA)
  259. Asm->OutStreamer->EmitValue(
  260. create32bitRef(Asm->GetBlockAddressSymbol(BA)), 4);
  261. else
  262. Asm->OutStreamer->EmitIntValue(0, 4);
  263. }
  264. }
  265. }
  266. void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
  267. const Function *F = MF->getFunction();
  268. const Function *ParentF = MMI->getWinEHParent(F);
  269. auto &OS = *Asm->OutStreamer;
  270. WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
  271. StringRef ParentLinkageName =
  272. GlobalValue::getRealLinkageName(ParentF->getName());
  273. MCSymbol *FuncInfoXData = nullptr;
  274. if (shouldEmitPersonality) {
  275. FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
  276. Twine("$cppxdata$", ParentLinkageName));
  277. OS.EmitValue(create32bitRef(FuncInfoXData), 4);
  278. extendIP2StateTable(MF, ParentF, FuncInfo);
  279. // Defer emission until we've visited the parent function and all the catch
  280. // handlers. Cleanups don't contribute to the ip2state table, so don't count
  281. // them.
  282. if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F))
  283. return;
  284. ++FuncInfo.NumIPToStateFuncsVisited;
  285. if (FuncInfo.NumIPToStateFuncsVisited != FuncInfo.CatchHandlerMaxState.size())
  286. return;
  287. } else {
  288. FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(ParentLinkageName);
  289. emitEHRegistrationOffsetLabel(FuncInfo, ParentLinkageName);
  290. }
  291. MCSymbol *UnwindMapXData = nullptr;
  292. MCSymbol *TryBlockMapXData = nullptr;
  293. MCSymbol *IPToStateXData = nullptr;
  294. if (!FuncInfo.UnwindMap.empty())
  295. UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
  296. Twine("$stateUnwindMap$", ParentLinkageName));
  297. if (!FuncInfo.TryBlockMap.empty())
  298. TryBlockMapXData = Asm->OutContext.getOrCreateSymbol(
  299. Twine("$tryMap$", ParentLinkageName));
  300. if (!FuncInfo.IPToStateList.empty())
  301. IPToStateXData = Asm->OutContext.getOrCreateSymbol(
  302. Twine("$ip2state$", ParentLinkageName));
  303. // FuncInfo {
  304. // uint32_t MagicNumber
  305. // int32_t MaxState;
  306. // UnwindMapEntry *UnwindMap;
  307. // uint32_t NumTryBlocks;
  308. // TryBlockMapEntry *TryBlockMap;
  309. // uint32_t IPMapEntries; // always 0 for x86
  310. // IPToStateMapEntry *IPToStateMap; // always 0 for x86
  311. // uint32_t UnwindHelp; // non-x86 only
  312. // ESTypeList *ESTypeList;
  313. // int32_t EHFlags;
  314. // }
  315. // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
  316. // EHFlags & 2 -> ???
  317. // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
  318. OS.EmitValueToAlignment(4);
  319. OS.EmitLabel(FuncInfoXData);
  320. OS.EmitIntValue(0x19930522, 4); // MagicNumber
  321. OS.EmitIntValue(FuncInfo.UnwindMap.size(), 4); // MaxState
  322. OS.EmitValue(create32bitRef(UnwindMapXData), 4); // UnwindMap
  323. OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4); // NumTryBlocks
  324. OS.EmitValue(create32bitRef(TryBlockMapXData), 4); // TryBlockMap
  325. OS.EmitIntValue(FuncInfo.IPToStateList.size(), 4); // IPMapEntries
  326. OS.EmitValue(create32bitRef(IPToStateXData), 4); // IPToStateMap
  327. if (Asm->MAI->usesWindowsCFI())
  328. OS.EmitIntValue(FuncInfo.UnwindHelpFrameOffset, 4); // UnwindHelp
  329. OS.EmitIntValue(0, 4); // ESTypeList
  330. OS.EmitIntValue(1, 4); // EHFlags
  331. // UnwindMapEntry {
  332. // int32_t ToState;
  333. // void (*Action)();
  334. // };
  335. if (UnwindMapXData) {
  336. OS.EmitLabel(UnwindMapXData);
  337. for (const WinEHUnwindMapEntry &UME : FuncInfo.UnwindMap) {
  338. OS.EmitIntValue(UME.ToState, 4); // ToState
  339. OS.EmitValue(create32bitRef(UME.Cleanup), 4); // Action
  340. }
  341. }
  342. // TryBlockMap {
  343. // int32_t TryLow;
  344. // int32_t TryHigh;
  345. // int32_t CatchHigh;
  346. // int32_t NumCatches;
  347. // HandlerType *HandlerArray;
  348. // };
  349. if (TryBlockMapXData) {
  350. OS.EmitLabel(TryBlockMapXData);
  351. SmallVector<MCSymbol *, 1> HandlerMaps;
  352. for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
  353. WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
  354. MCSymbol *HandlerMapXData = nullptr;
  355. if (!TBME.HandlerArray.empty())
  356. HandlerMapXData =
  357. Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
  358. .concat(Twine(I))
  359. .concat("$")
  360. .concat(ParentLinkageName));
  361. HandlerMaps.push_back(HandlerMapXData);
  362. int CatchHigh = -1;
  363. for (WinEHHandlerType &HT : TBME.HandlerArray)
  364. CatchHigh =
  365. std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[HT.Handler]);
  366. assert(TBME.TryLow <= TBME.TryHigh);
  367. OS.EmitIntValue(TBME.TryLow, 4); // TryLow
  368. OS.EmitIntValue(TBME.TryHigh, 4); // TryHigh
  369. OS.EmitIntValue(CatchHigh, 4); // CatchHigh
  370. OS.EmitIntValue(TBME.HandlerArray.size(), 4); // NumCatches
  371. OS.EmitValue(create32bitRef(HandlerMapXData), 4); // HandlerArray
  372. }
  373. for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
  374. WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
  375. MCSymbol *HandlerMapXData = HandlerMaps[I];
  376. if (!HandlerMapXData)
  377. continue;
  378. // HandlerType {
  379. // int32_t Adjectives;
  380. // TypeDescriptor *Type;
  381. // int32_t CatchObjOffset;
  382. // void (*Handler)();
  383. // int32_t ParentFrameOffset; // x64 only
  384. // };
  385. OS.EmitLabel(HandlerMapXData);
  386. for (const WinEHHandlerType &HT : TBME.HandlerArray) {
  387. // Get the frame escape label with the offset of the catch object. If
  388. // the index is -1, then there is no catch object, and we should emit an
  389. // offset of zero, indicating that no copy will occur.
  390. const MCExpr *FrameAllocOffsetRef = nullptr;
  391. if (HT.CatchObjRecoverIdx >= 0) {
  392. MCSymbol *FrameAllocOffset =
  393. Asm->OutContext.getOrCreateFrameAllocSymbol(
  394. GlobalValue::getRealLinkageName(ParentF->getName()),
  395. HT.CatchObjRecoverIdx);
  396. FrameAllocOffsetRef = MCSymbolRefExpr::create(
  397. FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
  398. } else {
  399. FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
  400. }
  401. OS.EmitIntValue(HT.Adjectives, 4); // Adjectives
  402. OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
  403. OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
  404. OS.EmitValue(create32bitRef(HT.Handler), 4); // Handler
  405. if (shouldEmitPersonality) {
  406. MCSymbol *ParentFrameOffset =
  407. Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
  408. GlobalValue::getRealLinkageName(HT.Handler->getName()));
  409. const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create(
  410. ParentFrameOffset, Asm->OutContext);
  411. OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
  412. }
  413. }
  414. }
  415. }
  416. // IPToStateMapEntry {
  417. // void *IP;
  418. // int32_t State;
  419. // };
  420. if (IPToStateXData) {
  421. OS.EmitLabel(IPToStateXData);
  422. for (auto &IPStatePair : FuncInfo.IPToStateList) {
  423. OS.EmitValue(create32bitRef(IPStatePair.first), 4); // IP
  424. OS.EmitIntValue(IPStatePair.second, 4); // State
  425. }
  426. }
  427. }
  428. void WinException::extendIP2StateTable(const MachineFunction *MF,
  429. const Function *ParentF,
  430. WinEHFuncInfo &FuncInfo) {
  431. const Function *F = MF->getFunction();
  432. // The Itanium LSDA table sorts similar landing pads together to simplify the
  433. // actions table, but we don't need that.
  434. SmallVector<const LandingPadInfo *, 64> LandingPads;
  435. const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
  436. LandingPads.reserve(PadInfos.size());
  437. for (const auto &LP : PadInfos)
  438. LandingPads.push_back(&LP);
  439. RangeMapType PadMap;
  440. computePadMap(LandingPads, PadMap);
  441. // The end label of the previous invoke or nounwind try-range.
  442. MCSymbol *LastLabel = Asm->getFunctionBegin();
  443. // Whether there is a potentially throwing instruction (currently this means
  444. // an ordinary call) between the end of the previous try-range and now.
  445. bool SawPotentiallyThrowing = false;
  446. int LastEHState = -2;
  447. // The parent function and the catch handlers contribute to the 'ip2state'
  448. // table.
  449. // Include ip2state entries for the beginning of the main function and
  450. // for catch handler functions.
  451. if (F == ParentF) {
  452. FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
  453. LastEHState = -1;
  454. } else if (FuncInfo.HandlerBaseState.count(F)) {
  455. FuncInfo.IPToStateList.push_back(
  456. std::make_pair(LastLabel, FuncInfo.HandlerBaseState[F]));
  457. LastEHState = FuncInfo.HandlerBaseState[F];
  458. }
  459. for (const auto &MBB : *MF) {
  460. for (const auto &MI : MBB) {
  461. if (!MI.isEHLabel()) {
  462. if (MI.isCall())
  463. SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
  464. continue;
  465. }
  466. // End of the previous try-range?
  467. MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
  468. if (BeginLabel == LastLabel)
  469. SawPotentiallyThrowing = false;
  470. // Beginning of a new try-range?
  471. RangeMapType::const_iterator L = PadMap.find(BeginLabel);
  472. if (L == PadMap.end())
  473. // Nope, it was just some random label.
  474. continue;
  475. const PadRange &P = L->second;
  476. const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
  477. assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
  478. "Inconsistent landing pad map!");
  479. // FIXME: Should this be using FuncInfo.HandlerBaseState?
  480. if (SawPotentiallyThrowing && LastEHState != -1) {
  481. FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
  482. SawPotentiallyThrowing = false;
  483. LastEHState = -1;
  484. }
  485. if (LandingPad->WinEHState != LastEHState)
  486. FuncInfo.IPToStateList.push_back(
  487. std::make_pair(BeginLabel, LandingPad->WinEHState));
  488. LastEHState = LandingPad->WinEHState;
  489. LastLabel = LandingPad->EndLabels[P.RangeIndex];
  490. }
  491. }
  492. }
  493. void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
  494. StringRef FLinkageName) {
  495. // Outlined helpers called by the EH runtime need to know the offset of the EH
  496. // registration in order to recover the parent frame pointer. Now that we know
  497. // we've code generated the parent, we can emit the label assignment that
  498. // those helpers use to get the offset of the registration node.
  499. assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX &&
  500. "no EH reg node localescape index");
  501. MCSymbol *ParentFrameOffset =
  502. Asm->OutContext.getOrCreateParentFrameOffsetSymbol(FLinkageName);
  503. MCSymbol *RegistrationOffsetSym = Asm->OutContext.getOrCreateFrameAllocSymbol(
  504. FLinkageName, FuncInfo.EHRegNodeEscapeIndex);
  505. const MCExpr *RegistrationOffsetSymRef =
  506. MCSymbolRefExpr::create(RegistrationOffsetSym, Asm->OutContext);
  507. Asm->OutStreamer->EmitAssignment(ParentFrameOffset, RegistrationOffsetSymRef);
  508. }
  509. /// Emit the language-specific data that _except_handler3 and 4 expect. This is
  510. /// functionally equivalent to the __C_specific_handler table, except it is
  511. /// indexed by state number instead of IP.
  512. void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
  513. MCStreamer &OS = *Asm->OutStreamer;
  514. const Function *F = MF->getFunction();
  515. StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
  516. WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F);
  517. emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
  518. // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
  519. MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
  520. OS.EmitValueToAlignment(4);
  521. OS.EmitLabel(LSDALabel);
  522. const Function *Per =
  523. dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
  524. StringRef PerName = Per->getName();
  525. int BaseState = -1;
  526. if (PerName == "_except_handler4") {
  527. // The LSDA for _except_handler4 starts with this struct, followed by the
  528. // scope table:
  529. //
  530. // struct EH4ScopeTable {
  531. // int32_t GSCookieOffset;
  532. // int32_t GSCookieXOROffset;
  533. // int32_t EHCookieOffset;
  534. // int32_t EHCookieXOROffset;
  535. // ScopeTableEntry ScopeRecord[];
  536. // };
  537. //
  538. // Only the EHCookieOffset field appears to vary, and it appears to be the
  539. // offset from the final saved SP value to the retaddr.
  540. OS.EmitIntValue(-2, 4);
  541. OS.EmitIntValue(0, 4);
  542. // FIXME: Calculate.
  543. OS.EmitIntValue(9999, 4);
  544. OS.EmitIntValue(0, 4);
  545. BaseState = -2;
  546. }
  547. // Build a list of pointers to LandingPadInfos and then sort by WinEHState.
  548. const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
  549. SmallVector<const LandingPadInfo *, 4> LPads;
  550. LPads.reserve((PadInfos.size()));
  551. for (const LandingPadInfo &LPInfo : PadInfos)
  552. LPads.push_back(&LPInfo);
  553. std::sort(LPads.begin(), LPads.end(),
  554. [](const LandingPadInfo *L, const LandingPadInfo *R) {
  555. return L->WinEHState < R->WinEHState;
  556. });
  557. // For each action in each lpad, emit one of these:
  558. // struct ScopeTableEntry {
  559. // int32_t EnclosingLevel;
  560. // int32_t (__cdecl *Filter)();
  561. // void *HandlerOrFinally;
  562. // };
  563. //
  564. // The "outermost" action will use BaseState as its enclosing level. Each
  565. // other action will refer to the previous state as its enclosing level.
  566. int CurState = 0;
  567. for (const LandingPadInfo *LPInfo : LPads) {
  568. int EnclosingLevel = BaseState;
  569. assert(CurState + int(LPInfo->SEHHandlers.size()) - 1 ==
  570. LPInfo->WinEHState &&
  571. "gaps in the SEH scope table");
  572. for (auto I = LPInfo->SEHHandlers.rbegin(), E = LPInfo->SEHHandlers.rend();
  573. I != E; ++I) {
  574. const SEHHandler &Handler = *I;
  575. const BlockAddress *BA = Handler.RecoverBA;
  576. const Function *F = Handler.FilterOrFinally;
  577. assert(F && "cannot catch all in 32-bit SEH without filter function");
  578. const MCExpr *FilterOrNull =
  579. create32bitRef(BA ? Asm->getSymbol(F) : nullptr);
  580. const MCExpr *ExceptOrFinally = create32bitRef(
  581. BA ? Asm->GetBlockAddressSymbol(BA) : Asm->getSymbol(F));
  582. OS.EmitIntValue(EnclosingLevel, 4);
  583. OS.EmitValue(FilterOrNull, 4);
  584. OS.EmitValue(ExceptOrFinally, 4);
  585. // The next state unwinds to this state.
  586. EnclosingLevel = CurState;
  587. CurState++;
  588. }
  589. }
  590. }