LLVM: lib/MC/MCWin64EH.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
17namespace llvm {
19}
20
21using namespace llvm;
22
23
24
27 for (const auto &I : Insns) {
29 default:
35 Count += 1;
36 break;
39 Count += 2;
40 break;
43 Count += 3;
44 break;
46 Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
47 break;
48 }
49 }
50 return Count;
51}
52
60}
61
68 default:
72 b2 |= (inst.Register & 0x0F) << 4;
74 break;
77 if (inst.Offset > 512 * 1024 - 8) {
78 b2 |= 0x10;
80 w = inst.Offset & 0xFFF8;
82 w = inst.Offset >> 16;
83 } else {
86 }
88 break;
90 b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
93 break;
97 break;
100 b2 |= (inst.Register & 0x0F) << 4;
103 w = inst.Offset >> 3;
105 w >>= 1;
107 break;
110 b2 |= (inst.Register & 0x0F) << 4;
114 w = inst.Offset & 0xFFF0;
115 else
116 w = inst.Offset & 0xFFF8;
118 w = inst.Offset >> 16;
120 break;
122 if (inst.Offset == 1)
123 b2 |= 0x10;
126 break;
127 }
128}
129
137 Context);
139}
140
150 Context);
152}
153
157
163 context), 4);
164}
165
167
168 if (info->Symbol)
169 return;
170
173
176 info->Symbol = Label;
177
178
180 if (info->ChainedParent)
182 else {
183 if (info->HandlesUnwind)
185 if (info->HandlesExceptions)
187 }
189
190 if (info->PrologEnd)
192 else
194
197
199 if (info->LastFrameInst >= 0) {
202 frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
203 }
205
206
207 uint8_t numInst = info->Instructions.size();
208 for (uint8_t c = 0; c < numInst; ++c) {
210 info->Instructions.pop_back();
212 }
213
214
215
216
217
218 if (numCodes & 1) {
220 }
221
224 else if (flags &
228 context), 4);
229 else if (numCodes == 0) {
230
231
232
234 }
235}
236
238
243 }
244
245
250 }
251}
252
255 bool HandlerData) const {
256
257
260
262}
263
270 if (Div != 1)
272 Context);
273 return Expr;
274}
275
284
285
286
288 if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))
289 return std::nullopt;
291}
292
295 std::optional<int64_t> MaybeDiff =
297 if (!MaybeDiff)
298 report_fatal_error("Failed to evaluate function length in SEH unwind info");
299 return *MaybeDiff;
300}
301
306 if ()
307 return;
308 std::optional<int64_t> MaybeDistance =
310 if (!MaybeDistance)
311 return;
313
314 for (const auto &I : Insns) {
316 default:
317 break;
323
324
325 return;
326 }
327 }
328
329 uint32_t InstructionBytes = 4 * (Insns.size() - 1);
330 if (Distance != InstructionBytes) {
332 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
333 Twine(Distance) +
334 " bytes of instructions in range, but .seh directives "
335 "corresponding to " +
336 Twine(InstructionBytes) + " bytes\n");
337 }
338}
339
342 for (const auto &I : Insns) {
344 default:
347 Count += 1;
348 break;
350 Count += 2;
351 break;
353 Count += 4;
354 break;
356 Count += 1;
357 break;
359 Count += 1;
360 break;
362 Count += 1;
363 break;
365 Count += 2;
366 break;
368 Count += 2;
369 break;
371 Count += 2;
372 break;
374 Count += 2;
375 break;
377 Count += 2;
378 break;
380 Count += 2;
381 break;
383 Count += 2;
384 break;
386 Count += 2;
387 break;
389 Count += 2;
390 break;
392 Count += 1;
393 break;
395 Count += 2;
396 break;
398 Count += 1;
399 break;
401 Count += 1;
402 break;
404 Count += 1;
405 break;
407 Count += 1;
408 break;
410 Count += 1;
411 break;
413 Count += 1;
414 break;
416 Count += 1;
417 break;
419 Count += 1;
420 break;
422 Count += 1;
423 break;
436 Count += 3;
437 break;
438 }
439 }
440 return Count;
441}
442
443
444
449 default:
452 b = (inst.Offset >> 4) & 0x1F;
454 break;
457 b = 0xC0;
458 b |= (hw >> 8);
460 b = hw & 0xFF;
462 break;
463 }
466 b = 0xE0;
468 w = inst.Offset >> 4;
469 b = (w & 0x00FF0000) >> 16;
471 b = (w & 0x0000FF00) >> 8;
473 b = w & 0x000000FF;
475 break;
476 }
478 b = 0xE1;
480 break;
482 b = 0xE2;
484 b = (inst.Offset >> 3);
486 break;
488 b = 0xE3;
490 break;
492 b = 0x20;
493 b |= (inst.Offset >> 3) & 0x1F;
495 break;
497 b = 0x80;
498 b |= ((inst.Offset - 1) >> 3) & 0x3F;
500 break;
502 b = 0x40;
503 b |= (inst.Offset >> 3) & 0x3F;
505 break;
507 assert(inst.Register >= 19 && "Saved reg must be >= 19");
509 b = 0xD0 | ((reg & 0xC) >> 2);
511 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
513 break;
515 assert(inst.Register >= 19 && "Saved reg must be >= 19");
517 b = 0xD4 | ((reg & 0x8) >> 3);
519 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
521 break;
523 assert(inst.Register >= 19 && "Saved registers must be >= 19");
525 b = 0xC8 | ((reg & 0xC) >> 2);
527 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
529 break;
531 assert(inst.Register >= 19 && "Saved registers must be >= 19");
533 b = 0xCC | ((reg & 0xC) >> 2);
535 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
537 break;
539 assert(inst.Register >= 19 && "Saved reg must be >= 19");
541 assert((reg % 2) == 0 && "Saved reg must be 19+2*X");
542 reg /= 2;
543 b = 0xD6 | ((reg & 0x7) >> 2);
545 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
547 break;
549 assert(inst.Register >= 8 && "Saved dreg must be >= 8");
551 b = 0xDC | ((reg & 0x4) >> 2);
553 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
555 break;
557 assert(inst.Register >= 8 && "Saved dreg must be >= 8");
559 b = 0xDE;
561 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
563 break;
565 assert(inst.Register >= 8 && "Saved dregs must be >= 8");
567 b = 0xD8 | ((reg & 0x4) >> 2);
569 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
571 break;
573 assert(inst.Register >= 8 && "Saved dregs must be >= 8");
575 b = 0xDA | ((reg & 0x4) >> 2);
577 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
579 break;
581 b = 0xE4;
583 break;
585 b = 0xE6;
587 break;
589 b = 0xE8;
591 break;
593 b = 0xE9;
595 break;
597 b = 0xEA;
599 break;
601 b = 0xEB;
603 break;
605 b = 0xEC;
607 break;
609 b = 0xFC;
611 break;
624
626 int Writeback = Op / 6;
627 int Paired = Op % 2;
630 if (Writeback || Paired || Mode == 2)
632 if (Writeback)
634 b = 0xE7;
637 b = inst.Register | (Writeback << 5) | (Paired << 6);
641 break;
642 }
643 }
644}
645
646
647
648
649
652 const std::vector<MCSymbol *>& Epilogs,
654 for (auto *EpilogStart : Epilogs) {
655 auto InstrsIter = info->EpilogMap.find(EpilogStart);
656 assert(InstrsIter != info->EpilogMap.end() &&
657 "Epilog not found in EpilogMap");
658 const auto &Instrs = InstrsIter->second.Instructions;
659
660 if (Instrs.size() != EpilogInstrs.size())
661 continue;
662
663 bool Match = true;
664 for (unsigned i = 0; i < Instrs.size(); ++i)
665 if (Instrs[i] != EpilogInstrs[i]) {
667 break;
668 }
669
671 return EpilogStart;
672 }
673 return nullptr;
674}
675
678 unsigned PrevOffset = -1;
679 unsigned PrevRegister = -1;
680
682
685 Inst.Register = -1;
687 Inst.Register == 29) {
689 Inst.Register = -1;
691 Inst.Register == 19 && Inst.Offset <= 248) {
693 Inst.Register = -1;
694 } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {
697 Inst.Register == PrevRegister + 2 &&
698 Inst.Offset == PrevOffset + 16) {
700 Inst.Register = -1;
701 Inst.Offset = 0;
702
703
704
705 }
706
707
709 PrevOffset = 0;
710 PrevRegister = 19;
712 PrevOffset = 0;
713 PrevRegister = Inst.Register;
715 PrevOffset = Inst.Offset;
716 PrevRegister = Inst.Register;
718 PrevRegister += 2;
719 PrevOffset += 16;
720 } else {
721 PrevRegister = -1;
722 PrevOffset = -1;
723 }
724 };
725
726
727
728
730 for (auto It = Instructions.rbegin(); It != Instructions.rend(); It++)
731 VisitInstruction(*It);
732 } else {
734 VisitInstruction(Inst);
735 }
736}
737
738
739static int
741 const std::vectorWinEH::Instruction &Epilog) {
742
744 return -1;
745
746
747
748 for (int I = Epilog.size() - 1; I >= 0; I--) {
750 return -1;
751 }
752
754 return 0;
755
756
759}
760
763 int PrologCodeBytes) {
764
765 if (Seg->Epilogs.size() != 1)
766 return -1;
767
769 const std::vectorWinEH::Instruction &Epilog =
770 info->EpilogMap[Sym].Instructions;
771
772
773
776 if (DistanceFromEnd / 4 != Epilog.size())
777 return -1;
778
779 int RetVal = -1;
780
781
782
783
784 if (PrologCodeBytes <= 31 &&
786 RetVal = PrologCodeBytes;
787
790 return RetVal;
791
792
793
794
795 if (Offset > 31 || PrologCodeBytes > 124)
796 return RetVal;
797
798
799
800 info->EpilogMap.erase(Sym);
802}
803
805 int PackedEpilogOffset) {
806 if (PackedEpilogOffset == 0) {
807
808
809
810
811
812 } else if (PackedEpilogOffset == 1) {
813
814
815
817 return false;
818 } else {
819
820 return false;
821 }
822 unsigned RegI = 0, RegF = 0;
823 int Predecrement = 0;
824 enum {
825 Start,
826 Start2,
827 Start3,
829 FloatRegs,
830 InputArgs,
831 StackAdjust,
832 FrameRecord,
834 } Location = Start;
835 bool StandaloneLR = false, FPLRPair = false;
836 bool PAC = false;
838 int Nops = 0;
839
840
841
842
843
844
848 if (Location != Start)
849 return false;
850 Location = Start2;
851 break;
853 if (Location != Start2)
854 return false;
855 PAC = true;
856 Location = Start3;
857 break;
859 if (Location != Start2 && Location != Start3)
860 return false;
861 Predecrement = Inst.Offset;
862 RegI = 2;
864 break;
866 if (Location != Start2 && Location != Start3)
867 return false;
868 Predecrement = Inst.Offset;
870 RegI += 1;
871 else if (Inst.Register == 30)
872 StandaloneLR = true;
873 else
874 return false;
875
876 Location = FloatRegs;
877 break;
879
880
881
882
883
884
885
886
887
888
889
890 return false;
892 if (Location != IntRegs || Inst.Offset != 8 * RegI ||
894 return false;
895 RegI += 2;
896 break;
898 if (Location != IntRegs || Inst.Offset != 8 * RegI)
899 return false;
900 if (Inst.Register == 19 + RegI)
901 RegI += 1;
902 else if (Inst.Register == 30)
903 StandaloneLR = true;
904 else
905 return false;
906
907 Location = FloatRegs;
908 break;
910 if (Location != IntRegs || Inst.Offset != 8 * RegI ||
912 return false;
913 RegI += 1;
914 StandaloneLR = true;
915 Location = FloatRegs;
916 break;
918
919
920 return false;
922 if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
923 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
924 return false;
925 RegF += 1;
926 Location = InputArgs;
927 break;
929 if ((Location != Start2 && Location != Start3) || Inst.Register != 8)
930 return false;
931 Predecrement = Inst.Offset;
932 RegF = 2;
933 Location = FloatRegs;
934 break;
936 if ((Location != IntRegs && Location != FloatRegs) ||
938 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
939 return false;
940 RegF += 2;
941 Location = FloatRegs;
942 break;
945 RegI += 2;
946 else if (Location == FloatRegs)
947 RegF += 2;
948 else
949 return false;
950 break;
952 if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
953 return false;
954 Location = InputArgs;
955 Nops++;
956 break;
959 if (Location != Start2 && Location != Start3 && Location != IntRegs &&
960 Location != FloatRegs && Location != InputArgs &&
961 Location != StackAdjust)
962 return false;
963
964
968 return false;
969 else
971 Location = StackAdjust;
972 break;
974
975
976 if (Location != Start2 && Location != Start3 && Location != IntRegs &&
977 Location != FloatRegs && Location != InputArgs)
978 return false;
980 Location = FrameRecord;
981 FPLRPair = true;
982 break;
984
985 if (Location != StackAdjust || Inst.Offset != 0)
986 return false;
987 Location = FrameRecord;
988 FPLRPair = true;
989 break;
991 if (Location != FrameRecord)
992 return false;
993 Location = End;
994 break;
1007
1008
1009 return false;
1011
1012
1013
1014 return false;
1016
1017
1018 return false;
1024
1025 return false;
1026 default:
1028 }
1029 }
1030 if (RegI > 10 || RegF > 8)
1031 return false;
1032 if (StandaloneLR && FPLRPair)
1033 return false;
1034 if (FPLRPair && Location != End)
1035 return false;
1036 if (Nops != 0 && Nops != 4)
1037 return false;
1038 if (PAC && !FPLRPair)
1039 return false;
1040 int H = Nops == 4;
1041
1042
1043
1044
1045
1046
1047
1048
1049 if (H)
1050 return false;
1051 int IntSZ = 8 * RegI;
1052 if (StandaloneLR)
1053 IntSZ += 8;
1054 int FpSZ = 8 * RegF;
1055 int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
1056 if (Predecrement != SavSZ)
1057 return false;
1059 return false;
1061 return false;
1063 if (FrameSize > 0x1FF)
1064 return false;
1065 assert(RegF != 1 && "One single float reg not allowed");
1066 if (RegF > 0)
1067 RegF--;
1068 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
1069 int Flag = 0x01;
1070 int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
1071 info->PackedInfo |= Flag << 0;
1072 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
1073 info->PackedInfo |= (RegF & 0x7) << 13;
1074 info->PackedInfo |= (RegI & 0xF) << 16;
1075 info->PackedInfo |= (H & 0x1) << 20;
1076 info->PackedInfo |= (CR & 0x3) << 21;
1077 info->PackedInfo |= (FrameSize & 0x1FF) << 23;
1078 return true;
1079}
1080
1085
1086 std::vector<MCSymbol *> EpilogStarts;
1087 for (auto &I : Seg->Epilogs)
1088 EpilogStarts.push_back(I.first);
1089
1090
1091 std::vector<MCSymbol *> AddedEpilogs;
1092 for (auto *S : EpilogStarts) {
1094 auto &EpilogInstrs = info->EpilogMap[S].Instructions;
1096
1099 int PrologOffset;
1100 if (MatchingEpilog) {
1102 "Duplicate epilog not found");
1103 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
1104
1105
1106 EpilogInstrs.clear();
1108 EpilogInstrs)) >= 0) {
1109 EpilogInfo[EpilogStart] = PrologOffset;
1110
1111
1113 EpilogInfo[EpilogStart] += 1;
1114
1115
1116 EpilogInstrs.clear();
1117 } else {
1118 EpilogInfo[EpilogStart] = TotalCodeBytes;
1119 TotalCodeBytes += CodeBytes;
1120 AddedEpilogs.push_back(EpilogStart);
1121 }
1122 }
1123}
1124
1127 int64_t RawFuncLength) {
1128 if (info->PrologEnd)
1130 info->PrologEnd, info->Function->getName(),
1131 "prologue");
1132 struct EpilogStartEnd {
1135 int64_t End;
1136 };
1137
1139 for (auto &I : info->EpilogMap) {
1141 auto &Instrs = I.second.Instructions;
1144 info->Function->getName(), "epilogue");
1146 "Epilogs should be monotonically ordered");
1147
1148
1150 }
1151
1152 unsigned E = 0;
1153 int64_t SegLimit = 0xFFFFC;
1154 int64_t SegOffset = 0;
1155
1156 if (RawFuncLength > SegLimit) {
1157
1158 int64_t RemainingLength = RawFuncLength;
1159
1160 while (RemainingLength > SegLimit) {
1161
1162
1163
1164 int64_t SegLength = SegLimit;
1165 int64_t SegEnd = SegOffset + SegLength;
1166
1168
1169 while (E < Epilogs.size() && Epilogs[E].End < SegEnd) {
1170
1171 EpilogsInSegment[Epilogs[E].Start] = Epilogs[E].Offset;
1172 ++E;
1173 }
1174
1175
1176
1177
1178
1179
1180
1181
1182 if (E < Epilogs.size() && Epilogs[E].Offset <= SegEnd)
1183
1184 SegLength = Epilogs[E].Offset - SegOffset;
1185
1187 SegOffset, SegLength, !SegOffset);
1188 Seg.Epilogs = std::move(EpilogsInSegment);
1189 info->Segments.push_back(Seg);
1190
1191 SegOffset += SegLength;
1192 RemainingLength -= SegLength;
1193 }
1194 }
1195
1196
1197
1198 auto LastSeg =
1200 !SegOffset);
1201 for (; E < Epilogs.size(); ++E)
1202 LastSeg.Epilogs[Epilogs[E].Start] = Epilogs[E].Offset;
1203 info->Segments.push_back(LastSeg);
1204}
1205
1209 bool TryPacked = true) {
1212
1216
1217 if (Seg.Offset == 0)
1218 info->Symbol = Label;
1219
1221 bool HasEpilogs = (Seg.Epilogs.size() != 0);
1222
1224 uint32_t PrologCodeBytes = info->PrologCodeBytes;
1225
1226 int PackedEpilogOffset = HasEpilogs ?
1228
1229
1230
1231
1232
1233 if (info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
1234 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
1235 ->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
1236
1237
1238
1239
1240
1241
1242
1244 return;
1245 }
1246
1247
1248
1249 if (!HasProlog) {
1250 PrologCodeBytes += 1;
1251 if (PackedEpilogOffset >= 0)
1252 PackedEpilogOffset += 1;
1253
1254
1255
1256
1257
1258 if (!HasEpilogs)
1259
1260 PackedEpilogOffset = 0;
1261 }
1262
1263 uint32_t TotalCodeBytes = PrologCodeBytes;
1264
1265
1268
1269
1271 uint32_t CodeWords = TotalCodeBytes / 4;
1272 uint32_t CodeWordsMod = TotalCodeBytes % 4;
1273 if (CodeWordsMod)
1274 CodeWords++;
1276 PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.Epilogs.size();
1277 bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
1278 if (!ExtensionWord) {
1279 row1 |= (EpilogCount & 0x1F) << 22;
1280 row1 |= (CodeWords & 0x1F) << 27;
1281 }
1282 if (info->HandlesExceptions)
1283 row1 |= 1 << 20;
1284 if (PackedEpilogOffset >= 0)
1285 row1 |= 1 << 21;
1286 row1 |= SegLength & 0x3FFFF;
1288
1289
1290 if (ExtensionWord) {
1291
1292 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
1294 "SEH unwind data splitting is only implemented for large functions, "
1295 "cases of too many code words or too many epilogs will be done "
1296 "later");
1298 row2 |= (CodeWords & 0xFF) << 16;
1299 row2 |= (EpilogCount & 0xFFFF);
1301 }
1302
1303 if (PackedEpilogOffset < 0) {
1304
1305 for (auto &I : EpilogInfo) {
1306 MCSymbol *EpilogStart = I.first;
1307 uint32_t EpilogIndex = I.second;
1308
1310 if (EpilogOffset)
1311 EpilogOffset /= 4;
1312 uint32_t row3 = EpilogOffset;
1313 row3 |= (EpilogIndex & 0x3FF) << 22;
1315 }
1316 }
1317
1318
1319
1320
1321
1322
1323
1324 if (!HasProlog)
1325
1327
1328
1331
1332
1333 for (auto &I : Seg.Epilogs) {
1334 auto &EpilogInstrs = info->EpilogMap[I.first].Instructions;
1337 }
1338
1339 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
1340 assert(BytesMod >= 0);
1341 for (int i = 0; i < BytesMod; i++)
1343
1344 if (info->HandlesExceptions)
1348 4);
1349}
1350
1351
1352
1354 bool TryPacked = true) {
1355
1356 if (info->Symbol)
1357 return;
1358
1359
1360
1361
1362 if (info->empty()) {
1363 info->EmitAttempted = true;
1364 return;
1365 }
1366 if (info->EmitAttempted) {
1367
1368
1369
1370
1371
1373 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
1374 " skipped due to no unwind info at the time "
1375 "(.seh_handlerdata too early?), but the function later "
1376 "did get unwind info that can't be emitted");
1377 return;
1378 }
1379
1381 for (auto &I : info->EpilogMap)
1383
1384 int64_t RawFuncLength;
1385 if (->FuncletOrFuncEnd) {
1387 } else {
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1418 info->Begin);
1419 }
1420
1422
1424 for (auto &S : info->Segments)
1426
1427
1428 info->Instructions.clear();
1429}
1430
1433 for (const auto &I : Insns) {
1435 default:
1438 Count += 1;
1439 break;
1441 Count += 3;
1442 break;
1444 Count += 4;
1445 break;
1447 Count += 2;
1448 break;
1450 Count += 3;
1451 break;
1453 Count += 4;
1454 break;
1456 Count += 2;
1457 break;
1459 Count += 1;
1460 break;
1462 Count += 1;
1463 break;
1465 Count += 1;
1466 break;
1468 Count += 1;
1469 break;
1471 Count += 2;
1472 break;
1474 Count += 2;
1475 break;
1477 Count += 2;
1478 break;
1480 Count += 2;
1481 break;
1487 Count += 1;
1488 break;
1490 int J;
1491 for (J = 3; J > 0; J--)
1492 if (I.Offset & (0xffu << (8 * J)))
1493 break;
1494 Count += J + 1;
1495 break;
1496 }
1497 }
1498 }
1499 return Count;
1500}
1501
1503 bool *HasCustom = nullptr) {
1505 for (const auto &I : Insns) {
1507 default:
1512 Count += 2;
1513 break;
1517 Count += 4;
1518 break;
1521 Count += 4;
1522 break;
1524 Count += 2;
1525 break;
1528 Count += 2;
1529 break;
1533 Count += 4;
1534 break;
1536 Count += 4;
1537 break;
1540 Count += 2;
1541 break;
1544 Count += 4;
1545 break;
1547
1548 break;
1550
1551
1552 Count += 1000;
1553 if (HasCustom)
1554 *HasCustom = true;
1555 break;
1556 }
1557 }
1558 return Count;
1559}
1560
1565 if ()
1566 return;
1567 std::optional<int64_t> MaybeDistance =
1569 if (!MaybeDistance)
1570 return;
1572 bool HasCustom = false;
1574 if (HasCustom)
1575 return;
1576 if (Distance != InstructionBytes) {
1578 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
1579 Twine(Distance) +
1580 " bytes of instructions in range, but .seh directives "
1581 "corresponding to " +
1582 Twine(InstructionBytes) + " bytes\n");
1583 }
1584}
1585
1591 return true;
1592 default:
1593 return false;
1594 }
1595}
1596
1597
1598
1602 int i;
1604 default:
1610 break;
1613 lr = (inst.Register >> 14) & 1;
1614 w = 0x8000 | (inst.Register & 0x1fff) | (lr << 13);
1615 streamer.emitInt8((w >> 8) & 0xff);
1616 streamer.emitInt8((w >> 0) & 0xff);
1617 break;
1621 break;
1626 break;
1631 break;
1635 break;
1639 w = 0xe800 | (inst.Offset / 4);
1640 streamer.emitInt8((w >> 8) & 0xff);
1641 streamer.emitInt8((w >> 0) & 0xff);
1642 break;
1645 lr = (inst.Register >> 14) & 1;
1646 w = 0xec00 | (inst.Register & 0x0ff) | (lr << 8);
1647 streamer.emitInt8((w >> 8) & 0xff);
1648 streamer.emitInt8((w >> 0) & 0xff);
1649 break;
1655 break;
1662 break;
1669 break;
1673 w = inst.Offset / 4;
1675 streamer.emitInt8((w >> 8) & 0xff);
1676 streamer.emitInt8((w >> 0) & 0xff);
1677 break;
1681 w = inst.Offset / 4;
1683 streamer.emitInt8((w >> 16) & 0xff);
1684 streamer.emitInt8((w >> 8) & 0xff);
1685 streamer.emitInt8((w >> 0) & 0xff);
1686 break;
1690 w = inst.Offset / 4;
1692 streamer.emitInt8((w >> 8) & 0xff);
1693 streamer.emitInt8((w >> 0) & 0xff);
1694 break;
1698 w = inst.Offset / 4;
1700 streamer.emitInt8((w >> 16) & 0xff);
1701 streamer.emitInt8((w >> 8) & 0xff);
1702 streamer.emitInt8((w >> 0) & 0xff);
1703 break;
1706 break;
1709 break;
1712 break;
1715 break;
1718 break;
1720 for (i = 3; i > 0; i--)
1721 if (inst.Offset & (0xffu << (8 * i)))
1722 break;
1723 for (; i >= 0; i--)
1725 break;
1726 }
1727}
1728
1729
1730
1731
1732
1733
1734
1736 const std::vectorWinEH::Instruction &Epilog,
1737 bool CanTweakProlog) {
1738
1740 return -1;
1741
1742
1743
1744
1745
1746 int EndIdx = CanTweakProlog ? 1 : 0;
1747 for (int I = Epilog.size() - 1; I >= EndIdx; I--) {
1748
1749
1751 return -1;
1752 }
1753
1754 if (CanTweakProlog) {
1755
1757 return -1;
1761 return -1;
1762 }
1763
1764
1766 return 0;
1769}
1770
1772 int PrologCodeBytes) {
1773
1774 if (info->EpilogMap.size() != 1)
1775 return -1;
1776
1778
1779 if (EpilogInfo.Condition != 0xe)
1780 return -1;
1781
1782 const std::vectorWinEH::Instruction &Epilog = EpilogInfo.Instructions;
1783
1784 if (info->Instructions.empty() || Epilog.empty())
1785 return -1;
1786
1787
1788
1790 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
1791 if (!MaybeDistance)
1792 return -1;
1795 if (DistanceFromEnd != InstructionBytes)
1796 return -1;
1797
1798 int RetVal = -1;
1799
1800
1801
1802
1803 if (PrologCodeBytes <= 31 &&
1805 RetVal = PrologCodeBytes;
1806
1810 return RetVal;
1811
1812
1813
1814
1815 if (Offset > 31 || PrologCodeBytes > 63)
1816 return RetVal;
1817
1818
1819
1820 info->Instructions.front() = Epilog.back();
1821
1822
1823
1824 info->EpilogMap.clear();
1826}
1827
1828static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11,
1829 unsigned &Folded, int &IntRegs) {
1830 if (Mask & (1 << 14)) {
1831 HasLR = true;
1832 Mask &= ~(1 << 14);
1833 }
1834 if (Mask & (1 << 11)) {
1835 HasR11 = true;
1836 Mask &= ~(1 << 11);
1837 }
1838 Folded = 0;
1840 if (!Mask)
1841 return true;
1843
1844 while ((Mask & 1) == 0) {
1846 Mask >>= 1;
1847 }
1848 if ((Mask & (Mask + 1)) != 0)
1849 return false;
1850
1851 int N = 0;
1852 while (Mask & (1 << N))
1853 N++;
1854 if (First < 4) {
1856 return false;
1857 Folded = 4 - First;
1858 N -= Folded;
1860 }
1862 return false;
1863 if (N >= 1)
1865 return true;
1866}
1867
1870 int Step = 0;
1871 bool Homing = false;
1872 bool HasR11 = false;
1873 bool HasChain = false;
1874 bool HasLR = false;
1875 int IntRegs = -1;
1876 int FloatRegs = -1;
1877 unsigned PF = 0;
1878 unsigned StackAdjust = 0;
1879
1880
1883 default:
1892
1893 return false;
1895
1896
1897 return false;
1899
1900 return false;
1901
1905 if (Step != 0)
1906 return false;
1907 Step = 1;
1908 break;
1909
1912
1913 if (Step != 1 && Step != 2)
1914 return false;
1919 HasR11 = true;
1921 }
1923 HasLR = true;
1924 Step = 3;
1925 break;
1926
1928 if (Step == 1 && Inst.Register == 0x0f) {
1929
1930 Homing = true;
1931 Step = 2;
1932 break;
1933 }
1934 [[fallthrough]];
1936 if (Step != 1 && Step != 2)
1937 return false;
1938
1939
1940
1942 return false;
1943 Step = 3;
1944 break;
1945
1947
1948 if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)
1949 return false;
1950 HasChain = true;
1951 Step = 4;
1952 break;
1954
1955 if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))
1956 return false;
1957 HasChain = true;
1958 Step = 4;
1959 break;
1960
1962 if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
1963 return false;
1966 return false;
1968 return false;
1969 FloatRegs = Inst.Register - 8;
1970 Step = 5;
1971 break;
1972
1975 if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
1976 return false;
1977 if (PF > 0)
1978 return false;
1979 if (Inst.Offset / 4 >= 0x3f4)
1980 return false;
1981 StackAdjust = Inst.Offset / 4;
1982 Step = 6;
1983 break;
1984 }
1985 }
1986 if (HasR11 && !HasChain) {
1987 if (IntRegs + 4 == 10) {
1988
1989
1991 HasR11 = false;
1992 } else
1993 return false;
1994 }
1995 if (HasChain && !HasLR)
1996 return false;
1997
1998
1999 if (info->EpilogMap.size() > 1)
2000 return false;
2001
2002 unsigned EF = 0;
2003 int Ret = 0;
2004 if (info->EpilogMap.size() == 0) {
2005 Ret = 3;
2006 } else {
2007
2008
2009
2011 info->EpilogMap.begin()->second;
2012 if (EpilogInfo.Condition != 0xe)
2013 return false;
2014 const std::vectorWinEH::Instruction &Epilog = EpilogInfo.Instructions;
2016 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
2017 if (!MaybeDistance)
2018 return false;
2021 if (DistanceFromEnd != InstructionBytes)
2022 return false;
2023
2024 bool GotStackAdjust = false;
2025 bool GotFloatRegs = false;
2026 bool GotIntRegs = false;
2027 bool GotHomingRestore = false;
2028 bool GotLRRestore = false;
2029 bool NeedsReturn = false;
2030 bool GotReturn = false;
2031
2032 Step = 6;
2035 default:
2047
2048 return false;
2049
2052 if (Inst.Offset / 4 >= 0x3f4)
2053 return false;
2054 if (Step == 6) {
2055 if (Homing && FloatRegs < 0 && IntRegs < 0 && StackAdjust == 0 &&
2056 PF == 0 && Inst.Offset == 16) {
2057 GotHomingRestore = true;
2058 Step = 10;
2059 } else {
2060 if (StackAdjust > 0) {
2061
2062 if (StackAdjust != Inst.Offset / 4)
2063 return false;
2064 GotStackAdjust = true;
2065 } else if (PF == Inst.Offset / 4) {
2066
2067 StackAdjust = Inst.Offset / 4;
2068 GotStackAdjust = true;
2069 } else {
2070
2071 return false;
2072 }
2073 Step = 7;
2074 }
2075 } else if (Step == 7 || Step == 8 || Step == 9) {
2076 if (!Homing || Inst.Offset != 16)
2077 return false;
2078 GotHomingRestore = true;
2079 Step = 10;
2080 } else
2081 return false;
2082 break;
2083
2085 if (Step != 6 && Step != 7)
2086 return false;
2088 if (FloatRegs != (int)(Inst.Register - 8))
2089 return false;
2090 GotFloatRegs = true;
2091 Step = 8;
2092 break;
2093
2096
2097 if (Step != 6 && Step != 7 && Step != 8)
2098 return false;
2101 if (Homing && HasLR) {
2102
2103
2105 GotLRRestore = true;
2106 NeedsReturn = true;
2107 } else {
2108
2109 }
2110 } else {
2111 if (HasLR != (Inst.Offset == 1))
2112 return false;
2113 }
2114 GotLRRestore = Inst.Offset == 1;
2115 if (IntRegs < 0)
2116 return false;
2118 if (HasChain) {
2119
2121 return false;
2123 }
2125 return false;
2126 GotIntRegs = true;
2127 Step = 9;
2128 break;
2129 }
2130
2133 if (Step != 6 && Step != 7 && Step != 8)
2134 return false;
2135
2136
2137
2138 bool CurHasLR = false, CurHasR11 = false;
2139 int Regs;
2141 return false;
2142 if (EF > 0) {
2143 if (EF != PF && EF != StackAdjust)
2144 return false;
2145 }
2146 if (Homing && HasLR) {
2147
2148
2149 if (CurHasLR) {
2150 GotLRRestore = true;
2151 NeedsReturn = true;
2152 } else {
2153
2154 }
2155 } else {
2156 if (CurHasLR != HasLR)
2157 return false;
2158 GotLRRestore = CurHasLR;
2159 }
2161 if (HasChain) {
2162
2163 if (!CurHasR11)
2164 return false;
2166
2167
2169 if (!CurHasR11)
2170 return false;
2171 } else {
2172
2173
2174 if (CurHasR11)
2175 return false;
2176 }
2178 return false;
2179 GotIntRegs = true;
2180 Step = 9;
2181 break;
2182 }
2183
2185 if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
2186 return false;
2187 if (!Homing || Inst.Offset != 20 || GotLRRestore)
2188 return false;
2189 GotLRRestore = true;
2190 GotHomingRestore = true;
2191 Step = 10;
2192 break;
2193
2196 GotReturn = true;
2198 [[fallthrough]];
2200 if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
2201 return false;
2202 Step = 11;
2203 break;
2204 }
2205 }
2206
2207 if (Step != 11)
2208 return false;
2209 if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
2210 return false;
2211 if (FloatRegs >= 0 && !GotFloatRegs)
2212 return false;
2213 if (IntRegs >= 0 && !GotIntRegs)
2214 return false;
2215 if (Homing && !GotHomingRestore)
2216 return false;
2217 if (HasLR && !GotLRRestore)
2218 return false;
2219 if (NeedsReturn && !GotReturn)
2220 return false;
2221 }
2222
2223 assert(PF == 0 || EF == 0 ||
2224 StackAdjust == 0);
2225 if (PF > 0 || EF > 0) {
2226 StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
2227 assert(StackAdjust <= 3);
2228 StackAdjust |= 0x3f0;
2229 if (PF > 0)
2230 StackAdjust |= 1 << 2;
2231 if (EF > 0)
2232 StackAdjust |= 1 << 3;
2233 }
2234
2235 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
2236 int Flag = info->Fragment ? 0x02 : 0x01;
2237 int H = Homing ? 1 : 0;
2238 int L = HasLR ? 1 : 0;
2239 int C = HasChain ? 1 : 0;
2241 unsigned Reg, R;
2245 R = 0;
2246 } else if (FloatRegs >= 0) {
2247 Reg = FloatRegs;
2249 R = 1;
2250 } else {
2251
2252 Reg = 7;
2253 R = 1;
2254 }
2255 info->PackedInfo |= Flag << 0;
2256 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
2257 info->PackedInfo |= (Ret & 0x3) << 13;
2258 info->PackedInfo |= H << 15;
2259 info->PackedInfo |= Reg << 16;
2260 info->PackedInfo |= R << 19;
2261 info->PackedInfo |= L << 20;
2262 info->PackedInfo |= C << 21;
2263 assert(StackAdjust <= 0x3ff);
2264 info->PackedInfo |= StackAdjust << 22;
2265 return true;
2266}
2267
2268
2269
2271 bool TryPacked = true) {
2272
2273 if (info->Symbol)
2274 return;
2275
2276
2277
2278
2279 if (info->empty()) {
2280 info->EmitAttempted = true;
2281 return;
2282 }
2283 if (info->EmitAttempted) {
2284
2285
2286
2287
2288
2290 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
2291 " skipped due to no unwind info at the time "
2292 "(.seh_handlerdata too early?), but the function later "
2293 "did get unwind info that can't be emitted");
2294 return;
2295 }
2296
2299
2302 info->Symbol = Label;
2303
2304 if (->PrologEnd)
2306 info->Function->getName() +
2307 " not correctly terminated");
2308
2309 if (info->PrologEnd && ->Fragment)
2311 info->PrologEnd, info->Function->getName(),
2312 "prologue");
2313 for (auto &I : info->EpilogMap) {
2314 MCSymbol *EpilogStart = I.first;
2317 info->Function->getName(), "epilogue");
2318 if (Epilog.Instructions.empty() ||
2321 SMLoc(), "Epilogue in " + info->Function->getName() +
2322 " not correctly terminated");
2323 }
2324
2325 std::optional<int64_t> RawFuncLength;
2326 const MCExpr *FuncLengthExpr = nullptr;
2327 if (->FuncletOrFuncEnd) {
2329 } else {
2330
2331
2332
2333
2334
2335
2336
2337
2338 RawFuncLength =
2340 if (!RawFuncLength)
2341 FuncLengthExpr =
2343 }
2345 if (RawFuncLength)
2346 FuncLength = (uint32_t)*RawFuncLength / 2;
2347 if (FuncLength > 0x3FFFF)
2348 report_fatal_error("SEH unwind data splitting not yet implemented");
2350 uint32_t TotalCodeBytes = PrologCodeBytes;
2351
2352 if (->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
2353 TryPacked) {
2354
2355
2356
2357
2358
2359
2360
2361
2363 return;
2364 }
2365
2366 int PackedEpilogOffset =
2368
2369
2371
2372 std::vector<MCSymbol *> AddedEpilogs;
2373
2374 bool CanTweakProlog = true;
2375 for (auto &I : info->EpilogMap) {
2376 MCSymbol *EpilogStart = I.first;
2377 auto &EpilogInstrs = I.second.Instructions;
2379
2382 int PrologOffset;
2383 if (MatchingEpilog) {
2385 "Duplicate epilog not found");
2386 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
2387
2388
2389 EpilogInstrs.clear();
2391 info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
2392 if (CanTweakProlog) {
2393
2394
2395 info->Instructions.front() = EpilogInstrs.back();
2396
2397 CanTweakProlog = false;
2398 }
2399 EpilogInfo[EpilogStart] = PrologOffset;
2400
2401
2402 EpilogInstrs.clear();
2403 } else {
2404 EpilogInfo[EpilogStart] = TotalCodeBytes;
2405 TotalCodeBytes += CodeBytes;
2406 AddedEpilogs.push_back(EpilogStart);
2407 }
2408 }
2409
2410
2412 uint32_t CodeWords = TotalCodeBytes / 4;
2413 uint32_t CodeWordsMod = TotalCodeBytes % 4;
2414 if (CodeWordsMod)
2415 CodeWords++;
2417 PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
2418 bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
2419 if (!ExtensionWord) {
2420 row1 |= (EpilogCount & 0x1F) << 23;
2421 row1 |= (CodeWords & 0x0F) << 28;
2422 }
2423 if (info->HandlesExceptions)
2424 row1 |= 1 << 20;
2425 if (PackedEpilogOffset >= 0)
2426 row1 |= 1 << 21;
2427 if (info->Fragment)
2428 row1 |= 1 << 22;
2429 row1 |= FuncLength & 0x3FFFF;
2430 if (RawFuncLength)
2432 else
2436 4);
2437
2438
2439 if (ExtensionWord) {
2440
2441 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
2442 report_fatal_error("SEH unwind data splitting not yet implemented");
2444 row2 |= (CodeWords & 0xFF) << 16;
2445 row2 |= (EpilogCount & 0xFFFF);
2447 }
2448
2449 if (PackedEpilogOffset < 0) {
2450
2451 for (auto &I : EpilogInfo) {
2452 MCSymbol *EpilogStart = I.first;
2453 uint32_t EpilogIndex = I.second;
2454
2455 std::optional<int64_t> MaybeEpilogOffset =
2457 const MCExpr *OffsetExpr = nullptr;
2459 if (MaybeEpilogOffset)
2460 EpilogOffset = *MaybeEpilogOffset / 2;
2461 else
2462 OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);
2463
2464 assert(info->EpilogMap.contains(EpilogStart));
2465 unsigned Condition = info->EpilogMap[EpilogStart].Condition;
2466 assert(Condition <= 0xf);
2467
2468 uint32_t row3 = EpilogOffset;
2469 row3 |= Condition << 20;
2470 row3 |= (EpilogIndex & 0x3FF) << 24;
2471 if (MaybeEpilogOffset)
2473 else
2477 4);
2478 }
2479 }
2480
2481
2482 uint8_t numInst = info->Instructions.size();
2483 for (uint8_t c = 0; c < numInst; ++c) {
2485 info->Instructions.pop_back();
2487 }
2488
2489
2490 for (auto &I : info->EpilogMap) {
2491 auto &EpilogInstrs = I.second.Instructions;
2494 }
2495
2496 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2497 assert(BytesMod >= 0);
2498 for (int i = 0; i < BytesMod; i++)
2500
2501 if (info->HandlesExceptions)
2505 4);
2506}
2507
2511
2513 for (const auto &S : info->Segments) {
2515 if (info->PackedInfo)
2517 else
2520 context),
2521 4);
2522 }
2523}
2524
2525
2529
2532 if (info->PackedInfo)
2534 else
2537 context),
2538 4);
2539}
2540
2542
2545 if (Info->empty())
2546 continue;
2550 }
2551
2552
2555
2556
2557
2558 if (->Symbol)
2559 continue;
2563 }
2564}
2565
2568 bool HandlerData) const {
2569
2570
2571
2572
2573
2574
2575 if (->FuncletOrFuncEnd) {
2578 }
2579
2580
2584}
2585
2587
2590 if (Info->empty())
2591 continue;
2595 }
2596
2597
2600
2601
2602
2603 if (->Symbol)
2604 continue;
2608 }
2609}
2610
2613 bool HandlerData) const {
2614
2615
2616
2617
2618
2619
2620 if (->FuncletOrFuncEnd) {
2623 }
2624
2625
2629}
Analysis containing CSE Info
Given that RA is a live value
std::optional< std::vector< StOtherPiece > > Other
static int checkARM64PackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, int PrologCodeBytes)
static void ARM64EmitUnwindInfoForSegment(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment &Seg, bool TryPacked=true)
static uint32_t ARMCountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
static uint32_t ARM64CountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
static void checkARMInstructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)
static bool isARMTerminator(const WinEH::Instruction &inst)
static void ARM64EmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
static void simplifyARM64Opcodes(std::vector< WinEH::Instruction > &Instructions, bool Reverse)
static void ARMEmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
static int getARM64OffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog)
static void ARMEmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength, int PackedEpilogOffset)
static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)
static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
static int getARMOffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog, bool CanTweakProlog)
static void ARM64EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, int64_t Offset)
static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11, unsigned &Folded, int &IntRegs)
static int checkARMPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)
static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
static void ARM64FindSegmentsInFunction(MCStreamer &streamer, WinEH::FrameInfo *info, int64_t RawFuncLength)
static bool tryARMPackedUnwind(MCStreamer &streamer, WinEH::FrameInfo *info, uint32_t FuncLength)
static MCSymbol * FindMatchingEpilog(const std::vector< WinEH::Instruction > &EpilogInstrs, const std::vector< MCSymbol * > &Epilogs, const WinEH::FrameInfo *info)
static void EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
static std::optional< int64_t > GetOptionalAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
static void checkARM64Instructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)
static const MCExpr * GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS, int Div)
static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
static void ARMEmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
static uint32_t ARMCountOfInstructionBytes(ArrayRef< WinEH::Instruction > Insns, bool *HasCustom=nullptr)
static void ARM64ProcessEpilogs(WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, uint32_t &TotalCodeBytes, MapVector< MCSymbol *, uint32_t > &EpilogInfo)
static uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)
static cl::opt< RegAllocEvictionAdvisorAnalysis::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development, "development", "for training")))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const MCPhysReg IntRegs[32]
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This class represents an Operation in the Expression.
Tagged union holding either a T or a Error.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
void reportError(SMLoc L, const Twine &Msg)
Base class for the full range of assembler expressions which are needed for parsing.
Streaming object file generation interface.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Streaming machine code generation interface.
virtual MCSymbol * emitCFILabel()
When emitting an object file, create and emit a real label.
MCSection * getAssociatedPDataSection(const MCSection *TextSec)
Get the .pdata section used for the given section.
MCContext & getContext() const
MCSection * getAssociatedXDataSection(const MCSection *TextSec)
Get the .xdata section used for the given section.
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void emitInt16(uint64_t Value)
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
void emitInt32(uint64_t Value)
ArrayRef< std::unique_ptr< WinEH::FrameInfo > > getWinFrameInfos() const
void emitInt8(uint64_t Value)
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
This class implements a map that also provides access to all stored values in a deterministic order.
bool contains(const KeyT &Key) const
ValueT lookup(const KeyT &Key) const
Represents a location in source code.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
UnwindOpcodes
UnwindOpcodes - Enumeration whose values specify a single operation in the prolog of a function.
@ UOP_WideSaveRegsR4R11LR
@ UNW_TerminateHandler
UNW_TerminateHandler - Specifies that this function has a termination handler.
@ UNW_ExceptionHandler
UNW_ExceptionHandler - Specifies that this function has an exception handler.
@ UNW_ChainInfo
UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to another one.
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
This struct is a compact representation of a valid (non-zero power of two) alignment.
std::vector< Instruction > Instructions
MapVector< MCSymbol *, int64_t > Epilogs