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
890
891
892
895
898 Inst.Register = -1;
900 Inst.Register == 29) {
902 Inst.Register = -1;
904 Inst.Register == 19 && Inst.Offset <= 248) {
906 Inst.Register = -1;
907 } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {
910 Inst.Register == PrevRegister + 2 &&
911 Inst.Offset == PrevOffset + 16) {
913 Inst.Register = -1;
914 Inst.Offset = 0;
915
916
917
918 }
919
920
922 PrevOffset = 0;
923 PrevRegister = 19;
925 PrevOffset = 0;
926 PrevRegister = Inst.Register;
928 PrevOffset = Inst.Offset;
929 PrevRegister = Inst.Register;
931 PrevRegister += 2;
932 PrevOffset += 16;
933 } else {
934 PrevRegister = -1;
935 PrevOffset = -1;
936 }
937 }
938}
939
940
941static int
943 const std::vectorWinEH::Instruction &Epilog) {
944
946 return -1;
947
948
949
950 for (int I = Epilog.size() - 1; I >= 0; I--) {
952 return -1;
953 }
954
956 return 0;
957
958
961}
962
965 int PrologCodeBytes) {
966
967 if (Seg->Epilogs.size() != 1)
968 return -1;
969
971 const std::vectorWinEH::Instruction &Epilog =
972 info->EpilogMap[Sym].Instructions;
973
974
975
978 if (DistanceFromEnd / 4 != Epilog.size())
979 return -1;
980
981 int RetVal = -1;
982
983
984
985
986 if (PrologCodeBytes <= 31 &&
988 RetVal = PrologCodeBytes;
989
992 return RetVal;
993
994
995
996
997 if (Offset > 31 || PrologCodeBytes > 124)
998 return RetVal;
999
1000
1001
1002 info->EpilogMap.erase(Sym);
1004}
1005
1007 int PackedEpilogOffset) {
1008 if (PackedEpilogOffset == 0) {
1009
1010
1011
1012
1013
1014 } else if (PackedEpilogOffset == 1) {
1015
1016
1017
1019 return false;
1020 } else {
1021
1022 return false;
1023 }
1024 unsigned RegI = 0, RegF = 0;
1025 int Predecrement = 0;
1026 enum {
1027 Start,
1028 Start2,
1029 Start3,
1031 FloatRegs,
1032 InputArgs,
1033 StackAdjust,
1034 FrameRecord,
1035 End
1036 } Location = Start;
1037 bool StandaloneLR = false, FPLRPair = false;
1038 bool PAC = false;
1040 int Nops = 0;
1041
1042
1043
1044
1045
1046
1047 for (auto It = info->Instructions.begin(), EndIt = info->Instructions.end();
1048 It != EndIt; It++) {
1052 if (Location != Start)
1053 return false;
1054 Location = Start2;
1055 break;
1057 if (Location != Start2)
1058 return false;
1059 PAC = true;
1060 Location = Start3;
1061 break;
1063 if (Location != Start2 && Location != Start3)
1064 return false;
1065 Predecrement = Inst.Offset;
1066 RegI = 2;
1068 break;
1070 if (Location != Start2 && Location != Start3)
1071 return false;
1072 Predecrement = Inst.Offset;
1074 RegI += 1;
1075 else if (Inst.Register == 30)
1076 StandaloneLR = true;
1077 else
1078 return false;
1079
1080 Location = FloatRegs;
1081 break;
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 return false;
1096 if (Location != IntRegs || Inst.Offset != 8 * RegI ||
1098 return false;
1099 RegI += 2;
1100 break;
1102 if (Location != IntRegs || Inst.Offset != 8 * RegI)
1103 return false;
1104 if (Inst.Register == 19 + RegI)
1105 RegI += 1;
1106 else if (Inst.Register == 30)
1107 StandaloneLR = true;
1108 else
1109 return false;
1110
1111 Location = FloatRegs;
1112 break;
1114 if (Location != IntRegs || Inst.Offset != 8 * RegI ||
1116 return false;
1117 RegI += 1;
1118 StandaloneLR = true;
1119 Location = FloatRegs;
1120 break;
1122
1123
1124 return false;
1126 if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
1127 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
1128 return false;
1129 RegF += 1;
1130 Location = InputArgs;
1131 break;
1133 if ((Location != Start2 && Location != Start3) || Inst.Register != 8)
1134 return false;
1135 Predecrement = Inst.Offset;
1136 RegF = 2;
1137 Location = FloatRegs;
1138 break;
1140 if ((Location != IntRegs && Location != FloatRegs) ||
1141 Inst.Register != 8 + RegF ||
1142 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
1143 return false;
1144 RegF += 2;
1145 Location = FloatRegs;
1146 break;
1148 if (Location == IntRegs)
1149 RegI += 2;
1150 else if (Location == FloatRegs)
1151 RegF += 2;
1152 else
1153 return false;
1154 break;
1156 if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
1157 return false;
1158 Location = InputArgs;
1159 Nops++;
1160 break;
1163 if (Location != Start2 && Location != Start3 && Location != IntRegs &&
1164 Location != FloatRegs && Location != InputArgs &&
1165 Location != StackAdjust)
1166 return false;
1167
1168
1169
1170
1171 if (Location == Start2) {
1172 auto NextIt = It + 1;
1173 if (NextIt != EndIt) {
1177 assert(Predecrement == 0);
1179 assert(!StandaloneLR);
1180 Predecrement = Inst.Offset;
1181 RegI = 1;
1182 StandaloneLR = true;
1183 Location = FloatRegs;
1184 It++;
1185 continue;
1186 }
1187 }
1188 }
1189
1190
1194 return false;
1195 else
1197 Location = StackAdjust;
1198 break;
1200
1201
1202 if (Location != Start2 && Location != Start3 && Location != IntRegs &&
1203 Location != FloatRegs && Location != InputArgs)
1204 return false;
1206 Location = FrameRecord;
1207 FPLRPair = true;
1208 break;
1210
1211 if (Location != StackAdjust || Inst.Offset != 0)
1212 return false;
1213 Location = FrameRecord;
1214 FPLRPair = true;
1215 break;
1217 if (Location != FrameRecord)
1218 return false;
1219 Location = End;
1220 break;
1233
1234
1235 return false;
1237
1238
1239
1240 return false;
1242
1243
1244 return false;
1248
1249 return false;
1255
1256 return false;
1257 default:
1259 }
1260 }
1261 if (RegI > 10 || RegF > 8)
1262 return false;
1263 if (StandaloneLR && FPLRPair)
1264 return false;
1265 if (FPLRPair && Location != End)
1266 return false;
1267 if (Nops != 0 && Nops != 4)
1268 return false;
1269 if (PAC && !FPLRPair)
1270 return false;
1271 int H = Nops == 4;
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287 if (H)
1288 return false;
1289
1290
1291
1292
1293
1294
1295
1296 if (StandaloneLR && RegI == 1 && RegF > 0)
1297 return false;
1298 int IntSZ = 8 * RegI;
1299 if (StandaloneLR)
1300 IntSZ += 8;
1301 int FpSZ = 8 * RegF;
1302 int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
1303 if (Predecrement != SavSZ)
1304 return false;
1306 return false;
1308 return false;
1310 if (FrameSize > 0x1FF)
1311 return false;
1312 assert(RegF != 1 && "One single float reg not allowed");
1313 if (RegF > 0)
1314 RegF--;
1315 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
1316 int Flag = 0x01;
1317 int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
1318 info->PackedInfo |= Flag << 0;
1319 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
1320 info->PackedInfo |= (RegF & 0x7) << 13;
1321 info->PackedInfo |= (RegI & 0xF) << 16;
1322 info->PackedInfo |= (H & 0x1) << 20;
1323 info->PackedInfo |= (CR & 0x3) << 21;
1324 info->PackedInfo |= (FrameSize & 0x1FF) << 23;
1325 return true;
1326}
1327
1332
1333 std::vector<MCSymbol *> EpilogStarts;
1334 for (auto &I : Seg->Epilogs)
1335 EpilogStarts.push_back(I.first);
1336
1337
1338 std::vector<MCSymbol *> AddedEpilogs;
1339 for (auto *S : EpilogStarts) {
1341 auto &EpilogInstrs = info->EpilogMap[S].Instructions;
1343
1346 int PrologOffset;
1347 if (MatchingEpilog) {
1349 "Duplicate epilog not found");
1350 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
1351
1352
1353 EpilogInstrs.clear();
1355 EpilogInstrs)) >= 0) {
1356 EpilogInfo[EpilogStart] = PrologOffset;
1357
1358
1360 EpilogInfo[EpilogStart] += 1;
1361
1362
1363 EpilogInstrs.clear();
1364 } else {
1365 EpilogInfo[EpilogStart] = TotalCodeBytes;
1366 TotalCodeBytes += CodeBytes;
1367 AddedEpilogs.push_back(EpilogStart);
1368 }
1369 }
1370}
1371
1374 int64_t RawFuncLength) {
1375 if (info->PrologEnd)
1377 info->PrologEnd, info->Function->getName(),
1378 "prologue");
1379 struct EpilogStartEnd {
1382 int64_t End;
1383 };
1384
1386 for (auto &I : info->EpilogMap) {
1388 auto &Instrs = I.second.Instructions;
1391 info->Function->getName(), "epilogue");
1393 "Epilogs should be monotonically ordered");
1394
1395
1397 }
1398
1399 unsigned E = 0;
1400 int64_t SegLimit = 0xFFFFC;
1401 int64_t SegOffset = 0;
1402
1403 if (RawFuncLength > SegLimit) {
1404
1405 int64_t RemainingLength = RawFuncLength;
1406
1407 while (RemainingLength > SegLimit) {
1408
1409
1410
1411 int64_t SegLength = SegLimit;
1412 int64_t SegEnd = SegOffset + SegLength;
1413
1415
1416 while (E < Epilogs.size() && Epilogs[E].End < SegEnd) {
1417
1418 EpilogsInSegment[Epilogs[E].Start] = Epilogs[E].Offset;
1419 ++E;
1420 }
1421
1422
1423
1424
1425
1426
1427
1428
1429 if (E < Epilogs.size() && Epilogs[E].Offset <= SegEnd)
1430
1431 SegLength = Epilogs[E].Offset - SegOffset;
1432
1434 SegOffset, SegLength, !SegOffset);
1435 Seg.Epilogs = std::move(EpilogsInSegment);
1436 info->Segments.push_back(Seg);
1437
1438 SegOffset += SegLength;
1439 RemainingLength -= SegLength;
1440 }
1441 }
1442
1443
1444
1445 auto LastSeg =
1447 !SegOffset);
1448 for (; E < Epilogs.size(); ++E)
1449 LastSeg.Epilogs[Epilogs[E].Start] = Epilogs[E].Offset;
1450 info->Segments.push_back(LastSeg);
1451}
1452
1456 bool TryPacked = true) {
1459
1463
1464 if (Seg.Offset == 0)
1465 info->Symbol = Label;
1466
1468 bool HasEpilogs = (Seg.Epilogs.size() != 0);
1469
1471 uint32_t PrologCodeBytes = info->PrologCodeBytes;
1472
1473 int PackedEpilogOffset = HasEpilogs ?
1475
1476
1477
1478
1479
1480 if (info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
1481 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
1482 ->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
1483
1484
1485
1486
1487
1488
1489
1491 return;
1492 }
1493
1494
1495
1496 if (!HasProlog) {
1497 PrologCodeBytes += 1;
1498 if (PackedEpilogOffset >= 0)
1499 PackedEpilogOffset += 1;
1500
1501
1502
1503
1504
1505 if (!HasEpilogs)
1506
1507 PackedEpilogOffset = 0;
1508 }
1509
1510 uint32_t TotalCodeBytes = PrologCodeBytes;
1511
1512
1515
1516
1518 uint32_t CodeWords = TotalCodeBytes / 4;
1519 uint32_t CodeWordsMod = TotalCodeBytes % 4;
1520 if (CodeWordsMod)
1521 CodeWords++;
1523 PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.Epilogs.size();
1524 bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
1525 if (!ExtensionWord) {
1526 row1 |= (EpilogCount & 0x1F) << 22;
1527 row1 |= (CodeWords & 0x1F) << 27;
1528 }
1529 if (info->HandlesExceptions)
1530 row1 |= 1 << 20;
1531 if (PackedEpilogOffset >= 0)
1532 row1 |= 1 << 21;
1533 row1 |= SegLength & 0x3FFFF;
1535
1536
1537 if (ExtensionWord) {
1538
1539 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
1541 "SEH unwind data splitting is only implemented for large functions, "
1542 "cases of too many code words or too many epilogs will be done "
1543 "later");
1545 row2 |= (CodeWords & 0xFF) << 16;
1546 row2 |= (EpilogCount & 0xFFFF);
1548 }
1549
1550 if (PackedEpilogOffset < 0) {
1551
1552 for (auto &I : EpilogInfo) {
1553 MCSymbol *EpilogStart = I.first;
1554 uint32_t EpilogIndex = I.second;
1555
1557 if (EpilogOffset)
1558 EpilogOffset /= 4;
1559 uint32_t row3 = EpilogOffset;
1560 row3 |= (EpilogIndex & 0x3FF) << 22;
1562 }
1563 }
1564
1565
1566
1567
1568
1569
1570
1571 if (!HasProlog)
1572
1574
1575
1578
1579
1580 for (auto &I : Seg.Epilogs) {
1581 auto &EpilogInstrs = info->EpilogMap[I.first].Instructions;
1584 }
1585
1586 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
1587 assert(BytesMod >= 0);
1588 for (int i = 0; i < BytesMod; i++)
1590
1591 if (info->HandlesExceptions)
1595 4);
1596}
1597
1598
1599
1601 bool TryPacked = true) {
1602
1603 if (info->Symbol)
1604 return;
1605
1606
1607
1608
1609 if (info->empty()) {
1610 info->EmitAttempted = true;
1611 return;
1612 }
1613 if (info->EmitAttempted) {
1614
1615
1616
1617
1618
1620 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
1621 " skipped due to no unwind info at the time "
1622 "(.seh_handlerdata too early?), but the function later "
1623 "did get unwind info that can't be emitted");
1624 return;
1625 }
1626
1628 for (auto &I : info->EpilogMap)
1630
1631 int64_t RawFuncLength;
1632 if (->FuncletOrFuncEnd) {
1634 } else {
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1665 info->Begin);
1666 }
1667
1669
1671 for (auto &S : info->Segments)
1673
1674
1675 info->Instructions.clear();
1676}
1677
1680 for (const auto &I : Insns) {
1682 default:
1686 break;
1689 break;
1692 break;
1695 break;
1698 break;
1701 break;
1704 break;
1707 break;
1710 break;
1713 break;
1716 break;
1719 break;
1722 break;
1725 break;
1728 break;
1735 break;
1737 int J;
1738 for (J = 3; J > 0; J--)
1739 if (I.Offset & (0xffu << (8 * J)))
1740 break;
1742 break;
1743 }
1744 }
1745 }
1747}
1748
1750 bool *HasCustom = nullptr) {
1752 for (const auto &I : Insns) {
1754 default:
1760 break;
1765 break;
1769 break;
1772 break;
1776 break;
1781 break;
1784 break;
1788 break;
1792 break;
1794
1795 break;
1797
1798
1800 if (HasCustom)
1801 *HasCustom = true;
1802 break;
1803 }
1804 }
1806}
1807
1812 if (!End)
1813 return;
1814 std::optional<int64_t> MaybeDistance =
1816 if (!MaybeDistance)
1817 return;
1819 bool HasCustom = false;
1821 if (HasCustom)
1822 return;
1823 if (Distance != InstructionBytes) {
1825 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
1826 Twine(Distance) +
1827 " bytes of instructions in range, but .seh directives "
1828 "corresponding to " +
1829 Twine(InstructionBytes) + " bytes\n");
1830 }
1831}
1832
1838 return true;
1839 default:
1840 return false;
1841 }
1842}
1843
1844
1845
1849 int i;
1851 default:
1857 break;
1860 lr = (inst.Register >> 14) & 1;
1861 w = 0x8000 | (inst.Register & 0x1fff) | (lr << 13);
1862 streamer.emitInt8((w >> 8) & 0xff);
1863 streamer.emitInt8((w >> 0) & 0xff);
1864 break;
1868 break;
1873 break;
1878 break;
1882 break;
1886 w = 0xe800 | (inst.Offset / 4);
1887 streamer.emitInt8((w >> 8) & 0xff);
1888 streamer.emitInt8((w >> 0) & 0xff);
1889 break;
1892 lr = (inst.Register >> 14) & 1;
1893 w = 0xec00 | (inst.Register & 0x0ff) | (lr << 8);
1894 streamer.emitInt8((w >> 8) & 0xff);
1895 streamer.emitInt8((w >> 0) & 0xff);
1896 break;
1902 break;
1909 break;
1916 break;
1920 w = inst.Offset / 4;
1922 streamer.emitInt8((w >> 8) & 0xff);
1923 streamer.emitInt8((w >> 0) & 0xff);
1924 break;
1928 w = inst.Offset / 4;
1930 streamer.emitInt8((w >> 16) & 0xff);
1931 streamer.emitInt8((w >> 8) & 0xff);
1932 streamer.emitInt8((w >> 0) & 0xff);
1933 break;
1937 w = inst.Offset / 4;
1939 streamer.emitInt8((w >> 8) & 0xff);
1940 streamer.emitInt8((w >> 0) & 0xff);
1941 break;
1945 w = inst.Offset / 4;
1947 streamer.emitInt8((w >> 16) & 0xff);
1948 streamer.emitInt8((w >> 8) & 0xff);
1949 streamer.emitInt8((w >> 0) & 0xff);
1950 break;
1953 break;
1956 break;
1959 break;
1962 break;
1965 break;
1967 for (i = 3; i > 0; i--)
1968 if (inst.Offset & (0xffu << (8 * i)))
1969 break;
1970 for (; i >= 0; i--)
1972 break;
1973 }
1974}
1975
1976
1977
1978
1979
1980
1981
1983 const std::vectorWinEH::Instruction &Epilog,
1984 bool CanTweakProlog) {
1985
1987 return -1;
1988
1989
1990
1991
1992
1993 int EndIdx = CanTweakProlog ? 1 : 0;
1994 for (int I = Epilog.size() - 1; I >= EndIdx; I--) {
1995
1996
1998 return -1;
1999 }
2000
2001 if (CanTweakProlog) {
2002
2004 return -1;
2008 return -1;
2009 }
2010
2011
2013 return 0;
2016}
2017
2019 int PrologCodeBytes) {
2020
2021 if (info->EpilogMap.size() != 1)
2022 return -1;
2023
2025
2026 if (EpilogInfo.Condition != 0xe)
2027 return -1;
2028
2029 const std::vectorWinEH::Instruction &Epilog = EpilogInfo.Instructions;
2030
2031 if (info->Instructions.empty() || Epilog.empty())
2032 return -1;
2033
2034
2035
2037 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
2038 if (!MaybeDistance)
2039 return -1;
2042 if (DistanceFromEnd != InstructionBytes)
2043 return -1;
2044
2045 int RetVal = -1;
2046
2047
2048
2049
2050 if (PrologCodeBytes <= 31 &&
2052 RetVal = PrologCodeBytes;
2053
2057 return RetVal;
2058
2059
2060
2061
2062 if (Offset > 31 || PrologCodeBytes > 63)
2063 return RetVal;
2064
2065
2066
2067 info->Instructions.front() = Epilog.back();
2068
2069
2070
2071 info->EpilogMap.clear();
2073}
2074
2075static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11,
2076 unsigned &Folded, int &IntRegs) {
2077 if (Mask & (1 << 14)) {
2078 HasLR = true;
2079 Mask &= ~(1 << 14);
2080 }
2081 if (Mask & (1 << 11)) {
2082 HasR11 = true;
2083 Mask &= ~(1 << 11);
2084 }
2085 Folded = 0;
2087 if (!Mask)
2088 return true;
2090
2091 while ((Mask & 1) == 0) {
2093 Mask >>= 1;
2094 }
2095 if ((Mask & (Mask + 1)) != 0)
2096 return false;
2097
2098 int N = 0;
2099 while (Mask & (1 << N))
2100 N++;
2101 if (First < 4) {
2103 return false;
2104 Folded = 4 - First;
2105 N -= Folded;
2107 }
2109 return false;
2110 if (N >= 1)
2112 return true;
2113}
2114
2117 int Step = 0;
2118 bool Homing = false;
2119 bool HasR11 = false;
2120 bool HasChain = false;
2121 bool HasLR = false;
2122 int IntRegs = -1;
2123 int FloatRegs = -1;
2124 unsigned PF = 0;
2125 unsigned StackAdjust = 0;
2126
2127
2130 default:
2139
2140 return false;
2142
2143
2144 return false;
2146
2147 return false;
2148
2152 if (Step != 0)
2153 return false;
2154 Step = 1;
2155 break;
2156
2159
2160 if (Step != 1 && Step != 2)
2161 return false;
2166 HasR11 = true;
2168 }
2170 HasLR = true;
2171 Step = 3;
2172 break;
2173
2175 if (Step == 1 && Inst.Register == 0x0f) {
2176
2177 Homing = true;
2178 Step = 2;
2179 break;
2180 }
2181 [[fallthrough]];
2183 if (Step != 1 && Step != 2)
2184 return false;
2185
2186
2187
2189 return false;
2190 Step = 3;
2191 break;
2192
2194
2195 if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)
2196 return false;
2197 HasChain = true;
2198 Step = 4;
2199 break;
2201
2202 if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))
2203 return false;
2204 HasChain = true;
2205 Step = 4;
2206 break;
2207
2209 if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
2210 return false;
2213 return false;
2215 return false;
2216 FloatRegs = Inst.Register - 8;
2217 Step = 5;
2218 break;
2219
2222 if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
2223 return false;
2224 if (PF > 0)
2225 return false;
2226 if (Inst.Offset / 4 >= 0x3f4)
2227 return false;
2228 StackAdjust = Inst.Offset / 4;
2229 Step = 6;
2230 break;
2231 }
2232 }
2233 if (HasR11 && !HasChain) {
2234 if (IntRegs + 4 == 10) {
2235
2236
2238 HasR11 = false;
2239 } else
2240 return false;
2241 }
2242 if (HasChain && !HasLR)
2243 return false;
2244
2245
2246 if (info->EpilogMap.size() > 1)
2247 return false;
2248
2249 unsigned EF = 0;
2250 int Ret = 0;
2251 if (info->EpilogMap.size() == 0) {
2252 Ret = 3;
2253 } else {
2254
2255
2256
2258 info->EpilogMap.begin()->second;
2259 if (EpilogInfo.Condition != 0xe)
2260 return false;
2261 const std::vectorWinEH::Instruction &Epilog = EpilogInfo.Instructions;
2263 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
2264 if (!MaybeDistance)
2265 return false;
2268 if (DistanceFromEnd != InstructionBytes)
2269 return false;
2270
2271 bool GotStackAdjust = false;
2272 bool GotFloatRegs = false;
2273 bool GotIntRegs = false;
2274 bool GotHomingRestore = false;
2275 bool GotLRRestore = false;
2276 bool NeedsReturn = false;
2277 bool GotReturn = false;
2278
2279 Step = 6;
2282 default:
2294
2295 return false;
2296
2299 if (Inst.Offset / 4 >= 0x3f4)
2300 return false;
2301 if (Step == 6) {
2302 if (Homing && FloatRegs < 0 && IntRegs < 0 && StackAdjust == 0 &&
2303 PF == 0 && Inst.Offset == 16) {
2304 GotHomingRestore = true;
2305 Step = 10;
2306 } else {
2307 if (StackAdjust > 0) {
2308
2309 if (StackAdjust != Inst.Offset / 4)
2310 return false;
2311 GotStackAdjust = true;
2312 } else if (PF == Inst.Offset / 4) {
2313
2314 StackAdjust = Inst.Offset / 4;
2315 GotStackAdjust = true;
2316 } else {
2317
2318 return false;
2319 }
2320 Step = 7;
2321 }
2322 } else if (Step == 7 || Step == 8 || Step == 9) {
2323 if (!Homing || Inst.Offset != 16)
2324 return false;
2325 GotHomingRestore = true;
2326 Step = 10;
2327 } else
2328 return false;
2329 break;
2330
2332 if (Step != 6 && Step != 7)
2333 return false;
2335 if (FloatRegs != (int)(Inst.Register - 8))
2336 return false;
2337 GotFloatRegs = true;
2338 Step = 8;
2339 break;
2340
2343
2344 if (Step != 6 && Step != 7 && Step != 8)
2345 return false;
2348 if (Homing && HasLR) {
2349
2350
2352 GotLRRestore = true;
2353 NeedsReturn = true;
2354 } else {
2355
2356 }
2357 } else {
2358 if (HasLR != (Inst.Offset == 1))
2359 return false;
2360 }
2361 GotLRRestore = Inst.Offset == 1;
2362 if (IntRegs < 0)
2363 return false;
2365 if (HasChain) {
2366
2368 return false;
2370 }
2372 return false;
2373 GotIntRegs = true;
2374 Step = 9;
2375 break;
2376 }
2377
2380 if (Step != 6 && Step != 7 && Step != 8)
2381 return false;
2382
2383
2384
2385 bool CurHasLR = false, CurHasR11 = false;
2386 int Regs;
2388 return false;
2389 if (EF > 0) {
2390 if (EF != PF && EF != StackAdjust)
2391 return false;
2392 }
2393 if (Homing && HasLR) {
2394
2395
2396 if (CurHasLR) {
2397 GotLRRestore = true;
2398 NeedsReturn = true;
2399 } else {
2400
2401 }
2402 } else {
2403 if (CurHasLR != HasLR)
2404 return false;
2405 GotLRRestore = CurHasLR;
2406 }
2408 if (HasChain) {
2409
2410 if (!CurHasR11)
2411 return false;
2413
2414
2416 if (!CurHasR11)
2417 return false;
2418 } else {
2419
2420
2421 if (CurHasR11)
2422 return false;
2423 }
2425 return false;
2426 GotIntRegs = true;
2427 Step = 9;
2428 break;
2429 }
2430
2432 if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
2433 return false;
2434 if (!Homing || Inst.Offset != 20 || GotLRRestore)
2435 return false;
2436 GotLRRestore = true;
2437 GotHomingRestore = true;
2438 Step = 10;
2439 break;
2440
2443 GotReturn = true;
2445 [[fallthrough]];
2447 if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
2448 return false;
2449 Step = 11;
2450 break;
2451 }
2452 }
2453
2454 if (Step != 11)
2455 return false;
2456 if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
2457 return false;
2458 if (FloatRegs >= 0 && !GotFloatRegs)
2459 return false;
2460 if (IntRegs >= 0 && !GotIntRegs)
2461 return false;
2462 if (Homing && !GotHomingRestore)
2463 return false;
2464 if (HasLR && !GotLRRestore)
2465 return false;
2466 if (NeedsReturn && !GotReturn)
2467 return false;
2468 }
2469
2470 assert(PF == 0 || EF == 0 ||
2471 StackAdjust == 0);
2472 if (PF > 0 || EF > 0) {
2473 StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
2474 assert(StackAdjust <= 3);
2475 StackAdjust |= 0x3f0;
2476 if (PF > 0)
2477 StackAdjust |= 1 << 2;
2478 if (EF > 0)
2479 StackAdjust |= 1 << 3;
2480 }
2481
2482 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
2483 int Flag = info->Fragment ? 0x02 : 0x01;
2484 int H = Homing ? 1 : 0;
2485 int L = HasLR ? 1 : 0;
2486 int C = HasChain ? 1 : 0;
2488 unsigned Reg, R;
2492 R = 0;
2493 } else if (FloatRegs >= 0) {
2494 Reg = FloatRegs;
2496 R = 1;
2497 } else {
2498
2499 Reg = 7;
2500 R = 1;
2501 }
2502 info->PackedInfo |= Flag << 0;
2503 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
2504 info->PackedInfo |= (Ret & 0x3) << 13;
2505 info->PackedInfo |= H << 15;
2506 info->PackedInfo |= Reg << 16;
2507 info->PackedInfo |= R << 19;
2508 info->PackedInfo |= L << 20;
2509 info->PackedInfo |= C << 21;
2510 assert(StackAdjust <= 0x3ff);
2511 info->PackedInfo |= StackAdjust << 22;
2512 return true;
2513}
2514
2515
2516
2518 bool TryPacked = true) {
2519
2520 if (info->Symbol)
2521 return;
2522
2523
2524
2525
2526 if (info->empty()) {
2527 info->EmitAttempted = true;
2528 return;
2529 }
2530 if (info->EmitAttempted) {
2531
2532
2533
2534
2535
2537 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
2538 " skipped due to no unwind info at the time "
2539 "(.seh_handlerdata too early?), but the function later "
2540 "did get unwind info that can't be emitted");
2541 return;
2542 }
2543
2546
2549 info->Symbol = Label;
2550
2551 if (->PrologEnd)
2553 info->Function->getName() +
2554 " not correctly terminated");
2555
2556 if (info->PrologEnd && ->Fragment)
2558 info->PrologEnd, info->Function->getName(),
2559 "prologue");
2560 for (auto &I : info->EpilogMap) {
2561 MCSymbol *EpilogStart = I.first;
2564 info->Function->getName(), "epilogue");
2565 if (Epilog.Instructions.empty() ||
2568 SMLoc(), "Epilogue in " + info->Function->getName() +
2569 " not correctly terminated");
2570 }
2571
2572 std::optional<int64_t> RawFuncLength;
2573 const MCExpr *FuncLengthExpr = nullptr;
2574 if (->FuncletOrFuncEnd) {
2576 } else {
2577
2578
2579
2580
2581
2582
2583
2584
2585 RawFuncLength =
2587 if (!RawFuncLength)
2588 FuncLengthExpr =
2590 }
2592 if (RawFuncLength)
2593 FuncLength = (uint32_t)*RawFuncLength / 2;
2594 if (FuncLength > 0x3FFFF)
2595 report_fatal_error("SEH unwind data splitting not yet implemented");
2597 uint32_t TotalCodeBytes = PrologCodeBytes;
2598
2599 if (->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
2600 TryPacked) {
2601
2602
2603
2604
2605
2606
2607
2608
2610 return;
2611 }
2612
2613 int PackedEpilogOffset =
2615
2616
2618
2619 std::vector<MCSymbol *> AddedEpilogs;
2620
2621 bool CanTweakProlog = true;
2622 for (auto &I : info->EpilogMap) {
2623 MCSymbol *EpilogStart = I.first;
2624 auto &EpilogInstrs = I.second.Instructions;
2626
2629 int PrologOffset;
2630 if (MatchingEpilog) {
2632 "Duplicate epilog not found");
2633 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
2634
2635
2636 EpilogInstrs.clear();
2638 info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
2639 if (CanTweakProlog) {
2640
2641
2642 info->Instructions.front() = EpilogInstrs.back();
2643
2644 CanTweakProlog = false;
2645 }
2646 EpilogInfo[EpilogStart] = PrologOffset;
2647
2648
2649 EpilogInstrs.clear();
2650 } else {
2651 EpilogInfo[EpilogStart] = TotalCodeBytes;
2652 TotalCodeBytes += CodeBytes;
2653 AddedEpilogs.push_back(EpilogStart);
2654 }
2655 }
2656
2657
2659 uint32_t CodeWords = TotalCodeBytes / 4;
2660 uint32_t CodeWordsMod = TotalCodeBytes % 4;
2661 if (CodeWordsMod)
2662 CodeWords++;
2664 PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
2665 bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
2666 if (!ExtensionWord) {
2667 row1 |= (EpilogCount & 0x1F) << 23;
2668 row1 |= (CodeWords & 0x0F) << 28;
2669 }
2670 if (info->HandlesExceptions)
2671 row1 |= 1 << 20;
2672 if (PackedEpilogOffset >= 0)
2673 row1 |= 1 << 21;
2674 if (info->Fragment)
2675 row1 |= 1 << 22;
2676 row1 |= FuncLength & 0x3FFFF;
2677 if (RawFuncLength)
2679 else
2683 4);
2684
2685
2686 if (ExtensionWord) {
2687
2688 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
2689 report_fatal_error("SEH unwind data splitting not yet implemented");
2691 row2 |= (CodeWords & 0xFF) << 16;
2692 row2 |= (EpilogCount & 0xFFFF);
2694 }
2695
2696 if (PackedEpilogOffset < 0) {
2697
2698 for (auto &I : EpilogInfo) {
2699 MCSymbol *EpilogStart = I.first;
2700 uint32_t EpilogIndex = I.second;
2701
2702 std::optional<int64_t> MaybeEpilogOffset =
2704 const MCExpr *OffsetExpr = nullptr;
2706 if (MaybeEpilogOffset)
2707 EpilogOffset = *MaybeEpilogOffset / 2;
2708 else
2709 OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);
2710
2711 assert(info->EpilogMap.contains(EpilogStart));
2712 unsigned Condition = info->EpilogMap[EpilogStart].Condition;
2713 assert(Condition <= 0xf);
2714
2715 uint32_t row3 = EpilogOffset;
2716 row3 |= Condition << 20;
2717 row3 |= (EpilogIndex & 0x3FF) << 24;
2718 if (MaybeEpilogOffset)
2720 else
2724 4);
2725 }
2726 }
2727
2728
2729 uint8_t numInst = info->Instructions.size();
2730 for (uint8_t c = 0; c < numInst; ++c) {
2732 info->Instructions.pop_back();
2734 }
2735
2736
2737 for (auto &I : info->EpilogMap) {
2738 auto &EpilogInstrs = I.second.Instructions;
2741 }
2742
2743 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2744 assert(BytesMod >= 0);
2745 for (int i = 0; i < BytesMod; i++)
2747
2748 if (info->HandlesExceptions)
2752 4);
2753}
2754
2758
2760 for (const auto &S : info->Segments) {
2762 if (info->PackedInfo)
2764 else
2767 context),
2768 4);
2769 }
2770}
2771
2772
2776
2779 if (info->PackedInfo)
2781 else
2784 context),
2785 4);
2786}
2787
2789
2792 if (Info->empty())
2793 continue;
2797 }
2798
2799
2802
2803
2804
2805 if (!Info->Symbol)
2806 continue;
2810 }
2811}
2812
2815 bool HandlerData) const {
2816
2817
2818
2819
2820
2821
2822 if (->FuncletOrFuncEnd) {
2825 }
2826
2827
2831}
2832
2834
2837 if (Info->empty())
2838 continue;
2842 }
2843
2844
2847
2848
2849
2850 if (!Info->Symbol)
2851 continue;
2855 }
2856}
2857
2860 bool HandlerData) const {
2861
2862
2863
2864
2865
2866
2867 if (->FuncletOrFuncEnd) {
2870 }
2871
2872
2876}
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:963
static void ARM64EmitUnwindInfoForSegment(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment &Seg, bool TryPacked=true)
Definition MCWin64EH.cpp:1453
static uint32_t ARMCountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
Definition MCWin64EH.cpp:1678
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:1808
static bool isARMTerminator(const WinEH::Instruction &inst)
Definition MCWin64EH.cpp:1833
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:1846
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:942
static void ARMEmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition MCWin64EH.cpp:2773
static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength, int PackedEpilogOffset)
Definition MCWin64EH.cpp:1006
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:1600
static int getARMOffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog, bool CanTweakProlog)
Definition MCWin64EH.cpp:1982
static void ARM64EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition MCWin64EH.cpp:2755
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:2075
static int checkARMPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)
Definition MCWin64EH.cpp:2018
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:1372
static bool tryARMPackedUnwind(MCStreamer &streamer, WinEH::FrameInfo *info, uint32_t FuncLength)
Definition MCWin64EH.cpp:2115
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:2517
static uint32_t ARMCountOfInstructionBytes(ArrayRef< WinEH::Instruction > Insns, bool *HasCustom=nullptr)
Definition MCWin64EH.cpp:1749
static void ARM64ProcessEpilogs(WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, uint32_t &TotalCodeBytes, MapVector< MCSymbol *, uint32_t > &EpilogInfo)
Definition MCWin64EH.cpp:1328
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:2813
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition MCWin64EH.cpp:2788
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition MCWin64EH.cpp:2833
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition MCWin64EH.cpp:2858
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
auto reverse_conditionally(ContainerTy &&C, bool ShouldReverse)
Return a range that conditionally reverses C.
@ 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