WinException.cpp 53 KB

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