LLVM: lib/MC/MCWin64EH.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

17namespace llvm {

19}

20

21using namespace llvm;

22

23

24

27 for (const auto &I : Insns) {

29 default:

35 Count += 1;

36 break;

39 Count += 2;

40 break;

43 Count += 3;

44 break;

46 Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;

47 break;

48 }

49 }

50 return Count;

51}

52

60}

61

68 default:

72 b2 |= (inst.Register & 0x0F) << 4;

74 break;

77 if (inst.Offset > 512 * 1024 - 8) {

78 b2 |= 0x10;

80 w = inst.Offset & 0xFFF8;

82 w = inst.Offset >> 16;

83 } else {

86 }

88 break;

90 b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;

93 break;

97 break;

100 b2 |= (inst.Register & 0x0F) << 4;

103 w = inst.Offset >> 3;

105 w >>= 1;

107 break;

110 b2 |= (inst.Register & 0x0F) << 4;

114 w = inst.Offset & 0xFFF0;

115 else

116 w = inst.Offset & 0xFFF8;

118 w = inst.Offset >> 16;

120 break;

122 if (inst.Offset == 1)

123 b2 |= 0x10;

126 break;

127 }

128}

129

137 Context);

139}

140

150 Context);

152}

153

157

163 context), 4);

164}

165

167

168 if (info->Symbol)

169 return;

170

173

176 info->Symbol = Label;

177

178

180 if (info->ChainedParent)

182 else {

183 if (info->HandlesUnwind)

185 if (info->HandlesExceptions)

187 }

189

190 if (info->PrologEnd)

192 else

194

197

199 if (info->LastFrameInst >= 0) {

202 frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);

203 }

205

206

207 uint8_t numInst = info->Instructions.size();

208 for (uint8_t c = 0; c < numInst; ++c) {

210 info->Instructions.pop_back();

212 }

213

214

215

216

217

218 if (numCodes & 1) {

220 }

221

224 else if (flags &

228 context), 4);

229 else if (numCodes == 0) {

230

231

232

234 }

235}

236

238

243 }

244

245

250 }

251}

252

255 bool HandlerData) const {

256

257

260

262}

263

270 if (Div != 1)

272 Context);

273 return Expr;

274}

275

284

285

286

288 if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))

289 return std::nullopt;

291}

292

295 std::optional<int64_t> MaybeDiff =

297 if (!MaybeDiff)

298 report_fatal_error("Failed to evaluate function length in SEH unwind info");

299 return *MaybeDiff;

300}

301

306 if (End)

307 return;

308 std::optional<int64_t> MaybeDistance =

310 if (!MaybeDistance)

311 return;

313

314 for (const auto &I : Insns) {

316 default:

317 break;

323

324

325 return;

326 }

327 }

328

329 uint32_t InstructionBytes = 4 * (Insns.size() - 1);

330 if (Distance != InstructionBytes) {

332 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +

333 Twine(Distance) +

334 " bytes of instructions in range, but .seh directives "

335 "corresponding to " +

336 Twine(InstructionBytes) + " bytes\n");

337 }

338}

339

342 for (const auto &I : Insns) {

344 default:

347 Count += 1;

348 break;

350 Count += 2;

351 break;

353 Count += 4;

354 break;

356 Count += 1;

357 break;

359 Count += 1;

360 break;

362 Count += 1;

363 break;

365 Count += 2;

366 break;

368 Count += 2;

369 break;

371 Count += 2;

372 break;

374 Count += 2;

375 break;

377 Count += 2;

378 break;

380 Count += 2;

381 break;

383 Count += 2;

384 break;

386 Count += 2;

387 break;

389 Count += 2;

390 break;

392 Count += 1;

393 break;

395 Count += 2;

396 break;

398 Count += 1;

399 break;

401 Count += 1;

402 break;

404 Count += 1;

405 break;

407 Count += 1;

408 break;

410 Count += 1;

411 break;

413 Count += 1;

414 break;

416 Count += 1;

417 break;

419 Count += 1;

420 break;

422 Count += 1;

423 break;

436 Count += 3;

437 break;

438 }

439 }

440 return Count;

441}

442

443

444

449 default:

452 b = (inst.Offset >> 4) & 0x1F;

454 break;

457 b = 0xC0;

458 b |= (hw >> 8);

460 b = hw & 0xFF;

462 break;

463 }

466 b = 0xE0;

468 w = inst.Offset >> 4;

469 b = (w & 0x00FF0000) >> 16;

471 b = (w & 0x0000FF00) >> 8;

473 b = w & 0x000000FF;

475 break;

476 }

478 b = 0xE1;

480 break;

482 b = 0xE2;

484 b = (inst.Offset >> 3);

486 break;

488 b = 0xE3;

490 break;

492 b = 0x20;

493 b |= (inst.Offset >> 3) & 0x1F;

495 break;

497 b = 0x80;

498 b |= ((inst.Offset - 1) >> 3) & 0x3F;

500 break;

502 b = 0x40;

503 b |= (inst.Offset >> 3) & 0x3F;

505 break;

507 assert(inst.Register >= 19 && "Saved reg must be >= 19");

509 b = 0xD0 | ((reg & 0xC) >> 2);

511 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);

513 break;

515 assert(inst.Register >= 19 && "Saved reg must be >= 19");

517 b = 0xD4 | ((reg & 0x8) >> 3);

519 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);

521 break;

523 assert(inst.Register >= 19 && "Saved registers must be >= 19");

525 b = 0xC8 | ((reg & 0xC) >> 2);

527 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);

529 break;

531 assert(inst.Register >= 19 && "Saved registers must be >= 19");

533 b = 0xCC | ((reg & 0xC) >> 2);

535 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);

537 break;

539 assert(inst.Register >= 19 && "Saved reg must be >= 19");

541 assert((reg % 2) == 0 && "Saved reg must be 19+2*X");

542 reg /= 2;

543 b = 0xD6 | ((reg & 0x7) >> 2);

545 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);

547 break;

549 assert(inst.Register >= 8 && "Saved dreg must be >= 8");

551 b = 0xDC | ((reg & 0x4) >> 2);

553 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);

555 break;

557 assert(inst.Register >= 8 && "Saved dreg must be >= 8");

559 b = 0xDE;

561 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);

563 break;

565 assert(inst.Register >= 8 && "Saved dregs must be >= 8");

567 b = 0xD8 | ((reg & 0x4) >> 2);

569 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);

571 break;

573 assert(inst.Register >= 8 && "Saved dregs must be >= 8");

575 b = 0xDA | ((reg & 0x4) >> 2);

577 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);

579 break;

581 b = 0xE4;

583 break;

585 b = 0xE6;

587 break;

589 b = 0xE8;

591 break;

593 b = 0xE9;

595 break;

597 b = 0xEA;

599 break;

601 b = 0xEB;

603 break;

605 b = 0xEC;

607 break;

609 b = 0xFC;

611 break;

624

626 int Writeback = Op / 6;

627 int Paired = Op % 2;

628 int Mode = (Op / 2) % 3;

630 if (Writeback || Paired || Mode == 2)

632 if (Writeback)

634 b = 0xE7;

637 b = inst.Register | (Writeback << 5) | (Paired << 6);

641 break;

642 }

643 }

644}

645

646

647

648

649

652 const std::vector<MCSymbol *>& Epilogs,

654 for (auto *EpilogStart : Epilogs) {

655 auto InstrsIter = info->EpilogMap.find(EpilogStart);

656 assert(InstrsIter != info->EpilogMap.end() &&

657 "Epilog not found in EpilogMap");

658 const auto &Instrs = InstrsIter->second.Instructions;

659

660 if (Instrs.size() != EpilogInstrs.size())

661 continue;

662

663 bool Match = true;

664 for (unsigned i = 0; i < Instrs.size(); ++i)

665 if (Instrs[i] != EpilogInstrs[i]) {

667 break;

668 }

669

671 return EpilogStart;

672 }

673 return nullptr;

674}

675

678 unsigned PrevOffset = -1;

679 unsigned PrevRegister = -1;

680

682

685 Inst.Register = -1;

687 Inst.Register == 29) {

689 Inst.Register = -1;

691 Inst.Register == 19 && Inst.Offset <= 248) {

693 Inst.Register = -1;

694 } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {

697 Inst.Register == PrevRegister + 2 &&

698 Inst.Offset == PrevOffset + 16) {

700 Inst.Register = -1;

701 Inst.Offset = 0;

702

703

704

705 }

706

707

709 PrevOffset = 0;

710 PrevRegister = 19;

712 PrevOffset = 0;

713 PrevRegister = Inst.Register;

715 PrevOffset = Inst.Offset;

716 PrevRegister = Inst.Register;

718 PrevRegister += 2;

719 PrevOffset += 16;

720 } else {

721 PrevRegister = -1;

722 PrevOffset = -1;

723 }

724 };

725

726

727

728

730 for (auto It = Instructions.rbegin(); It != Instructions.rend(); It++)

731 VisitInstruction(*It);

732 } else {

734 VisitInstruction(Inst);

735 }

736}

737

738

739static int

741 const std::vectorWinEH::Instruction &Epilog) {

742

744 return -1;

745

746

747

748 for (int I = Epilog.size() - 1; I >= 0; I--) {

750 return -1;

751 }

752

754 return 0;

755

756

759}

760

763 int PrologCodeBytes) {

764

765 if (Seg->Epilogs.size() != 1)

766 return -1;

767

769 const std::vectorWinEH::Instruction &Epilog =

770 info->EpilogMap[Sym].Instructions;

771

772

773

776 if (DistanceFromEnd / 4 != Epilog.size())

777 return -1;

778

779 int RetVal = -1;

780

781

782

783

784 if (PrologCodeBytes <= 31 &&

786 RetVal = PrologCodeBytes;

787

790 return RetVal;

791

792

793

794

795 if (Offset > 31 || PrologCodeBytes > 124)

796 return RetVal;

797

798

799

800 info->EpilogMap.erase(Sym);

802}

803

805 int PackedEpilogOffset) {

806 if (PackedEpilogOffset == 0) {

807

808

809

810

811

812 } else if (PackedEpilogOffset == 1) {

813

814

815

817 return false;

818 } else {

819

820 return false;

821 }

822 unsigned RegI = 0, RegF = 0;

823 int Predecrement = 0;

824 enum {

825 Start,

826 Start2,

827 Start3,

829 FloatRegs,

830 InputArgs,

831 StackAdjust,

832 FrameRecord,

834 } Location = Start;

835 bool StandaloneLR = false, FPLRPair = false;

836 bool PAC = false;

838 int Nops = 0;

839

840

841

842

843

844

848 if (Location != Start)

849 return false;

850 Location = Start2;

851 break;

853 if (Location != Start2)

854 return false;

855 PAC = true;

856 Location = Start3;

857 break;

859 if (Location != Start2 && Location != Start3)

860 return false;

861 Predecrement = Inst.Offset;

862 RegI = 2;

864 break;

866 if (Location != Start2 && Location != Start3)

867 return false;

868 Predecrement = Inst.Offset;

870 RegI += 1;

871 else if (Inst.Register == 30)

872 StandaloneLR = true;

873 else

874 return false;

875

876 Location = FloatRegs;

877 break;

879

880

881

882

883

884

885

886

887

888

889

890 return false;

892 if (Location != IntRegs || Inst.Offset != 8 * RegI ||

894 return false;

895 RegI += 2;

896 break;

898 if (Location != IntRegs || Inst.Offset != 8 * RegI)

899 return false;

900 if (Inst.Register == 19 + RegI)

901 RegI += 1;

902 else if (Inst.Register == 30)

903 StandaloneLR = true;

904 else

905 return false;

906

907 Location = FloatRegs;

908 break;

910 if (Location != IntRegs || Inst.Offset != 8 * RegI ||

912 return false;

913 RegI += 1;

914 StandaloneLR = true;

915 Location = FloatRegs;

916 break;

918

919

920 return false;

922 if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||

923 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))

924 return false;

925 RegF += 1;

926 Location = InputArgs;

927 break;

929 if ((Location != Start2 && Location != Start3) || Inst.Register != 8)

930 return false;

931 Predecrement = Inst.Offset;

932 RegF = 2;

933 Location = FloatRegs;

934 break;

936 if ((Location != IntRegs && Location != FloatRegs) ||

938 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))

939 return false;

940 RegF += 2;

941 Location = FloatRegs;

942 break;

945 RegI += 2;

946 else if (Location == FloatRegs)

947 RegF += 2;

948 else

949 return false;

950 break;

952 if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)

953 return false;

954 Location = InputArgs;

955 Nops++;

956 break;

959 if (Location != Start2 && Location != Start3 && Location != IntRegs &&

960 Location != FloatRegs && Location != InputArgs &&

961 Location != StackAdjust)

962 return false;

963

964

968 return false;

969 else

971 Location = StackAdjust;

972 break;

974

975

976 if (Location != Start2 && Location != Start3 && Location != IntRegs &&

977 Location != FloatRegs && Location != InputArgs)

978 return false;

980 Location = FrameRecord;

981 FPLRPair = true;

982 break;

984

985 if (Location != StackAdjust || Inst.Offset != 0)

986 return false;

987 Location = FrameRecord;

988 FPLRPair = true;

989 break;

991 if (Location != FrameRecord)

992 return false;

993 Location = End;

994 break;

1007

1008

1009 return false;

1011

1012

1013

1014 return false;

1016

1017

1018 return false;

1024

1025 return false;

1026 default:

1028 }

1029 }

1030 if (RegI > 10 || RegF > 8)

1031 return false;

1032 if (StandaloneLR && FPLRPair)

1033 return false;

1034 if (FPLRPair && Location != End)

1035 return false;

1036 if (Nops != 0 && Nops != 4)

1037 return false;

1038 if (PAC && !FPLRPair)

1039 return false;

1040 int H = Nops == 4;

1041

1042

1043

1044

1045

1046

1047

1048

1049 if (H)

1050 return false;

1051 int IntSZ = 8 * RegI;

1052 if (StandaloneLR)

1053 IntSZ += 8;

1054 int FpSZ = 8 * RegF;

1055 int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;

1056 if (Predecrement != SavSZ)

1057 return false;

1059 return false;

1061 return false;

1063 if (FrameSize > 0x1FF)

1064 return false;

1065 assert(RegF != 1 && "One single float reg not allowed");

1066 if (RegF > 0)

1067 RegF--;

1068 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");

1069 int Flag = 0x01;

1070 int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;

1071 info->PackedInfo |= Flag << 0;

1072 info->PackedInfo |= (FuncLength & 0x7FF) << 2;

1073 info->PackedInfo |= (RegF & 0x7) << 13;

1074 info->PackedInfo |= (RegI & 0xF) << 16;

1075 info->PackedInfo |= (H & 0x1) << 20;

1076 info->PackedInfo |= (CR & 0x3) << 21;

1077 info->PackedInfo |= (FrameSize & 0x1FF) << 23;

1078 return true;

1079}

1080

1085

1086 std::vector<MCSymbol *> EpilogStarts;

1087 for (auto &I : Seg->Epilogs)

1088 EpilogStarts.push_back(I.first);

1089

1090

1091 std::vector<MCSymbol *> AddedEpilogs;

1092 for (auto *S : EpilogStarts) {

1094 auto &EpilogInstrs = info->EpilogMap[S].Instructions;

1096

1099 int PrologOffset;

1100 if (MatchingEpilog) {

1102 "Duplicate epilog not found");

1103 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);

1104

1105

1106 EpilogInstrs.clear();

1108 EpilogInstrs)) >= 0) {

1109 EpilogInfo[EpilogStart] = PrologOffset;

1110

1111

1113 EpilogInfo[EpilogStart] += 1;

1114

1115

1116 EpilogInstrs.clear();

1117 } else {

1118 EpilogInfo[EpilogStart] = TotalCodeBytes;

1119 TotalCodeBytes += CodeBytes;

1120 AddedEpilogs.push_back(EpilogStart);

1121 }

1122 }

1123}

1124

1127 int64_t RawFuncLength) {

1128 if (info->PrologEnd)

1130 info->PrologEnd, info->Function->getName(),

1131 "prologue");

1132 struct EpilogStartEnd {

1135 int64_t End;

1136 };

1137

1139 for (auto &I : info->EpilogMap) {

1141 auto &Instrs = I.second.Instructions;

1144 info->Function->getName(), "epilogue");

1146 "Epilogs should be monotonically ordered");

1147

1148

1150 }

1151

1152 unsigned E = 0;

1153 int64_t SegLimit = 0xFFFFC;

1154 int64_t SegOffset = 0;

1155

1156 if (RawFuncLength > SegLimit) {

1157

1158 int64_t RemainingLength = RawFuncLength;

1159

1160 while (RemainingLength > SegLimit) {

1161

1162

1163

1164 int64_t SegLength = SegLimit;

1165 int64_t SegEnd = SegOffset + SegLength;

1166

1168

1169 while (E < Epilogs.size() && Epilogs[E].End < SegEnd) {

1170

1171 EpilogsInSegment[Epilogs[E].Start] = Epilogs[E].Offset;

1172 ++E;

1173 }

1174

1175

1176

1177

1178

1179

1180

1181

1182 if (E < Epilogs.size() && Epilogs[E].Offset <= SegEnd)

1183

1184 SegLength = Epilogs[E].Offset - SegOffset;

1185

1187 SegOffset, SegLength, !SegOffset);

1188 Seg.Epilogs = std::move(EpilogsInSegment);

1189 info->Segments.push_back(Seg);

1190

1191 SegOffset += SegLength;

1192 RemainingLength -= SegLength;

1193 }

1194 }

1195

1196

1197

1198 auto LastSeg =

1200 !SegOffset);

1201 for (; E < Epilogs.size(); ++E)

1202 LastSeg.Epilogs[Epilogs[E].Start] = Epilogs[E].Offset;

1203 info->Segments.push_back(LastSeg);

1204}

1205

1209 bool TryPacked = true) {

1212

1216

1217 if (Seg.Offset == 0)

1218 info->Symbol = Label;

1219

1221 bool HasEpilogs = (Seg.Epilogs.size() != 0);

1222

1224 uint32_t PrologCodeBytes = info->PrologCodeBytes;

1225

1226 int PackedEpilogOffset = HasEpilogs ?

1228

1229

1230

1231

1232

1233 if (info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&

1234 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&

1235 info->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {

1236

1237

1238

1239

1240

1241

1242

1244 return;

1245 }

1246

1247

1248

1249 if (!HasProlog) {

1250 PrologCodeBytes += 1;

1251 if (PackedEpilogOffset >= 0)

1252 PackedEpilogOffset += 1;

1253

1254

1255

1256

1257

1258 if (!HasEpilogs)

1259

1260 PackedEpilogOffset = 0;

1261 }

1262

1263 uint32_t TotalCodeBytes = PrologCodeBytes;

1264

1265

1268

1269

1271 uint32_t CodeWords = TotalCodeBytes / 4;

1272 uint32_t CodeWordsMod = TotalCodeBytes % 4;

1273 if (CodeWordsMod)

1274 CodeWords++;

1276 PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.Epilogs.size();

1277 bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;

1278 if (!ExtensionWord) {

1279 row1 |= (EpilogCount & 0x1F) << 22;

1280 row1 |= (CodeWords & 0x1F) << 27;

1281 }

1282 if (info->HandlesExceptions)

1283 row1 |= 1 << 20;

1284 if (PackedEpilogOffset >= 0)

1285 row1 |= 1 << 21;

1286 row1 |= SegLength & 0x3FFFF;

1288

1289

1290 if (ExtensionWord) {

1291

1292 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)

1294 "SEH unwind data splitting is only implemented for large functions, "

1295 "cases of too many code words or too many epilogs will be done "

1296 "later");

1298 row2 |= (CodeWords & 0xFF) << 16;

1299 row2 |= (EpilogCount & 0xFFFF);

1301 }

1302

1303 if (PackedEpilogOffset < 0) {

1304

1305 for (auto &I : EpilogInfo) {

1306 MCSymbol *EpilogStart = I.first;

1307 uint32_t EpilogIndex = I.second;

1308

1310 if (EpilogOffset)

1311 EpilogOffset /= 4;

1312 uint32_t row3 = EpilogOffset;

1313 row3 |= (EpilogIndex & 0x3FF) << 22;

1315 }

1316 }

1317

1318

1319

1320

1321

1322

1323

1324 if (!HasProlog)

1325

1327

1328

1331

1332

1333 for (auto &I : Seg.Epilogs) {

1334 auto &EpilogInstrs = info->EpilogMap[I.first].Instructions;

1337 }

1338

1339 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;

1340 assert(BytesMod >= 0);

1341 for (int i = 0; i < BytesMod; i++)

1343

1344 if (info->HandlesExceptions)

1348 4);

1349}

1350

1351

1352

1354 bool TryPacked = true) {

1355

1356 if (info->Symbol)

1357 return;

1358

1359

1360

1361

1362 if (info->empty()) {

1363 info->EmitAttempted = true;

1364 return;

1365 }

1366 if (info->EmitAttempted) {

1367

1368

1369

1370

1371

1373 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +

1374 " skipped due to no unwind info at the time "

1375 "(.seh_handlerdata too early?), but the function later "

1376 "did get unwind info that can't be emitted");

1377 return;

1378 }

1379

1381 for (auto &I : info->EpilogMap)

1383

1384 int64_t RawFuncLength;

1385 if (info->FuncletOrFuncEnd) {

1387 } else {

1388

1389

1390

1391

1392

1393

1394

1395

1396

1397

1398

1399

1400

1401

1402

1403

1404

1405

1406

1407

1408

1409

1410

1411

1412

1413

1414

1415

1416

1418 info->Begin);

1419 }

1420

1422

1424 for (auto &S : info->Segments)

1426

1427

1428 info->Instructions.clear();

1429}

1430

1433 for (const auto &I : Insns) {

1435 default:

1438 Count += 1;

1439 break;

1441 Count += 3;

1442 break;

1444 Count += 4;

1445 break;

1447 Count += 2;

1448 break;

1450 Count += 3;

1451 break;

1453 Count += 4;

1454 break;

1456 Count += 2;

1457 break;

1459 Count += 1;

1460 break;

1462 Count += 1;

1463 break;

1465 Count += 1;

1466 break;

1468 Count += 1;

1469 break;

1471 Count += 2;

1472 break;

1474 Count += 2;

1475 break;

1477 Count += 2;

1478 break;

1480 Count += 2;

1481 break;

1487 Count += 1;

1488 break;

1490 int J;

1491 for (J = 3; J > 0; J--)

1492 if (I.Offset & (0xffu << (8 * J)))

1493 break;

1494 Count += J + 1;

1495 break;

1496 }

1497 }

1498 }

1499 return Count;

1500}

1501

1503 bool *HasCustom = nullptr) {

1505 for (const auto &I : Insns) {

1507 default:

1512 Count += 2;

1513 break;

1517 Count += 4;

1518 break;

1521 Count += 4;

1522 break;

1524 Count += 2;

1525 break;

1528 Count += 2;

1529 break;

1533 Count += 4;

1534 break;

1536 Count += 4;

1537 break;

1540 Count += 2;

1541 break;

1544 Count += 4;

1545 break;

1547

1548 break;

1550

1551

1552 Count += 1000;

1553 if (HasCustom)

1554 *HasCustom = true;

1555 break;

1556 }

1557 }

1558 return Count;

1559}

1560

1565 if (End)

1566 return;

1567 std::optional<int64_t> MaybeDistance =

1569 if (!MaybeDistance)

1570 return;

1572 bool HasCustom = false;

1574 if (HasCustom)

1575 return;

1576 if (Distance != InstructionBytes) {

1578 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +

1579 Twine(Distance) +

1580 " bytes of instructions in range, but .seh directives "

1581 "corresponding to " +

1582 Twine(InstructionBytes) + " bytes\n");

1583 }

1584}

1585

1591 return true;

1592 default:

1593 return false;

1594 }

1595}

1596

1597

1598

1602 int i;

1604 default:

1610 break;

1613 lr = (inst.Register >> 14) & 1;

1614 w = 0x8000 | (inst.Register & 0x1fff) | (lr << 13);

1615 streamer.emitInt8((w >> 8) & 0xff);

1616 streamer.emitInt8((w >> 0) & 0xff);

1617 break;

1621 break;

1626 break;

1631 break;

1635 break;

1639 w = 0xe800 | (inst.Offset / 4);

1640 streamer.emitInt8((w >> 8) & 0xff);

1641 streamer.emitInt8((w >> 0) & 0xff);

1642 break;

1645 lr = (inst.Register >> 14) & 1;

1646 w = 0xec00 | (inst.Register & 0x0ff) | (lr << 8);

1647 streamer.emitInt8((w >> 8) & 0xff);

1648 streamer.emitInt8((w >> 0) & 0xff);

1649 break;

1655 break;

1662 break;

1669 break;

1673 w = inst.Offset / 4;

1675 streamer.emitInt8((w >> 8) & 0xff);

1676 streamer.emitInt8((w >> 0) & 0xff);

1677 break;

1681 w = inst.Offset / 4;

1683 streamer.emitInt8((w >> 16) & 0xff);

1684 streamer.emitInt8((w >> 8) & 0xff);

1685 streamer.emitInt8((w >> 0) & 0xff);

1686 break;

1690 w = inst.Offset / 4;

1692 streamer.emitInt8((w >> 8) & 0xff);

1693 streamer.emitInt8((w >> 0) & 0xff);

1694 break;

1698 w = inst.Offset / 4;

1700 streamer.emitInt8((w >> 16) & 0xff);

1701 streamer.emitInt8((w >> 8) & 0xff);

1702 streamer.emitInt8((w >> 0) & 0xff);

1703 break;

1706 break;

1709 break;

1712 break;

1715 break;

1718 break;

1720 for (i = 3; i > 0; i--)

1721 if (inst.Offset & (0xffu << (8 * i)))

1722 break;

1723 for (; i >= 0; i--)

1725 break;

1726 }

1727}

1728

1729

1730

1731

1732

1733

1734

1736 const std::vectorWinEH::Instruction &Epilog,

1737 bool CanTweakProlog) {

1738

1740 return -1;

1741

1742

1743

1744

1745

1746 int EndIdx = CanTweakProlog ? 1 : 0;

1747 for (int I = Epilog.size() - 1; I >= EndIdx; I--) {

1748

1749

1751 return -1;

1752 }

1753

1754 if (CanTweakProlog) {

1755

1757 return -1;

1761 return -1;

1762 }

1763

1764

1766 return 0;

1769}

1770

1772 int PrologCodeBytes) {

1773

1774 if (info->EpilogMap.size() != 1)

1775 return -1;

1776

1778

1779 if (EpilogInfo.Condition != 0xe)

1780 return -1;

1781

1782 const std::vectorWinEH::Instruction &Epilog = EpilogInfo.Instructions;

1783

1784 if (info->Instructions.empty() || Epilog.empty())

1785 return -1;

1786

1787

1788

1790 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);

1791 if (!MaybeDistance)

1792 return -1;

1795 if (DistanceFromEnd != InstructionBytes)

1796 return -1;

1797

1798 int RetVal = -1;

1799

1800

1801

1802

1803 if (PrologCodeBytes <= 31 &&

1805 RetVal = PrologCodeBytes;

1806

1810 return RetVal;

1811

1812

1813

1814

1815 if (Offset > 31 || PrologCodeBytes > 63)

1816 return RetVal;

1817

1818

1819

1820 info->Instructions.front() = Epilog.back();

1821

1822

1823

1824 info->EpilogMap.clear();

1826}

1827

1828static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11,

1829 unsigned &Folded, int &IntRegs) {

1830 if (Mask & (1 << 14)) {

1831 HasLR = true;

1832 Mask &= ~(1 << 14);

1833 }

1834 if (Mask & (1 << 11)) {

1835 HasR11 = true;

1836 Mask &= ~(1 << 11);

1837 }

1838 Folded = 0;

1840 if (!Mask)

1841 return true;

1843

1844 while ((Mask & 1) == 0) {

1846 Mask >>= 1;

1847 }

1848 if ((Mask & (Mask + 1)) != 0)

1849 return false;

1850

1851 int N = 0;

1852 while (Mask & (1 << N))

1853 N++;

1854 if (First < 4) {

1856 return false;

1857 Folded = 4 - First;

1858 N -= Folded;

1860 }

1862 return false;

1863 if (N >= 1)

1865 return true;

1866}

1867

1870 int Step = 0;

1871 bool Homing = false;

1872 bool HasR11 = false;

1873 bool HasChain = false;

1874 bool HasLR = false;

1875 int IntRegs = -1;

1876 int FloatRegs = -1;

1877 unsigned PF = 0;

1878 unsigned StackAdjust = 0;

1879

1880

1883 default:

1892

1893 return false;

1895

1896

1897 return false;

1899

1900 return false;

1901

1905 if (Step != 0)

1906 return false;

1907 Step = 1;

1908 break;

1909

1912

1913 if (Step != 1 && Step != 2)

1914 return false;

1919 HasR11 = true;

1921 }

1923 HasLR = true;

1924 Step = 3;

1925 break;

1926

1928 if (Step == 1 && Inst.Register == 0x0f) {

1929

1930 Homing = true;

1931 Step = 2;

1932 break;

1933 }

1934 [[fallthrough]];

1936 if (Step != 1 && Step != 2)

1937 return false;

1938

1939

1940

1942 return false;

1943 Step = 3;

1944 break;

1945

1947

1948 if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)

1949 return false;

1950 HasChain = true;

1951 Step = 4;

1952 break;

1954

1955 if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))

1956 return false;

1957 HasChain = true;

1958 Step = 4;

1959 break;

1960

1962 if (Step != 1 && Step != 2 && Step != 3 && Step != 4)

1963 return false;

1966 return false;

1968 return false;

1969 FloatRegs = Inst.Register - 8;

1970 Step = 5;

1971 break;

1972

1975 if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)

1976 return false;

1977 if (PF > 0)

1978 return false;

1979 if (Inst.Offset / 4 >= 0x3f4)

1980 return false;

1981 StackAdjust = Inst.Offset / 4;

1982 Step = 6;

1983 break;

1984 }

1985 }

1986 if (HasR11 && !HasChain) {

1987 if (IntRegs + 4 == 10) {

1988

1989

1991 HasR11 = false;

1992 } else

1993 return false;

1994 }

1995 if (HasChain && !HasLR)

1996 return false;

1997

1998

1999 if (info->EpilogMap.size() > 1)

2000 return false;

2001

2002 unsigned EF = 0;

2003 int Ret = 0;

2004 if (info->EpilogMap.size() == 0) {

2005 Ret = 3;

2006 } else {

2007

2008

2009

2011 info->EpilogMap.begin()->second;

2012 if (EpilogInfo.Condition != 0xe)

2013 return false;

2014 const std::vectorWinEH::Instruction &Epilog = EpilogInfo.Instructions;

2016 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);

2017 if (!MaybeDistance)

2018 return false;

2021 if (DistanceFromEnd != InstructionBytes)

2022 return false;

2023

2024 bool GotStackAdjust = false;

2025 bool GotFloatRegs = false;

2026 bool GotIntRegs = false;

2027 bool GotHomingRestore = false;

2028 bool GotLRRestore = false;

2029 bool NeedsReturn = false;

2030 bool GotReturn = false;

2031

2032 Step = 6;

2035 default:

2047

2048 return false;

2049

2052 if (Inst.Offset / 4 >= 0x3f4)

2053 return false;

2054 if (Step == 6) {

2055 if (Homing && FloatRegs < 0 && IntRegs < 0 && StackAdjust == 0 &&

2056 PF == 0 && Inst.Offset == 16) {

2057 GotHomingRestore = true;

2058 Step = 10;

2059 } else {

2060 if (StackAdjust > 0) {

2061

2062 if (StackAdjust != Inst.Offset / 4)

2063 return false;

2064 GotStackAdjust = true;

2065 } else if (PF == Inst.Offset / 4) {

2066

2067 StackAdjust = Inst.Offset / 4;

2068 GotStackAdjust = true;

2069 } else {

2070

2071 return false;

2072 }

2073 Step = 7;

2074 }

2075 } else if (Step == 7 || Step == 8 || Step == 9) {

2076 if (!Homing || Inst.Offset != 16)

2077 return false;

2078 GotHomingRestore = true;

2079 Step = 10;

2080 } else

2081 return false;

2082 break;

2083

2085 if (Step != 6 && Step != 7)

2086 return false;

2088 if (FloatRegs != (int)(Inst.Register - 8))

2089 return false;

2090 GotFloatRegs = true;

2091 Step = 8;

2092 break;

2093

2096

2097 if (Step != 6 && Step != 7 && Step != 8)

2098 return false;

2101 if (Homing && HasLR) {

2102

2103

2105 GotLRRestore = true;

2106 NeedsReturn = true;

2107 } else {

2108

2109 }

2110 } else {

2111 if (HasLR != (Inst.Offset == 1))

2112 return false;

2113 }

2114 GotLRRestore = Inst.Offset == 1;

2115 if (IntRegs < 0)

2116 return false;

2118 if (HasChain) {

2119

2121 return false;

2123 }

2125 return false;

2126 GotIntRegs = true;

2127 Step = 9;

2128 break;

2129 }

2130

2133 if (Step != 6 && Step != 7 && Step != 8)

2134 return false;

2135

2136

2137

2138 bool CurHasLR = false, CurHasR11 = false;

2139 int Regs;

2141 return false;

2142 if (EF > 0) {

2143 if (EF != PF && EF != StackAdjust)

2144 return false;

2145 }

2146 if (Homing && HasLR) {

2147

2148

2149 if (CurHasLR) {

2150 GotLRRestore = true;

2151 NeedsReturn = true;

2152 } else {

2153

2154 }

2155 } else {

2156 if (CurHasLR != HasLR)

2157 return false;

2158 GotLRRestore = CurHasLR;

2159 }

2161 if (HasChain) {

2162

2163 if (!CurHasR11)

2164 return false;

2166

2167

2169 if (!CurHasR11)

2170 return false;

2171 } else {

2172

2173

2174 if (CurHasR11)

2175 return false;

2176 }

2178 return false;

2179 GotIntRegs = true;

2180 Step = 9;

2181 break;

2182 }

2183

2185 if (Step != 6 && Step != 7 && Step != 8 && Step != 9)

2186 return false;

2187 if (!Homing || Inst.Offset != 20 || GotLRRestore)

2188 return false;

2189 GotLRRestore = true;

2190 GotHomingRestore = true;

2191 Step = 10;

2192 break;

2193

2196 GotReturn = true;

2198 [[fallthrough]];

2200 if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)

2201 return false;

2202 Step = 11;

2203 break;

2204 }

2205 }

2206

2207 if (Step != 11)

2208 return false;

2209 if (StackAdjust > 0 && !GotStackAdjust && EF == 0)

2210 return false;

2211 if (FloatRegs >= 0 && !GotFloatRegs)

2212 return false;

2213 if (IntRegs >= 0 && !GotIntRegs)

2214 return false;

2215 if (Homing && !GotHomingRestore)

2216 return false;

2217 if (HasLR && !GotLRRestore)

2218 return false;

2219 if (NeedsReturn && !GotReturn)

2220 return false;

2221 }

2222

2223 assert(PF == 0 || EF == 0 ||

2224 StackAdjust == 0);

2225 if (PF > 0 || EF > 0) {

2226 StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);

2227 assert(StackAdjust <= 3);

2228 StackAdjust |= 0x3f0;

2229 if (PF > 0)

2230 StackAdjust |= 1 << 2;

2231 if (EF > 0)

2232 StackAdjust |= 1 << 3;

2233 }

2234

2235 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");

2236 int Flag = info->Fragment ? 0x02 : 0x01;

2237 int H = Homing ? 1 : 0;

2238 int L = HasLR ? 1 : 0;

2239 int C = HasChain ? 1 : 0;

2241 unsigned Reg, R;

2245 R = 0;

2246 } else if (FloatRegs >= 0) {

2247 Reg = FloatRegs;

2249 R = 1;

2250 } else {

2251

2252 Reg = 7;

2253 R = 1;

2254 }

2255 info->PackedInfo |= Flag << 0;

2256 info->PackedInfo |= (FuncLength & 0x7FF) << 2;

2257 info->PackedInfo |= (Ret & 0x3) << 13;

2258 info->PackedInfo |= H << 15;

2259 info->PackedInfo |= Reg << 16;

2260 info->PackedInfo |= R << 19;

2261 info->PackedInfo |= L << 20;

2262 info->PackedInfo |= C << 21;

2263 assert(StackAdjust <= 0x3ff);

2264 info->PackedInfo |= StackAdjust << 22;

2265 return true;

2266}

2267

2268

2269

2271 bool TryPacked = true) {

2272

2273 if (info->Symbol)

2274 return;

2275

2276

2277

2278

2279 if (info->empty()) {

2280 info->EmitAttempted = true;

2281 return;

2282 }

2283 if (info->EmitAttempted) {

2284

2285

2286

2287

2288

2290 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +

2291 " skipped due to no unwind info at the time "

2292 "(.seh_handlerdata too early?), but the function later "

2293 "did get unwind info that can't be emitted");

2294 return;

2295 }

2296

2299

2302 info->Symbol = Label;

2303

2304 if (info->PrologEnd)

2306 info->Function->getName() +

2307 " not correctly terminated");

2308

2309 if (info->PrologEnd && info->Fragment)

2311 info->PrologEnd, info->Function->getName(),

2312 "prologue");

2313 for (auto &I : info->EpilogMap) {

2314 MCSymbol *EpilogStart = I.first;

2315 auto &Epilog = I.second;

2317 info->Function->getName(), "epilogue");

2318 if (Epilog.Instructions.empty() ||

2321 SMLoc(), "Epilogue in " + info->Function->getName() +

2322 " not correctly terminated");

2323 }

2324

2325 std::optional<int64_t> RawFuncLength;

2326 const MCExpr *FuncLengthExpr = nullptr;

2327 if (info->FuncletOrFuncEnd) {

2329 } else {

2330

2331

2332

2333

2334

2335

2336

2337

2338 RawFuncLength =

2340 if (!RawFuncLength)

2341 FuncLengthExpr =

2343 }

2345 if (RawFuncLength)

2346 FuncLength = (uint32_t)*RawFuncLength / 2;

2347 if (FuncLength > 0x3FFFF)

2348 report_fatal_error("SEH unwind data splitting not yet implemented");

2350 uint32_t TotalCodeBytes = PrologCodeBytes;

2351

2352 if (info->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&

2353 TryPacked) {

2354

2355

2356

2357

2358

2359

2360

2361

2363 return;

2364 }

2365

2366 int PackedEpilogOffset =

2368

2369

2371

2372 std::vector<MCSymbol *> AddedEpilogs;

2373

2374 bool CanTweakProlog = true;

2375 for (auto &I : info->EpilogMap) {

2376 MCSymbol *EpilogStart = I.first;

2377 auto &EpilogInstrs = I.second.Instructions;

2379

2382 int PrologOffset;

2383 if (MatchingEpilog) {

2385 "Duplicate epilog not found");

2386 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);

2387

2388

2389 EpilogInstrs.clear();

2391 info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {

2392 if (CanTweakProlog) {

2393

2394

2395 info->Instructions.front() = EpilogInstrs.back();

2396

2397 CanTweakProlog = false;

2398 }

2399 EpilogInfo[EpilogStart] = PrologOffset;

2400

2401

2402 EpilogInstrs.clear();

2403 } else {

2404 EpilogInfo[EpilogStart] = TotalCodeBytes;

2405 TotalCodeBytes += CodeBytes;

2406 AddedEpilogs.push_back(EpilogStart);

2407 }

2408 }

2409

2410

2412 uint32_t CodeWords = TotalCodeBytes / 4;

2413 uint32_t CodeWordsMod = TotalCodeBytes % 4;

2414 if (CodeWordsMod)

2415 CodeWords++;

2417 PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();

2418 bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;

2419 if (!ExtensionWord) {

2420 row1 |= (EpilogCount & 0x1F) << 23;

2421 row1 |= (CodeWords & 0x0F) << 28;

2422 }

2423 if (info->HandlesExceptions)

2424 row1 |= 1 << 20;

2425 if (PackedEpilogOffset >= 0)

2426 row1 |= 1 << 21;

2427 if (info->Fragment)

2428 row1 |= 1 << 22;

2429 row1 |= FuncLength & 0x3FFFF;

2430 if (RawFuncLength)

2432 else

2436 4);

2437

2438

2439 if (ExtensionWord) {

2440

2441 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)

2442 report_fatal_error("SEH unwind data splitting not yet implemented");

2444 row2 |= (CodeWords & 0xFF) << 16;

2445 row2 |= (EpilogCount & 0xFFFF);

2447 }

2448

2449 if (PackedEpilogOffset < 0) {

2450

2451 for (auto &I : EpilogInfo) {

2452 MCSymbol *EpilogStart = I.first;

2453 uint32_t EpilogIndex = I.second;

2454

2455 std::optional<int64_t> MaybeEpilogOffset =

2457 const MCExpr *OffsetExpr = nullptr;

2459 if (MaybeEpilogOffset)

2460 EpilogOffset = *MaybeEpilogOffset / 2;

2461 else

2462 OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);

2463

2464 assert(info->EpilogMap.contains(EpilogStart));

2465 unsigned Condition = info->EpilogMap[EpilogStart].Condition;

2466 assert(Condition <= 0xf);

2467

2468 uint32_t row3 = EpilogOffset;

2469 row3 |= Condition << 20;

2470 row3 |= (EpilogIndex & 0x3FF) << 24;

2471 if (MaybeEpilogOffset)

2473 else

2477 4);

2478 }

2479 }

2480

2481

2482 uint8_t numInst = info->Instructions.size();

2483 for (uint8_t c = 0; c < numInst; ++c) {

2485 info->Instructions.pop_back();

2487 }

2488

2489

2490 for (auto &I : info->EpilogMap) {

2491 auto &EpilogInstrs = I.second.Instructions;

2494 }

2495

2496 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;

2497 assert(BytesMod >= 0);

2498 for (int i = 0; i < BytesMod; i++)

2500

2501 if (info->HandlesExceptions)

2505 4);

2506}

2507

2511

2513 for (const auto &S : info->Segments) {

2515 if (info->PackedInfo)

2517 else

2520 context),

2521 4);

2522 }

2523}

2524

2525

2529

2532 if (info->PackedInfo)

2534 else

2537 context),

2538 4);

2539}

2540

2542

2545 if (Info->empty())

2546 continue;

2550 }

2551

2552

2555

2556

2557

2558 if (Info->Symbol)

2559 continue;

2563 }

2564}

2565

2568 bool HandlerData) const {

2569

2570

2571

2572

2573

2574

2575 if (info->FuncletOrFuncEnd) {

2578 }

2579

2580

2584}

2585

2587

2590 if (Info->empty())

2591 continue;

2595 }

2596

2597

2600

2601

2602

2603 if (Info->Symbol)

2604 continue;

2608 }

2609}

2610

2613 bool HandlerData) const {

2614

2615

2616

2617

2618

2619

2620 if (info->FuncletOrFuncEnd) {

2623 }

2624

2625

2629}

Analysis containing CSE Info

Given that RA is a live value

std::optional< std::vector< StOtherPiece > > Other

static int checkARM64PackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, int PrologCodeBytes)

static void ARM64EmitUnwindInfoForSegment(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment &Seg, bool TryPacked=true)

static uint32_t ARMCountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)

static uint32_t ARM64CountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)

static void checkARMInstructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)

static bool isARMTerminator(const WinEH::Instruction &inst)

static void ARM64EmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)

static void simplifyARM64Opcodes(std::vector< WinEH::Instruction > &Instructions, bool Reverse)

static void ARMEmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)

static int getARM64OffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog)

static void ARMEmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)

static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength, int PackedEpilogOffset)

static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)

static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)

static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)

static int getARMOffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog, bool CanTweakProlog)

static void ARM64EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)

static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, int64_t Offset)

static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11, unsigned &Folded, int &IntRegs)

static int checkARMPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)

static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)

static void ARM64FindSegmentsInFunction(MCStreamer &streamer, WinEH::FrameInfo *info, int64_t RawFuncLength)

static bool tryARMPackedUnwind(MCStreamer &streamer, WinEH::FrameInfo *info, uint32_t FuncLength)

static MCSymbol * FindMatchingEpilog(const std::vector< WinEH::Instruction > &EpilogInstrs, const std::vector< MCSymbol * > &Epilogs, const WinEH::FrameInfo *info)

static void EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)

static std::optional< int64_t > GetOptionalAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)

static void checkARM64Instructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)

static const MCExpr * GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS, int Div)

static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)

static void ARMEmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)

static uint32_t ARMCountOfInstructionBytes(ArrayRef< WinEH::Instruction > Insns, bool *HasCustom=nullptr)

static void ARM64ProcessEpilogs(WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, uint32_t &TotalCodeBytes, MapVector< MCSymbol *, uint32_t > &EpilogInfo)

static uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)

static cl::opt< RegAllocEvictionAdvisorAnalysis::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development, "development", "for training")))

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

static const MCPhysReg IntRegs[32]

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

This class represents an Operation in the Expression.

Tagged union holding either a T or a Error.

static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)

static const MCBinaryExpr * createOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)

static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)

static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)

static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

Context object for machine code objects.

MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

void reportError(SMLoc L, const Twine &Msg)

Base class for the full range of assembler expressions which are needed for parsing.

Streaming object file generation interface.

Instances of this class represent a uniqued identifier for a section in the current translation unit.

Streaming machine code generation interface.

virtual MCSymbol * emitCFILabel()

When emitting an object file, create and emit a real label.

MCSection * getAssociatedPDataSection(const MCSection *TextSec)

Get the .pdata section used for the given section.

MCContext & getContext() const

MCSection * getAssociatedXDataSection(const MCSection *TextSec)

Get the .xdata section used for the given section.

void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())

virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())

Emit a label for Symbol into the current section.

virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)

Emit some number of copies of Value until the byte alignment ByteAlignment is reached.

void emitInt16(uint64_t Value)

virtual void switchSection(MCSection *Section, uint32_t Subsec=0)

Set the current section where code is being emitted to Section.

void emitInt32(uint64_t Value)

ArrayRef< std::unique_ptr< WinEH::FrameInfo > > getWinFrameInfos() const

void emitInt8(uint64_t Value)

Represent a reference to a symbol from inside an expression.

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

This class implements a map that also provides access to all stored values in a deterministic order.

bool contains(const KeyT &Key) const

ValueT lookup(const KeyT &Key) const

Represents a location in source code.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StackOffset holds a fixed and a scalable offset in bytes.

StringRef - Represent a constant reference to a string, i.e.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override

void Emit(MCStreamer &Streamer) const override

This emits the unwind info sections (.pdata and .xdata in PE/COFF).

void Emit(MCStreamer &Streamer) const override

This emits the unwind info sections (.pdata and .xdata in PE/COFF).

void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override

void Emit(MCStreamer &Streamer) const override

This emits the unwind info sections (.pdata and .xdata in PE/COFF).

void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ C

The default llvm calling convention, compatible with C.

UnwindOpcodes

UnwindOpcodes - Enumeration whose values specify a single operation in the prolog of a function.

@ UOP_WideSaveRegsR4R11LR

@ UNW_TerminateHandler

UNW_TerminateHandler - Specifies that this function has a termination handler.

@ UNW_ExceptionHandler

UNW_ExceptionHandler - Specifies that this function has an exception handler.

@ UNW_ChainInfo

UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to another one.

This is an optimization pass for GlobalISel generic memory operations.

auto reverse(ContainerTy &&C)

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

This struct is a compact representation of a valid (non-zero power of two) alignment.

std::vector< Instruction > Instructions

MapVector< MCSymbol *, int64_t > Epilogs