LLVM: lib/MC/MCWin64EH.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
19
20namespace llvm {
22}
23
24using namespace llvm;
25
26namespace {
27
28class MCUnwindV2EpilogTargetExpr final : public MCTargetExpr {
31 const MCSymbol *UnwindV2Start;
33 uint8_t EpilogSize;
34 SMLoc Loc;
35
36 MCUnwindV2EpilogTargetExpr(const WinEH::FrameInfo &FrameInfo,
37 const WinEH::FrameInfo::Epilog &Epilog,
38 uint8_t EpilogSize_)
39 : Function(FrameInfo.Function), FunctionEnd(FrameInfo.FuncletOrFuncEnd),
40 UnwindV2Start(Epilog.UnwindV2Start), EpilogEnd(Epilog.End),
41 EpilogSize(EpilogSize_), Loc(Epilog.Loc) {}
42
43public:
44 static MCUnwindV2EpilogTargetExpr *
45 create(const WinEH::FrameInfo &FrameInfo,
46 const WinEH::FrameInfo::Epilog &Epilog, uint8_t EpilogSize_,
47 MCContext &Ctx) {
48 return new (Ctx) MCUnwindV2EpilogTargetExpr(FrameInfo, Epilog, EpilogSize_);
49 }
50
51 void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override {
52 OS << ":epilog:";
53 UnwindV2Start->print(OS, MAI);
54 }
55
56 bool evaluateAsRelocatableImpl(MCValue &Res,
57 const MCAssembler *Asm) const override;
58
59 void visitUsedExpr(MCStreamer &Streamer) const override {
60
61 }
62
63 MCFragment *findAssociatedFragment() const override {
65 }
66};
67}
68
69
70
73 for (const auto &I : Insns) {
75 default:
82 break;
86 break;
90 break;
92 Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
93 break;
94 }
95 }
97}
98
107
114 default:
118 b2 |= (inst.Register & 0x0F) << 4;
120 break;
123 if (inst.Offset > 512 * 1024 - 8) {
124 b2 |= 0x10;
126 w = inst.Offset & 0xFFF8;
128 w = inst.Offset >> 16;
129 } else {
131 w = inst.Offset >> 3;
132 }
134 break;
136 b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
139 break;
143 break;
146 b2 |= (inst.Register & 0x0F) << 4;
149 w = inst.Offset >> 3;
151 w >>= 1;
153 break;
156 b2 |= (inst.Register & 0x0F) << 4;
160 w = inst.Offset & 0xFFF0;
161 else
162 w = inst.Offset & 0xFFF8;
164 w = inst.Offset >> 16;
166 break;
168 if (inst.Offset == 1)
169 b2 |= 0x10;
172 break;
173 }
174}
175
186
199
203
209 context), 4);
210}
211
212static std::optional<int64_t>
219
220
221
222 int64_t value;
223 if (!Diff->evaluateAsAbsolute(value, Assembler))
224 return std::nullopt;
225 return value;
226}
227
229
230 if (info->Symbol)
231 return;
232
236
239 info->Symbol = Label;
240
242 bool LastEpilogIsAtEnd = false;
243 bool AddPaddingEpilogCode = false;
245 bool EnableUnwindV2 = (info->Version >= 2) && ->EpilogMap.empty();
246 if (EnableUnwindV2) {
247 auto &LastEpilog = info->EpilogMap.back().second;
248
249
250
251
252
253
254
256 OS->getAssembler(), LastEpilog.End, LastEpilog.UnwindV2Start);
257 if (!MaybeSize) {
259 "Failed to evaluate epilog size for Unwind v2 in " +
260 info->Function->getName());
261 return;
262 }
263 assert(*MaybeSize >= 0);
264 if (*MaybeSize >= (int64_t)UINT8_MAX) {
266 "Epilog size is too large for Unwind v2 in " +
267 info->Function->getName());
268 return;
269 }
270 EpilogSize = *MaybeSize + 1;
271
272
273
274
276 OS->getAssembler(), info->FuncletOrFuncEnd, LastEpilog.UnwindV2Start);
277 LastEpilogIsAtEnd = (LastEpilogToFuncEnd == EpilogSize);
278
279
280 size_t numEpilogCodes =
281 info->EpilogMap.size() + (LastEpilogIsAtEnd ? 0 : 1);
282 if ((numEpilogCodes % 2) != 0) {
283 AddPaddingEpilogCode = true;
284 numEpilogCodes++;
285 }
286
287
288 if ((size_t)numCodes + numEpilogCodes > UINT8_MAX) {
290 "Too many unwind codes with Unwind v2 enabled in " +
291 info->Function->getName());
292 return;
293 }
294
295 numCodes += numEpilogCodes;
296 }
297
298
300 if (info->ChainedParent)
302 else {
303 if (info->HandlesUnwind)
305 if (info->HandlesExceptions)
307 }
309
310 if (info->PrologEnd)
312 else
314
316
318 if (info->LastFrameInst >= 0) {
321 frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
322 }
324
325
326 if (EnableUnwindV2) {
327
329
330 bool IsLast = true;
332 if (IsLast) {
333 IsLast = false;
334 uint8_t Flags = LastEpilogIsAtEnd ? 0x01 : 0;
337
338 if (LastEpilogIsAtEnd)
339 continue;
340 }
341
342
343
344
345 auto *MCE = MCUnwindV2EpilogTargetExpr::create(*info, Epilog.second,
346 EpilogSize, context);
349 }
350 }
351 if (AddPaddingEpilogCode)
353
354
355 uint8_t numInst = info->Instructions.size();
356 for (uint8_t c = 0; c < numInst; ++c) {
358 info->Instructions.pop_back();
360 }
361
362
363
364
365
366 if (numCodes & 1) {
368 }
369
372 else if (flags &
376 context), 4);
377 else if (numCodes == 0) {
378
379
380
382 }
383}
384
385bool MCUnwindV2EpilogTargetExpr::evaluateAsRelocatableImpl(
387
388
391 Asm->getContext().reportError(
392 Loc, "Failed to evaluate epilog offset for Unwind v2 in " +
394 return false;
395 }
397 constexpr uint16_t MaxEpilogOffset = 0x0fff;
398 if (*Offset > MaxEpilogOffset) {
399 Asm->getContext().reportError(
400 Loc,
401 "Epilog offset is too large for Unwind v2 in " + Function->getName());
402 return false;
403 }
404
405
407 if (Size != (EpilogSize - 1)) {
408 Asm->getContext().reportError(
409 Loc, "Size of this epilog does not match size of last epilog in " +
411 return false;
412 }
413
414 auto HighBits = *Offset >> 8;
417 return true;
418}
419
421
426 }
427
428
433 }
434}
435
438 bool HandlerData) const {
439
440
443
445}
446
453 if (Div != 1)
455 Context);
456 return Expr;
457}
458
465
468 std::optional<int64_t> MaybeDiff =
470 if (!MaybeDiff)
471 report_fatal_error("Failed to evaluate function length in SEH unwind info");
472 return *MaybeDiff;
473}
474
479 if (!End)
480 return;
481 std::optional<int64_t> MaybeDistance =
483 if (!MaybeDistance)
484 return;
486
487 for (const auto &I : Insns) {
489 default:
490 break;
496
497
498 return;
499 }
500 }
501
502 uint32_t InstructionBytes = 4 * (Insns.size() - 1);
503 if (Distance != InstructionBytes) {
505 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
506 Twine(Distance) +
507 " bytes of instructions in range, but .seh directives "
508 "corresponding to " +
509 Twine(InstructionBytes) + " bytes\n");
510 }
511}
512
515 for (const auto &I : Insns) {
517 default:
521 break;
524 break;
527 break;
530 break;
533 break;
536 break;
539 break;
542 break;
545 break;
548 break;
551 break;
554 break;
557 break;
560 break;
563 break;
566 break;
569 break;
572 break;
575 break;
578 break;
581 break;
584 break;
587 break;
590 break;
593 break;
596 break;
599 break;
615 break;
616 }
617 }
619}
620
621
622
627 default:
630 b = (inst.Offset >> 4) & 0x1F;
632 break;
635 b = 0xC0;
636 b |= (hw >> 8);
638 b = hw & 0xFF;
640 break;
641 }
644 b = 0xE0;
646 w = inst.Offset >> 4;
647 b = (w & 0x00FF0000) >> 16;
649 b = (w & 0x0000FF00) >> 8;
651 b = w & 0x000000FF;
653 break;
654 }
656 b = 0xE1;
658 break;
660 b = 0xE2;
662 b = (inst.Offset >> 3);
664 break;
666 b = 0xE3;
668 break;
670 b = 0x20;
671 b |= (inst.Offset >> 3) & 0x1F;
673 break;
675 b = 0x80;
676 b |= ((inst.Offset >> 3) - 1) & 0x3F;
678 break;
680 b = 0x40;
681 b |= (inst.Offset >> 3) & 0x3F;
683 break;
685 assert(inst.Register >= 19 && "Saved reg must be >= 19");
687 b = 0xD0 | ((reg & 0xC) >> 2);
689 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
691 break;
693 assert(inst.Register >= 19 && "Saved reg must be >= 19");
695 b = 0xD4 | ((reg & 0x8) >> 3);
697 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
699 break;
701 assert(inst.Register >= 19 && "Saved registers must be >= 19");
703 b = 0xC8 | ((reg & 0xC) >> 2);
705 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
707 break;
709 assert(inst.Register >= 19 && "Saved registers must be >= 19");
711 b = 0xCC | ((reg & 0xC) >> 2);
713 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
715 break;
717 assert(inst.Register >= 19 && "Saved reg must be >= 19");
719 assert((reg % 2) == 0 && "Saved reg must be 19+2*X");
720 reg /= 2;
721 b = 0xD6 | ((reg & 0x7) >> 2);
723 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
725 break;
727 assert(inst.Register >= 8 && "Saved dreg must be >= 8");
729 b = 0xDC | ((reg & 0x4) >> 2);
731 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
733 break;
735 assert(inst.Register >= 8 && "Saved dreg must be >= 8");
737 b = 0xDE;
739 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
741 break;
743 assert(inst.Register >= 8 && "Saved dregs must be >= 8");
745 b = 0xD8 | ((reg & 0x4) >> 2);
747 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
749 break;
751 assert(inst.Register >= 8 && "Saved dregs must be >= 8");
753 b = 0xDA | ((reg & 0x4) >> 2);
755 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
757 break;
759 b = 0xE4;
761 break;
763 b = 0xE6;
765 break;
767 b = 0xE8;
769 break;
771 b = 0xE9;
773 break;
775 b = 0xEA;
777 break;
779 b = 0xEB;
781 break;
783 b = 0xEC;
785 break;
787 b = 0xFC;
789 break;
802
804 int Writeback = Op / 6;
805 int Paired = Op % 2;
808 if (Writeback || Paired || Mode == 2)
810 if (Writeback)
812 b = 0xE7;
815 b = inst.Register | (Writeback << 5) | (Paired << 6);
819 break;
820 }
822 b = 0xDF;
826 break;
827 }
831 b = 0xE7;
834 b = ((inst.Offset & 0xC0) >> 1) | reg;
836 b = 0xC0 | (inst.Offset & 0x3F);
838 break;
839 }
843 b = 0xE7;
846 b = ((inst.Offset & 0xC0) >> 1) | 0x10 | reg;
848 b = 0xC0 | (inst.Offset & 0x3F);
850 break;
851 }
852 }
853}
854
855
856
857
858
861 const std::vector<MCSymbol *>& Epilogs,
863 for (auto *EpilogStart : Epilogs) {
864 auto InstrsIter = info->EpilogMap.find(EpilogStart);
865 assert(InstrsIter != info->EpilogMap.end() &&
866 "Epilog not found in EpilogMap");
867 const auto &Instrs = InstrsIter->second.Instructions;
868
869 if (Instrs.size() != EpilogInstrs.size())
870 continue;
871
872 bool Match = true;
873 for (unsigned i = 0; i < Instrs.size(); ++i)
874 if (Instrs[i] != EpilogInstrs[i]) {
875 Match = false;
876 break;
877 }
878
879 if (Match)
880 return EpilogStart;
881 }
882 return nullptr;
883}
884
887 unsigned PrevOffset = -1;
888 unsigned PrevRegister = -1;
889
891
894 Inst.Register = -1;
896 Inst.Register == 29) {
898 Inst.Register = -1;
900 Inst.Register == 19 && Inst.Offset <= 248) {
902 Inst.Register = -1;
903 } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {
906 Inst.Register == PrevRegister + 2 &&
907 Inst.Offset == PrevOffset + 16) {
909 Inst.Register = -1;
910 Inst.Offset = 0;
911
912
913
914 }
915
916
918 PrevOffset = 0;
919 PrevRegister = 19;
921 PrevOffset = 0;
922 PrevRegister = Inst.Register;
924 PrevOffset = Inst.Offset;
925 PrevRegister = Inst.Register;
927 PrevRegister += 2;
928 PrevOffset += 16;
929 } else {
930 PrevRegister = -1;
931 PrevOffset = -1;
932 }
933 };
934
935
936
937
939 for (auto It = Instructions.rbegin(); It != Instructions.rend(); It++)
940 VisitInstruction(*It);
941 } else {
943 VisitInstruction(Inst);
944 }
945}
946
947
948static int
950 const std::vectorWinEH::Instruction &Epilog) {
951
953 return -1;
954
955
956
957 for (int I = Epilog.size() - 1; I >= 0; I--) {
959 return -1;
960 }
961
963 return 0;
964
965
968}
969
972 int PrologCodeBytes) {
973
974 if (Seg->Epilogs.size() != 1)
975 return -1;
976
978 const std::vectorWinEH::Instruction &Epilog =
979 info->EpilogMap[Sym].Instructions;
980
981
982
985 if (DistanceFromEnd / 4 != Epilog.size())
986 return -1;
987
988 int RetVal = -1;
989
990
991
992
993 if (PrologCodeBytes <= 31 &&
995 RetVal = PrologCodeBytes;
996
999 return RetVal;
1000
1001
1002
1003
1004 if (Offset > 31 || PrologCodeBytes > 124)
1005 return RetVal;
1006
1007
1008
1009 info->EpilogMap.erase(Sym);
1011}
1012
1014 int PackedEpilogOffset) {
1015 if (PackedEpilogOffset == 0) {
1016
1017
1018
1019
1020
1021 } else if (PackedEpilogOffset == 1) {
1022
1023
1024
1026 return false;
1027 } else {
1028
1029 return false;
1030 }
1031 unsigned RegI = 0, RegF = 0;
1032 int Predecrement = 0;
1033 enum {
1034 Start,
1035 Start2,
1036 Start3,
1038 FloatRegs,
1039 InputArgs,
1040 StackAdjust,
1041 FrameRecord,
1042 End
1043 } Location = Start;
1044 bool StandaloneLR = false, FPLRPair = false;
1045 bool PAC = false;
1047 int Nops = 0;
1048
1049
1050
1051
1052
1053
1054 for (auto It = info->Instructions.begin(), EndIt = info->Instructions.end();
1055 It != EndIt; It++) {
1059 if (Location != Start)
1060 return false;
1061 Location = Start2;
1062 break;
1064 if (Location != Start2)
1065 return false;
1066 PAC = true;
1067 Location = Start3;
1068 break;
1070 if (Location != Start2 && Location != Start3)
1071 return false;
1072 Predecrement = Inst.Offset;
1073 RegI = 2;
1075 break;
1077 if (Location != Start2 && Location != Start3)
1078 return false;
1079 Predecrement = Inst.Offset;
1081 RegI += 1;
1082 else if (Inst.Register == 30)
1083 StandaloneLR = true;
1084 else
1085 return false;
1086
1087 Location = FloatRegs;
1088 break;
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101 return false;
1103 if (Location != IntRegs || Inst.Offset != 8 * RegI ||
1105 return false;
1106 RegI += 2;
1107 break;
1109 if (Location != IntRegs || Inst.Offset != 8 * RegI)
1110 return false;
1111 if (Inst.Register == 19 + RegI)
1112 RegI += 1;
1113 else if (Inst.Register == 30)
1114 StandaloneLR = true;
1115 else
1116 return false;
1117
1118 Location = FloatRegs;
1119 break;
1121 if (Location != IntRegs || Inst.Offset != 8 * RegI ||
1123 return false;
1124 RegI += 1;
1125 StandaloneLR = true;
1126 Location = FloatRegs;
1127 break;
1129
1130
1131 return false;
1133 if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
1134 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
1135 return false;
1136 RegF += 1;
1137 Location = InputArgs;
1138 break;
1140 if ((Location != Start2 && Location != Start3) || Inst.Register != 8)
1141 return false;
1142 Predecrement = Inst.Offset;
1143 RegF = 2;
1144 Location = FloatRegs;
1145 break;
1147 if ((Location != IntRegs && Location != FloatRegs) ||
1148 Inst.Register != 8 + RegF ||
1149 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
1150 return false;
1151 RegF += 2;
1152 Location = FloatRegs;
1153 break;
1155 if (Location == IntRegs)
1156 RegI += 2;
1157 else if (Location == FloatRegs)
1158 RegF += 2;
1159 else
1160 return false;
1161 break;
1163 if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
1164 return false;
1165 Location = InputArgs;
1166 Nops++;
1167 break;
1170 if (Location != Start2 && Location != Start3 && Location != IntRegs &&
1171 Location != FloatRegs && Location != InputArgs &&
1172 Location != StackAdjust)
1173 return false;
1174
1175
1176
1177
1178 if (Location == Start2) {
1179 auto NextIt = It + 1;
1180 if (NextIt != EndIt) {
1184 assert(Predecrement == 0);
1186 assert(!StandaloneLR);
1187 Predecrement = Inst.Offset;
1188 RegI = 1;
1189 StandaloneLR = true;
1190 Location = FloatRegs;
1191 It++;
1192 continue;
1193 }
1194 }
1195 }
1196
1197
1201 return false;
1202 else
1204 Location = StackAdjust;
1205 break;
1207
1208
1209 if (Location != Start2 && Location != Start3 && Location != IntRegs &&
1210 Location != FloatRegs && Location != InputArgs)
1211 return false;
1213 Location = FrameRecord;
1214 FPLRPair = true;
1215 break;
1217
1218 if (Location != StackAdjust || Inst.Offset != 0)
1219 return false;
1220 Location = FrameRecord;
1221 FPLRPair = true;
1222 break;
1224 if (Location != FrameRecord)
1225 return false;
1226 Location = End;
1227 break;
1240
1241
1242 return false;
1244
1245
1246
1247 return false;
1249
1250
1251 return false;
1255
1256 return false;
1262
1263 return false;
1264 default:
1266 }
1267 }
1268 if (RegI > 10 || RegF > 8)
1269 return false;
1270 if (StandaloneLR && FPLRPair)
1271 return false;
1272 if (FPLRPair && Location != End)
1273 return false;
1274 if (Nops != 0 && Nops != 4)
1275 return false;
1276 if (PAC && !FPLRPair)
1277 return false;
1278 int H = Nops == 4;
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294 if (H)
1295 return false;
1296
1297
1298
1299
1300
1301
1302
1303 if (StandaloneLR && RegI == 1 && RegF > 0)
1304 return false;
1305 int IntSZ = 8 * RegI;
1306 if (StandaloneLR)
1307 IntSZ += 8;
1308 int FpSZ = 8 * RegF;
1309 int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
1310 if (Predecrement != SavSZ)
1311 return false;
1313 return false;
1315 return false;
1317 if (FrameSize > 0x1FF)
1318 return false;
1319 assert(RegF != 1 && "One single float reg not allowed");
1320 if (RegF > 0)
1321 RegF--;
1322 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
1323 int Flag = 0x01;
1324 int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
1325 info->PackedInfo |= Flag << 0;
1326 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
1327 info->PackedInfo |= (RegF & 0x7) << 13;
1328 info->PackedInfo |= (RegI & 0xF) << 16;
1329 info->PackedInfo |= (H & 0x1) << 20;
1330 info->PackedInfo |= (CR & 0x3) << 21;
1331 info->PackedInfo |= (FrameSize & 0x1FF) << 23;
1332 return true;
1333}
1334
1339
1340 std::vector<MCSymbol *> EpilogStarts;
1341 for (auto &I : Seg->Epilogs)
1342 EpilogStarts.push_back(I.first);
1343
1344
1345 std::vector<MCSymbol *> AddedEpilogs;
1346 for (auto *S : EpilogStarts) {
1348 auto &EpilogInstrs = info->EpilogMap[S].Instructions;
1350
1353 int PrologOffset;
1354 if (MatchingEpilog) {
1356 "Duplicate epilog not found");
1357 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
1358
1359
1360 EpilogInstrs.clear();
1362 EpilogInstrs)) >= 0) {
1363 EpilogInfo[EpilogStart] = PrologOffset;
1364
1365
1367 EpilogInfo[EpilogStart] += 1;
1368
1369
1370 EpilogInstrs.clear();
1371 } else {
1372 EpilogInfo[EpilogStart] = TotalCodeBytes;
1373 TotalCodeBytes += CodeBytes;
1374 AddedEpilogs.push_back(EpilogStart);
1375 }
1376 }
1377}
1378
1381 int64_t RawFuncLength) {
1382 if (info->PrologEnd)
1384 info->PrologEnd, info->Function->getName(),
1385 "prologue");
1386 struct EpilogStartEnd {
1389 int64_t End;
1390 };
1391
1393 for (auto &I : info->EpilogMap) {
1395 auto &Instrs = I.second.Instructions;
1398 info->Function->getName(), "epilogue");
1400 "Epilogs should be monotonically ordered");
1401
1402
1404 }
1405
1406 unsigned E = 0;
1407 int64_t SegLimit = 0xFFFFC;
1408 int64_t SegOffset = 0;
1409
1410 if (RawFuncLength > SegLimit) {
1411
1412 int64_t RemainingLength = RawFuncLength;
1413
1414 while (RemainingLength > SegLimit) {
1415
1416
1417
1418 int64_t SegLength = SegLimit;
1419 int64_t SegEnd = SegOffset + SegLength;
1420
1422
1423 while (E < Epilogs.size() && Epilogs[E].End < SegEnd) {
1424
1425 EpilogsInSegment[Epilogs[E].Start] = Epilogs[E].Offset;
1426 ++E;
1427 }
1428
1429
1430
1431
1432
1433
1434
1435
1436 if (E < Epilogs.size() && Epilogs[E].Offset <= SegEnd)
1437
1438 SegLength = Epilogs[E].Offset - SegOffset;
1439
1441 SegOffset, SegLength, !SegOffset);
1442 Seg.Epilogs = std::move(EpilogsInSegment);
1443 info->Segments.push_back(Seg);
1444
1445 SegOffset += SegLength;
1446 RemainingLength -= SegLength;
1447 }
1448 }
1449
1450
1451
1452 auto LastSeg =
1454 !SegOffset);
1455 for (; E < Epilogs.size(); ++E)
1456 LastSeg.Epilogs[Epilogs[E].Start] = Epilogs[E].Offset;
1457 info->Segments.push_back(LastSeg);
1458}
1459
1463 bool TryPacked = true) {
1466
1470
1471 if (Seg.Offset == 0)
1472 info->Symbol = Label;
1473
1475 bool HasEpilogs = (Seg.Epilogs.size() != 0);
1476
1478 uint32_t PrologCodeBytes = info->PrologCodeBytes;
1479
1480 int PackedEpilogOffset = HasEpilogs ?
1482
1483
1484
1485
1486
1487 if (info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
1488 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
1489 ->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
1490
1491
1492
1493
1494
1495
1496
1498 return;
1499 }
1500
1501
1502
1503 if (!HasProlog) {
1504 PrologCodeBytes += 1;
1505 if (PackedEpilogOffset >= 0)
1506 PackedEpilogOffset += 1;
1507
1508
1509
1510
1511
1512 if (!HasEpilogs)
1513
1514 PackedEpilogOffset = 0;
1515 }
1516
1517 uint32_t TotalCodeBytes = PrologCodeBytes;
1518
1519
1522
1523
1525 uint32_t CodeWords = TotalCodeBytes / 4;
1526 uint32_t CodeWordsMod = TotalCodeBytes % 4;
1527 if (CodeWordsMod)
1528 CodeWords++;
1530 PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.Epilogs.size();
1531 bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
1532 if (!ExtensionWord) {
1533 row1 |= (EpilogCount & 0x1F) << 22;
1534 row1 |= (CodeWords & 0x1F) << 27;
1535 }
1536 if (info->HandlesExceptions)
1537 row1 |= 1 << 20;
1538 if (PackedEpilogOffset >= 0)
1539 row1 |= 1 << 21;
1540 row1 |= SegLength & 0x3FFFF;
1542
1543
1544 if (ExtensionWord) {
1545
1546 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
1548 "SEH unwind data splitting is only implemented for large functions, "
1549 "cases of too many code words or too many epilogs will be done "
1550 "later");
1552 row2 |= (CodeWords & 0xFF) << 16;
1553 row2 |= (EpilogCount & 0xFFFF);
1555 }
1556
1557 if (PackedEpilogOffset < 0) {
1558
1559 for (auto &I : EpilogInfo) {
1560 MCSymbol *EpilogStart = I.first;
1561 uint32_t EpilogIndex = I.second;
1562
1564 if (EpilogOffset)
1565 EpilogOffset /= 4;
1566 uint32_t row3 = EpilogOffset;
1567 row3 |= (EpilogIndex & 0x3FF) << 22;
1569 }
1570 }
1571
1572
1573
1574
1575
1576
1577
1578 if (!HasProlog)
1579
1581
1582
1585
1586
1587 for (auto &I : Seg.Epilogs) {
1588 auto &EpilogInstrs = info->EpilogMap[I.first].Instructions;
1591 }
1592
1593 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
1594 assert(BytesMod >= 0);
1595 for (int i = 0; i < BytesMod; i++)
1597
1598 if (info->HandlesExceptions)
1602 4);
1603}
1604
1605
1606
1608 bool TryPacked = true) {
1609
1610 if (info->Symbol)
1611 return;
1612
1613
1614
1615
1616 if (info->empty()) {
1617 info->EmitAttempted = true;
1618 return;
1619 }
1620 if (info->EmitAttempted) {
1621
1622
1623
1624
1625
1627 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
1628 " skipped due to no unwind info at the time "
1629 "(.seh_handlerdata too early?), but the function later "
1630 "did get unwind info that can't be emitted");
1631 return;
1632 }
1633
1635 for (auto &I : info->EpilogMap)
1637
1638 int64_t RawFuncLength;
1639 if (->FuncletOrFuncEnd) {
1641 } else {
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1672 info->Begin);
1673 }
1674
1676
1678 for (auto &S : info->Segments)
1680
1681
1682 info->Instructions.clear();
1683}
1684
1687 for (const auto &I : Insns) {
1689 default:
1693 break;
1696 break;
1699 break;
1702 break;
1705 break;
1708 break;
1711 break;
1714 break;
1717 break;
1720 break;
1723 break;
1726 break;
1729 break;
1732 break;
1735 break;
1742 break;
1744 int J;
1745 for (J = 3; J > 0; J--)
1746 if (I.Offset & (0xffu << (8 * J)))
1747 break;
1749 break;
1750 }
1751 }
1752 }
1754}
1755
1757 bool *HasCustom = nullptr) {
1759 for (const auto &I : Insns) {
1761 default:
1767 break;
1772 break;
1776 break;
1779 break;
1783 break;
1788 break;
1791 break;
1795 break;
1799 break;
1801
1802 break;
1804
1805
1807 if (HasCustom)
1808 *HasCustom = true;
1809 break;
1810 }
1811 }
1813}
1814
1819 if (!End)
1820 return;
1821 std::optional<int64_t> MaybeDistance =
1823 if (!MaybeDistance)
1824 return;
1826 bool HasCustom = false;
1828 if (HasCustom)
1829 return;
1830 if (Distance != InstructionBytes) {
1832 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
1833 Twine(Distance) +
1834 " bytes of instructions in range, but .seh directives "
1835 "corresponding to " +
1836 Twine(InstructionBytes) + " bytes\n");
1837 }
1838}
1839
1845 return true;
1846 default:
1847 return false;
1848 }
1849}
1850
1851
1852
1856 int i;
1858 default:
1864 break;
1867 lr = (inst.Register >> 14) & 1;
1868 w = 0x8000 | (inst.Register & 0x1fff) | (lr << 13);
1869 streamer.emitInt8((w >> 8) & 0xff);
1870 streamer.emitInt8((w >> 0) & 0xff);
1871 break;
1875 break;
1880 break;
1885 break;
1889 break;
1893 w = 0xe800 | (inst.Offset / 4);
1894 streamer.emitInt8((w >> 8) & 0xff);
1895 streamer.emitInt8((w >> 0) & 0xff);
1896 break;
1899 lr = (inst.Register >> 14) & 1;
1900 w = 0xec00 | (inst.Register & 0x0ff) | (lr << 8);
1901 streamer.emitInt8((w >> 8) & 0xff);
1902 streamer.emitInt8((w >> 0) & 0xff);
1903 break;
1909 break;
1916 break;
1923 break;
1927 w = inst.Offset / 4;
1929 streamer.emitInt8((w >> 8) & 0xff);
1930 streamer.emitInt8((w >> 0) & 0xff);
1931 break;
1935 w = inst.Offset / 4;
1937 streamer.emitInt8((w >> 16) & 0xff);
1938 streamer.emitInt8((w >> 8) & 0xff);
1939 streamer.emitInt8((w >> 0) & 0xff);
1940 break;
1944 w = inst.Offset / 4;
1946 streamer.emitInt8((w >> 8) & 0xff);
1947 streamer.emitInt8((w >> 0) & 0xff);
1948 break;
1952 w = inst.Offset / 4;
1954 streamer.emitInt8((w >> 16) & 0xff);
1955 streamer.emitInt8((w >> 8) & 0xff);
1956 streamer.emitInt8((w >> 0) & 0xff);
1957 break;
1960 break;
1963 break;
1966 break;
1969 break;
1972 break;
1974 for (i = 3; i > 0; i--)
1975 if (inst.Offset & (0xffu << (8 * i)))
1976 break;
1977 for (; i >= 0; i--)
1979 break;
1980 }
1981}
1982
1983
1984
1985
1986
1987
1988
1990 const std::vectorWinEH::Instruction &Epilog,
1991 bool CanTweakProlog) {
1992
1994 return -1;
1995
1996
1997
1998
1999
2000 int EndIdx = CanTweakProlog ? 1 : 0;
2001 for (int I = Epilog.size() - 1; I >= EndIdx; I--) {
2002
2003
2005 return -1;
2006 }
2007
2008 if (CanTweakProlog) {
2009
2011 return -1;
2015 return -1;
2016 }
2017
2018
2020 return 0;
2023}
2024
2026 int PrologCodeBytes) {
2027
2028 if (info->EpilogMap.size() != 1)
2029 return -1;
2030
2032
2033 if (EpilogInfo.Condition != 0xe)
2034 return -1;
2035
2036 const std::vectorWinEH::Instruction &Epilog = EpilogInfo.Instructions;
2037
2038 if (info->Instructions.empty() || Epilog.empty())
2039 return -1;
2040
2041
2042
2044 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
2045 if (!MaybeDistance)
2046 return -1;
2049 if (DistanceFromEnd != InstructionBytes)
2050 return -1;
2051
2052 int RetVal = -1;
2053
2054
2055
2056
2057 if (PrologCodeBytes <= 31 &&
2059 RetVal = PrologCodeBytes;
2060
2064 return RetVal;
2065
2066
2067
2068
2069 if (Offset > 31 || PrologCodeBytes > 63)
2070 return RetVal;
2071
2072
2073
2074 info->Instructions.front() = Epilog.back();
2075
2076
2077
2078 info->EpilogMap.clear();
2080}
2081
2082static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11,
2083 unsigned &Folded, int &IntRegs) {
2084 if (Mask & (1 << 14)) {
2085 HasLR = true;
2086 Mask &= ~(1 << 14);
2087 }
2088 if (Mask & (1 << 11)) {
2089 HasR11 = true;
2090 Mask &= ~(1 << 11);
2091 }
2092 Folded = 0;
2094 if (!Mask)
2095 return true;
2097
2098 while ((Mask & 1) == 0) {
2100 Mask >>= 1;
2101 }
2102 if ((Mask & (Mask + 1)) != 0)
2103 return false;
2104
2105 int N = 0;
2106 while (Mask & (1 << N))
2107 N++;
2108 if (First < 4) {
2110 return false;
2111 Folded = 4 - First;
2112 N -= Folded;
2114 }
2116 return false;
2117 if (N >= 1)
2119 return true;
2120}
2121
2124 int Step = 0;
2125 bool Homing = false;
2126 bool HasR11 = false;
2127 bool HasChain = false;
2128 bool HasLR = false;
2129 int IntRegs = -1;
2130 int FloatRegs = -1;
2131 unsigned PF = 0;
2132 unsigned StackAdjust = 0;
2133
2134
2137 default:
2146
2147 return false;
2149
2150
2151 return false;
2153
2154 return false;
2155
2159 if (Step != 0)
2160 return false;
2161 Step = 1;
2162 break;
2163
2166
2167 if (Step != 1 && Step != 2)
2168 return false;
2173 HasR11 = true;
2175 }
2177 HasLR = true;
2178 Step = 3;
2179 break;
2180
2182 if (Step == 1 && Inst.Register == 0x0f) {
2183
2184 Homing = true;
2185 Step = 2;
2186 break;
2187 }
2188 [[fallthrough]];
2190 if (Step != 1 && Step != 2)
2191 return false;
2192
2193
2194
2196 return false;
2197 Step = 3;
2198 break;
2199
2201
2202 if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)
2203 return false;
2204 HasChain = true;
2205 Step = 4;
2206 break;
2208
2209 if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))
2210 return false;
2211 HasChain = true;
2212 Step = 4;
2213 break;
2214
2216 if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
2217 return false;
2220 return false;
2222 return false;
2223 FloatRegs = Inst.Register - 8;
2224 Step = 5;
2225 break;
2226
2229 if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
2230 return false;
2231 if (PF > 0)
2232 return false;
2233 if (Inst.Offset / 4 >= 0x3f4)
2234 return false;
2235 StackAdjust = Inst.Offset / 4;
2236 Step = 6;
2237 break;
2238 }
2239 }
2240 if (HasR11 && !HasChain) {
2241 if (IntRegs + 4 == 10) {
2242
2243
2245 HasR11 = false;
2246 } else
2247 return false;
2248 }
2249 if (HasChain && !HasLR)
2250 return false;
2251
2252
2253 if (info->EpilogMap.size() > 1)
2254 return false;
2255
2256 unsigned EF = 0;
2257 int Ret = 0;
2258 if (info->EpilogMap.size() == 0) {
2259 Ret = 3;
2260 } else {
2261
2262
2263
2265 info->EpilogMap.begin()->second;
2266 if (EpilogInfo.Condition != 0xe)
2267 return false;
2268 const std::vectorWinEH::Instruction &Epilog = EpilogInfo.Instructions;
2270 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
2271 if (!MaybeDistance)
2272 return false;
2275 if (DistanceFromEnd != InstructionBytes)
2276 return false;
2277
2278 bool GotStackAdjust = false;
2279 bool GotFloatRegs = false;
2280 bool GotIntRegs = false;
2281 bool GotHomingRestore = false;
2282 bool GotLRRestore = false;
2283 bool NeedsReturn = false;
2284 bool GotReturn = false;
2285
2286 Step = 6;
2289 default:
2301
2302 return false;
2303
2306 if (Inst.Offset / 4 >= 0x3f4)
2307 return false;
2308 if (Step == 6) {
2309 if (Homing && FloatRegs < 0 && IntRegs < 0 && StackAdjust == 0 &&
2310 PF == 0 && Inst.Offset == 16) {
2311 GotHomingRestore = true;
2312 Step = 10;
2313 } else {
2314 if (StackAdjust > 0) {
2315
2316 if (StackAdjust != Inst.Offset / 4)
2317 return false;
2318 GotStackAdjust = true;
2319 } else if (PF == Inst.Offset / 4) {
2320
2321 StackAdjust = Inst.Offset / 4;
2322 GotStackAdjust = true;
2323 } else {
2324
2325 return false;
2326 }
2327 Step = 7;
2328 }
2329 } else if (Step == 7 || Step == 8 || Step == 9) {
2330 if (!Homing || Inst.Offset != 16)
2331 return false;
2332 GotHomingRestore = true;
2333 Step = 10;
2334 } else
2335 return false;
2336 break;
2337
2339 if (Step != 6 && Step != 7)
2340 return false;
2342 if (FloatRegs != (int)(Inst.Register - 8))
2343 return false;
2344 GotFloatRegs = true;
2345 Step = 8;
2346 break;
2347
2350
2351 if (Step != 6 && Step != 7 && Step != 8)
2352 return false;
2355 if (Homing && HasLR) {
2356
2357
2359 GotLRRestore = true;
2360 NeedsReturn = true;
2361 } else {
2362
2363 }
2364 } else {
2365 if (HasLR != (Inst.Offset == 1))
2366 return false;
2367 }
2368 GotLRRestore = Inst.Offset == 1;
2369 if (IntRegs < 0)
2370 return false;
2372 if (HasChain) {
2373
2375 return false;
2377 }
2379 return false;
2380 GotIntRegs = true;
2381 Step = 9;
2382 break;
2383 }
2384
2387 if (Step != 6 && Step != 7 && Step != 8)
2388 return false;
2389
2390
2391
2392 bool CurHasLR = false, CurHasR11 = false;
2393 int Regs;
2395 return false;
2396 if (EF > 0) {
2397 if (EF != PF && EF != StackAdjust)
2398 return false;
2399 }
2400 if (Homing && HasLR) {
2401
2402
2403 if (CurHasLR) {
2404 GotLRRestore = true;
2405 NeedsReturn = true;
2406 } else {
2407
2408 }
2409 } else {
2410 if (CurHasLR != HasLR)
2411 return false;
2412 GotLRRestore = CurHasLR;
2413 }
2415 if (HasChain) {
2416
2417 if (!CurHasR11)
2418 return false;
2420
2421
2423 if (!CurHasR11)
2424 return false;
2425 } else {
2426
2427
2428 if (CurHasR11)
2429 return false;
2430 }
2432 return false;
2433 GotIntRegs = true;
2434 Step = 9;
2435 break;
2436 }
2437
2439 if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
2440 return false;
2441 if (!Homing || Inst.Offset != 20 || GotLRRestore)
2442 return false;
2443 GotLRRestore = true;
2444 GotHomingRestore = true;
2445 Step = 10;
2446 break;
2447
2450 GotReturn = true;
2452 [[fallthrough]];
2454 if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
2455 return false;
2456 Step = 11;
2457 break;
2458 }
2459 }
2460
2461 if (Step != 11)
2462 return false;
2463 if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
2464 return false;
2465 if (FloatRegs >= 0 && !GotFloatRegs)
2466 return false;
2467 if (IntRegs >= 0 && !GotIntRegs)
2468 return false;
2469 if (Homing && !GotHomingRestore)
2470 return false;
2471 if (HasLR && !GotLRRestore)
2472 return false;
2473 if (NeedsReturn && !GotReturn)
2474 return false;
2475 }
2476
2477 assert(PF == 0 || EF == 0 ||
2478 StackAdjust == 0);
2479 if (PF > 0 || EF > 0) {
2480 StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
2481 assert(StackAdjust <= 3);
2482 StackAdjust |= 0x3f0;
2483 if (PF > 0)
2484 StackAdjust |= 1 << 2;
2485 if (EF > 0)
2486 StackAdjust |= 1 << 3;
2487 }
2488
2489 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
2490 int Flag = info->Fragment ? 0x02 : 0x01;
2491 int H = Homing ? 1 : 0;
2492 int L = HasLR ? 1 : 0;
2493 int C = HasChain ? 1 : 0;
2495 unsigned Reg, R;
2499 R = 0;
2500 } else if (FloatRegs >= 0) {
2501 Reg = FloatRegs;
2503 R = 1;
2504 } else {
2505
2506 Reg = 7;
2507 R = 1;
2508 }
2509 info->PackedInfo |= Flag << 0;
2510 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
2511 info->PackedInfo |= (Ret & 0x3) << 13;
2512 info->PackedInfo |= H << 15;
2513 info->PackedInfo |= Reg << 16;
2514 info->PackedInfo |= R << 19;
2515 info->PackedInfo |= L << 20;
2516 info->PackedInfo |= C << 21;
2517 assert(StackAdjust <= 0x3ff);
2518 info->PackedInfo |= StackAdjust << 22;
2519 return true;
2520}
2521
2522
2523
2525 bool TryPacked = true) {
2526
2527 if (info->Symbol)
2528 return;
2529
2530
2531
2532
2533 if (info->empty()) {
2534 info->EmitAttempted = true;
2535 return;
2536 }
2537 if (info->EmitAttempted) {
2538
2539
2540
2541
2542
2544 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
2545 " skipped due to no unwind info at the time "
2546 "(.seh_handlerdata too early?), but the function later "
2547 "did get unwind info that can't be emitted");
2548 return;
2549 }
2550
2553
2556 info->Symbol = Label;
2557
2558 if (->PrologEnd)
2560 info->Function->getName() +
2561 " not correctly terminated");
2562
2563 if (info->PrologEnd && ->Fragment)
2565 info->PrologEnd, info->Function->getName(),
2566 "prologue");
2567 for (auto &I : info->EpilogMap) {
2568 MCSymbol *EpilogStart = I.first;
2571 info->Function->getName(), "epilogue");
2572 if (Epilog.Instructions.empty() ||
2575 SMLoc(), "Epilogue in " + info->Function->getName() +
2576 " not correctly terminated");
2577 }
2578
2579 std::optional<int64_t> RawFuncLength;
2580 const MCExpr *FuncLengthExpr = nullptr;
2581 if (->FuncletOrFuncEnd) {
2583 } else {
2584
2585
2586
2587
2588
2589
2590
2591
2592 RawFuncLength =
2594 if (!RawFuncLength)
2595 FuncLengthExpr =
2597 }
2599 if (RawFuncLength)
2600 FuncLength = (uint32_t)*RawFuncLength / 2;
2601 if (FuncLength > 0x3FFFF)
2602 report_fatal_error("SEH unwind data splitting not yet implemented");
2604 uint32_t TotalCodeBytes = PrologCodeBytes;
2605
2606 if (->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
2607 TryPacked) {
2608
2609
2610
2611
2612
2613
2614
2615
2617 return;
2618 }
2619
2620 int PackedEpilogOffset =
2622
2623
2625
2626 std::vector<MCSymbol *> AddedEpilogs;
2627
2628 bool CanTweakProlog = true;
2629 for (auto &I : info->EpilogMap) {
2630 MCSymbol *EpilogStart = I.first;
2631 auto &EpilogInstrs = I.second.Instructions;
2633
2636 int PrologOffset;
2637 if (MatchingEpilog) {
2639 "Duplicate epilog not found");
2640 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
2641
2642
2643 EpilogInstrs.clear();
2645 info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
2646 if (CanTweakProlog) {
2647
2648
2649 info->Instructions.front() = EpilogInstrs.back();
2650
2651 CanTweakProlog = false;
2652 }
2653 EpilogInfo[EpilogStart] = PrologOffset;
2654
2655
2656 EpilogInstrs.clear();
2657 } else {
2658 EpilogInfo[EpilogStart] = TotalCodeBytes;
2659 TotalCodeBytes += CodeBytes;
2660 AddedEpilogs.push_back(EpilogStart);
2661 }
2662 }
2663
2664
2666 uint32_t CodeWords = TotalCodeBytes / 4;
2667 uint32_t CodeWordsMod = TotalCodeBytes % 4;
2668 if (CodeWordsMod)
2669 CodeWords++;
2671 PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
2672 bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
2673 if (!ExtensionWord) {
2674 row1 |= (EpilogCount & 0x1F) << 23;
2675 row1 |= (CodeWords & 0x0F) << 28;
2676 }
2677 if (info->HandlesExceptions)
2678 row1 |= 1 << 20;
2679 if (PackedEpilogOffset >= 0)
2680 row1 |= 1 << 21;
2681 if (info->Fragment)
2682 row1 |= 1 << 22;
2683 row1 |= FuncLength & 0x3FFFF;
2684 if (RawFuncLength)
2686 else
2690 4);
2691
2692
2693 if (ExtensionWord) {
2694
2695 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
2696 report_fatal_error("SEH unwind data splitting not yet implemented");
2698 row2 |= (CodeWords & 0xFF) << 16;
2699 row2 |= (EpilogCount & 0xFFFF);
2701 }
2702
2703 if (PackedEpilogOffset < 0) {
2704
2705 for (auto &I : EpilogInfo) {
2706 MCSymbol *EpilogStart = I.first;
2707 uint32_t EpilogIndex = I.second;
2708
2709 std::optional<int64_t> MaybeEpilogOffset =
2711 const MCExpr *OffsetExpr = nullptr;
2713 if (MaybeEpilogOffset)
2714 EpilogOffset = *MaybeEpilogOffset / 2;
2715 else
2716 OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);
2717
2718 assert(info->EpilogMap.contains(EpilogStart));
2719 unsigned Condition = info->EpilogMap[EpilogStart].Condition;
2720 assert(Condition <= 0xf);
2721
2722 uint32_t row3 = EpilogOffset;
2723 row3 |= Condition << 20;
2724 row3 |= (EpilogIndex & 0x3FF) << 24;
2725 if (MaybeEpilogOffset)
2727 else
2731 4);
2732 }
2733 }
2734
2735
2736 uint8_t numInst = info->Instructions.size();
2737 for (uint8_t c = 0; c < numInst; ++c) {
2739 info->Instructions.pop_back();
2741 }
2742
2743
2744 for (auto &I : info->EpilogMap) {
2745 auto &EpilogInstrs = I.second.Instructions;
2748 }
2749
2750 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2751 assert(BytesMod >= 0);
2752 for (int i = 0; i < BytesMod; i++)
2754
2755 if (info->HandlesExceptions)
2759 4);
2760}
2761
2765
2767 for (const auto &S : info->Segments) {
2769 if (info->PackedInfo)
2771 else
2774 context),
2775 4);
2776 }
2777}
2778
2779
2783
2786 if (info->PackedInfo)
2788 else
2791 context),
2792 4);
2793}
2794
2796
2799 if (Info->empty())
2800 continue;
2804 }
2805
2806
2809
2810
2811
2812 if (!Info->Symbol)
2813 continue;
2817 }
2818}
2819
2822 bool HandlerData) const {
2823
2824
2825
2826
2827
2828
2829 if (->FuncletOrFuncEnd) {
2832 }
2833
2834
2838}
2839
2841
2844 if (Info->empty())
2845 continue;
2849 }
2850
2851
2854
2855
2856
2857 if (!Info->Symbol)
2858 continue;
2862 }
2863}
2864
2867 bool HandlerData) const {
2868
2869
2870
2871
2872
2873
2874 if (->FuncletOrFuncEnd) {
2877 }
2878
2879
2883}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static int checkARM64PackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, int PrologCodeBytes)
Definition MCWin64EH.cpp:970
static void ARM64EmitUnwindInfoForSegment(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment &Seg, bool TryPacked=true)
Definition MCWin64EH.cpp:1460
static uint32_t ARMCountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
Definition MCWin64EH.cpp:1685
static uint32_t ARM64CountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
Definition MCWin64EH.cpp:513
static void checkARMInstructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)
Definition MCWin64EH.cpp:1815
static bool isARMTerminator(const WinEH::Instruction &inst)
Definition MCWin64EH.cpp:1840
static void ARM64EmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
Definition MCWin64EH.cpp:623
static void simplifyARM64Opcodes(std::vector< WinEH::Instruction > &Instructions, bool Reverse)
Definition MCWin64EH.cpp:885
static void ARMEmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
Definition MCWin64EH.cpp:1853
static std::optional< int64_t > GetOptionalAbsDifference(const MCAssembler &Assembler, const MCSymbol *LHS, const MCSymbol *RHS)
Definition MCWin64EH.cpp:213
static int getARM64OffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog)
Definition MCWin64EH.cpp:949
static void ARMEmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition MCWin64EH.cpp:2780
static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength, int PackedEpilogOffset)
Definition MCWin64EH.cpp:1013
static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)
Definition MCWin64EH.cpp:228
static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)
Definition MCWin64EH.cpp:108
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
Definition MCWin64EH.cpp:1607
static int getARMOffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog, bool CanTweakProlog)
Definition MCWin64EH.cpp:1989
static void ARM64EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition MCWin64EH.cpp:2762
static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, int64_t Offset)
Definition MCWin64EH.cpp:176
static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11, unsigned &Folded, int &IntRegs)
Definition MCWin64EH.cpp:2082
static int checkARMPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)
Definition MCWin64EH.cpp:2025
static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition MCWin64EH.cpp:466
static void ARM64FindSegmentsInFunction(MCStreamer &streamer, WinEH::FrameInfo *info, int64_t RawFuncLength)
Definition MCWin64EH.cpp:1379
static bool tryARMPackedUnwind(MCStreamer &streamer, WinEH::FrameInfo *info, uint32_t FuncLength)
Definition MCWin64EH.cpp:2122
static MCSymbol * FindMatchingEpilog(const std::vector< WinEH::Instruction > &EpilogInstrs, const std::vector< MCSymbol * > &Epilogs, const WinEH::FrameInfo *info)
Definition MCWin64EH.cpp:860
static void EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition MCWin64EH.cpp:200
static void checkARM64Instructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)
Definition MCWin64EH.cpp:475
static const MCExpr * GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS, int Div)
Definition MCWin64EH.cpp:447
static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition MCWin64EH.cpp:99
static void ARMEmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
Definition MCWin64EH.cpp:2524
static uint32_t ARMCountOfInstructionBytes(ArrayRef< WinEH::Instruction > Insns, bool *HasCustom=nullptr)
Definition MCWin64EH.cpp:1756
static void ARM64ProcessEpilogs(WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, uint32_t &TotalCodeBytes, MapVector< MCSymbol *, uint32_t > &EpilogInfo)
Definition MCWin64EH.cpp:1335
static uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)
Definition MCWin64EH.cpp:71
static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, const MCSpecifierExpr &Expr)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
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.
Tagged union holding either a T or a Error.
MCContext & getContext() const
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
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 LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI 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.
MCAssembler & getAssembler()
void appendContents(ArrayRef< char > Contents)
void addFixup(const MCExpr *Value, MCFixupKind Kind)
void ensureHeadroom(size_t Headroom)
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 Fill=0, uint8_t FillLen=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, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
MCFragment * getFragment() const
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)
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
Definition MCWin64EH.cpp:2820
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition MCWin64EH.cpp:2795
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition MCWin64EH.cpp:2840
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition MCWin64EH.cpp:2865
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition MCWin64EH.cpp:420
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition MCWin64EH.cpp:436
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ 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.
UnwindOpcodes
UnwindOpcodes - Enumeration whose values specify a single operation in the prolog of a function.
@ UOP_WideSaveRegsR4R11LR
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ FK_Data_2
A two-byte fixup.
DWARFExpression::Operation Op
This struct is a compact representation of a valid (non-zero power of two) alignment.
std::vector< Instruction > Instructions
MapVector< MCSymbol *, int64_t > Epilogs