WinException.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
  1. //===-- CodeGen/AsmPrinter/WinException.cpp - Dwarf Exception Impl ------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains support for writing Win64 exception info into asm files.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "WinException.h"
  13. #include "llvm/ADT/Twine.h"
  14. #include "llvm/BinaryFormat/COFF.h"
  15. #include "llvm/BinaryFormat/Dwarf.h"
  16. #include "llvm/CodeGen/AsmPrinter.h"
  17. #include "llvm/CodeGen/MachineFrameInfo.h"
  18. #include "llvm/CodeGen/MachineFunction.h"
  19. #include "llvm/CodeGen/MachineModuleInfo.h"
  20. #include "llvm/CodeGen/TargetFrameLowering.h"
  21. #include "llvm/CodeGen/TargetLowering.h"
  22. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  23. #include "llvm/CodeGen/WinEHFuncInfo.h"
  24. #include "llvm/IR/DataLayout.h"
  25. #include "llvm/IR/Module.h"
  26. #include "llvm/MC/MCAsmInfo.h"
  27. #include "llvm/MC/MCContext.h"
  28. #include "llvm/MC/MCExpr.h"
  29. #include "llvm/MC/MCStreamer.h"
  30. #include "llvm/Target/TargetLoweringObjectFile.h"
  31. #include "llvm/Target/TargetMachine.h"
  32. using namespace llvm;
  33. WinException::WinException(AsmPrinter *A) : EHStreamer(A) {
  34. // MSVC's EH tables are always composed of 32-bit words. All known 64-bit
  35. // platforms use an imagerel32 relocation to refer to symbols.
  36. useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64);
  37. isAArch64 = Asm->TM.getTargetTriple().isAArch64();
  38. isThumb = Asm->TM.getTargetTriple().isThumb();
  39. }
  40. WinException::~WinException() = default;
  41. /// endModule - Emit all exception information that should come after the
  42. /// content.
  43. void WinException::endModule() {
  44. auto &OS = *Asm->OutStreamer;
  45. const Module *M = MMI->getModule();
  46. for (const Function &F : *M)
  47. if (F.hasFnAttribute("safeseh"))
  48. OS.emitCOFFSafeSEH(Asm->getSymbol(&F));
  49. if (M->getModuleFlag("ehcontguard") && !EHContTargets.empty()) {
  50. // Emit the symbol index of each ehcont target.
  51. OS.switchSection(Asm->OutContext.getObjectFileInfo()->getGEHContSection());
  52. for (const MCSymbol *S : EHContTargets) {
  53. OS.emitCOFFSymbolIndex(S);
  54. }
  55. }
  56. }
  57. void WinException::beginFunction(const MachineFunction *MF) {
  58. shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
  59. // If any landing pads survive, we need an EH table.
  60. bool hasLandingPads = !MF->getLandingPads().empty();
  61. bool hasEHFunclets = MF->hasEHFunclets();
  62. const Function &F = MF->getFunction();
  63. shouldEmitMoves = Asm->needsSEHMoves() && MF->hasWinCFI();
  64. const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  65. unsigned PerEncoding = TLOF.getPersonalityEncoding();
  66. EHPersonality Per = EHPersonality::Unknown;
  67. const Function *PerFn = nullptr;
  68. if (F.hasPersonalityFn()) {
  69. PerFn = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
  70. Per = classifyEHPersonality(PerFn);
  71. }
  72. bool forceEmitPersonality = F.hasPersonalityFn() &&
  73. !isNoOpWithoutInvoke(Per) &&
  74. F.needsUnwindTableEntry();
  75. shouldEmitPersonality =
  76. forceEmitPersonality || ((hasLandingPads || hasEHFunclets) &&
  77. PerEncoding != dwarf::DW_EH_PE_omit && PerFn);
  78. unsigned LSDAEncoding = TLOF.getLSDAEncoding();
  79. shouldEmitLSDA = shouldEmitPersonality &&
  80. LSDAEncoding != dwarf::DW_EH_PE_omit;
  81. // If we're not using CFI, we don't want the CFI or the personality, but we
  82. // might want EH tables if we had EH pads.
  83. if (!Asm->MAI->usesWindowsCFI()) {
  84. if (Per == EHPersonality::MSVC_X86SEH && !hasEHFunclets) {
  85. // If this is 32-bit SEH and we don't have any funclets (really invokes),
  86. // make sure we emit the parent offset label. Some unreferenced filter
  87. // functions may still refer to it.
  88. const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
  89. StringRef FLinkageName =
  90. GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName());
  91. emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
  92. }
  93. shouldEmitLSDA = hasEHFunclets;
  94. shouldEmitPersonality = false;
  95. return;
  96. }
  97. beginFunclet(MF->front(), Asm->CurrentFnSym);
  98. }
  99. void WinException::markFunctionEnd() {
  100. if (isAArch64 && CurrentFuncletEntry &&
  101. (shouldEmitMoves || shouldEmitPersonality))
  102. Asm->OutStreamer->emitWinCFIFuncletOrFuncEnd();
  103. }
  104. /// endFunction - Gather and emit post-function exception information.
  105. ///
  106. void WinException::endFunction(const MachineFunction *MF) {
  107. if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA)
  108. return;
  109. const Function &F = MF->getFunction();
  110. EHPersonality Per = EHPersonality::Unknown;
  111. if (F.hasPersonalityFn())
  112. Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts());
  113. endFuncletImpl();
  114. // endFunclet will emit the necessary .xdata tables for table-based SEH.
  115. if (Per == EHPersonality::MSVC_TableSEH && MF->hasEHFunclets())
  116. return;
  117. if (shouldEmitPersonality || shouldEmitLSDA) {
  118. Asm->OutStreamer->pushSection();
  119. // Just switch sections to the right xdata section.
  120. MCSection *XData = Asm->OutStreamer->getAssociatedXDataSection(
  121. Asm->OutStreamer->getCurrentSectionOnly());
  122. Asm->OutStreamer->switchSection(XData);
  123. // Emit the tables appropriate to the personality function in use. If we
  124. // don't recognize the personality, assume it uses an Itanium-style LSDA.
  125. if (Per == EHPersonality::MSVC_TableSEH)
  126. emitCSpecificHandlerTable(MF);
  127. else if (Per == EHPersonality::MSVC_X86SEH)
  128. emitExceptHandlerTable(MF);
  129. else if (Per == EHPersonality::MSVC_CXX)
  130. emitCXXFrameHandler3Table(MF);
  131. else if (Per == EHPersonality::CoreCLR)
  132. emitCLRExceptionTable(MF);
  133. else
  134. emitExceptionTable();
  135. Asm->OutStreamer->popSection();
  136. }
  137. if (!MF->getCatchretTargets().empty()) {
  138. // Copy the function's catchret targets to a module-level list.
  139. EHContTargets.insert(EHContTargets.end(), MF->getCatchretTargets().begin(),
  140. MF->getCatchretTargets().end());
  141. }
  142. }
  143. /// Retrieve the MCSymbol for a GlobalValue or MachineBasicBlock.
  144. static MCSymbol *getMCSymbolForMBB(AsmPrinter *Asm,
  145. const MachineBasicBlock *MBB) {
  146. if (!MBB)
  147. return nullptr;
  148. assert(MBB->isEHFuncletEntry());
  149. // Give catches and cleanups a name based off of their parent function and
  150. // their funclet entry block's number.
  151. const MachineFunction *MF = MBB->getParent();
  152. const Function &F = MF->getFunction();
  153. StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
  154. MCContext &Ctx = MF->getContext();
  155. StringRef HandlerPrefix = MBB->isCleanupFuncletEntry() ? "dtor" : "catch";
  156. return Ctx.getOrCreateSymbol("?" + HandlerPrefix + "$" +
  157. Twine(MBB->getNumber()) + "@?0?" +
  158. FuncLinkageName + "@4HA");
  159. }
  160. void WinException::beginFunclet(const MachineBasicBlock &MBB,
  161. MCSymbol *Sym) {
  162. CurrentFuncletEntry = &MBB;
  163. const Function &F = Asm->MF->getFunction();
  164. // If a symbol was not provided for the funclet, invent one.
  165. if (!Sym) {
  166. Sym = getMCSymbolForMBB(Asm, &MBB);
  167. // Describe our funclet symbol as a function with internal linkage.
  168. Asm->OutStreamer->beginCOFFSymbolDef(Sym);
  169. Asm->OutStreamer->emitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC);
  170. Asm->OutStreamer->emitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
  171. << COFF::SCT_COMPLEX_TYPE_SHIFT);
  172. Asm->OutStreamer->endCOFFSymbolDef();
  173. // We want our funclet's entry point to be aligned such that no nops will be
  174. // present after the label.
  175. Asm->emitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()),
  176. &F);
  177. // Now that we've emitted the alignment directive, point at our funclet.
  178. Asm->OutStreamer->emitLabel(Sym);
  179. }
  180. // Mark 'Sym' as starting our funclet.
  181. if (shouldEmitMoves || shouldEmitPersonality) {
  182. CurrentFuncletTextSection = Asm->OutStreamer->getCurrentSectionOnly();
  183. Asm->OutStreamer->emitWinCFIStartProc(Sym);
  184. }
  185. if (shouldEmitPersonality) {
  186. const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  187. const Function *PerFn = nullptr;
  188. // Determine which personality routine we are using for this funclet.
  189. if (F.hasPersonalityFn())
  190. PerFn = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
  191. const MCSymbol *PersHandlerSym =
  192. TLOF.getCFIPersonalitySymbol(PerFn, Asm->TM, MMI);
  193. // Do not emit a .seh_handler directives for cleanup funclets.
  194. // FIXME: This means cleanup funclets cannot handle exceptions. Given that
  195. // Clang doesn't produce EH constructs inside cleanup funclets and LLVM's
  196. // inliner doesn't allow inlining them, this isn't a major problem in
  197. // practice.
  198. if (!CurrentFuncletEntry->isCleanupFuncletEntry())
  199. Asm->OutStreamer->emitWinEHHandler(PersHandlerSym, true, true);
  200. }
  201. }
  202. void WinException::endFunclet() {
  203. if (isAArch64 && CurrentFuncletEntry &&
  204. (shouldEmitMoves || shouldEmitPersonality)) {
  205. Asm->OutStreamer->switchSection(CurrentFuncletTextSection);
  206. Asm->OutStreamer->emitWinCFIFuncletOrFuncEnd();
  207. }
  208. endFuncletImpl();
  209. }
  210. void WinException::endFuncletImpl() {
  211. // No funclet to process? Great, we have nothing to do.
  212. if (!CurrentFuncletEntry)
  213. return;
  214. const MachineFunction *MF = Asm->MF;
  215. if (shouldEmitMoves || shouldEmitPersonality) {
  216. const Function &F = MF->getFunction();
  217. EHPersonality Per = EHPersonality::Unknown;
  218. if (F.hasPersonalityFn())
  219. Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts());
  220. if (Per == EHPersonality::MSVC_CXX && shouldEmitPersonality &&
  221. !CurrentFuncletEntry->isCleanupFuncletEntry()) {
  222. // Emit an UNWIND_INFO struct describing the prologue.
  223. Asm->OutStreamer->emitWinEHHandlerData();
  224. // If this is a C++ catch funclet (or the parent function),
  225. // emit a reference to the LSDA for the parent function.
  226. StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
  227. MCSymbol *FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
  228. Twine("$cppxdata$", FuncLinkageName));
  229. Asm->OutStreamer->emitValue(create32bitRef(FuncInfoXData), 4);
  230. } else if (Per == EHPersonality::MSVC_TableSEH && MF->hasEHFunclets() &&
  231. !CurrentFuncletEntry->isEHFuncletEntry()) {
  232. // Emit an UNWIND_INFO struct describing the prologue.
  233. Asm->OutStreamer->emitWinEHHandlerData();
  234. // If this is the parent function in Win64 SEH, emit the LSDA immediately
  235. // following .seh_handlerdata.
  236. emitCSpecificHandlerTable(MF);
  237. } else if (shouldEmitPersonality || shouldEmitLSDA) {
  238. // Emit an UNWIND_INFO struct describing the prologue.
  239. Asm->OutStreamer->emitWinEHHandlerData();
  240. // In these cases, no further info is written to the .xdata section
  241. // right here, but is written by e.g. emitExceptionTable in endFunction()
  242. // above.
  243. } else {
  244. // No need to emit the EH handler data right here if nothing needs
  245. // writing to the .xdata section; it will be emitted for all
  246. // functions that need it in the end anyway.
  247. }
  248. // Switch back to the funclet start .text section now that we are done
  249. // writing to .xdata, and emit an .seh_endproc directive to mark the end of
  250. // the function.
  251. Asm->OutStreamer->switchSection(CurrentFuncletTextSection);
  252. Asm->OutStreamer->emitWinCFIEndProc();
  253. }
  254. // Let's make sure we don't try to end the same funclet twice.
  255. CurrentFuncletEntry = nullptr;
  256. }
  257. const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
  258. if (!Value)
  259. return MCConstantExpr::create(0, Asm->OutContext);
  260. return MCSymbolRefExpr::create(Value, useImageRel32
  261. ? MCSymbolRefExpr::VK_COFF_IMGREL32
  262. : MCSymbolRefExpr::VK_None,
  263. Asm->OutContext);
  264. }
  265. const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
  266. if (!GV)
  267. return MCConstantExpr::create(0, Asm->OutContext);
  268. return create32bitRef(Asm->getSymbol(GV));
  269. }
  270. const MCExpr *WinException::getLabel(const MCSymbol *Label) {
  271. return MCSymbolRefExpr::create(Label, MCSymbolRefExpr::VK_COFF_IMGREL32,
  272. Asm->OutContext);
  273. }
  274. const MCExpr *WinException::getLabelPlusOne(const MCSymbol *Label) {
  275. return MCBinaryExpr::createAdd(getLabel(Label),
  276. MCConstantExpr::create(1, Asm->OutContext),
  277. Asm->OutContext);
  278. }
  279. const MCExpr *WinException::getOffset(const MCSymbol *OffsetOf,
  280. const MCSymbol *OffsetFrom) {
  281. return MCBinaryExpr::createSub(
  282. MCSymbolRefExpr::create(OffsetOf, Asm->OutContext),
  283. MCSymbolRefExpr::create(OffsetFrom, Asm->OutContext), Asm->OutContext);
  284. }
  285. const MCExpr *WinException::getOffsetPlusOne(const MCSymbol *OffsetOf,
  286. const MCSymbol *OffsetFrom) {
  287. return MCBinaryExpr::createAdd(getOffset(OffsetOf, OffsetFrom),
  288. MCConstantExpr::create(1, Asm->OutContext),
  289. Asm->OutContext);
  290. }
  291. int WinException::getFrameIndexOffset(int FrameIndex,
  292. const WinEHFuncInfo &FuncInfo) {
  293. const TargetFrameLowering &TFI = *Asm->MF->getSubtarget().getFrameLowering();
  294. Register UnusedReg;
  295. if (Asm->MAI->usesWindowsCFI()) {
  296. StackOffset Offset =
  297. TFI.getFrameIndexReferencePreferSP(*Asm->MF, FrameIndex, UnusedReg,
  298. /*IgnoreSPUpdates*/ true);
  299. assert(UnusedReg ==
  300. Asm->MF->getSubtarget()
  301. .getTargetLowering()
  302. ->getStackPointerRegisterToSaveRestore());
  303. return Offset.getFixed();
  304. }
  305. // For 32-bit, offsets should be relative to the end of the EH registration
  306. // node. For 64-bit, it's relative to SP at the end of the prologue.
  307. assert(FuncInfo.EHRegNodeEndOffset != INT_MAX);
  308. StackOffset Offset = TFI.getFrameIndexReference(*Asm->MF, FrameIndex, UnusedReg);
  309. Offset += StackOffset::getFixed(FuncInfo.EHRegNodeEndOffset);
  310. assert(!Offset.getScalable() &&
  311. "Frame offsets with a scalable component are not supported");
  312. return Offset.getFixed();
  313. }
  314. namespace {
  315. /// Top-level state used to represent unwind to caller
  316. const int NullState = -1;
  317. struct InvokeStateChange {
  318. /// EH Label immediately after the last invoke in the previous state, or
  319. /// nullptr if the previous state was the null state.
  320. const MCSymbol *PreviousEndLabel;
  321. /// EH label immediately before the first invoke in the new state, or nullptr
  322. /// if the new state is the null state.
  323. const MCSymbol *NewStartLabel;
  324. /// State of the invoke following NewStartLabel, or NullState to indicate
  325. /// the presence of calls which may unwind to caller.
  326. int NewState;
  327. };
  328. /// Iterator that reports all the invoke state changes in a range of machine
  329. /// basic blocks. Changes to the null state are reported whenever a call that
  330. /// may unwind to caller is encountered. The MBB range is expected to be an
  331. /// entire function or funclet, and the start and end of the range are treated
  332. /// as being in the NullState even if there's not an unwind-to-caller call
  333. /// before the first invoke or after the last one (i.e., the first state change
  334. /// reported is the first change to something other than NullState, and a
  335. /// change back to NullState is always reported at the end of iteration).
  336. class InvokeStateChangeIterator {
  337. InvokeStateChangeIterator(const WinEHFuncInfo &EHInfo,
  338. MachineFunction::const_iterator MFI,
  339. MachineFunction::const_iterator MFE,
  340. MachineBasicBlock::const_iterator MBBI,
  341. int BaseState)
  342. : EHInfo(EHInfo), MFI(MFI), MFE(MFE), MBBI(MBBI), BaseState(BaseState) {
  343. LastStateChange.PreviousEndLabel = nullptr;
  344. LastStateChange.NewStartLabel = nullptr;
  345. LastStateChange.NewState = BaseState;
  346. scan();
  347. }
  348. public:
  349. static iterator_range<InvokeStateChangeIterator>
  350. range(const WinEHFuncInfo &EHInfo, MachineFunction::const_iterator Begin,
  351. MachineFunction::const_iterator End, int BaseState = NullState) {
  352. // Reject empty ranges to simplify bookkeeping by ensuring that we can get
  353. // the end of the last block.
  354. assert(Begin != End);
  355. auto BlockBegin = Begin->begin();
  356. auto BlockEnd = std::prev(End)->end();
  357. return make_range(
  358. InvokeStateChangeIterator(EHInfo, Begin, End, BlockBegin, BaseState),
  359. InvokeStateChangeIterator(EHInfo, End, End, BlockEnd, BaseState));
  360. }
  361. // Iterator methods.
  362. bool operator==(const InvokeStateChangeIterator &O) const {
  363. assert(BaseState == O.BaseState);
  364. // Must be visiting same block.
  365. if (MFI != O.MFI)
  366. return false;
  367. // Must be visiting same isntr.
  368. if (MBBI != O.MBBI)
  369. return false;
  370. // At end of block/instr iteration, we can still have two distinct states:
  371. // one to report the final EndLabel, and another indicating the end of the
  372. // state change iteration. Check for CurrentEndLabel equality to
  373. // distinguish these.
  374. return CurrentEndLabel == O.CurrentEndLabel;
  375. }
  376. bool operator!=(const InvokeStateChangeIterator &O) const {
  377. return !operator==(O);
  378. }
  379. InvokeStateChange &operator*() { return LastStateChange; }
  380. InvokeStateChange *operator->() { return &LastStateChange; }
  381. InvokeStateChangeIterator &operator++() { return scan(); }
  382. private:
  383. InvokeStateChangeIterator &scan();
  384. const WinEHFuncInfo &EHInfo;
  385. const MCSymbol *CurrentEndLabel = nullptr;
  386. MachineFunction::const_iterator MFI;
  387. MachineFunction::const_iterator MFE;
  388. MachineBasicBlock::const_iterator MBBI;
  389. InvokeStateChange LastStateChange;
  390. bool VisitingInvoke = false;
  391. int BaseState;
  392. };
  393. } // end anonymous namespace
  394. InvokeStateChangeIterator &InvokeStateChangeIterator::scan() {
  395. bool IsNewBlock = false;
  396. for (; MFI != MFE; ++MFI, IsNewBlock = true) {
  397. if (IsNewBlock)
  398. MBBI = MFI->begin();
  399. for (auto MBBE = MFI->end(); MBBI != MBBE; ++MBBI) {
  400. const MachineInstr &MI = *MBBI;
  401. if (!VisitingInvoke && LastStateChange.NewState != BaseState &&
  402. MI.isCall() && !EHStreamer::callToNoUnwindFunction(&MI)) {
  403. // Indicate a change of state to the null state. We don't have
  404. // start/end EH labels handy but the caller won't expect them for
  405. // null state regions.
  406. LastStateChange.PreviousEndLabel = CurrentEndLabel;
  407. LastStateChange.NewStartLabel = nullptr;
  408. LastStateChange.NewState = BaseState;
  409. CurrentEndLabel = nullptr;
  410. // Don't re-visit this instr on the next scan
  411. ++MBBI;
  412. return *this;
  413. }
  414. // All other state changes are at EH labels before/after invokes.
  415. if (!MI.isEHLabel())
  416. continue;
  417. MCSymbol *Label = MI.getOperand(0).getMCSymbol();
  418. if (Label == CurrentEndLabel) {
  419. VisitingInvoke = false;
  420. continue;
  421. }
  422. auto InvokeMapIter = EHInfo.LabelToStateMap.find(Label);
  423. // Ignore EH labels that aren't the ones inserted before an invoke
  424. if (InvokeMapIter == EHInfo.LabelToStateMap.end())
  425. continue;
  426. auto &StateAndEnd = InvokeMapIter->second;
  427. int NewState = StateAndEnd.first;
  428. // Keep track of the fact that we're between EH start/end labels so
  429. // we know not to treat the inoke we'll see as unwinding to caller.
  430. VisitingInvoke = true;
  431. if (NewState == LastStateChange.NewState) {
  432. // The state isn't actually changing here. Record the new end and
  433. // keep going.
  434. CurrentEndLabel = StateAndEnd.second;
  435. continue;
  436. }
  437. // Found a state change to report
  438. LastStateChange.PreviousEndLabel = CurrentEndLabel;
  439. LastStateChange.NewStartLabel = Label;
  440. LastStateChange.NewState = NewState;
  441. // Start keeping track of the new current end
  442. CurrentEndLabel = StateAndEnd.second;
  443. // Don't re-visit this instr on the next scan
  444. ++MBBI;
  445. return *this;
  446. }
  447. }
  448. // Iteration hit the end of the block range.
  449. if (LastStateChange.NewState != BaseState) {
  450. // Report the end of the last new state
  451. LastStateChange.PreviousEndLabel = CurrentEndLabel;
  452. LastStateChange.NewStartLabel = nullptr;
  453. LastStateChange.NewState = BaseState;
  454. // Leave CurrentEndLabel non-null to distinguish this state from end.
  455. assert(CurrentEndLabel != nullptr);
  456. return *this;
  457. }
  458. // We've reported all state changes and hit the end state.
  459. CurrentEndLabel = nullptr;
  460. return *this;
  461. }
  462. /// Emit the language-specific data that __C_specific_handler expects. This
  463. /// handler lives in the x64 Microsoft C runtime and allows catching or cleaning
  464. /// up after faults with __try, __except, and __finally. The typeinfo values
  465. /// are not really RTTI data, but pointers to filter functions that return an
  466. /// integer (1, 0, or -1) indicating how to handle the exception. For __finally
  467. /// blocks and other cleanups, the landing pad label is zero, and the filter
  468. /// function is actually a cleanup handler with the same prototype. A catch-all
  469. /// entry is modeled with a null filter function field and a non-zero landing
  470. /// pad label.
  471. ///
  472. /// Possible filter function return values:
  473. /// EXCEPTION_EXECUTE_HANDLER (1):
  474. /// Jump to the landing pad label after cleanups.
  475. /// EXCEPTION_CONTINUE_SEARCH (0):
  476. /// Continue searching this table or continue unwinding.
  477. /// EXCEPTION_CONTINUE_EXECUTION (-1):
  478. /// Resume execution at the trapping PC.
  479. ///
  480. /// Inferred table structure:
  481. /// struct Table {
  482. /// int NumEntries;
  483. /// struct Entry {
  484. /// imagerel32 LabelStart; // Inclusive
  485. /// imagerel32 LabelEnd; // Exclusive
  486. /// imagerel32 FilterOrFinally; // One means catch-all.
  487. /// imagerel32 LabelLPad; // Zero means __finally.
  488. /// } Entries[NumEntries];
  489. /// };
  490. void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
  491. auto &OS = *Asm->OutStreamer;
  492. MCContext &Ctx = Asm->OutContext;
  493. const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
  494. bool VerboseAsm = OS.isVerboseAsm();
  495. auto AddComment = [&](const Twine &Comment) {
  496. if (VerboseAsm)
  497. OS.AddComment(Comment);
  498. };
  499. if (!isAArch64) {
  500. // Emit a label assignment with the SEH frame offset so we can use it for
  501. // llvm.eh.recoverfp.
  502. StringRef FLinkageName =
  503. GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName());
  504. MCSymbol *ParentFrameOffset =
  505. Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
  506. const MCExpr *MCOffset =
  507. MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx);
  508. Asm->OutStreamer->emitAssignment(ParentFrameOffset, MCOffset);
  509. }
  510. // Use the assembler to compute the number of table entries through label
  511. // difference and division.
  512. MCSymbol *TableBegin =
  513. Ctx.createTempSymbol("lsda_begin", /*AlwaysAddSuffix=*/true);
  514. MCSymbol *TableEnd =
  515. Ctx.createTempSymbol("lsda_end", /*AlwaysAddSuffix=*/true);
  516. const MCExpr *LabelDiff = getOffset(TableEnd, TableBegin);
  517. const MCExpr *EntrySize = MCConstantExpr::create(16, Ctx);
  518. const MCExpr *EntryCount = MCBinaryExpr::createDiv(LabelDiff, EntrySize, Ctx);
  519. AddComment("Number of call sites");
  520. OS.emitValue(EntryCount, 4);
  521. OS.emitLabel(TableBegin);
  522. // Iterate over all the invoke try ranges. Unlike MSVC, LLVM currently only
  523. // models exceptions from invokes. LLVM also allows arbitrary reordering of
  524. // the code, so our tables end up looking a bit different. Rather than
  525. // trying to match MSVC's tables exactly, we emit a denormalized table. For
  526. // each range of invokes in the same state, we emit table entries for all
  527. // the actions that would be taken in that state. This means our tables are
  528. // slightly bigger, which is OK.
  529. const MCSymbol *LastStartLabel = nullptr;
  530. int LastEHState = -1;
  531. // Break out before we enter into a finally funclet.
  532. // FIXME: We need to emit separate EH tables for cleanups.
  533. MachineFunction::const_iterator End = MF->end();
  534. MachineFunction::const_iterator Stop = std::next(MF->begin());
  535. while (Stop != End && !Stop->isEHFuncletEntry())
  536. ++Stop;
  537. for (const auto &StateChange :
  538. InvokeStateChangeIterator::range(FuncInfo, MF->begin(), Stop)) {
  539. // Emit all the actions for the state we just transitioned out of
  540. // if it was not the null state
  541. if (LastEHState != -1)
  542. emitSEHActionsForRange(FuncInfo, LastStartLabel,
  543. StateChange.PreviousEndLabel, LastEHState);
  544. LastStartLabel = StateChange.NewStartLabel;
  545. LastEHState = StateChange.NewState;
  546. }
  547. OS.emitLabel(TableEnd);
  548. }
  549. void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
  550. const MCSymbol *BeginLabel,
  551. const MCSymbol *EndLabel, int State) {
  552. auto &OS = *Asm->OutStreamer;
  553. MCContext &Ctx = Asm->OutContext;
  554. bool VerboseAsm = OS.isVerboseAsm();
  555. auto AddComment = [&](const Twine &Comment) {
  556. if (VerboseAsm)
  557. OS.AddComment(Comment);
  558. };
  559. assert(BeginLabel && EndLabel);
  560. while (State != -1) {
  561. const SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State];
  562. const MCExpr *FilterOrFinally;
  563. const MCExpr *ExceptOrNull;
  564. auto *Handler = UME.Handler.get<MachineBasicBlock *>();
  565. if (UME.IsFinally) {
  566. FilterOrFinally = create32bitRef(getMCSymbolForMBB(Asm, Handler));
  567. ExceptOrNull = MCConstantExpr::create(0, Ctx);
  568. } else {
  569. // For an except, the filter can be 1 (catch-all) or a function
  570. // label.
  571. FilterOrFinally = UME.Filter ? create32bitRef(UME.Filter)
  572. : MCConstantExpr::create(1, Ctx);
  573. ExceptOrNull = create32bitRef(Handler->getSymbol());
  574. }
  575. AddComment("LabelStart");
  576. OS.emitValue(getLabel(BeginLabel), 4);
  577. AddComment("LabelEnd");
  578. OS.emitValue(getLabelPlusOne(EndLabel), 4);
  579. AddComment(UME.IsFinally ? "FinallyFunclet" : UME.Filter ? "FilterFunction"
  580. : "CatchAll");
  581. OS.emitValue(FilterOrFinally, 4);
  582. AddComment(UME.IsFinally ? "Null" : "ExceptionHandler");
  583. OS.emitValue(ExceptOrNull, 4);
  584. assert(UME.ToState < State && "states should decrease");
  585. State = UME.ToState;
  586. }
  587. }
  588. void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
  589. const Function &F = MF->getFunction();
  590. auto &OS = *Asm->OutStreamer;
  591. const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
  592. StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
  593. SmallVector<std::pair<const MCExpr *, int>, 4> IPToStateTable;
  594. MCSymbol *FuncInfoXData = nullptr;
  595. if (shouldEmitPersonality) {
  596. // If we're 64-bit, emit a pointer to the C++ EH data, and build a map from
  597. // IPs to state numbers.
  598. FuncInfoXData =
  599. Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", FuncLinkageName));
  600. computeIP2StateTable(MF, FuncInfo, IPToStateTable);
  601. } else {
  602. FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(FuncLinkageName);
  603. }
  604. int UnwindHelpOffset = 0;
  605. // TODO: The check for UnwindHelpFrameIdx against max() below (and the
  606. // second check further below) can be removed if MS C++ unwinding is
  607. // implemented for ARM, when test/CodeGen/ARM/Windows/wineh-basic.ll
  608. // passes without the check.
  609. if (Asm->MAI->usesWindowsCFI() &&
  610. FuncInfo.UnwindHelpFrameIdx != std::numeric_limits<int>::max())
  611. UnwindHelpOffset =
  612. getFrameIndexOffset(FuncInfo.UnwindHelpFrameIdx, FuncInfo);
  613. MCSymbol *UnwindMapXData = nullptr;
  614. MCSymbol *TryBlockMapXData = nullptr;
  615. MCSymbol *IPToStateXData = nullptr;
  616. if (!FuncInfo.CxxUnwindMap.empty())
  617. UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
  618. Twine("$stateUnwindMap$", FuncLinkageName));
  619. if (!FuncInfo.TryBlockMap.empty())
  620. TryBlockMapXData =
  621. Asm->OutContext.getOrCreateSymbol(Twine("$tryMap$", FuncLinkageName));
  622. if (!IPToStateTable.empty())
  623. IPToStateXData =
  624. Asm->OutContext.getOrCreateSymbol(Twine("$ip2state$", FuncLinkageName));
  625. bool VerboseAsm = OS.isVerboseAsm();
  626. auto AddComment = [&](const Twine &Comment) {
  627. if (VerboseAsm)
  628. OS.AddComment(Comment);
  629. };
  630. // FuncInfo {
  631. // uint32_t MagicNumber
  632. // int32_t MaxState;
  633. // UnwindMapEntry *UnwindMap;
  634. // uint32_t NumTryBlocks;
  635. // TryBlockMapEntry *TryBlockMap;
  636. // uint32_t IPMapEntries; // always 0 for x86
  637. // IPToStateMapEntry *IPToStateMap; // always 0 for x86
  638. // uint32_t UnwindHelp; // non-x86 only
  639. // ESTypeList *ESTypeList;
  640. // int32_t EHFlags;
  641. // }
  642. // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
  643. // EHFlags & 2 -> ???
  644. // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
  645. OS.emitValueToAlignment(Align(4));
  646. OS.emitLabel(FuncInfoXData);
  647. AddComment("MagicNumber");
  648. OS.emitInt32(0x19930522);
  649. AddComment("MaxState");
  650. OS.emitInt32(FuncInfo.CxxUnwindMap.size());
  651. AddComment("UnwindMap");
  652. OS.emitValue(create32bitRef(UnwindMapXData), 4);
  653. AddComment("NumTryBlocks");
  654. OS.emitInt32(FuncInfo.TryBlockMap.size());
  655. AddComment("TryBlockMap");
  656. OS.emitValue(create32bitRef(TryBlockMapXData), 4);
  657. AddComment("IPMapEntries");
  658. OS.emitInt32(IPToStateTable.size());
  659. AddComment("IPToStateXData");
  660. OS.emitValue(create32bitRef(IPToStateXData), 4);
  661. if (Asm->MAI->usesWindowsCFI() &&
  662. FuncInfo.UnwindHelpFrameIdx != std::numeric_limits<int>::max()) {
  663. AddComment("UnwindHelp");
  664. OS.emitInt32(UnwindHelpOffset);
  665. }
  666. AddComment("ESTypeList");
  667. OS.emitInt32(0);
  668. AddComment("EHFlags");
  669. OS.emitInt32(1);
  670. // UnwindMapEntry {
  671. // int32_t ToState;
  672. // void (*Action)();
  673. // };
  674. if (UnwindMapXData) {
  675. OS.emitLabel(UnwindMapXData);
  676. for (const CxxUnwindMapEntry &UME : FuncInfo.CxxUnwindMap) {
  677. MCSymbol *CleanupSym =
  678. getMCSymbolForMBB(Asm, UME.Cleanup.dyn_cast<MachineBasicBlock *>());
  679. AddComment("ToState");
  680. OS.emitInt32(UME.ToState);
  681. AddComment("Action");
  682. OS.emitValue(create32bitRef(CleanupSym), 4);
  683. }
  684. }
  685. // TryBlockMap {
  686. // int32_t TryLow;
  687. // int32_t TryHigh;
  688. // int32_t CatchHigh;
  689. // int32_t NumCatches;
  690. // HandlerType *HandlerArray;
  691. // };
  692. if (TryBlockMapXData) {
  693. OS.emitLabel(TryBlockMapXData);
  694. SmallVector<MCSymbol *, 1> HandlerMaps;
  695. for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
  696. const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
  697. MCSymbol *HandlerMapXData = nullptr;
  698. if (!TBME.HandlerArray.empty())
  699. HandlerMapXData =
  700. Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
  701. .concat(Twine(I))
  702. .concat("$")
  703. .concat(FuncLinkageName));
  704. HandlerMaps.push_back(HandlerMapXData);
  705. // TBMEs should form intervals.
  706. assert(0 <= TBME.TryLow && "bad trymap interval");
  707. assert(TBME.TryLow <= TBME.TryHigh && "bad trymap interval");
  708. assert(TBME.TryHigh < TBME.CatchHigh && "bad trymap interval");
  709. assert(TBME.CatchHigh < int(FuncInfo.CxxUnwindMap.size()) &&
  710. "bad trymap interval");
  711. AddComment("TryLow");
  712. OS.emitInt32(TBME.TryLow);
  713. AddComment("TryHigh");
  714. OS.emitInt32(TBME.TryHigh);
  715. AddComment("CatchHigh");
  716. OS.emitInt32(TBME.CatchHigh);
  717. AddComment("NumCatches");
  718. OS.emitInt32(TBME.HandlerArray.size());
  719. AddComment("HandlerArray");
  720. OS.emitValue(create32bitRef(HandlerMapXData), 4);
  721. }
  722. // All funclets use the same parent frame offset currently.
  723. unsigned ParentFrameOffset = 0;
  724. if (shouldEmitPersonality) {
  725. const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
  726. ParentFrameOffset = TFI->getWinEHParentFrameOffset(*MF);
  727. }
  728. for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
  729. const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
  730. MCSymbol *HandlerMapXData = HandlerMaps[I];
  731. if (!HandlerMapXData)
  732. continue;
  733. // HandlerType {
  734. // int32_t Adjectives;
  735. // TypeDescriptor *Type;
  736. // int32_t CatchObjOffset;
  737. // void (*Handler)();
  738. // int32_t ParentFrameOffset; // x64 and AArch64 only
  739. // };
  740. OS.emitLabel(HandlerMapXData);
  741. for (const WinEHHandlerType &HT : TBME.HandlerArray) {
  742. // Get the frame escape label with the offset of the catch object. If
  743. // the index is INT_MAX, then there is no catch object, and we should
  744. // emit an offset of zero, indicating that no copy will occur.
  745. const MCExpr *FrameAllocOffsetRef = nullptr;
  746. if (HT.CatchObj.FrameIndex != INT_MAX) {
  747. int Offset = getFrameIndexOffset(HT.CatchObj.FrameIndex, FuncInfo);
  748. assert(Offset != 0 && "Illegal offset for catch object!");
  749. FrameAllocOffsetRef = MCConstantExpr::create(Offset, Asm->OutContext);
  750. } else {
  751. FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
  752. }
  753. MCSymbol *HandlerSym =
  754. getMCSymbolForMBB(Asm, HT.Handler.dyn_cast<MachineBasicBlock *>());
  755. AddComment("Adjectives");
  756. OS.emitInt32(HT.Adjectives);
  757. AddComment("Type");
  758. OS.emitValue(create32bitRef(HT.TypeDescriptor), 4);
  759. AddComment("CatchObjOffset");
  760. OS.emitValue(FrameAllocOffsetRef, 4);
  761. AddComment("Handler");
  762. OS.emitValue(create32bitRef(HandlerSym), 4);
  763. if (shouldEmitPersonality) {
  764. AddComment("ParentFrameOffset");
  765. OS.emitInt32(ParentFrameOffset);
  766. }
  767. }
  768. }
  769. }
  770. // IPToStateMapEntry {
  771. // void *IP;
  772. // int32_t State;
  773. // };
  774. if (IPToStateXData) {
  775. OS.emitLabel(IPToStateXData);
  776. for (auto &IPStatePair : IPToStateTable) {
  777. AddComment("IP");
  778. OS.emitValue(IPStatePair.first, 4);
  779. AddComment("ToState");
  780. OS.emitInt32(IPStatePair.second);
  781. }
  782. }
  783. }
  784. void WinException::computeIP2StateTable(
  785. const MachineFunction *MF, const WinEHFuncInfo &FuncInfo,
  786. SmallVectorImpl<std::pair<const MCExpr *, int>> &IPToStateTable) {
  787. for (MachineFunction::const_iterator FuncletStart = MF->begin(),
  788. FuncletEnd = MF->begin(),
  789. End = MF->end();
  790. FuncletStart != End; FuncletStart = FuncletEnd) {
  791. // Find the end of the funclet
  792. while (++FuncletEnd != End) {
  793. if (FuncletEnd->isEHFuncletEntry()) {
  794. break;
  795. }
  796. }
  797. // Don't emit ip2state entries for cleanup funclets. Any interesting
  798. // exceptional actions in cleanups must be handled in a separate IR
  799. // function.
  800. if (FuncletStart->isCleanupFuncletEntry())
  801. continue;
  802. MCSymbol *StartLabel;
  803. int BaseState;
  804. if (FuncletStart == MF->begin()) {
  805. BaseState = NullState;
  806. StartLabel = Asm->getFunctionBegin();
  807. } else {
  808. auto *FuncletPad =
  809. cast<FuncletPadInst>(FuncletStart->getBasicBlock()->getFirstNonPHI());
  810. assert(FuncInfo.FuncletBaseStateMap.count(FuncletPad) != 0);
  811. BaseState = FuncInfo.FuncletBaseStateMap.find(FuncletPad)->second;
  812. StartLabel = getMCSymbolForMBB(Asm, &*FuncletStart);
  813. }
  814. assert(StartLabel && "need local function start label");
  815. IPToStateTable.push_back(
  816. std::make_pair(create32bitRef(StartLabel), BaseState));
  817. for (const auto &StateChange : InvokeStateChangeIterator::range(
  818. FuncInfo, FuncletStart, FuncletEnd, BaseState)) {
  819. // Compute the label to report as the start of this entry; use the EH
  820. // start label for the invoke if we have one, otherwise (this is a call
  821. // which may unwind to our caller and does not have an EH start label, so)
  822. // use the previous end label.
  823. const MCSymbol *ChangeLabel = StateChange.NewStartLabel;
  824. if (!ChangeLabel)
  825. ChangeLabel = StateChange.PreviousEndLabel;
  826. // Emit an entry indicating that PCs after 'Label' have this EH state.
  827. // NOTE: On ARM architectures, the StateFromIp automatically takes into
  828. // account that the return address is after the call instruction (whose EH
  829. // state we should be using), but on other platforms we need to +1 to the
  830. // label so that we are using the correct EH state.
  831. const MCExpr *LabelExpression = (isAArch64 || isThumb)
  832. ? getLabel(ChangeLabel)
  833. : getLabelPlusOne(ChangeLabel);
  834. IPToStateTable.push_back(
  835. std::make_pair(LabelExpression, StateChange.NewState));
  836. // FIXME: assert that NewState is between CatchLow and CatchHigh.
  837. }
  838. }
  839. }
  840. void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
  841. StringRef FLinkageName) {
  842. // Outlined helpers called by the EH runtime need to know the offset of the EH
  843. // registration in order to recover the parent frame pointer. Now that we know
  844. // we've code generated the parent, we can emit the label assignment that
  845. // those helpers use to get the offset of the registration node.
  846. // Compute the parent frame offset. The EHRegNodeFrameIndex will be invalid if
  847. // after optimization all the invokes were eliminated. We still need to emit
  848. // the parent frame offset label, but it should be garbage and should never be
  849. // used.
  850. int64_t Offset = 0;
  851. int FI = FuncInfo.EHRegNodeFrameIndex;
  852. if (FI != INT_MAX) {
  853. const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
  854. Offset = TFI->getNonLocalFrameIndexReference(*Asm->MF, FI).getFixed();
  855. }
  856. MCContext &Ctx = Asm->OutContext;
  857. MCSymbol *ParentFrameOffset =
  858. Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
  859. Asm->OutStreamer->emitAssignment(ParentFrameOffset,
  860. MCConstantExpr::create(Offset, Ctx));
  861. }
  862. /// Emit the language-specific data that _except_handler3 and 4 expect. This is
  863. /// functionally equivalent to the __C_specific_handler table, except it is
  864. /// indexed by state number instead of IP.
  865. void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
  866. MCStreamer &OS = *Asm->OutStreamer;
  867. const Function &F = MF->getFunction();
  868. StringRef FLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
  869. bool VerboseAsm = OS.isVerboseAsm();
  870. auto AddComment = [&](const Twine &Comment) {
  871. if (VerboseAsm)
  872. OS.AddComment(Comment);
  873. };
  874. const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
  875. emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
  876. // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
  877. MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
  878. OS.emitValueToAlignment(Align(4));
  879. OS.emitLabel(LSDALabel);
  880. const auto *Per = cast<Function>(F.getPersonalityFn()->stripPointerCasts());
  881. StringRef PerName = Per->getName();
  882. int BaseState = -1;
  883. if (PerName == "_except_handler4") {
  884. // The LSDA for _except_handler4 starts with this struct, followed by the
  885. // scope table:
  886. //
  887. // struct EH4ScopeTable {
  888. // int32_t GSCookieOffset;
  889. // int32_t GSCookieXOROffset;
  890. // int32_t EHCookieOffset;
  891. // int32_t EHCookieXOROffset;
  892. // ScopeTableEntry ScopeRecord[];
  893. // };
  894. //
  895. // Offsets are %ebp relative.
  896. //
  897. // The GS cookie is present only if the function needs stack protection.
  898. // GSCookieOffset = -2 means that GS cookie is not used.
  899. //
  900. // The EH cookie is always present.
  901. //
  902. // Check is done the following way:
  903. // (ebp+CookieXOROffset) ^ [ebp+CookieOffset] == _security_cookie
  904. // Retrieve the Guard Stack slot.
  905. int GSCookieOffset = -2;
  906. const MachineFrameInfo &MFI = MF->getFrameInfo();
  907. if (MFI.hasStackProtectorIndex()) {
  908. Register UnusedReg;
  909. const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
  910. int SSPIdx = MFI.getStackProtectorIndex();
  911. GSCookieOffset =
  912. TFI->getFrameIndexReference(*MF, SSPIdx, UnusedReg).getFixed();
  913. }
  914. // Retrieve the EH Guard slot.
  915. // TODO(etienneb): Get rid of this value and change it for and assertion.
  916. int EHCookieOffset = 9999;
  917. if (FuncInfo.EHGuardFrameIndex != INT_MAX) {
  918. Register UnusedReg;
  919. const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
  920. int EHGuardIdx = FuncInfo.EHGuardFrameIndex;
  921. EHCookieOffset =
  922. TFI->getFrameIndexReference(*MF, EHGuardIdx, UnusedReg).getFixed();
  923. }
  924. AddComment("GSCookieOffset");
  925. OS.emitInt32(GSCookieOffset);
  926. AddComment("GSCookieXOROffset");
  927. OS.emitInt32(0);
  928. AddComment("EHCookieOffset");
  929. OS.emitInt32(EHCookieOffset);
  930. AddComment("EHCookieXOROffset");
  931. OS.emitInt32(0);
  932. BaseState = -2;
  933. }
  934. assert(!FuncInfo.SEHUnwindMap.empty());
  935. for (const SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) {
  936. auto *Handler = UME.Handler.get<MachineBasicBlock *>();
  937. const MCSymbol *ExceptOrFinally =
  938. UME.IsFinally ? getMCSymbolForMBB(Asm, Handler) : Handler->getSymbol();
  939. // -1 is usually the base state for "unwind to caller", but for
  940. // _except_handler4 it's -2. Do that replacement here if necessary.
  941. int ToState = UME.ToState == -1 ? BaseState : UME.ToState;
  942. AddComment("ToState");
  943. OS.emitInt32(ToState);
  944. AddComment(UME.IsFinally ? "Null" : "FilterFunction");
  945. OS.emitValue(create32bitRef(UME.Filter), 4);
  946. AddComment(UME.IsFinally ? "FinallyFunclet" : "ExceptionHandler");
  947. OS.emitValue(create32bitRef(ExceptOrFinally), 4);
  948. }
  949. }
  950. static int getTryRank(const WinEHFuncInfo &FuncInfo, int State) {
  951. int Rank = 0;
  952. while (State != -1) {
  953. ++Rank;
  954. State = FuncInfo.ClrEHUnwindMap[State].TryParentState;
  955. }
  956. return Rank;
  957. }
  958. static int getTryAncestor(const WinEHFuncInfo &FuncInfo, int Left, int Right) {
  959. int LeftRank = getTryRank(FuncInfo, Left);
  960. int RightRank = getTryRank(FuncInfo, Right);
  961. while (LeftRank < RightRank) {
  962. Right = FuncInfo.ClrEHUnwindMap[Right].TryParentState;
  963. --RightRank;
  964. }
  965. while (RightRank < LeftRank) {
  966. Left = FuncInfo.ClrEHUnwindMap[Left].TryParentState;
  967. --LeftRank;
  968. }
  969. while (Left != Right) {
  970. Left = FuncInfo.ClrEHUnwindMap[Left].TryParentState;
  971. Right = FuncInfo.ClrEHUnwindMap[Right].TryParentState;
  972. }
  973. return Left;
  974. }
  975. void WinException::emitCLRExceptionTable(const MachineFunction *MF) {
  976. // CLR EH "states" are really just IDs that identify handlers/funclets;
  977. // states, handlers, and funclets all have 1:1 mappings between them, and a
  978. // handler/funclet's "state" is its index in the ClrEHUnwindMap.
  979. MCStreamer &OS = *Asm->OutStreamer;
  980. const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
  981. MCSymbol *FuncBeginSym = Asm->getFunctionBegin();
  982. MCSymbol *FuncEndSym = Asm->getFunctionEnd();
  983. // A ClrClause describes a protected region.
  984. struct ClrClause {
  985. const MCSymbol *StartLabel; // Start of protected region
  986. const MCSymbol *EndLabel; // End of protected region
  987. int State; // Index of handler protecting the protected region
  988. int EnclosingState; // Index of funclet enclosing the protected region
  989. };
  990. SmallVector<ClrClause, 8> Clauses;
  991. // Build a map from handler MBBs to their corresponding states (i.e. their
  992. // indices in the ClrEHUnwindMap).
  993. int NumStates = FuncInfo.ClrEHUnwindMap.size();
  994. assert(NumStates > 0 && "Don't need exception table!");
  995. DenseMap<const MachineBasicBlock *, int> HandlerStates;
  996. for (int State = 0; State < NumStates; ++State) {
  997. MachineBasicBlock *HandlerBlock =
  998. FuncInfo.ClrEHUnwindMap[State].Handler.get<MachineBasicBlock *>();
  999. HandlerStates[HandlerBlock] = State;
  1000. // Use this loop through all handlers to verify our assumption (used in
  1001. // the MinEnclosingState computation) that enclosing funclets have lower
  1002. // state numbers than their enclosed funclets.
  1003. assert(FuncInfo.ClrEHUnwindMap[State].HandlerParentState < State &&
  1004. "ill-formed state numbering");
  1005. }
  1006. // Map the main function to the NullState.
  1007. HandlerStates[&MF->front()] = NullState;
  1008. // Write out a sentinel indicating the end of the standard (Windows) xdata
  1009. // and the start of the additional (CLR) info.
  1010. OS.emitInt32(0xffffffff);
  1011. // Write out the number of funclets
  1012. OS.emitInt32(NumStates);
  1013. // Walk the machine blocks/instrs, computing and emitting a few things:
  1014. // 1. Emit a list of the offsets to each handler entry, in lexical order.
  1015. // 2. Compute a map (EndSymbolMap) from each funclet to the symbol at its end.
  1016. // 3. Compute the list of ClrClauses, in the required order (inner before
  1017. // outer, earlier before later; the order by which a forward scan with
  1018. // early termination will find the innermost enclosing clause covering
  1019. // a given address).
  1020. // 4. A map (MinClauseMap) from each handler index to the index of the
  1021. // outermost funclet/function which contains a try clause targeting the
  1022. // key handler. This will be used to determine IsDuplicate-ness when
  1023. // emitting ClrClauses. The NullState value is used to indicate that the
  1024. // top-level function contains a try clause targeting the key handler.
  1025. // HandlerStack is a stack of (PendingStartLabel, PendingState) pairs for
  1026. // try regions we entered before entering the PendingState try but which
  1027. // we haven't yet exited.
  1028. SmallVector<std::pair<const MCSymbol *, int>, 4> HandlerStack;
  1029. // EndSymbolMap and MinClauseMap are maps described above.
  1030. std::unique_ptr<MCSymbol *[]> EndSymbolMap(new MCSymbol *[NumStates]);
  1031. SmallVector<int, 4> MinClauseMap((size_t)NumStates, NumStates);
  1032. // Visit the root function and each funclet.
  1033. for (MachineFunction::const_iterator FuncletStart = MF->begin(),
  1034. FuncletEnd = MF->begin(),
  1035. End = MF->end();
  1036. FuncletStart != End; FuncletStart = FuncletEnd) {
  1037. int FuncletState = HandlerStates[&*FuncletStart];
  1038. // Find the end of the funclet
  1039. MCSymbol *EndSymbol = FuncEndSym;
  1040. while (++FuncletEnd != End) {
  1041. if (FuncletEnd->isEHFuncletEntry()) {
  1042. EndSymbol = getMCSymbolForMBB(Asm, &*FuncletEnd);
  1043. break;
  1044. }
  1045. }
  1046. // Emit the function/funclet end and, if this is a funclet (and not the
  1047. // root function), record it in the EndSymbolMap.
  1048. OS.emitValue(getOffset(EndSymbol, FuncBeginSym), 4);
  1049. if (FuncletState != NullState) {
  1050. // Record the end of the handler.
  1051. EndSymbolMap[FuncletState] = EndSymbol;
  1052. }
  1053. // Walk the state changes in this function/funclet and compute its clauses.
  1054. // Funclets always start in the null state.
  1055. const MCSymbol *CurrentStartLabel = nullptr;
  1056. int CurrentState = NullState;
  1057. assert(HandlerStack.empty());
  1058. for (const auto &StateChange :
  1059. InvokeStateChangeIterator::range(FuncInfo, FuncletStart, FuncletEnd)) {
  1060. // Close any try regions we're not still under
  1061. int StillPendingState =
  1062. getTryAncestor(FuncInfo, CurrentState, StateChange.NewState);
  1063. while (CurrentState != StillPendingState) {
  1064. assert(CurrentState != NullState &&
  1065. "Failed to find still-pending state!");
  1066. // Close the pending clause
  1067. Clauses.push_back({CurrentStartLabel, StateChange.PreviousEndLabel,
  1068. CurrentState, FuncletState});
  1069. // Now the next-outer try region is current
  1070. CurrentState = FuncInfo.ClrEHUnwindMap[CurrentState].TryParentState;
  1071. // Pop the new start label from the handler stack if we've exited all
  1072. // inner try regions of the corresponding try region.
  1073. if (HandlerStack.back().second == CurrentState)
  1074. CurrentStartLabel = HandlerStack.pop_back_val().first;
  1075. }
  1076. if (StateChange.NewState != CurrentState) {
  1077. // For each clause we're starting, update the MinClauseMap so we can
  1078. // know which is the topmost funclet containing a clause targeting
  1079. // it.
  1080. for (int EnteredState = StateChange.NewState;
  1081. EnteredState != CurrentState;
  1082. EnteredState =
  1083. FuncInfo.ClrEHUnwindMap[EnteredState].TryParentState) {
  1084. int &MinEnclosingState = MinClauseMap[EnteredState];
  1085. if (FuncletState < MinEnclosingState)
  1086. MinEnclosingState = FuncletState;
  1087. }
  1088. // Save the previous current start/label on the stack and update to
  1089. // the newly-current start/state.
  1090. HandlerStack.emplace_back(CurrentStartLabel, CurrentState);
  1091. CurrentStartLabel = StateChange.NewStartLabel;
  1092. CurrentState = StateChange.NewState;
  1093. }
  1094. }
  1095. assert(HandlerStack.empty());
  1096. }
  1097. // Now emit the clause info, starting with the number of clauses.
  1098. OS.emitInt32(Clauses.size());
  1099. for (ClrClause &Clause : Clauses) {
  1100. // Emit a CORINFO_EH_CLAUSE :
  1101. /*
  1102. struct CORINFO_EH_CLAUSE
  1103. {
  1104. CORINFO_EH_CLAUSE_FLAGS Flags; // actually a CorExceptionFlag
  1105. DWORD TryOffset;
  1106. DWORD TryLength; // actually TryEndOffset
  1107. DWORD HandlerOffset;
  1108. DWORD HandlerLength; // actually HandlerEndOffset
  1109. union
  1110. {
  1111. DWORD ClassToken; // use for catch clauses
  1112. DWORD FilterOffset; // use for filter clauses
  1113. };
  1114. };
  1115. enum CORINFO_EH_CLAUSE_FLAGS
  1116. {
  1117. CORINFO_EH_CLAUSE_NONE = 0,
  1118. CORINFO_EH_CLAUSE_FILTER = 0x0001, // This clause is for a filter
  1119. CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause
  1120. CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause
  1121. };
  1122. typedef enum CorExceptionFlag
  1123. {
  1124. COR_ILEXCEPTION_CLAUSE_NONE,
  1125. COR_ILEXCEPTION_CLAUSE_FILTER = 0x0001, // This is a filter clause
  1126. COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002, // This is a finally clause
  1127. COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004, // This is a fault clause
  1128. COR_ILEXCEPTION_CLAUSE_DUPLICATED = 0x0008, // duplicated clause. This
  1129. // clause was duplicated
  1130. // to a funclet which was
  1131. // pulled out of line
  1132. } CorExceptionFlag;
  1133. */
  1134. // Add 1 to the start/end of the EH clause; the IP associated with a
  1135. // call when the runtime does its scan is the IP of the next instruction
  1136. // (the one to which control will return after the call), so we need
  1137. // to add 1 to the end of the clause to cover that offset. We also add
  1138. // 1 to the start of the clause to make sure that the ranges reported
  1139. // for all clauses are disjoint. Note that we'll need some additional
  1140. // logic when machine traps are supported, since in that case the IP
  1141. // that the runtime uses is the offset of the faulting instruction
  1142. // itself; if such an instruction immediately follows a call but the
  1143. // two belong to different clauses, we'll need to insert a nop between
  1144. // them so the runtime can distinguish the point to which the call will
  1145. // return from the point at which the fault occurs.
  1146. const MCExpr *ClauseBegin =
  1147. getOffsetPlusOne(Clause.StartLabel, FuncBeginSym);
  1148. const MCExpr *ClauseEnd = getOffsetPlusOne(Clause.EndLabel, FuncBeginSym);
  1149. const ClrEHUnwindMapEntry &Entry = FuncInfo.ClrEHUnwindMap[Clause.State];
  1150. MachineBasicBlock *HandlerBlock = Entry.Handler.get<MachineBasicBlock *>();
  1151. MCSymbol *BeginSym = getMCSymbolForMBB(Asm, HandlerBlock);
  1152. const MCExpr *HandlerBegin = getOffset(BeginSym, FuncBeginSym);
  1153. MCSymbol *EndSym = EndSymbolMap[Clause.State];
  1154. const MCExpr *HandlerEnd = getOffset(EndSym, FuncBeginSym);
  1155. uint32_t Flags = 0;
  1156. switch (Entry.HandlerType) {
  1157. case ClrHandlerType::Catch:
  1158. // Leaving bits 0-2 clear indicates catch.
  1159. break;
  1160. case ClrHandlerType::Filter:
  1161. Flags |= 1;
  1162. break;
  1163. case ClrHandlerType::Finally:
  1164. Flags |= 2;
  1165. break;
  1166. case ClrHandlerType::Fault:
  1167. Flags |= 4;
  1168. break;
  1169. }
  1170. if (Clause.EnclosingState != MinClauseMap[Clause.State]) {
  1171. // This is a "duplicate" clause; the handler needs to be entered from a
  1172. // frame above the one holding the invoke.
  1173. assert(Clause.EnclosingState > MinClauseMap[Clause.State]);
  1174. Flags |= 8;
  1175. }
  1176. OS.emitInt32(Flags);
  1177. // Write the clause start/end
  1178. OS.emitValue(ClauseBegin, 4);
  1179. OS.emitValue(ClauseEnd, 4);
  1180. // Write out the handler start/end
  1181. OS.emitValue(HandlerBegin, 4);
  1182. OS.emitValue(HandlerEnd, 4);
  1183. // Write out the type token or filter offset
  1184. assert(Entry.HandlerType != ClrHandlerType::Filter && "NYI: filters");
  1185. OS.emitInt32(Entry.TypeToken);
  1186. }
  1187. }