MCWin64EH.cpp 89 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617
  1. //===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===//
  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. #include "llvm/MC/MCWin64EH.h"
  9. #include "llvm/ADT/Twine.h"
  10. #include "llvm/MC/MCContext.h"
  11. #include "llvm/MC/MCExpr.h"
  12. #include "llvm/MC/MCObjectStreamer.h"
  13. #include "llvm/MC/MCStreamer.h"
  14. #include "llvm/MC/MCSymbol.h"
  15. #include "llvm/Support/Win64EH.h"
  16. namespace llvm {
  17. class MCSection;
  18. }
  19. using namespace llvm;
  20. // NOTE: All relocations generated here are 4-byte image-relative.
  21. static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
  22. uint8_t Count = 0;
  23. for (const auto &I : Insns) {
  24. switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
  25. default:
  26. llvm_unreachable("Unsupported unwind code");
  27. case Win64EH::UOP_PushNonVol:
  28. case Win64EH::UOP_AllocSmall:
  29. case Win64EH::UOP_SetFPReg:
  30. case Win64EH::UOP_PushMachFrame:
  31. Count += 1;
  32. break;
  33. case Win64EH::UOP_SaveNonVol:
  34. case Win64EH::UOP_SaveXMM128:
  35. Count += 2;
  36. break;
  37. case Win64EH::UOP_SaveNonVolBig:
  38. case Win64EH::UOP_SaveXMM128Big:
  39. Count += 3;
  40. break;
  41. case Win64EH::UOP_AllocLarge:
  42. Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
  43. break;
  44. }
  45. }
  46. return Count;
  47. }
  48. static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
  49. const MCSymbol *RHS) {
  50. MCContext &Context = Streamer.getContext();
  51. const MCExpr *Diff =
  52. MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context),
  53. MCSymbolRefExpr::create(RHS, Context), Context);
  54. Streamer.emitValue(Diff, 1);
  55. }
  56. static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
  57. WinEH::Instruction &inst) {
  58. uint8_t b2;
  59. uint16_t w;
  60. b2 = (inst.Operation & 0x0F);
  61. switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
  62. default:
  63. llvm_unreachable("Unsupported unwind code");
  64. case Win64EH::UOP_PushNonVol:
  65. EmitAbsDifference(streamer, inst.Label, begin);
  66. b2 |= (inst.Register & 0x0F) << 4;
  67. streamer.emitInt8(b2);
  68. break;
  69. case Win64EH::UOP_AllocLarge:
  70. EmitAbsDifference(streamer, inst.Label, begin);
  71. if (inst.Offset > 512 * 1024 - 8) {
  72. b2 |= 0x10;
  73. streamer.emitInt8(b2);
  74. w = inst.Offset & 0xFFF8;
  75. streamer.emitInt16(w);
  76. w = inst.Offset >> 16;
  77. } else {
  78. streamer.emitInt8(b2);
  79. w = inst.Offset >> 3;
  80. }
  81. streamer.emitInt16(w);
  82. break;
  83. case Win64EH::UOP_AllocSmall:
  84. b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
  85. EmitAbsDifference(streamer, inst.Label, begin);
  86. streamer.emitInt8(b2);
  87. break;
  88. case Win64EH::UOP_SetFPReg:
  89. EmitAbsDifference(streamer, inst.Label, begin);
  90. streamer.emitInt8(b2);
  91. break;
  92. case Win64EH::UOP_SaveNonVol:
  93. case Win64EH::UOP_SaveXMM128:
  94. b2 |= (inst.Register & 0x0F) << 4;
  95. EmitAbsDifference(streamer, inst.Label, begin);
  96. streamer.emitInt8(b2);
  97. w = inst.Offset >> 3;
  98. if (inst.Operation == Win64EH::UOP_SaveXMM128)
  99. w >>= 1;
  100. streamer.emitInt16(w);
  101. break;
  102. case Win64EH::UOP_SaveNonVolBig:
  103. case Win64EH::UOP_SaveXMM128Big:
  104. b2 |= (inst.Register & 0x0F) << 4;
  105. EmitAbsDifference(streamer, inst.Label, begin);
  106. streamer.emitInt8(b2);
  107. if (inst.Operation == Win64EH::UOP_SaveXMM128Big)
  108. w = inst.Offset & 0xFFF0;
  109. else
  110. w = inst.Offset & 0xFFF8;
  111. streamer.emitInt16(w);
  112. w = inst.Offset >> 16;
  113. streamer.emitInt16(w);
  114. break;
  115. case Win64EH::UOP_PushMachFrame:
  116. if (inst.Offset == 1)
  117. b2 |= 0x10;
  118. EmitAbsDifference(streamer, inst.Label, begin);
  119. streamer.emitInt8(b2);
  120. break;
  121. }
  122. }
  123. static void EmitSymbolRefWithOfs(MCStreamer &streamer,
  124. const MCSymbol *Base,
  125. int64_t Offset) {
  126. MCContext &Context = streamer.getContext();
  127. const MCConstantExpr *OffExpr = MCConstantExpr::create(Offset, Context);
  128. const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
  129. MCSymbolRefExpr::VK_COFF_IMGREL32,
  130. Context);
  131. streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, OffExpr, Context), 4);
  132. }
  133. static void EmitSymbolRefWithOfs(MCStreamer &streamer,
  134. const MCSymbol *Base,
  135. const MCSymbol *Other) {
  136. MCContext &Context = streamer.getContext();
  137. const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::create(Base, Context);
  138. const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::create(Other, Context);
  139. const MCExpr *Ofs = MCBinaryExpr::createSub(OtherRef, BaseRef, Context);
  140. const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
  141. MCSymbolRefExpr::VK_COFF_IMGREL32,
  142. Context);
  143. streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
  144. }
  145. static void EmitRuntimeFunction(MCStreamer &streamer,
  146. const WinEH::FrameInfo *info) {
  147. MCContext &context = streamer.getContext();
  148. streamer.emitValueToAlignment(Align(4));
  149. EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
  150. EmitSymbolRefWithOfs(streamer, info->Begin, info->End);
  151. streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
  152. MCSymbolRefExpr::VK_COFF_IMGREL32,
  153. context), 4);
  154. }
  155. static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
  156. // If this UNWIND_INFO already has a symbol, it's already been emitted.
  157. if (info->Symbol)
  158. return;
  159. MCContext &context = streamer.getContext();
  160. MCSymbol *Label = context.createTempSymbol();
  161. streamer.emitValueToAlignment(Align(4));
  162. streamer.emitLabel(Label);
  163. info->Symbol = Label;
  164. // Upper 3 bits are the version number (currently 1).
  165. uint8_t flags = 0x01;
  166. if (info->ChainedParent)
  167. flags |= Win64EH::UNW_ChainInfo << 3;
  168. else {
  169. if (info->HandlesUnwind)
  170. flags |= Win64EH::UNW_TerminateHandler << 3;
  171. if (info->HandlesExceptions)
  172. flags |= Win64EH::UNW_ExceptionHandler << 3;
  173. }
  174. streamer.emitInt8(flags);
  175. if (info->PrologEnd)
  176. EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
  177. else
  178. streamer.emitInt8(0);
  179. uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
  180. streamer.emitInt8(numCodes);
  181. uint8_t frame = 0;
  182. if (info->LastFrameInst >= 0) {
  183. WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
  184. assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
  185. frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
  186. }
  187. streamer.emitInt8(frame);
  188. // Emit unwind instructions (in reverse order).
  189. uint8_t numInst = info->Instructions.size();
  190. for (uint8_t c = 0; c < numInst; ++c) {
  191. WinEH::Instruction inst = info->Instructions.back();
  192. info->Instructions.pop_back();
  193. EmitUnwindCode(streamer, info->Begin, inst);
  194. }
  195. // For alignment purposes, the instruction array will always have an even
  196. // number of entries, with the final entry potentially unused (in which case
  197. // the array will be one longer than indicated by the count of unwind codes
  198. // field).
  199. if (numCodes & 1) {
  200. streamer.emitInt16(0);
  201. }
  202. if (flags & (Win64EH::UNW_ChainInfo << 3))
  203. EmitRuntimeFunction(streamer, info->ChainedParent);
  204. else if (flags &
  205. ((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3))
  206. streamer.emitValue(MCSymbolRefExpr::create(info->ExceptionHandler,
  207. MCSymbolRefExpr::VK_COFF_IMGREL32,
  208. context), 4);
  209. else if (numCodes == 0) {
  210. // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
  211. // a chained unwind info, if there is no handler, and if there are fewer
  212. // than 2 slots used in the unwind code array, we have to pad to 8 bytes.
  213. streamer.emitInt32(0);
  214. }
  215. }
  216. void llvm::Win64EH::UnwindEmitter::Emit(MCStreamer &Streamer) const {
  217. // Emit the unwind info structs first.
  218. for (const auto &CFI : Streamer.getWinFrameInfos()) {
  219. MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
  220. Streamer.switchSection(XData);
  221. ::EmitUnwindInfo(Streamer, CFI.get());
  222. }
  223. // Now emit RUNTIME_FUNCTION entries.
  224. for (const auto &CFI : Streamer.getWinFrameInfos()) {
  225. MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
  226. Streamer.switchSection(PData);
  227. EmitRuntimeFunction(Streamer, CFI.get());
  228. }
  229. }
  230. void llvm::Win64EH::UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer,
  231. WinEH::FrameInfo *info,
  232. bool HandlerData) const {
  233. // Switch sections (the static function above is meant to be called from
  234. // here and from Emit().
  235. MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
  236. Streamer.switchSection(XData);
  237. ::EmitUnwindInfo(Streamer, info);
  238. }
  239. static const MCExpr *GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS,
  240. const MCSymbol *RHS, int Div) {
  241. MCContext &Context = Streamer.getContext();
  242. const MCExpr *Expr =
  243. MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context),
  244. MCSymbolRefExpr::create(RHS, Context), Context);
  245. if (Div != 1)
  246. Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(Div, Context),
  247. Context);
  248. return Expr;
  249. }
  250. static std::optional<int64_t> GetOptionalAbsDifference(MCStreamer &Streamer,
  251. const MCSymbol *LHS,
  252. const MCSymbol *RHS) {
  253. MCContext &Context = Streamer.getContext();
  254. const MCExpr *Diff =
  255. MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context),
  256. MCSymbolRefExpr::create(RHS, Context), Context);
  257. MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer);
  258. // It should normally be possible to calculate the length of a function
  259. // at this point, but it might not be possible in the presence of certain
  260. // unusual constructs, like an inline asm with an alignment directive.
  261. int64_t value;
  262. if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))
  263. return std::nullopt;
  264. return value;
  265. }
  266. static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
  267. const MCSymbol *RHS) {
  268. std::optional<int64_t> MaybeDiff =
  269. GetOptionalAbsDifference(Streamer, LHS, RHS);
  270. if (!MaybeDiff)
  271. report_fatal_error("Failed to evaluate function length in SEH unwind info");
  272. return *MaybeDiff;
  273. }
  274. static void checkARM64Instructions(MCStreamer &Streamer,
  275. ArrayRef<WinEH::Instruction> Insns,
  276. const MCSymbol *Begin, const MCSymbol *End,
  277. StringRef Name, StringRef Type) {
  278. if (!End)
  279. return;
  280. std::optional<int64_t> MaybeDistance =
  281. GetOptionalAbsDifference(Streamer, End, Begin);
  282. if (!MaybeDistance)
  283. return;
  284. uint32_t Distance = (uint32_t)*MaybeDistance;
  285. for (const auto &I : Insns) {
  286. switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
  287. default:
  288. break;
  289. case Win64EH::UOP_TrapFrame:
  290. case Win64EH::UOP_PushMachFrame:
  291. case Win64EH::UOP_Context:
  292. case Win64EH::UOP_ClearUnwoundToCall:
  293. // Can't reason about these opcodes and how they map to actual
  294. // instructions.
  295. return;
  296. }
  297. }
  298. // Exclude the end opcode which doesn't map to an instruction.
  299. uint32_t InstructionBytes = 4 * (Insns.size() - 1);
  300. if (Distance != InstructionBytes) {
  301. Streamer.getContext().reportError(
  302. SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
  303. Twine(Distance) +
  304. " bytes of instructions in range, but .seh directives "
  305. "corresponding to " +
  306. Twine(InstructionBytes) + " bytes\n");
  307. }
  308. }
  309. static uint32_t ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
  310. uint32_t Count = 0;
  311. for (const auto &I : Insns) {
  312. switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
  313. default:
  314. llvm_unreachable("Unsupported ARM64 unwind code");
  315. case Win64EH::UOP_AllocSmall:
  316. Count += 1;
  317. break;
  318. case Win64EH::UOP_AllocMedium:
  319. Count += 2;
  320. break;
  321. case Win64EH::UOP_AllocLarge:
  322. Count += 4;
  323. break;
  324. case Win64EH::UOP_SaveR19R20X:
  325. Count += 1;
  326. break;
  327. case Win64EH::UOP_SaveFPLRX:
  328. Count += 1;
  329. break;
  330. case Win64EH::UOP_SaveFPLR:
  331. Count += 1;
  332. break;
  333. case Win64EH::UOP_SaveReg:
  334. Count += 2;
  335. break;
  336. case Win64EH::UOP_SaveRegP:
  337. Count += 2;
  338. break;
  339. case Win64EH::UOP_SaveRegPX:
  340. Count += 2;
  341. break;
  342. case Win64EH::UOP_SaveRegX:
  343. Count += 2;
  344. break;
  345. case Win64EH::UOP_SaveLRPair:
  346. Count += 2;
  347. break;
  348. case Win64EH::UOP_SaveFReg:
  349. Count += 2;
  350. break;
  351. case Win64EH::UOP_SaveFRegP:
  352. Count += 2;
  353. break;
  354. case Win64EH::UOP_SaveFRegX:
  355. Count += 2;
  356. break;
  357. case Win64EH::UOP_SaveFRegPX:
  358. Count += 2;
  359. break;
  360. case Win64EH::UOP_SetFP:
  361. Count += 1;
  362. break;
  363. case Win64EH::UOP_AddFP:
  364. Count += 2;
  365. break;
  366. case Win64EH::UOP_Nop:
  367. Count += 1;
  368. break;
  369. case Win64EH::UOP_End:
  370. Count += 1;
  371. break;
  372. case Win64EH::UOP_SaveNext:
  373. Count += 1;
  374. break;
  375. case Win64EH::UOP_TrapFrame:
  376. Count += 1;
  377. break;
  378. case Win64EH::UOP_PushMachFrame:
  379. Count += 1;
  380. break;
  381. case Win64EH::UOP_Context:
  382. Count += 1;
  383. break;
  384. case Win64EH::UOP_ClearUnwoundToCall:
  385. Count += 1;
  386. break;
  387. case Win64EH::UOP_PACSignLR:
  388. Count += 1;
  389. break;
  390. case Win64EH::UOP_SaveAnyRegI:
  391. case Win64EH::UOP_SaveAnyRegIP:
  392. case Win64EH::UOP_SaveAnyRegD:
  393. case Win64EH::UOP_SaveAnyRegDP:
  394. case Win64EH::UOP_SaveAnyRegQ:
  395. case Win64EH::UOP_SaveAnyRegQP:
  396. case Win64EH::UOP_SaveAnyRegIX:
  397. case Win64EH::UOP_SaveAnyRegIPX:
  398. case Win64EH::UOP_SaveAnyRegDX:
  399. case Win64EH::UOP_SaveAnyRegDPX:
  400. case Win64EH::UOP_SaveAnyRegQX:
  401. case Win64EH::UOP_SaveAnyRegQPX:
  402. Count += 3;
  403. break;
  404. }
  405. }
  406. return Count;
  407. }
  408. // Unwind opcode encodings and restrictions are documented at
  409. // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
  410. static void ARM64EmitUnwindCode(MCStreamer &streamer,
  411. const WinEH::Instruction &inst) {
  412. uint8_t b, reg;
  413. switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
  414. default:
  415. llvm_unreachable("Unsupported ARM64 unwind code");
  416. case Win64EH::UOP_AllocSmall:
  417. b = (inst.Offset >> 4) & 0x1F;
  418. streamer.emitInt8(b);
  419. break;
  420. case Win64EH::UOP_AllocMedium: {
  421. uint16_t hw = (inst.Offset >> 4) & 0x7FF;
  422. b = 0xC0;
  423. b |= (hw >> 8);
  424. streamer.emitInt8(b);
  425. b = hw & 0xFF;
  426. streamer.emitInt8(b);
  427. break;
  428. }
  429. case Win64EH::UOP_AllocLarge: {
  430. uint32_t w;
  431. b = 0xE0;
  432. streamer.emitInt8(b);
  433. w = inst.Offset >> 4;
  434. b = (w & 0x00FF0000) >> 16;
  435. streamer.emitInt8(b);
  436. b = (w & 0x0000FF00) >> 8;
  437. streamer.emitInt8(b);
  438. b = w & 0x000000FF;
  439. streamer.emitInt8(b);
  440. break;
  441. }
  442. case Win64EH::UOP_SetFP:
  443. b = 0xE1;
  444. streamer.emitInt8(b);
  445. break;
  446. case Win64EH::UOP_AddFP:
  447. b = 0xE2;
  448. streamer.emitInt8(b);
  449. b = (inst.Offset >> 3);
  450. streamer.emitInt8(b);
  451. break;
  452. case Win64EH::UOP_Nop:
  453. b = 0xE3;
  454. streamer.emitInt8(b);
  455. break;
  456. case Win64EH::UOP_SaveR19R20X:
  457. b = 0x20;
  458. b |= (inst.Offset >> 3) & 0x1F;
  459. streamer.emitInt8(b);
  460. break;
  461. case Win64EH::UOP_SaveFPLRX:
  462. b = 0x80;
  463. b |= ((inst.Offset - 1) >> 3) & 0x3F;
  464. streamer.emitInt8(b);
  465. break;
  466. case Win64EH::UOP_SaveFPLR:
  467. b = 0x40;
  468. b |= (inst.Offset >> 3) & 0x3F;
  469. streamer.emitInt8(b);
  470. break;
  471. case Win64EH::UOP_SaveReg:
  472. assert(inst.Register >= 19 && "Saved reg must be >= 19");
  473. reg = inst.Register - 19;
  474. b = 0xD0 | ((reg & 0xC) >> 2);
  475. streamer.emitInt8(b);
  476. b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
  477. streamer.emitInt8(b);
  478. break;
  479. case Win64EH::UOP_SaveRegX:
  480. assert(inst.Register >= 19 && "Saved reg must be >= 19");
  481. reg = inst.Register - 19;
  482. b = 0xD4 | ((reg & 0x8) >> 3);
  483. streamer.emitInt8(b);
  484. b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
  485. streamer.emitInt8(b);
  486. break;
  487. case Win64EH::UOP_SaveRegP:
  488. assert(inst.Register >= 19 && "Saved registers must be >= 19");
  489. reg = inst.Register - 19;
  490. b = 0xC8 | ((reg & 0xC) >> 2);
  491. streamer.emitInt8(b);
  492. b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
  493. streamer.emitInt8(b);
  494. break;
  495. case Win64EH::UOP_SaveRegPX:
  496. assert(inst.Register >= 19 && "Saved registers must be >= 19");
  497. reg = inst.Register - 19;
  498. b = 0xCC | ((reg & 0xC) >> 2);
  499. streamer.emitInt8(b);
  500. b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
  501. streamer.emitInt8(b);
  502. break;
  503. case Win64EH::UOP_SaveLRPair:
  504. assert(inst.Register >= 19 && "Saved reg must be >= 19");
  505. reg = inst.Register - 19;
  506. assert((reg % 2) == 0 && "Saved reg must be 19+2*X");
  507. reg /= 2;
  508. b = 0xD6 | ((reg & 0x7) >> 2);
  509. streamer.emitInt8(b);
  510. b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
  511. streamer.emitInt8(b);
  512. break;
  513. case Win64EH::UOP_SaveFReg:
  514. assert(inst.Register >= 8 && "Saved dreg must be >= 8");
  515. reg = inst.Register - 8;
  516. b = 0xDC | ((reg & 0x4) >> 2);
  517. streamer.emitInt8(b);
  518. b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
  519. streamer.emitInt8(b);
  520. break;
  521. case Win64EH::UOP_SaveFRegX:
  522. assert(inst.Register >= 8 && "Saved dreg must be >= 8");
  523. reg = inst.Register - 8;
  524. b = 0xDE;
  525. streamer.emitInt8(b);
  526. b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
  527. streamer.emitInt8(b);
  528. break;
  529. case Win64EH::UOP_SaveFRegP:
  530. assert(inst.Register >= 8 && "Saved dregs must be >= 8");
  531. reg = inst.Register - 8;
  532. b = 0xD8 | ((reg & 0x4) >> 2);
  533. streamer.emitInt8(b);
  534. b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
  535. streamer.emitInt8(b);
  536. break;
  537. case Win64EH::UOP_SaveFRegPX:
  538. assert(inst.Register >= 8 && "Saved dregs must be >= 8");
  539. reg = inst.Register - 8;
  540. b = 0xDA | ((reg & 0x4) >> 2);
  541. streamer.emitInt8(b);
  542. b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
  543. streamer.emitInt8(b);
  544. break;
  545. case Win64EH::UOP_End:
  546. b = 0xE4;
  547. streamer.emitInt8(b);
  548. break;
  549. case Win64EH::UOP_SaveNext:
  550. b = 0xE6;
  551. streamer.emitInt8(b);
  552. break;
  553. case Win64EH::UOP_TrapFrame:
  554. b = 0xE8;
  555. streamer.emitInt8(b);
  556. break;
  557. case Win64EH::UOP_PushMachFrame:
  558. b = 0xE9;
  559. streamer.emitInt8(b);
  560. break;
  561. case Win64EH::UOP_Context:
  562. b = 0xEA;
  563. streamer.emitInt8(b);
  564. break;
  565. case Win64EH::UOP_ClearUnwoundToCall:
  566. b = 0xEC;
  567. streamer.emitInt8(b);
  568. break;
  569. case Win64EH::UOP_PACSignLR:
  570. b = 0xFC;
  571. streamer.emitInt8(b);
  572. break;
  573. case Win64EH::UOP_SaveAnyRegI:
  574. case Win64EH::UOP_SaveAnyRegIP:
  575. case Win64EH::UOP_SaveAnyRegD:
  576. case Win64EH::UOP_SaveAnyRegDP:
  577. case Win64EH::UOP_SaveAnyRegQ:
  578. case Win64EH::UOP_SaveAnyRegQP:
  579. case Win64EH::UOP_SaveAnyRegIX:
  580. case Win64EH::UOP_SaveAnyRegIPX:
  581. case Win64EH::UOP_SaveAnyRegDX:
  582. case Win64EH::UOP_SaveAnyRegDPX:
  583. case Win64EH::UOP_SaveAnyRegQX:
  584. case Win64EH::UOP_SaveAnyRegQPX: {
  585. // This assumes the opcodes are listed in the enum in a particular order.
  586. int Op = inst.Operation - Win64EH::UOP_SaveAnyRegI;
  587. int Writeback = Op / 6;
  588. int Paired = Op % 2;
  589. int Mode = (Op / 2) % 3;
  590. int Offset = inst.Offset >> 3;
  591. if (Writeback || Paired || Mode == 2)
  592. Offset >>= 1;
  593. if (Writeback)
  594. --Offset;
  595. b = 0xE7;
  596. streamer.emitInt8(b);
  597. assert(inst.Register < 32);
  598. b = inst.Register | (Writeback << 5) | (Paired << 6);
  599. streamer.emitInt8(b);
  600. b = Offset | (Mode << 6);
  601. streamer.emitInt8(b);
  602. break;
  603. }
  604. }
  605. }
  606. // Returns the epilog symbol of an epilog with the exact same unwind code
  607. // sequence, if it exists. Otherwise, returns nullptr.
  608. // EpilogInstrs - Unwind codes for the current epilog.
  609. // Epilogs - Epilogs that potentialy match the current epilog.
  610. static MCSymbol*
  611. FindMatchingEpilog(const std::vector<WinEH::Instruction>& EpilogInstrs,
  612. const std::vector<MCSymbol *>& Epilogs,
  613. const WinEH::FrameInfo *info) {
  614. for (auto *EpilogStart : Epilogs) {
  615. auto InstrsIter = info->EpilogMap.find(EpilogStart);
  616. assert(InstrsIter != info->EpilogMap.end() &&
  617. "Epilog not found in EpilogMap");
  618. const auto &Instrs = InstrsIter->second.Instructions;
  619. if (Instrs.size() != EpilogInstrs.size())
  620. continue;
  621. bool Match = true;
  622. for (unsigned i = 0; i < Instrs.size(); ++i)
  623. if (Instrs[i] != EpilogInstrs[i]) {
  624. Match = false;
  625. break;
  626. }
  627. if (Match)
  628. return EpilogStart;
  629. }
  630. return nullptr;
  631. }
  632. static void simplifyARM64Opcodes(std::vector<WinEH::Instruction> &Instructions,
  633. bool Reverse) {
  634. unsigned PrevOffset = -1;
  635. unsigned PrevRegister = -1;
  636. auto VisitInstruction = [&](WinEH::Instruction &Inst) {
  637. // Convert 2-byte opcodes into equivalent 1-byte ones.
  638. if (Inst.Operation == Win64EH::UOP_SaveRegP && Inst.Register == 29) {
  639. Inst.Operation = Win64EH::UOP_SaveFPLR;
  640. Inst.Register = -1;
  641. } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
  642. Inst.Register == 29) {
  643. Inst.Operation = Win64EH::UOP_SaveFPLRX;
  644. Inst.Register = -1;
  645. } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
  646. Inst.Register == 19 && Inst.Offset <= 248) {
  647. Inst.Operation = Win64EH::UOP_SaveR19R20X;
  648. Inst.Register = -1;
  649. } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {
  650. Inst.Operation = Win64EH::UOP_SetFP;
  651. } else if (Inst.Operation == Win64EH::UOP_SaveRegP &&
  652. Inst.Register == PrevRegister + 2 &&
  653. Inst.Offset == PrevOffset + 16) {
  654. Inst.Operation = Win64EH::UOP_SaveNext;
  655. Inst.Register = -1;
  656. Inst.Offset = 0;
  657. // Intentionally not creating UOP_SaveNext for float register pairs,
  658. // as current versions of Windows (up to at least 20.04) is buggy
  659. // regarding SaveNext for float pairs.
  660. }
  661. // Update info about the previous instruction, for detecting if
  662. // the next one can be made a UOP_SaveNext
  663. if (Inst.Operation == Win64EH::UOP_SaveR19R20X) {
  664. PrevOffset = 0;
  665. PrevRegister = 19;
  666. } else if (Inst.Operation == Win64EH::UOP_SaveRegPX) {
  667. PrevOffset = 0;
  668. PrevRegister = Inst.Register;
  669. } else if (Inst.Operation == Win64EH::UOP_SaveRegP) {
  670. PrevOffset = Inst.Offset;
  671. PrevRegister = Inst.Register;
  672. } else if (Inst.Operation == Win64EH::UOP_SaveNext) {
  673. PrevRegister += 2;
  674. PrevOffset += 16;
  675. } else {
  676. PrevRegister = -1;
  677. PrevOffset = -1;
  678. }
  679. };
  680. // Iterate over instructions in a forward order (for prologues),
  681. // backwards for epilogues (i.e. always reverse compared to how the
  682. // opcodes are stored).
  683. if (Reverse) {
  684. for (auto It = Instructions.rbegin(); It != Instructions.rend(); It++)
  685. VisitInstruction(*It);
  686. } else {
  687. for (WinEH::Instruction &Inst : Instructions)
  688. VisitInstruction(Inst);
  689. }
  690. }
  691. // Check if an epilog exists as a subset of the end of a prolog (backwards).
  692. static int
  693. getARM64OffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
  694. const std::vector<WinEH::Instruction> &Epilog) {
  695. // Can't find an epilog as a subset if it is longer than the prolog.
  696. if (Epilog.size() > Prolog.size())
  697. return -1;
  698. // Check that the epilog actually is a perfect match for the end (backwrds)
  699. // of the prolog.
  700. for (int I = Epilog.size() - 1; I >= 0; I--) {
  701. if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
  702. return -1;
  703. }
  704. if (Epilog.size() == Prolog.size())
  705. return 0;
  706. // If the epilog was a subset of the prolog, find its offset.
  707. return ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction>(
  708. &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
  709. }
  710. static int checkARM64PackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info,
  711. WinEH::FrameInfo::Segment *Seg,
  712. int PrologCodeBytes) {
  713. // Can only pack if there's one single epilog
  714. if (Seg->Epilogs.size() != 1)
  715. return -1;
  716. MCSymbol *Sym = Seg->Epilogs.begin()->first;
  717. const std::vector<WinEH::Instruction> &Epilog =
  718. info->EpilogMap[Sym].Instructions;
  719. // Check that the epilog actually is at the very end of the function,
  720. // otherwise it can't be packed.
  721. uint32_t DistanceFromEnd =
  722. (uint32_t)(Seg->Offset + Seg->Length - Seg->Epilogs.begin()->second);
  723. if (DistanceFromEnd / 4 != Epilog.size())
  724. return -1;
  725. int RetVal = -1;
  726. // Even if we don't end up sharing opcodes with the prolog, we can still
  727. // write the offset as a packed offset, if the single epilog is located at
  728. // the end of the function and the offset (pointing after the prolog) fits
  729. // as a packed offset.
  730. if (PrologCodeBytes <= 31 &&
  731. PrologCodeBytes + ARM64CountOfUnwindCodes(Epilog) <= 124)
  732. RetVal = PrologCodeBytes;
  733. int Offset = getARM64OffsetInProlog(info->Instructions, Epilog);
  734. if (Offset < 0)
  735. return RetVal;
  736. // Check that the offset and prolog size fits in the first word; it's
  737. // unclear whether the epilog count in the extension word can be taken
  738. // as packed epilog offset.
  739. if (Offset > 31 || PrologCodeBytes > 124)
  740. return RetVal;
  741. // As we choose to express the epilog as part of the prolog, remove the
  742. // epilog from the map, so we don't try to emit its opcodes.
  743. info->EpilogMap.erase(Sym);
  744. return Offset;
  745. }
  746. static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
  747. int PackedEpilogOffset) {
  748. if (PackedEpilogOffset == 0) {
  749. // Fully symmetric prolog and epilog, should be ok for packed format.
  750. // For CR=3, the corresponding synthesized epilog actually lacks the
  751. // SetFP opcode, but unwinding should work just fine despite that
  752. // (if at the SetFP opcode, the unwinder considers it as part of the
  753. // function body and just unwinds the full prolog instead).
  754. } else if (PackedEpilogOffset == 1) {
  755. // One single case of differences between prolog and epilog is allowed:
  756. // The epilog can lack a single SetFP that is the last opcode in the
  757. // prolog, for the CR=3 case.
  758. if (info->Instructions.back().Operation != Win64EH::UOP_SetFP)
  759. return false;
  760. } else {
  761. // Too much difference between prolog and epilog.
  762. return false;
  763. }
  764. unsigned RegI = 0, RegF = 0;
  765. int Predecrement = 0;
  766. enum {
  767. Start,
  768. Start2,
  769. Start3,
  770. IntRegs,
  771. FloatRegs,
  772. InputArgs,
  773. StackAdjust,
  774. FrameRecord,
  775. End
  776. } Location = Start;
  777. bool StandaloneLR = false, FPLRPair = false;
  778. bool PAC = false;
  779. int StackOffset = 0;
  780. int Nops = 0;
  781. // Iterate over the prolog and check that all opcodes exactly match
  782. // the canonical order and form. A more lax check could verify that
  783. // all saved registers are in the expected locations, but not enforce
  784. // the order - that would work fine when unwinding from within
  785. // functions, but not be exactly right if unwinding happens within
  786. // prologs/epilogs.
  787. for (const WinEH::Instruction &Inst : info->Instructions) {
  788. switch (Inst.Operation) {
  789. case Win64EH::UOP_End:
  790. if (Location != Start)
  791. return false;
  792. Location = Start2;
  793. break;
  794. case Win64EH::UOP_PACSignLR:
  795. if (Location != Start2)
  796. return false;
  797. PAC = true;
  798. Location = Start3;
  799. break;
  800. case Win64EH::UOP_SaveR19R20X:
  801. if (Location != Start2 && Location != Start3)
  802. return false;
  803. Predecrement = Inst.Offset;
  804. RegI = 2;
  805. Location = IntRegs;
  806. break;
  807. case Win64EH::UOP_SaveRegX:
  808. if (Location != Start2 && Location != Start3)
  809. return false;
  810. Predecrement = Inst.Offset;
  811. if (Inst.Register == 19)
  812. RegI += 1;
  813. else if (Inst.Register == 30)
  814. StandaloneLR = true;
  815. else
  816. return false;
  817. // Odd register; can't be any further int registers.
  818. Location = FloatRegs;
  819. break;
  820. case Win64EH::UOP_SaveRegPX:
  821. // Can't have this in a canonical prologue. Either this has been
  822. // canonicalized into SaveR19R20X or SaveFPLRX, or it's an unsupported
  823. // register pair.
  824. // It can't be canonicalized into SaveR19R20X if the offset is
  825. // larger than 248 bytes, but even with the maximum case with
  826. // RegI=10/RegF=8/CR=1/H=1, we end up with SavSZ = 216, which should
  827. // fit into SaveR19R20X.
  828. // The unwinding opcodes can't describe the otherwise seemingly valid
  829. // case for RegI=1 CR=1, that would start with a
  830. // "stp x19, lr, [sp, #-...]!" as that fits neither SaveRegPX nor
  831. // SaveLRPair.
  832. return false;
  833. case Win64EH::UOP_SaveRegP:
  834. if (Location != IntRegs || Inst.Offset != 8 * RegI ||
  835. Inst.Register != 19 + RegI)
  836. return false;
  837. RegI += 2;
  838. break;
  839. case Win64EH::UOP_SaveReg:
  840. if (Location != IntRegs || Inst.Offset != 8 * RegI)
  841. return false;
  842. if (Inst.Register == 19 + RegI)
  843. RegI += 1;
  844. else if (Inst.Register == 30)
  845. StandaloneLR = true;
  846. else
  847. return false;
  848. // Odd register; can't be any further int registers.
  849. Location = FloatRegs;
  850. break;
  851. case Win64EH::UOP_SaveLRPair:
  852. if (Location != IntRegs || Inst.Offset != 8 * RegI ||
  853. Inst.Register != 19 + RegI)
  854. return false;
  855. RegI += 1;
  856. StandaloneLR = true;
  857. Location = FloatRegs;
  858. break;
  859. case Win64EH::UOP_SaveFRegX:
  860. // Packed unwind can't handle prologs that only save one single
  861. // float register.
  862. return false;
  863. case Win64EH::UOP_SaveFReg:
  864. if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
  865. Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
  866. return false;
  867. RegF += 1;
  868. Location = InputArgs;
  869. break;
  870. case Win64EH::UOP_SaveFRegPX:
  871. if ((Location != Start2 && Location != Start3) || Inst.Register != 8)
  872. return false;
  873. Predecrement = Inst.Offset;
  874. RegF = 2;
  875. Location = FloatRegs;
  876. break;
  877. case Win64EH::UOP_SaveFRegP:
  878. if ((Location != IntRegs && Location != FloatRegs) ||
  879. Inst.Register != 8 + RegF ||
  880. Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
  881. return false;
  882. RegF += 2;
  883. Location = FloatRegs;
  884. break;
  885. case Win64EH::UOP_SaveNext:
  886. if (Location == IntRegs)
  887. RegI += 2;
  888. else if (Location == FloatRegs)
  889. RegF += 2;
  890. else
  891. return false;
  892. break;
  893. case Win64EH::UOP_Nop:
  894. if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
  895. return false;
  896. Location = InputArgs;
  897. Nops++;
  898. break;
  899. case Win64EH::UOP_AllocSmall:
  900. case Win64EH::UOP_AllocMedium:
  901. if (Location != Start2 && Location != Start3 && Location != IntRegs &&
  902. Location != FloatRegs && Location != InputArgs &&
  903. Location != StackAdjust)
  904. return false;
  905. // Can have either a single decrement, or a pair of decrements with
  906. // 4080 and another decrement.
  907. if (StackOffset == 0)
  908. StackOffset = Inst.Offset;
  909. else if (StackOffset != 4080)
  910. return false;
  911. else
  912. StackOffset += Inst.Offset;
  913. Location = StackAdjust;
  914. break;
  915. case Win64EH::UOP_SaveFPLRX:
  916. // Not allowing FPLRX after StackAdjust; if a StackAdjust is used, it
  917. // should be followed by a FPLR instead.
  918. if (Location != Start2 && Location != Start3 && Location != IntRegs &&
  919. Location != FloatRegs && Location != InputArgs)
  920. return false;
  921. StackOffset = Inst.Offset;
  922. Location = FrameRecord;
  923. FPLRPair = true;
  924. break;
  925. case Win64EH::UOP_SaveFPLR:
  926. // This can only follow after a StackAdjust
  927. if (Location != StackAdjust || Inst.Offset != 0)
  928. return false;
  929. Location = FrameRecord;
  930. FPLRPair = true;
  931. break;
  932. case Win64EH::UOP_SetFP:
  933. if (Location != FrameRecord)
  934. return false;
  935. Location = End;
  936. break;
  937. case Win64EH::UOP_SaveAnyRegI:
  938. case Win64EH::UOP_SaveAnyRegIP:
  939. case Win64EH::UOP_SaveAnyRegD:
  940. case Win64EH::UOP_SaveAnyRegDP:
  941. case Win64EH::UOP_SaveAnyRegQ:
  942. case Win64EH::UOP_SaveAnyRegQP:
  943. case Win64EH::UOP_SaveAnyRegIX:
  944. case Win64EH::UOP_SaveAnyRegIPX:
  945. case Win64EH::UOP_SaveAnyRegDX:
  946. case Win64EH::UOP_SaveAnyRegDPX:
  947. case Win64EH::UOP_SaveAnyRegQX:
  948. case Win64EH::UOP_SaveAnyRegQPX:
  949. // These are never canonical; they don't show up with the usual Arm64
  950. // calling convention.
  951. return false;
  952. case Win64EH::UOP_AllocLarge:
  953. // Allocations this large can't be represented in packed unwind (and
  954. // usually don't fit the canonical form anyway because we need to use
  955. // __chkstk to allocate the stack space).
  956. return false;
  957. case Win64EH::UOP_AddFP:
  958. // "add x29, sp, #N" doesn't show up in the canonical pattern (except for
  959. // N=0, which is UOP_SetFP).
  960. return false;
  961. case Win64EH::UOP_TrapFrame:
  962. case Win64EH::UOP_Context:
  963. case Win64EH::UOP_ClearUnwoundToCall:
  964. case Win64EH::UOP_PushMachFrame:
  965. // These are special opcodes that aren't normally generated.
  966. return false;
  967. default:
  968. report_fatal_error("Unknown Arm64 unwind opcode");
  969. }
  970. }
  971. if (RegI > 10 || RegF > 8)
  972. return false;
  973. if (StandaloneLR && FPLRPair)
  974. return false;
  975. if (FPLRPair && Location != End)
  976. return false;
  977. if (Nops != 0 && Nops != 4)
  978. return false;
  979. if (PAC && !FPLRPair)
  980. return false;
  981. int H = Nops == 4;
  982. // There's an inconsistency regarding packed unwind info with homed
  983. // parameters; according to the documentation, the epilog shouldn't have
  984. // the same corresponding nops (and thus, to set the H bit, we should
  985. // require an epilog which isn't exactly symmetrical - we shouldn't accept
  986. // an exact mirrored epilog for those cases), but in practice,
  987. // RtlVirtualUnwind behaves as if it does expect the epilogue to contain
  988. // the same nops. See https://github.com/llvm/llvm-project/issues/54879.
  989. // To play it safe, don't produce packed unwind info with homed parameters.
  990. if (H)
  991. return false;
  992. int IntSZ = 8 * RegI;
  993. if (StandaloneLR)
  994. IntSZ += 8;
  995. int FpSZ = 8 * RegF; // RegF not yet decremented
  996. int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
  997. if (Predecrement != SavSZ)
  998. return false;
  999. if (FPLRPair && StackOffset < 16)
  1000. return false;
  1001. if (StackOffset % 16)
  1002. return false;
  1003. uint32_t FrameSize = (StackOffset + SavSZ) / 16;
  1004. if (FrameSize > 0x1FF)
  1005. return false;
  1006. assert(RegF != 1 && "One single float reg not allowed");
  1007. if (RegF > 0)
  1008. RegF--; // Convert from actual number of registers, to value stored
  1009. assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
  1010. int Flag = 0x01; // Function segments not supported yet
  1011. int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
  1012. info->PackedInfo |= Flag << 0;
  1013. info->PackedInfo |= (FuncLength & 0x7FF) << 2;
  1014. info->PackedInfo |= (RegF & 0x7) << 13;
  1015. info->PackedInfo |= (RegI & 0xF) << 16;
  1016. info->PackedInfo |= (H & 0x1) << 20;
  1017. info->PackedInfo |= (CR & 0x3) << 21;
  1018. info->PackedInfo |= (FrameSize & 0x1FF) << 23;
  1019. return true;
  1020. }
  1021. static void ARM64ProcessEpilogs(WinEH::FrameInfo *info,
  1022. WinEH::FrameInfo::Segment *Seg,
  1023. uint32_t &TotalCodeBytes,
  1024. MapVector<MCSymbol *, uint32_t> &EpilogInfo) {
  1025. std::vector<MCSymbol *> EpilogStarts;
  1026. for (auto &I : Seg->Epilogs)
  1027. EpilogStarts.push_back(I.first);
  1028. // Epilogs processed so far.
  1029. std::vector<MCSymbol *> AddedEpilogs;
  1030. for (auto *S : EpilogStarts) {
  1031. MCSymbol *EpilogStart = S;
  1032. auto &EpilogInstrs = info->EpilogMap[S].Instructions;
  1033. uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs);
  1034. MCSymbol* MatchingEpilog =
  1035. FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
  1036. int PrologOffset;
  1037. if (MatchingEpilog) {
  1038. assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
  1039. "Duplicate epilog not found");
  1040. EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
  1041. // Clear the unwind codes in the EpilogMap, so that they don't get output
  1042. // in ARM64EmitUnwindInfoForSegment().
  1043. EpilogInstrs.clear();
  1044. } else if ((PrologOffset = getARM64OffsetInProlog(info->Instructions,
  1045. EpilogInstrs)) >= 0) {
  1046. EpilogInfo[EpilogStart] = PrologOffset;
  1047. // If the segment doesn't have a prolog, an end_c will be emitted before
  1048. // prolog opcodes. So epilog start index in opcodes array is moved by 1.
  1049. if (!Seg->HasProlog)
  1050. EpilogInfo[EpilogStart] += 1;
  1051. // Clear the unwind codes in the EpilogMap, so that they don't get output
  1052. // in ARM64EmitUnwindInfoForSegment().
  1053. EpilogInstrs.clear();
  1054. } else {
  1055. EpilogInfo[EpilogStart] = TotalCodeBytes;
  1056. TotalCodeBytes += CodeBytes;
  1057. AddedEpilogs.push_back(EpilogStart);
  1058. }
  1059. }
  1060. }
  1061. static void ARM64FindSegmentsInFunction(MCStreamer &streamer,
  1062. WinEH::FrameInfo *info,
  1063. int64_t RawFuncLength) {
  1064. if (info->PrologEnd)
  1065. checkARM64Instructions(streamer, info->Instructions, info->Begin,
  1066. info->PrologEnd, info->Function->getName(),
  1067. "prologue");
  1068. struct EpilogStartEnd {
  1069. MCSymbol *Start;
  1070. int64_t Offset;
  1071. int64_t End;
  1072. };
  1073. // Record Start and End of each epilog.
  1074. SmallVector<struct EpilogStartEnd, 4> Epilogs;
  1075. for (auto &I : info->EpilogMap) {
  1076. MCSymbol *Start = I.first;
  1077. auto &Instrs = I.second.Instructions;
  1078. int64_t Offset = GetAbsDifference(streamer, Start, info->Begin);
  1079. checkARM64Instructions(streamer, Instrs, Start, I.second.End,
  1080. info->Function->getName(), "epilogue");
  1081. assert((Epilogs.size() == 0 || Offset >= Epilogs.back().End) &&
  1082. "Epilogs should be monotonically ordered");
  1083. // Exclue the end opcode from Instrs.size() when calculating the end of the
  1084. // epilog.
  1085. Epilogs.push_back({Start, Offset, Offset + (int64_t)(Instrs.size() - 1) * 4});
  1086. }
  1087. unsigned E = 0;
  1088. int64_t SegLimit = 0xFFFFC;
  1089. int64_t SegOffset = 0;
  1090. if (RawFuncLength > SegLimit) {
  1091. int64_t RemainingLength = RawFuncLength;
  1092. while (RemainingLength > SegLimit) {
  1093. // Try divide the function into segments, requirements:
  1094. // 1. Segment length <= 0xFFFFC;
  1095. // 2. Each Prologue or Epilogue must be fully within a segment.
  1096. int64_t SegLength = SegLimit;
  1097. int64_t SegEnd = SegOffset + SegLength;
  1098. // Keep record on symbols and offsets of epilogs in this segment.
  1099. MapVector<MCSymbol *, int64_t> EpilogsInSegment;
  1100. while (E < Epilogs.size() && Epilogs[E].End < SegEnd) {
  1101. // Epilogs within current segment.
  1102. EpilogsInSegment[Epilogs[E].Start] = Epilogs[E].Offset;
  1103. ++E;
  1104. }
  1105. // At this point, we have:
  1106. // 1. Put all epilogs in segments already. No action needed here; or
  1107. // 2. Found an epilog that will cross segments boundry. We need to
  1108. // move back current segment's end boundry, so the epilog is entirely
  1109. // in the next segment; or
  1110. // 3. Left at least one epilog that is entirely after this segment.
  1111. // It'll be handled by the next iteration, or the last segment.
  1112. if (E < Epilogs.size() && Epilogs[E].Offset <= SegEnd)
  1113. // Move back current Segment's end boundry.
  1114. SegLength = Epilogs[E].Offset - SegOffset;
  1115. auto Seg = WinEH::FrameInfo::Segment(
  1116. SegOffset, SegLength, /* HasProlog */!SegOffset);
  1117. Seg.Epilogs = std::move(EpilogsInSegment);
  1118. info->Segments.push_back(Seg);
  1119. SegOffset += SegLength;
  1120. RemainingLength -= SegLength;
  1121. }
  1122. }
  1123. // Add the last segment when RawFuncLength > 0xFFFFC,
  1124. // or the only segment otherwise.
  1125. auto LastSeg =
  1126. WinEH::FrameInfo::Segment(SegOffset, RawFuncLength - SegOffset,
  1127. /* HasProlog */!SegOffset);
  1128. for (; E < Epilogs.size(); ++E)
  1129. LastSeg.Epilogs[Epilogs[E].Start] = Epilogs[E].Offset;
  1130. info->Segments.push_back(LastSeg);
  1131. }
  1132. static void ARM64EmitUnwindInfoForSegment(MCStreamer &streamer,
  1133. WinEH::FrameInfo *info,
  1134. WinEH::FrameInfo::Segment &Seg,
  1135. bool TryPacked = true) {
  1136. MCContext &context = streamer.getContext();
  1137. MCSymbol *Label = context.createTempSymbol();
  1138. streamer.emitValueToAlignment(Align(4));
  1139. streamer.emitLabel(Label);
  1140. Seg.Symbol = Label;
  1141. // Use the 1st segemnt's label as function's.
  1142. if (Seg.Offset == 0)
  1143. info->Symbol = Label;
  1144. bool HasProlog = Seg.HasProlog;
  1145. bool HasEpilogs = (Seg.Epilogs.size() != 0);
  1146. uint32_t SegLength = (uint32_t)Seg.Length / 4;
  1147. uint32_t PrologCodeBytes = info->PrologCodeBytes;
  1148. int PackedEpilogOffset = HasEpilogs ?
  1149. checkARM64PackedEpilog(streamer, info, &Seg, PrologCodeBytes) : -1;
  1150. // TODO:
  1151. // 1. Enable packed unwind info (.pdata only) for multi-segment functions.
  1152. // 2. Emit packed unwind info (.pdata only) for segments that have neithor
  1153. // prolog nor epilog.
  1154. if (info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
  1155. uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
  1156. !info->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
  1157. // Matching prolog/epilog and no exception handlers; check if the
  1158. // prolog matches the patterns that can be described by the packed
  1159. // format.
  1160. // info->Symbol was already set even if we didn't actually write any
  1161. // unwind info there. Keep using that as indicator that this unwind
  1162. // info has been generated already.
  1163. if (tryARM64PackedUnwind(info, SegLength, PackedEpilogOffset))
  1164. return;
  1165. }
  1166. // If the prolog is not in this segment, we need to emit an end_c, which takes
  1167. // 1 byte, before prolog unwind ops.
  1168. if (!HasProlog) {
  1169. PrologCodeBytes += 1;
  1170. if (PackedEpilogOffset >= 0)
  1171. PackedEpilogOffset += 1;
  1172. // If a segment has neither prolog nor epilog, "With full .xdata record,
  1173. // Epilog Count = 1. Epilog Start Index points to end_c."
  1174. // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#function-fragments
  1175. // TODO: We can remove this if testing shows zero epilog scope is ok with
  1176. // MS unwinder.
  1177. if (!HasEpilogs)
  1178. // Pack the fake epilog into phantom prolog.
  1179. PackedEpilogOffset = 0;
  1180. }
  1181. uint32_t TotalCodeBytes = PrologCodeBytes;
  1182. // Process epilogs.
  1183. MapVector<MCSymbol *, uint32_t> EpilogInfo;
  1184. ARM64ProcessEpilogs(info, &Seg, TotalCodeBytes, EpilogInfo);
  1185. // Code Words, Epilog count, E, X, Vers, Function Length
  1186. uint32_t row1 = 0x0;
  1187. uint32_t CodeWords = TotalCodeBytes / 4;
  1188. uint32_t CodeWordsMod = TotalCodeBytes % 4;
  1189. if (CodeWordsMod)
  1190. CodeWords++;
  1191. uint32_t EpilogCount =
  1192. PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.Epilogs.size();
  1193. bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
  1194. if (!ExtensionWord) {
  1195. row1 |= (EpilogCount & 0x1F) << 22;
  1196. row1 |= (CodeWords & 0x1F) << 27;
  1197. }
  1198. if (info->HandlesExceptions) // X
  1199. row1 |= 1 << 20;
  1200. if (PackedEpilogOffset >= 0) // E
  1201. row1 |= 1 << 21;
  1202. row1 |= SegLength & 0x3FFFF;
  1203. streamer.emitInt32(row1);
  1204. // Extended Code Words, Extended Epilog Count
  1205. if (ExtensionWord) {
  1206. // FIXME: We should be able to split unwind info into multiple sections.
  1207. if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
  1208. report_fatal_error(
  1209. "SEH unwind data splitting is only implemented for large functions, "
  1210. "cases of too many code words or too many epilogs will be done "
  1211. "later");
  1212. uint32_t row2 = 0x0;
  1213. row2 |= (CodeWords & 0xFF) << 16;
  1214. row2 |= (EpilogCount & 0xFFFF);
  1215. streamer.emitInt32(row2);
  1216. }
  1217. if (PackedEpilogOffset < 0) {
  1218. // Epilog Start Index, Epilog Start Offset
  1219. for (auto &I : EpilogInfo) {
  1220. MCSymbol *EpilogStart = I.first;
  1221. uint32_t EpilogIndex = I.second;
  1222. // Epilog offset within the Segment.
  1223. uint32_t EpilogOffset = (uint32_t)(Seg.Epilogs[EpilogStart] - Seg.Offset);
  1224. if (EpilogOffset)
  1225. EpilogOffset /= 4;
  1226. uint32_t row3 = EpilogOffset;
  1227. row3 |= (EpilogIndex & 0x3FF) << 22;
  1228. streamer.emitInt32(row3);
  1229. }
  1230. }
  1231. // Note that even for segments that have no prolog, we still need to emit
  1232. // prolog unwinding opcodes so that the unwinder knows how to unwind from
  1233. // such a segment.
  1234. // The end_c opcode at the start indicates to the unwinder that the actual
  1235. // prolog is outside of the current segment, and the unwinder shouldn't try
  1236. // to check for unwinding from a partial prolog.
  1237. if (!HasProlog)
  1238. // Emit an end_c.
  1239. streamer.emitInt8((uint8_t)0xE5);
  1240. // Emit prolog unwind instructions (in reverse order).
  1241. for (auto Inst : llvm::reverse(info->Instructions))
  1242. ARM64EmitUnwindCode(streamer, Inst);
  1243. // Emit epilog unwind instructions
  1244. for (auto &I : Seg.Epilogs) {
  1245. auto &EpilogInstrs = info->EpilogMap[I.first].Instructions;
  1246. for (const WinEH::Instruction &inst : EpilogInstrs)
  1247. ARM64EmitUnwindCode(streamer, inst);
  1248. }
  1249. int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
  1250. assert(BytesMod >= 0);
  1251. for (int i = 0; i < BytesMod; i++)
  1252. streamer.emitInt8(0xE3);
  1253. if (info->HandlesExceptions)
  1254. streamer.emitValue(
  1255. MCSymbolRefExpr::create(info->ExceptionHandler,
  1256. MCSymbolRefExpr::VK_COFF_IMGREL32, context),
  1257. 4);
  1258. }
  1259. // Populate the .xdata section. The format of .xdata on ARM64 is documented at
  1260. // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
  1261. static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info,
  1262. bool TryPacked = true) {
  1263. // If this UNWIND_INFO already has a symbol, it's already been emitted.
  1264. if (info->Symbol)
  1265. return;
  1266. // If there's no unwind info here (not even a terminating UOP_End), the
  1267. // unwind info is considered bogus and skipped. If this was done in
  1268. // response to an explicit .seh_handlerdata, the associated trailing
  1269. // handler data is left orphaned in the xdata section.
  1270. if (info->empty()) {
  1271. info->EmitAttempted = true;
  1272. return;
  1273. }
  1274. if (info->EmitAttempted) {
  1275. // If we tried to emit unwind info before (due to an explicit
  1276. // .seh_handlerdata directive), but skipped it (because there was no
  1277. // valid information to emit at the time), and it later got valid unwind
  1278. // opcodes, we can't emit it here, because the trailing handler data
  1279. // was already emitted elsewhere in the xdata section.
  1280. streamer.getContext().reportError(
  1281. SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
  1282. " skipped due to no unwind info at the time "
  1283. "(.seh_handlerdata too early?), but the function later "
  1284. "did get unwind info that can't be emitted");
  1285. return;
  1286. }
  1287. simplifyARM64Opcodes(info->Instructions, false);
  1288. for (auto &I : info->EpilogMap)
  1289. simplifyARM64Opcodes(I.second.Instructions, true);
  1290. int64_t RawFuncLength;
  1291. if (!info->FuncletOrFuncEnd) {
  1292. report_fatal_error("FuncletOrFuncEnd not set");
  1293. } else {
  1294. // FIXME: GetAbsDifference tries to compute the length of the function
  1295. // immediately, before the whole file is emitted, but in general
  1296. // that's impossible: the size in bytes of certain assembler directives
  1297. // like .align and .fill is not known until the whole file is parsed and
  1298. // relaxations are applied. Currently, GetAbsDifference fails with a fatal
  1299. // error in that case. (We mostly don't hit this because inline assembly
  1300. // specifying those directives is rare, and we don't normally try to
  1301. // align loops on AArch64.)
  1302. //
  1303. // There are two potential approaches to delaying the computation. One,
  1304. // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000",
  1305. // as long as we have some conservative estimate we could use to prove
  1306. // that we don't need to split the unwind data. Emitting the constant
  1307. // is straightforward, but there's no existing code for estimating the
  1308. // size of the function.
  1309. //
  1310. // The other approach would be to use a dedicated, relaxable fragment,
  1311. // which could grow to accommodate splitting the unwind data if
  1312. // necessary. This is more straightforward, since it automatically works
  1313. // without any new infrastructure, and it's consistent with how we handle
  1314. // relaxation in other contexts. But it would require some refactoring
  1315. // to move parts of the pdata/xdata emission into the implementation of
  1316. // a fragment. We could probably continue to encode the unwind codes
  1317. // here, but we'd have to emit the pdata, the xdata header, and the
  1318. // epilogue scopes later, since they depend on whether the we need to
  1319. // split the unwind data.
  1320. RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd,
  1321. info->Begin);
  1322. }
  1323. ARM64FindSegmentsInFunction(streamer, info, RawFuncLength);
  1324. info->PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
  1325. for (auto &S : info->Segments)
  1326. ARM64EmitUnwindInfoForSegment(streamer, info, S, TryPacked);
  1327. // Clear prolog instructions after unwind info is emitted for all segments.
  1328. info->Instructions.clear();
  1329. }
  1330. static uint32_t ARMCountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
  1331. uint32_t Count = 0;
  1332. for (const auto &I : Insns) {
  1333. switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
  1334. default:
  1335. llvm_unreachable("Unsupported ARM unwind code");
  1336. case Win64EH::UOP_AllocSmall:
  1337. Count += 1;
  1338. break;
  1339. case Win64EH::UOP_AllocLarge:
  1340. Count += 3;
  1341. break;
  1342. case Win64EH::UOP_AllocHuge:
  1343. Count += 4;
  1344. break;
  1345. case Win64EH::UOP_WideAllocMedium:
  1346. Count += 2;
  1347. break;
  1348. case Win64EH::UOP_WideAllocLarge:
  1349. Count += 3;
  1350. break;
  1351. case Win64EH::UOP_WideAllocHuge:
  1352. Count += 4;
  1353. break;
  1354. case Win64EH::UOP_WideSaveRegMask:
  1355. Count += 2;
  1356. break;
  1357. case Win64EH::UOP_SaveSP:
  1358. Count += 1;
  1359. break;
  1360. case Win64EH::UOP_SaveRegsR4R7LR:
  1361. Count += 1;
  1362. break;
  1363. case Win64EH::UOP_WideSaveRegsR4R11LR:
  1364. Count += 1;
  1365. break;
  1366. case Win64EH::UOP_SaveFRegD8D15:
  1367. Count += 1;
  1368. break;
  1369. case Win64EH::UOP_SaveRegMask:
  1370. Count += 2;
  1371. break;
  1372. case Win64EH::UOP_SaveLR:
  1373. Count += 2;
  1374. break;
  1375. case Win64EH::UOP_SaveFRegD0D15:
  1376. Count += 2;
  1377. break;
  1378. case Win64EH::UOP_SaveFRegD16D31:
  1379. Count += 2;
  1380. break;
  1381. case Win64EH::UOP_Nop:
  1382. case Win64EH::UOP_WideNop:
  1383. case Win64EH::UOP_End:
  1384. case Win64EH::UOP_EndNop:
  1385. case Win64EH::UOP_WideEndNop:
  1386. Count += 1;
  1387. break;
  1388. case Win64EH::UOP_Custom: {
  1389. int J;
  1390. for (J = 3; J > 0; J--)
  1391. if (I.Offset & (0xffu << (8 * J)))
  1392. break;
  1393. Count += J + 1;
  1394. break;
  1395. }
  1396. }
  1397. }
  1398. return Count;
  1399. }
  1400. static uint32_t ARMCountOfInstructionBytes(ArrayRef<WinEH::Instruction> Insns,
  1401. bool *HasCustom = nullptr) {
  1402. uint32_t Count = 0;
  1403. for (const auto &I : Insns) {
  1404. switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
  1405. default:
  1406. llvm_unreachable("Unsupported ARM unwind code");
  1407. case Win64EH::UOP_AllocSmall:
  1408. case Win64EH::UOP_AllocLarge:
  1409. case Win64EH::UOP_AllocHuge:
  1410. Count += 2;
  1411. break;
  1412. case Win64EH::UOP_WideAllocMedium:
  1413. case Win64EH::UOP_WideAllocLarge:
  1414. case Win64EH::UOP_WideAllocHuge:
  1415. Count += 4;
  1416. break;
  1417. case Win64EH::UOP_WideSaveRegMask:
  1418. case Win64EH::UOP_WideSaveRegsR4R11LR:
  1419. Count += 4;
  1420. break;
  1421. case Win64EH::UOP_SaveSP:
  1422. Count += 2;
  1423. break;
  1424. case Win64EH::UOP_SaveRegMask:
  1425. case Win64EH::UOP_SaveRegsR4R7LR:
  1426. Count += 2;
  1427. break;
  1428. case Win64EH::UOP_SaveFRegD8D15:
  1429. case Win64EH::UOP_SaveFRegD0D15:
  1430. case Win64EH::UOP_SaveFRegD16D31:
  1431. Count += 4;
  1432. break;
  1433. case Win64EH::UOP_SaveLR:
  1434. Count += 4;
  1435. break;
  1436. case Win64EH::UOP_Nop:
  1437. case Win64EH::UOP_EndNop:
  1438. Count += 2;
  1439. break;
  1440. case Win64EH::UOP_WideNop:
  1441. case Win64EH::UOP_WideEndNop:
  1442. Count += 4;
  1443. break;
  1444. case Win64EH::UOP_End:
  1445. // This doesn't map to any instruction
  1446. break;
  1447. case Win64EH::UOP_Custom:
  1448. // We can't reason about what instructions this maps to; return a
  1449. // phony number to make sure we don't accidentally do epilog packing.
  1450. Count += 1000;
  1451. if (HasCustom)
  1452. *HasCustom = true;
  1453. break;
  1454. }
  1455. }
  1456. return Count;
  1457. }
  1458. static void checkARMInstructions(MCStreamer &Streamer,
  1459. ArrayRef<WinEH::Instruction> Insns,
  1460. const MCSymbol *Begin, const MCSymbol *End,
  1461. StringRef Name, StringRef Type) {
  1462. if (!End)
  1463. return;
  1464. std::optional<int64_t> MaybeDistance =
  1465. GetOptionalAbsDifference(Streamer, End, Begin);
  1466. if (!MaybeDistance)
  1467. return;
  1468. uint32_t Distance = (uint32_t)*MaybeDistance;
  1469. bool HasCustom = false;
  1470. uint32_t InstructionBytes = ARMCountOfInstructionBytes(Insns, &HasCustom);
  1471. if (HasCustom)
  1472. return;
  1473. if (Distance != InstructionBytes) {
  1474. Streamer.getContext().reportError(
  1475. SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
  1476. Twine(Distance) +
  1477. " bytes of instructions in range, but .seh directives "
  1478. "corresponding to " +
  1479. Twine(InstructionBytes) + " bytes\n");
  1480. }
  1481. }
  1482. static bool isARMTerminator(const WinEH::Instruction &inst) {
  1483. switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
  1484. case Win64EH::UOP_End:
  1485. case Win64EH::UOP_EndNop:
  1486. case Win64EH::UOP_WideEndNop:
  1487. return true;
  1488. default:
  1489. return false;
  1490. }
  1491. }
  1492. // Unwind opcode encodings and restrictions are documented at
  1493. // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
  1494. static void ARMEmitUnwindCode(MCStreamer &streamer,
  1495. const WinEH::Instruction &inst) {
  1496. uint32_t w, lr;
  1497. int i;
  1498. switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
  1499. default:
  1500. llvm_unreachable("Unsupported ARM unwind code");
  1501. case Win64EH::UOP_AllocSmall:
  1502. assert((inst.Offset & 3) == 0);
  1503. assert(inst.Offset / 4 <= 0x7f);
  1504. streamer.emitInt8(inst.Offset / 4);
  1505. break;
  1506. case Win64EH::UOP_WideSaveRegMask:
  1507. assert((inst.Register & ~0x5fff) == 0);
  1508. lr = (inst.Register >> 14) & 1;
  1509. w = 0x8000 | (inst.Register & 0x1fff) | (lr << 13);
  1510. streamer.emitInt8((w >> 8) & 0xff);
  1511. streamer.emitInt8((w >> 0) & 0xff);
  1512. break;
  1513. case Win64EH::UOP_SaveSP:
  1514. assert(inst.Register <= 0x0f);
  1515. streamer.emitInt8(0xc0 | inst.Register);
  1516. break;
  1517. case Win64EH::UOP_SaveRegsR4R7LR:
  1518. assert(inst.Register >= 4 && inst.Register <= 7);
  1519. assert(inst.Offset <= 1);
  1520. streamer.emitInt8(0xd0 | (inst.Register - 4) | (inst.Offset << 2));
  1521. break;
  1522. case Win64EH::UOP_WideSaveRegsR4R11LR:
  1523. assert(inst.Register >= 8 && inst.Register <= 11);
  1524. assert(inst.Offset <= 1);
  1525. streamer.emitInt8(0xd8 | (inst.Register - 8) | (inst.Offset << 2));
  1526. break;
  1527. case Win64EH::UOP_SaveFRegD8D15:
  1528. assert(inst.Register >= 8 && inst.Register <= 15);
  1529. streamer.emitInt8(0xe0 | (inst.Register - 8));
  1530. break;
  1531. case Win64EH::UOP_WideAllocMedium:
  1532. assert((inst.Offset & 3) == 0);
  1533. assert(inst.Offset / 4 <= 0x3ff);
  1534. w = 0xe800 | (inst.Offset / 4);
  1535. streamer.emitInt8((w >> 8) & 0xff);
  1536. streamer.emitInt8((w >> 0) & 0xff);
  1537. break;
  1538. case Win64EH::UOP_SaveRegMask:
  1539. assert((inst.Register & ~0x40ff) == 0);
  1540. lr = (inst.Register >> 14) & 1;
  1541. w = 0xec00 | (inst.Register & 0x0ff) | (lr << 8);
  1542. streamer.emitInt8((w >> 8) & 0xff);
  1543. streamer.emitInt8((w >> 0) & 0xff);
  1544. break;
  1545. case Win64EH::UOP_SaveLR:
  1546. assert((inst.Offset & 3) == 0);
  1547. assert(inst.Offset / 4 <= 0x0f);
  1548. streamer.emitInt8(0xef);
  1549. streamer.emitInt8(inst.Offset / 4);
  1550. break;
  1551. case Win64EH::UOP_SaveFRegD0D15:
  1552. assert(inst.Register <= 15);
  1553. assert(inst.Offset <= 15);
  1554. assert(inst.Register <= inst.Offset);
  1555. streamer.emitInt8(0xf5);
  1556. streamer.emitInt8((inst.Register << 4) | inst.Offset);
  1557. break;
  1558. case Win64EH::UOP_SaveFRegD16D31:
  1559. assert(inst.Register >= 16 && inst.Register <= 31);
  1560. assert(inst.Offset >= 16 && inst.Offset <= 31);
  1561. assert(inst.Register <= inst.Offset);
  1562. streamer.emitInt8(0xf6);
  1563. streamer.emitInt8(((inst.Register - 16) << 4) | (inst.Offset - 16));
  1564. break;
  1565. case Win64EH::UOP_AllocLarge:
  1566. assert((inst.Offset & 3) == 0);
  1567. assert(inst.Offset / 4 <= 0xffff);
  1568. w = inst.Offset / 4;
  1569. streamer.emitInt8(0xf7);
  1570. streamer.emitInt8((w >> 8) & 0xff);
  1571. streamer.emitInt8((w >> 0) & 0xff);
  1572. break;
  1573. case Win64EH::UOP_AllocHuge:
  1574. assert((inst.Offset & 3) == 0);
  1575. assert(inst.Offset / 4 <= 0xffffff);
  1576. w = inst.Offset / 4;
  1577. streamer.emitInt8(0xf8);
  1578. streamer.emitInt8((w >> 16) & 0xff);
  1579. streamer.emitInt8((w >> 8) & 0xff);
  1580. streamer.emitInt8((w >> 0) & 0xff);
  1581. break;
  1582. case Win64EH::UOP_WideAllocLarge:
  1583. assert((inst.Offset & 3) == 0);
  1584. assert(inst.Offset / 4 <= 0xffff);
  1585. w = inst.Offset / 4;
  1586. streamer.emitInt8(0xf9);
  1587. streamer.emitInt8((w >> 8) & 0xff);
  1588. streamer.emitInt8((w >> 0) & 0xff);
  1589. break;
  1590. case Win64EH::UOP_WideAllocHuge:
  1591. assert((inst.Offset & 3) == 0);
  1592. assert(inst.Offset / 4 <= 0xffffff);
  1593. w = inst.Offset / 4;
  1594. streamer.emitInt8(0xfa);
  1595. streamer.emitInt8((w >> 16) & 0xff);
  1596. streamer.emitInt8((w >> 8) & 0xff);
  1597. streamer.emitInt8((w >> 0) & 0xff);
  1598. break;
  1599. case Win64EH::UOP_Nop:
  1600. streamer.emitInt8(0xfb);
  1601. break;
  1602. case Win64EH::UOP_WideNop:
  1603. streamer.emitInt8(0xfc);
  1604. break;
  1605. case Win64EH::UOP_EndNop:
  1606. streamer.emitInt8(0xfd);
  1607. break;
  1608. case Win64EH::UOP_WideEndNop:
  1609. streamer.emitInt8(0xfe);
  1610. break;
  1611. case Win64EH::UOP_End:
  1612. streamer.emitInt8(0xff);
  1613. break;
  1614. case Win64EH::UOP_Custom:
  1615. for (i = 3; i > 0; i--)
  1616. if (inst.Offset & (0xffu << (8 * i)))
  1617. break;
  1618. for (; i >= 0; i--)
  1619. streamer.emitInt8((inst.Offset >> (8 * i)) & 0xff);
  1620. break;
  1621. }
  1622. }
  1623. // Check if an epilog exists as a subset of the end of a prolog (backwards).
  1624. // An epilog may end with one out of three different end opcodes; if this
  1625. // is the first epilog that shares opcodes with the prolog, we can tolerate
  1626. // that this opcode differs (and the caller will update the prolog to use
  1627. // the same end opcode as the epilog). If another epilog already shares
  1628. // opcodes with the prolog, the ending opcode must be a strict match.
  1629. static int getARMOffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
  1630. const std::vector<WinEH::Instruction> &Epilog,
  1631. bool CanTweakProlog) {
  1632. // Can't find an epilog as a subset if it is longer than the prolog.
  1633. if (Epilog.size() > Prolog.size())
  1634. return -1;
  1635. // Check that the epilog actually is a perfect match for the end (backwrds)
  1636. // of the prolog.
  1637. // If we can adjust the prolog afterwards, don't check that the end opcodes
  1638. // match.
  1639. int EndIdx = CanTweakProlog ? 1 : 0;
  1640. for (int I = Epilog.size() - 1; I >= EndIdx; I--) {
  1641. // TODO: Could also allow minor mismatches, e.g. "add sp, #16" vs
  1642. // "push {r0-r3}".
  1643. if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
  1644. return -1;
  1645. }
  1646. if (CanTweakProlog) {
  1647. // Check that both prolog and epilog end with an expected end opcode.
  1648. if (Prolog.front().Operation != Win64EH::UOP_End)
  1649. return -1;
  1650. if (Epilog.back().Operation != Win64EH::UOP_End &&
  1651. Epilog.back().Operation != Win64EH::UOP_EndNop &&
  1652. Epilog.back().Operation != Win64EH::UOP_WideEndNop)
  1653. return -1;
  1654. }
  1655. // If the epilog was a subset of the prolog, find its offset.
  1656. if (Epilog.size() == Prolog.size())
  1657. return 0;
  1658. return ARMCountOfUnwindCodes(ArrayRef<WinEH::Instruction>(
  1659. &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
  1660. }
  1661. static int checkARMPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info,
  1662. int PrologCodeBytes) {
  1663. // Can only pack if there's one single epilog
  1664. if (info->EpilogMap.size() != 1)
  1665. return -1;
  1666. const WinEH::FrameInfo::Epilog &EpilogInfo = info->EpilogMap.begin()->second;
  1667. // Can only pack if the epilog is unconditional
  1668. if (EpilogInfo.Condition != 0xe) // ARMCC::AL
  1669. return -1;
  1670. const std::vector<WinEH::Instruction> &Epilog = EpilogInfo.Instructions;
  1671. // Make sure we have at least the trailing end opcode
  1672. if (info->Instructions.empty() || Epilog.empty())
  1673. return -1;
  1674. // Check that the epilog actually is at the very end of the function,
  1675. // otherwise it can't be packed.
  1676. std::optional<int64_t> MaybeDistance = GetOptionalAbsDifference(
  1677. streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
  1678. if (!MaybeDistance)
  1679. return -1;
  1680. uint32_t DistanceFromEnd = (uint32_t)*MaybeDistance;
  1681. uint32_t InstructionBytes = ARMCountOfInstructionBytes(Epilog);
  1682. if (DistanceFromEnd != InstructionBytes)
  1683. return -1;
  1684. int RetVal = -1;
  1685. // Even if we don't end up sharing opcodes with the prolog, we can still
  1686. // write the offset as a packed offset, if the single epilog is located at
  1687. // the end of the function and the offset (pointing after the prolog) fits
  1688. // as a packed offset.
  1689. if (PrologCodeBytes <= 31 &&
  1690. PrologCodeBytes + ARMCountOfUnwindCodes(Epilog) <= 63)
  1691. RetVal = PrologCodeBytes;
  1692. int Offset =
  1693. getARMOffsetInProlog(info->Instructions, Epilog, /*CanTweakProlog=*/true);
  1694. if (Offset < 0)
  1695. return RetVal;
  1696. // Check that the offset and prolog size fits in the first word; it's
  1697. // unclear whether the epilog count in the extension word can be taken
  1698. // as packed epilog offset.
  1699. if (Offset > 31 || PrologCodeBytes > 63)
  1700. return RetVal;
  1701. // Replace the regular end opcode of the prolog with the one from the
  1702. // epilog.
  1703. info->Instructions.front() = Epilog.back();
  1704. // As we choose to express the epilog as part of the prolog, remove the
  1705. // epilog from the map, so we don't try to emit its opcodes.
  1706. info->EpilogMap.clear();
  1707. return Offset;
  1708. }
  1709. static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11,
  1710. unsigned &Folded, int &IntRegs) {
  1711. if (Mask & (1 << 14)) {
  1712. HasLR = true;
  1713. Mask &= ~(1 << 14);
  1714. }
  1715. if (Mask & (1 << 11)) {
  1716. HasR11 = true;
  1717. Mask &= ~(1 << 11);
  1718. }
  1719. Folded = 0;
  1720. IntRegs = -1;
  1721. if (!Mask)
  1722. return true;
  1723. int First = 0;
  1724. // Shift right until we have the bits at the bottom
  1725. while ((Mask & 1) == 0) {
  1726. First++;
  1727. Mask >>= 1;
  1728. }
  1729. if ((Mask & (Mask + 1)) != 0)
  1730. return false; // Not a consecutive series of bits? Can't be packed.
  1731. // Count the bits
  1732. int N = 0;
  1733. while (Mask & (1 << N))
  1734. N++;
  1735. if (First < 4) {
  1736. if (First + N < 4)
  1737. return false;
  1738. Folded = 4 - First;
  1739. N -= Folded;
  1740. First = 4;
  1741. }
  1742. if (First > 4)
  1743. return false; // Can't be packed
  1744. if (N >= 1)
  1745. IntRegs = N - 1;
  1746. return true;
  1747. }
  1748. static bool tryARMPackedUnwind(MCStreamer &streamer, WinEH::FrameInfo *info,
  1749. uint32_t FuncLength) {
  1750. int Step = 0;
  1751. bool Homing = false;
  1752. bool HasR11 = false;
  1753. bool HasChain = false;
  1754. bool HasLR = false;
  1755. int IntRegs = -1; // r4 - r(4+N)
  1756. int FloatRegs = -1; // d8 - d(8+N)
  1757. unsigned PF = 0; // Number of extra pushed registers
  1758. unsigned StackAdjust = 0;
  1759. // Iterate over the prolog and check that all opcodes exactly match
  1760. // the canonical order and form.
  1761. for (const WinEH::Instruction &Inst : info->Instructions) {
  1762. switch (Inst.Operation) {
  1763. default:
  1764. llvm_unreachable("Unsupported ARM unwind code");
  1765. case Win64EH::UOP_Custom:
  1766. case Win64EH::UOP_AllocLarge:
  1767. case Win64EH::UOP_AllocHuge:
  1768. case Win64EH::UOP_WideAllocLarge:
  1769. case Win64EH::UOP_WideAllocHuge:
  1770. case Win64EH::UOP_SaveFRegD0D15:
  1771. case Win64EH::UOP_SaveFRegD16D31:
  1772. // Can't be packed
  1773. return false;
  1774. case Win64EH::UOP_SaveSP:
  1775. // Can't be packed; we can't rely on restoring sp from r11 when
  1776. // unwinding a packed prologue.
  1777. return false;
  1778. case Win64EH::UOP_SaveLR:
  1779. // Can't be present in a packed prologue
  1780. return false;
  1781. case Win64EH::UOP_End:
  1782. case Win64EH::UOP_EndNop:
  1783. case Win64EH::UOP_WideEndNop:
  1784. if (Step != 0)
  1785. return false;
  1786. Step = 1;
  1787. break;
  1788. case Win64EH::UOP_SaveRegsR4R7LR:
  1789. case Win64EH::UOP_WideSaveRegsR4R11LR:
  1790. // push {r4-r11,lr}
  1791. if (Step != 1 && Step != 2)
  1792. return false;
  1793. assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
  1794. assert(Inst.Offset <= 1); // Lr
  1795. IntRegs = Inst.Register - 4;
  1796. if (Inst.Register == 11) {
  1797. HasR11 = true;
  1798. IntRegs--;
  1799. }
  1800. if (Inst.Offset)
  1801. HasLR = true;
  1802. Step = 3;
  1803. break;
  1804. case Win64EH::UOP_SaveRegMask:
  1805. if (Step == 1 && Inst.Register == 0x0f) {
  1806. // push {r0-r3}
  1807. Homing = true;
  1808. Step = 2;
  1809. break;
  1810. }
  1811. [[fallthrough]];
  1812. case Win64EH::UOP_WideSaveRegMask:
  1813. if (Step != 1 && Step != 2)
  1814. return false;
  1815. // push {r4-r9,r11,lr}
  1816. // push {r11,lr}
  1817. // push {r1-r5}
  1818. if (!parseRegMask(Inst.Register, HasLR, HasR11, PF, IntRegs))
  1819. return false;
  1820. Step = 3;
  1821. break;
  1822. case Win64EH::UOP_Nop:
  1823. // mov r11, sp
  1824. if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)
  1825. return false;
  1826. HasChain = true;
  1827. Step = 4;
  1828. break;
  1829. case Win64EH::UOP_WideNop:
  1830. // add.w r11, sp, #xx
  1831. if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))
  1832. return false;
  1833. HasChain = true;
  1834. Step = 4;
  1835. break;
  1836. case Win64EH::UOP_SaveFRegD8D15:
  1837. if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
  1838. return false;
  1839. assert(Inst.Register >= 8 && Inst.Register <= 15);
  1840. if (Inst.Register == 15)
  1841. return false; // Can't pack this case, R==7 means no IntRegs
  1842. if (IntRegs >= 0)
  1843. return false;
  1844. FloatRegs = Inst.Register - 8;
  1845. Step = 5;
  1846. break;
  1847. case Win64EH::UOP_AllocSmall:
  1848. case Win64EH::UOP_WideAllocMedium:
  1849. if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
  1850. return false;
  1851. if (PF > 0) // Can't have both folded and explicit stack allocation
  1852. return false;
  1853. if (Inst.Offset / 4 >= 0x3f4)
  1854. return false;
  1855. StackAdjust = Inst.Offset / 4;
  1856. Step = 6;
  1857. break;
  1858. }
  1859. }
  1860. if (HasR11 && !HasChain) {
  1861. if (IntRegs + 4 == 10) {
  1862. // r11 stored, but not chaining; can be packed if already saving r4-r10
  1863. // and we can fit r11 into this range.
  1864. IntRegs++;
  1865. HasR11 = false;
  1866. } else
  1867. return false;
  1868. }
  1869. if (HasChain && !HasLR)
  1870. return false;
  1871. // Packed uneind info can't express multiple epilogues.
  1872. if (info->EpilogMap.size() > 1)
  1873. return false;
  1874. unsigned EF = 0;
  1875. int Ret = 0;
  1876. if (info->EpilogMap.size() == 0) {
  1877. Ret = 3; // No epilogue
  1878. } else {
  1879. // As the prologue and epilogue aren't exact mirrors of each other,
  1880. // we have to check the epilogue too and see if it matches what we've
  1881. // concluded from the prologue.
  1882. const WinEH::FrameInfo::Epilog &EpilogInfo =
  1883. info->EpilogMap.begin()->second;
  1884. if (EpilogInfo.Condition != 0xe) // ARMCC::AL
  1885. return false;
  1886. const std::vector<WinEH::Instruction> &Epilog = EpilogInfo.Instructions;
  1887. std::optional<int64_t> MaybeDistance = GetOptionalAbsDifference(
  1888. streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
  1889. if (!MaybeDistance)
  1890. return false;
  1891. uint32_t DistanceFromEnd = (uint32_t)*MaybeDistance;
  1892. uint32_t InstructionBytes = ARMCountOfInstructionBytes(Epilog);
  1893. if (DistanceFromEnd != InstructionBytes)
  1894. return false;
  1895. bool GotStackAdjust = false;
  1896. bool GotFloatRegs = false;
  1897. bool GotIntRegs = false;
  1898. bool GotHomingRestore = false;
  1899. bool GotLRRestore = false;
  1900. bool NeedsReturn = false;
  1901. bool GotReturn = false;
  1902. Step = 6;
  1903. for (const WinEH::Instruction &Inst : Epilog) {
  1904. switch (Inst.Operation) {
  1905. default:
  1906. llvm_unreachable("Unsupported ARM unwind code");
  1907. case Win64EH::UOP_Custom:
  1908. case Win64EH::UOP_AllocLarge:
  1909. case Win64EH::UOP_AllocHuge:
  1910. case Win64EH::UOP_WideAllocLarge:
  1911. case Win64EH::UOP_WideAllocHuge:
  1912. case Win64EH::UOP_SaveFRegD0D15:
  1913. case Win64EH::UOP_SaveFRegD16D31:
  1914. case Win64EH::UOP_SaveSP:
  1915. case Win64EH::UOP_Nop:
  1916. case Win64EH::UOP_WideNop:
  1917. // Can't be packed in an epilogue
  1918. return false;
  1919. case Win64EH::UOP_AllocSmall:
  1920. case Win64EH::UOP_WideAllocMedium:
  1921. if (Inst.Offset / 4 >= 0x3f4)
  1922. return false;
  1923. if (Step == 6) {
  1924. if (Homing && FloatRegs < 0 && IntRegs < 0 && StackAdjust == 0 &&
  1925. PF == 0 && Inst.Offset == 16) {
  1926. GotHomingRestore = true;
  1927. Step = 10;
  1928. } else {
  1929. if (StackAdjust > 0) {
  1930. // Got stack adjust in prologue too; must match.
  1931. if (StackAdjust != Inst.Offset / 4)
  1932. return false;
  1933. GotStackAdjust = true;
  1934. } else if (PF == Inst.Offset / 4) {
  1935. // Folded prologue, non-folded epilogue
  1936. StackAdjust = Inst.Offset / 4;
  1937. GotStackAdjust = true;
  1938. } else {
  1939. // StackAdjust == 0 in prologue, mismatch
  1940. return false;
  1941. }
  1942. Step = 7;
  1943. }
  1944. } else if (Step == 7 || Step == 8 || Step == 9) {
  1945. if (!Homing || Inst.Offset != 16)
  1946. return false;
  1947. GotHomingRestore = true;
  1948. Step = 10;
  1949. } else
  1950. return false;
  1951. break;
  1952. case Win64EH::UOP_SaveFRegD8D15:
  1953. if (Step != 6 && Step != 7)
  1954. return false;
  1955. assert(Inst.Register >= 8 && Inst.Register <= 15);
  1956. if (FloatRegs != (int)(Inst.Register - 8))
  1957. return false;
  1958. GotFloatRegs = true;
  1959. Step = 8;
  1960. break;
  1961. case Win64EH::UOP_SaveRegsR4R7LR:
  1962. case Win64EH::UOP_WideSaveRegsR4R11LR: {
  1963. // push {r4-r11,lr}
  1964. if (Step != 6 && Step != 7 && Step != 8)
  1965. return false;
  1966. assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
  1967. assert(Inst.Offset <= 1); // Lr
  1968. if (Homing && HasLR) {
  1969. // If homing and LR is backed up, we can either restore LR here
  1970. // and return with Ret == 1 or 2, or return with SaveLR below
  1971. if (Inst.Offset) {
  1972. GotLRRestore = true;
  1973. NeedsReturn = true;
  1974. } else {
  1975. // Expecting a separate SaveLR below
  1976. }
  1977. } else {
  1978. if (HasLR != (Inst.Offset == 1))
  1979. return false;
  1980. }
  1981. GotLRRestore = Inst.Offset == 1;
  1982. if (IntRegs < 0) // This opcode must include r4
  1983. return false;
  1984. int Expected = IntRegs;
  1985. if (HasChain) {
  1986. // Can't express r11 here unless IntRegs describe r4-r10
  1987. if (IntRegs != 6)
  1988. return false;
  1989. Expected++;
  1990. }
  1991. if (Expected != (int)(Inst.Register - 4))
  1992. return false;
  1993. GotIntRegs = true;
  1994. Step = 9;
  1995. break;
  1996. }
  1997. case Win64EH::UOP_SaveRegMask:
  1998. case Win64EH::UOP_WideSaveRegMask: {
  1999. if (Step != 6 && Step != 7 && Step != 8)
  2000. return false;
  2001. // push {r4-r9,r11,lr}
  2002. // push {r11,lr}
  2003. // push {r1-r5}
  2004. bool CurHasLR = false, CurHasR11 = false;
  2005. int Regs;
  2006. if (!parseRegMask(Inst.Register, CurHasLR, CurHasR11, EF, Regs))
  2007. return false;
  2008. if (EF > 0) {
  2009. if (EF != PF && EF != StackAdjust)
  2010. return false;
  2011. }
  2012. if (Homing && HasLR) {
  2013. // If homing and LR is backed up, we can either restore LR here
  2014. // and return with Ret == 1 or 2, or return with SaveLR below
  2015. if (CurHasLR) {
  2016. GotLRRestore = true;
  2017. NeedsReturn = true;
  2018. } else {
  2019. // Expecting a separate SaveLR below
  2020. }
  2021. } else {
  2022. if (CurHasLR != HasLR)
  2023. return false;
  2024. GotLRRestore = CurHasLR;
  2025. }
  2026. int Expected = IntRegs;
  2027. if (HasChain) {
  2028. // If we have chaining, the mask must have included r11.
  2029. if (!CurHasR11)
  2030. return false;
  2031. } else if (Expected == 7) {
  2032. // If we don't have chaining, the mask could still include r11,
  2033. // expressed as part of IntRegs Instead.
  2034. Expected--;
  2035. if (!CurHasR11)
  2036. return false;
  2037. } else {
  2038. // Neither HasChain nor r11 included in IntRegs, must not have r11
  2039. // here either.
  2040. if (CurHasR11)
  2041. return false;
  2042. }
  2043. if (Expected != Regs)
  2044. return false;
  2045. GotIntRegs = true;
  2046. Step = 9;
  2047. break;
  2048. }
  2049. case Win64EH::UOP_SaveLR:
  2050. if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
  2051. return false;
  2052. if (!Homing || Inst.Offset != 20 || GotLRRestore)
  2053. return false;
  2054. GotLRRestore = true;
  2055. GotHomingRestore = true;
  2056. Step = 10;
  2057. break;
  2058. case Win64EH::UOP_EndNop:
  2059. case Win64EH::UOP_WideEndNop:
  2060. GotReturn = true;
  2061. Ret = (Inst.Operation == Win64EH::UOP_EndNop) ? 1 : 2;
  2062. [[fallthrough]];
  2063. case Win64EH::UOP_End:
  2064. if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
  2065. return false;
  2066. Step = 11;
  2067. break;
  2068. }
  2069. }
  2070. if (Step != 11)
  2071. return false;
  2072. if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
  2073. return false;
  2074. if (FloatRegs >= 0 && !GotFloatRegs)
  2075. return false;
  2076. if (IntRegs >= 0 && !GotIntRegs)
  2077. return false;
  2078. if (Homing && !GotHomingRestore)
  2079. return false;
  2080. if (HasLR && !GotLRRestore)
  2081. return false;
  2082. if (NeedsReturn && !GotReturn)
  2083. return false;
  2084. }
  2085. assert(PF == 0 || EF == 0 ||
  2086. StackAdjust == 0); // Can't have adjust in all three
  2087. if (PF > 0 || EF > 0) {
  2088. StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
  2089. assert(StackAdjust <= 3);
  2090. StackAdjust |= 0x3f0;
  2091. if (PF > 0)
  2092. StackAdjust |= 1 << 2;
  2093. if (EF > 0)
  2094. StackAdjust |= 1 << 3;
  2095. }
  2096. assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
  2097. int Flag = info->Fragment ? 0x02 : 0x01;
  2098. int H = Homing ? 1 : 0;
  2099. int L = HasLR ? 1 : 0;
  2100. int C = HasChain ? 1 : 0;
  2101. assert(IntRegs < 0 || FloatRegs < 0);
  2102. unsigned Reg, R;
  2103. if (IntRegs >= 0) {
  2104. Reg = IntRegs;
  2105. assert(Reg <= 7);
  2106. R = 0;
  2107. } else if (FloatRegs >= 0) {
  2108. Reg = FloatRegs;
  2109. assert(Reg < 7);
  2110. R = 1;
  2111. } else {
  2112. // No int or float regs stored (except possibly R11,LR)
  2113. Reg = 7;
  2114. R = 1;
  2115. }
  2116. info->PackedInfo |= Flag << 0;
  2117. info->PackedInfo |= (FuncLength & 0x7FF) << 2;
  2118. info->PackedInfo |= (Ret & 0x3) << 13;
  2119. info->PackedInfo |= H << 15;
  2120. info->PackedInfo |= Reg << 16;
  2121. info->PackedInfo |= R << 19;
  2122. info->PackedInfo |= L << 20;
  2123. info->PackedInfo |= C << 21;
  2124. assert(StackAdjust <= 0x3ff);
  2125. info->PackedInfo |= StackAdjust << 22;
  2126. return true;
  2127. }
  2128. // Populate the .xdata section. The format of .xdata on ARM is documented at
  2129. // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
  2130. static void ARMEmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info,
  2131. bool TryPacked = true) {
  2132. // If this UNWIND_INFO already has a symbol, it's already been emitted.
  2133. if (info->Symbol)
  2134. return;
  2135. // If there's no unwind info here (not even a terminating UOP_End), the
  2136. // unwind info is considered bogus and skipped. If this was done in
  2137. // response to an explicit .seh_handlerdata, the associated trailing
  2138. // handler data is left orphaned in the xdata section.
  2139. if (info->empty()) {
  2140. info->EmitAttempted = true;
  2141. return;
  2142. }
  2143. if (info->EmitAttempted) {
  2144. // If we tried to emit unwind info before (due to an explicit
  2145. // .seh_handlerdata directive), but skipped it (because there was no
  2146. // valid information to emit at the time), and it later got valid unwind
  2147. // opcodes, we can't emit it here, because the trailing handler data
  2148. // was already emitted elsewhere in the xdata section.
  2149. streamer.getContext().reportError(
  2150. SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
  2151. " skipped due to no unwind info at the time "
  2152. "(.seh_handlerdata too early?), but the function later "
  2153. "did get unwind info that can't be emitted");
  2154. return;
  2155. }
  2156. MCContext &context = streamer.getContext();
  2157. MCSymbol *Label = context.createTempSymbol();
  2158. streamer.emitValueToAlignment(Align(4));
  2159. streamer.emitLabel(Label);
  2160. info->Symbol = Label;
  2161. if (!info->PrologEnd)
  2162. streamer.getContext().reportError(SMLoc(), "Prologue in " +
  2163. info->Function->getName() +
  2164. " not correctly terminated");
  2165. if (info->PrologEnd && !info->Fragment)
  2166. checkARMInstructions(streamer, info->Instructions, info->Begin,
  2167. info->PrologEnd, info->Function->getName(),
  2168. "prologue");
  2169. for (auto &I : info->EpilogMap) {
  2170. MCSymbol *EpilogStart = I.first;
  2171. auto &Epilog = I.second;
  2172. checkARMInstructions(streamer, Epilog.Instructions, EpilogStart, Epilog.End,
  2173. info->Function->getName(), "epilogue");
  2174. if (Epilog.Instructions.empty() ||
  2175. !isARMTerminator(Epilog.Instructions.back()))
  2176. streamer.getContext().reportError(
  2177. SMLoc(), "Epilogue in " + info->Function->getName() +
  2178. " not correctly terminated");
  2179. }
  2180. std::optional<int64_t> RawFuncLength;
  2181. const MCExpr *FuncLengthExpr = nullptr;
  2182. if (!info->FuncletOrFuncEnd) {
  2183. report_fatal_error("FuncletOrFuncEnd not set");
  2184. } else {
  2185. // As the size of many thumb2 instructions isn't known until later,
  2186. // we can't always rely on being able to calculate the absolute
  2187. // length of the function here. If we can't calculate it, defer it
  2188. // to a relocation.
  2189. //
  2190. // In such a case, we won't know if the function is too long so that
  2191. // the unwind info would need to be split (but this isn't implemented
  2192. // anyway).
  2193. RawFuncLength =
  2194. GetOptionalAbsDifference(streamer, info->FuncletOrFuncEnd, info->Begin);
  2195. if (!RawFuncLength)
  2196. FuncLengthExpr =
  2197. GetSubDivExpr(streamer, info->FuncletOrFuncEnd, info->Begin, 2);
  2198. }
  2199. uint32_t FuncLength = 0;
  2200. if (RawFuncLength)
  2201. FuncLength = (uint32_t)*RawFuncLength / 2;
  2202. if (FuncLength > 0x3FFFF)
  2203. report_fatal_error("SEH unwind data splitting not yet implemented");
  2204. uint32_t PrologCodeBytes = ARMCountOfUnwindCodes(info->Instructions);
  2205. uint32_t TotalCodeBytes = PrologCodeBytes;
  2206. if (!info->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
  2207. TryPacked) {
  2208. // No exception handlers; check if the prolog and epilog matches the
  2209. // patterns that can be described by the packed format. If we don't
  2210. // know the exact function length yet, we can't do this.
  2211. // info->Symbol was already set even if we didn't actually write any
  2212. // unwind info there. Keep using that as indicator that this unwind
  2213. // info has been generated already.
  2214. if (tryARMPackedUnwind(streamer, info, FuncLength))
  2215. return;
  2216. }
  2217. int PackedEpilogOffset =
  2218. checkARMPackedEpilog(streamer, info, PrologCodeBytes);
  2219. // Process epilogs.
  2220. MapVector<MCSymbol *, uint32_t> EpilogInfo;
  2221. // Epilogs processed so far.
  2222. std::vector<MCSymbol *> AddedEpilogs;
  2223. bool CanTweakProlog = true;
  2224. for (auto &I : info->EpilogMap) {
  2225. MCSymbol *EpilogStart = I.first;
  2226. auto &EpilogInstrs = I.second.Instructions;
  2227. uint32_t CodeBytes = ARMCountOfUnwindCodes(EpilogInstrs);
  2228. MCSymbol *MatchingEpilog =
  2229. FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
  2230. int PrologOffset;
  2231. if (MatchingEpilog) {
  2232. assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
  2233. "Duplicate epilog not found");
  2234. EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
  2235. // Clear the unwind codes in the EpilogMap, so that they don't get output
  2236. // in the logic below.
  2237. EpilogInstrs.clear();
  2238. } else if ((PrologOffset = getARMOffsetInProlog(
  2239. info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
  2240. if (CanTweakProlog) {
  2241. // Replace the regular end opcode of the prolog with the one from the
  2242. // epilog.
  2243. info->Instructions.front() = EpilogInstrs.back();
  2244. // Later epilogs need a strict match for the end opcode.
  2245. CanTweakProlog = false;
  2246. }
  2247. EpilogInfo[EpilogStart] = PrologOffset;
  2248. // Clear the unwind codes in the EpilogMap, so that they don't get output
  2249. // in the logic below.
  2250. EpilogInstrs.clear();
  2251. } else {
  2252. EpilogInfo[EpilogStart] = TotalCodeBytes;
  2253. TotalCodeBytes += CodeBytes;
  2254. AddedEpilogs.push_back(EpilogStart);
  2255. }
  2256. }
  2257. // Code Words, Epilog count, F, E, X, Vers, Function Length
  2258. uint32_t row1 = 0x0;
  2259. uint32_t CodeWords = TotalCodeBytes / 4;
  2260. uint32_t CodeWordsMod = TotalCodeBytes % 4;
  2261. if (CodeWordsMod)
  2262. CodeWords++;
  2263. uint32_t EpilogCount =
  2264. PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
  2265. bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
  2266. if (!ExtensionWord) {
  2267. row1 |= (EpilogCount & 0x1F) << 23;
  2268. row1 |= (CodeWords & 0x0F) << 28;
  2269. }
  2270. if (info->HandlesExceptions) // X
  2271. row1 |= 1 << 20;
  2272. if (PackedEpilogOffset >= 0) // E
  2273. row1 |= 1 << 21;
  2274. if (info->Fragment) // F
  2275. row1 |= 1 << 22;
  2276. row1 |= FuncLength & 0x3FFFF;
  2277. if (RawFuncLength)
  2278. streamer.emitInt32(row1);
  2279. else
  2280. streamer.emitValue(
  2281. MCBinaryExpr::createOr(FuncLengthExpr,
  2282. MCConstantExpr::create(row1, context), context),
  2283. 4);
  2284. // Extended Code Words, Extended Epilog Count
  2285. if (ExtensionWord) {
  2286. // FIXME: We should be able to split unwind info into multiple sections.
  2287. if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
  2288. report_fatal_error("SEH unwind data splitting not yet implemented");
  2289. uint32_t row2 = 0x0;
  2290. row2 |= (CodeWords & 0xFF) << 16;
  2291. row2 |= (EpilogCount & 0xFFFF);
  2292. streamer.emitInt32(row2);
  2293. }
  2294. if (PackedEpilogOffset < 0) {
  2295. // Epilog Start Index, Epilog Start Offset
  2296. for (auto &I : EpilogInfo) {
  2297. MCSymbol *EpilogStart = I.first;
  2298. uint32_t EpilogIndex = I.second;
  2299. std::optional<int64_t> MaybeEpilogOffset =
  2300. GetOptionalAbsDifference(streamer, EpilogStart, info->Begin);
  2301. const MCExpr *OffsetExpr = nullptr;
  2302. uint32_t EpilogOffset = 0;
  2303. if (MaybeEpilogOffset)
  2304. EpilogOffset = *MaybeEpilogOffset / 2;
  2305. else
  2306. OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);
  2307. assert(info->EpilogMap.find(EpilogStart) != info->EpilogMap.end());
  2308. unsigned Condition = info->EpilogMap[EpilogStart].Condition;
  2309. assert(Condition <= 0xf);
  2310. uint32_t row3 = EpilogOffset;
  2311. row3 |= Condition << 20;
  2312. row3 |= (EpilogIndex & 0x3FF) << 24;
  2313. if (MaybeEpilogOffset)
  2314. streamer.emitInt32(row3);
  2315. else
  2316. streamer.emitValue(
  2317. MCBinaryExpr::createOr(
  2318. OffsetExpr, MCConstantExpr::create(row3, context), context),
  2319. 4);
  2320. }
  2321. }
  2322. // Emit prolog unwind instructions (in reverse order).
  2323. uint8_t numInst = info->Instructions.size();
  2324. for (uint8_t c = 0; c < numInst; ++c) {
  2325. WinEH::Instruction inst = info->Instructions.back();
  2326. info->Instructions.pop_back();
  2327. ARMEmitUnwindCode(streamer, inst);
  2328. }
  2329. // Emit epilog unwind instructions
  2330. for (auto &I : info->EpilogMap) {
  2331. auto &EpilogInstrs = I.second.Instructions;
  2332. for (const WinEH::Instruction &inst : EpilogInstrs)
  2333. ARMEmitUnwindCode(streamer, inst);
  2334. }
  2335. int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
  2336. assert(BytesMod >= 0);
  2337. for (int i = 0; i < BytesMod; i++)
  2338. streamer.emitInt8(0xFB);
  2339. if (info->HandlesExceptions)
  2340. streamer.emitValue(
  2341. MCSymbolRefExpr::create(info->ExceptionHandler,
  2342. MCSymbolRefExpr::VK_COFF_IMGREL32, context),
  2343. 4);
  2344. }
  2345. static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
  2346. const WinEH::FrameInfo *info) {
  2347. MCContext &context = streamer.getContext();
  2348. streamer.emitValueToAlignment(Align(4));
  2349. for (const auto &S : info->Segments) {
  2350. EmitSymbolRefWithOfs(streamer, info->Begin, S.Offset);
  2351. if (info->PackedInfo)
  2352. streamer.emitInt32(info->PackedInfo);
  2353. else
  2354. streamer.emitValue(
  2355. MCSymbolRefExpr::create(S.Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32,
  2356. context),
  2357. 4);
  2358. }
  2359. }
  2360. static void ARMEmitRuntimeFunction(MCStreamer &streamer,
  2361. const WinEH::FrameInfo *info) {
  2362. MCContext &context = streamer.getContext();
  2363. streamer.emitValueToAlignment(Align(4));
  2364. EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
  2365. if (info->PackedInfo)
  2366. streamer.emitInt32(info->PackedInfo);
  2367. else
  2368. streamer.emitValue(
  2369. MCSymbolRefExpr::create(info->Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32,
  2370. context),
  2371. 4);
  2372. }
  2373. void llvm::Win64EH::ARM64UnwindEmitter::Emit(MCStreamer &Streamer) const {
  2374. // Emit the unwind info structs first.
  2375. for (const auto &CFI : Streamer.getWinFrameInfos()) {
  2376. WinEH::FrameInfo *Info = CFI.get();
  2377. if (Info->empty())
  2378. continue;
  2379. MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
  2380. Streamer.switchSection(XData);
  2381. ARM64EmitUnwindInfo(Streamer, Info);
  2382. }
  2383. // Now emit RUNTIME_FUNCTION entries.
  2384. for (const auto &CFI : Streamer.getWinFrameInfos()) {
  2385. WinEH::FrameInfo *Info = CFI.get();
  2386. // ARM64EmitUnwindInfo above clears the info struct, so we can't check
  2387. // empty here. But if a Symbol is set, we should create the corresponding
  2388. // pdata entry.
  2389. if (!Info->Symbol)
  2390. continue;
  2391. MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
  2392. Streamer.switchSection(PData);
  2393. ARM64EmitRuntimeFunction(Streamer, Info);
  2394. }
  2395. }
  2396. void llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer,
  2397. WinEH::FrameInfo *info,
  2398. bool HandlerData) const {
  2399. // Called if there's an .seh_handlerdata directive before the end of the
  2400. // function. This forces writing the xdata record already here - and
  2401. // in this case, the function isn't actually ended already, but the xdata
  2402. // record needs to know the function length. In these cases, if the funclet
  2403. // end hasn't been marked yet, the xdata function length won't cover the
  2404. // whole function, only up to this point.
  2405. if (!info->FuncletOrFuncEnd) {
  2406. Streamer.switchSection(info->TextSection);
  2407. info->FuncletOrFuncEnd = Streamer.emitCFILabel();
  2408. }
  2409. // Switch sections (the static function above is meant to be called from
  2410. // here and from Emit().
  2411. MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
  2412. Streamer.switchSection(XData);
  2413. ARM64EmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
  2414. }
  2415. void llvm::Win64EH::ARMUnwindEmitter::Emit(MCStreamer &Streamer) const {
  2416. // Emit the unwind info structs first.
  2417. for (const auto &CFI : Streamer.getWinFrameInfos()) {
  2418. WinEH::FrameInfo *Info = CFI.get();
  2419. if (Info->empty())
  2420. continue;
  2421. MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
  2422. Streamer.switchSection(XData);
  2423. ARMEmitUnwindInfo(Streamer, Info);
  2424. }
  2425. // Now emit RUNTIME_FUNCTION entries.
  2426. for (const auto &CFI : Streamer.getWinFrameInfos()) {
  2427. WinEH::FrameInfo *Info = CFI.get();
  2428. // ARMEmitUnwindInfo above clears the info struct, so we can't check
  2429. // empty here. But if a Symbol is set, we should create the corresponding
  2430. // pdata entry.
  2431. if (!Info->Symbol)
  2432. continue;
  2433. MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
  2434. Streamer.switchSection(PData);
  2435. ARMEmitRuntimeFunction(Streamer, Info);
  2436. }
  2437. }
  2438. void llvm::Win64EH::ARMUnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer,
  2439. WinEH::FrameInfo *info,
  2440. bool HandlerData) const {
  2441. // Called if there's an .seh_handlerdata directive before the end of the
  2442. // function. This forces writing the xdata record already here - and
  2443. // in this case, the function isn't actually ended already, but the xdata
  2444. // record needs to know the function length. In these cases, if the funclet
  2445. // end hasn't been marked yet, the xdata function length won't cover the
  2446. // whole function, only up to this point.
  2447. if (!info->FuncletOrFuncEnd) {
  2448. Streamer.switchSection(info->TextSection);
  2449. info->FuncletOrFuncEnd = Streamer.emitCFILabel();
  2450. }
  2451. // Switch sections (the static function above is meant to be called from
  2452. // here and from Emit().
  2453. MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
  2454. Streamer.switchSection(XData);
  2455. ARMEmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
  2456. }