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) && info->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;

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

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

810 if (Writeback)

812 b = 0xE7;

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

819 break;

820 }

822 b = 0xDF;

826 break;

827 }

831 b = 0xE7;

834 b = ((inst.Offset & 0xC0) >> 1) | reg;

836 b = 0xC0 | (inst.Offset & 0x3F);

838 break;

839 }

843 b = 0xE7;

846 b = ((inst.Offset & 0xC0) >> 1) | 0x10 | reg;

848 b = 0xC0 | (inst.Offset & 0x3F);

850 break;

851 }

852 }

853}

854

855

856

857

858

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

863 for (auto *EpilogStart : Epilogs) {

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

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

866 "Epilog not found in EpilogMap");

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

868

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

870 continue;

871

872 bool Match = true;

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

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

875 Match = false;

876 break;

877 }

878

879 if (Match)

880 return EpilogStart;

881 }

882 return nullptr;

883}

884

887 unsigned PrevOffset = -1;

888 unsigned PrevRegister = -1;

889

891

894 Inst.Register = -1;

896 Inst.Register == 29) {

898 Inst.Register = -1;

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

902 Inst.Register = -1;

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

906 Inst.Register == PrevRegister + 2 &&

907 Inst.Offset == PrevOffset + 16) {

909 Inst.Register = -1;

910 Inst.Offset = 0;

911

912

913

914 }

915

916

918 PrevOffset = 0;

919 PrevRegister = 19;

921 PrevOffset = 0;

922 PrevRegister = Inst.Register;

924 PrevOffset = Inst.Offset;

925 PrevRegister = Inst.Register;

927 PrevRegister += 2;

928 PrevOffset += 16;

929 } else {

930 PrevRegister = -1;

931 PrevOffset = -1;

932 }

933 };

934

935

936

937

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

940 VisitInstruction(*It);

941 } else {

943 VisitInstruction(Inst);

944 }

945}

946

947

948static int

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

951

953 return -1;

954

955

956

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

959 return -1;

960 }

961

963 return 0;

964

965

968}

969

972 int PrologCodeBytes) {

973

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

975 return -1;

976

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

979 info->EpilogMap[Sym].Instructions;

980

981

982

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

986 return -1;

987

988 int RetVal = -1;

989

990

991

992

993 if (PrologCodeBytes <= 31 &&

995 RetVal = PrologCodeBytes;

996

999 return RetVal;

1000

1001

1002

1003

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

1005 return RetVal;

1006

1007

1008

1009 info->EpilogMap.erase(Sym);

1011}

1012

1014 int PackedEpilogOffset) {

1015 if (PackedEpilogOffset == 0) {

1016

1017

1018

1019

1020

1021 } else if (PackedEpilogOffset == 1) {

1022

1023

1024

1026 return false;

1027 } else {

1028

1029 return false;

1030 }

1031 unsigned RegI = 0, RegF = 0;

1032 int Predecrement = 0;

1033 enum {

1034 Start,

1035 Start2,

1036 Start3,

1038 FloatRegs,

1039 InputArgs,

1040 StackAdjust,

1041 FrameRecord,

1042 End

1043 } Location = Start;

1044 bool StandaloneLR = false, FPLRPair = false;

1045 bool PAC = false;

1047 int Nops = 0;

1048

1049

1050

1051

1052

1053

1054 for (auto It = info->Instructions.begin(), EndIt = info->Instructions.end();

1055 It != EndIt; It++) {

1059 if (Location != Start)

1060 return false;

1061 Location = Start2;

1062 break;

1064 if (Location != Start2)

1065 return false;

1066 PAC = true;

1067 Location = Start3;

1068 break;

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

1071 return false;

1072 Predecrement = Inst.Offset;

1073 RegI = 2;

1075 break;

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

1078 return false;

1079 Predecrement = Inst.Offset;

1081 RegI += 1;

1082 else if (Inst.Register == 30)

1083 StandaloneLR = true;

1084 else

1085 return false;

1086

1087 Location = FloatRegs;

1088 break;

1090

1091

1092

1093

1094

1095

1096

1097

1098

1099

1100

1101 return false;

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

1105 return false;

1106 RegI += 2;

1107 break;

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

1110 return false;

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

1112 RegI += 1;

1113 else if (Inst.Register == 30)

1114 StandaloneLR = true;

1115 else

1116 return false;

1117

1118 Location = FloatRegs;

1119 break;

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

1123 return false;

1124 RegI += 1;

1125 StandaloneLR = true;

1126 Location = FloatRegs;

1127 break;

1129

1130

1131 return false;

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

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

1135 return false;

1136 RegF += 1;

1137 Location = InputArgs;

1138 break;

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

1141 return false;

1142 Predecrement = Inst.Offset;

1143 RegF = 2;

1144 Location = FloatRegs;

1145 break;

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

1148 Inst.Register != 8 + RegF ||

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

1150 return false;

1151 RegF += 2;

1152 Location = FloatRegs;

1153 break;

1155 if (Location == IntRegs)

1156 RegI += 2;

1157 else if (Location == FloatRegs)

1158 RegF += 2;

1159 else

1160 return false;

1161 break;

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

1164 return false;

1165 Location = InputArgs;

1166 Nops++;

1167 break;

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

1171 Location != FloatRegs && Location != InputArgs &&

1172 Location != StackAdjust)

1173 return false;

1174

1175

1176

1177

1178 if (Location == Start2) {

1179 auto NextIt = It + 1;

1180 if (NextIt != EndIt) {

1184 assert(Predecrement == 0);

1186 assert(!StandaloneLR);

1187 Predecrement = Inst.Offset;

1188 RegI = 1;

1189 StandaloneLR = true;

1190 Location = FloatRegs;

1191 It++;

1192 continue;

1193 }

1194 }

1195 }

1196

1197

1201 return false;

1202 else

1204 Location = StackAdjust;

1205 break;

1207

1208

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

1210 Location != FloatRegs && Location != InputArgs)

1211 return false;

1213 Location = FrameRecord;

1214 FPLRPair = true;

1215 break;

1217

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

1219 return false;

1220 Location = FrameRecord;

1221 FPLRPair = true;

1222 break;

1224 if (Location != FrameRecord)

1225 return false;

1226 Location = End;

1227 break;

1240

1241

1242 return false;

1244

1245

1246

1247 return false;

1249

1250

1251 return false;

1255

1256 return false;

1262

1263 return false;

1264 default:

1266 }

1267 }

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

1269 return false;

1270 if (StandaloneLR && FPLRPair)

1271 return false;

1272 if (FPLRPair && Location != End)

1273 return false;

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

1275 return false;

1276 if (PAC && !FPLRPair)

1277 return false;

1278 int H = Nops == 4;

1279

1280

1281

1282

1283

1284

1285

1286

1287

1288

1289

1290

1291

1292

1293

1294 if (H)

1295 return false;

1296

1297

1298

1299

1300

1301

1302

1303 if (StandaloneLR && RegI == 1 && RegF > 0)

1304 return false;

1305 int IntSZ = 8 * RegI;

1306 if (StandaloneLR)

1307 IntSZ += 8;

1308 int FpSZ = 8 * RegF;

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

1310 if (Predecrement != SavSZ)

1311 return false;

1313 return false;

1315 return false;

1317 if (FrameSize > 0x1FF)

1318 return false;

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

1320 if (RegF > 0)

1321 RegF--;

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

1323 int Flag = 0x01;

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

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

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

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

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

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

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

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

1332 return true;

1333}

1334

1339

1340 std::vector<MCSymbol *> EpilogStarts;

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

1342 EpilogStarts.push_back(I.first);

1343

1344

1345 std::vector<MCSymbol *> AddedEpilogs;

1346 for (auto *S : EpilogStarts) {

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

1350

1353 int PrologOffset;

1354 if (MatchingEpilog) {

1356 "Duplicate epilog not found");

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

1358

1359

1360 EpilogInstrs.clear();

1362 EpilogInstrs)) >= 0) {

1363 EpilogInfo[EpilogStart] = PrologOffset;

1364

1365

1367 EpilogInfo[EpilogStart] += 1;

1368

1369

1370 EpilogInstrs.clear();

1371 } else {

1372 EpilogInfo[EpilogStart] = TotalCodeBytes;

1373 TotalCodeBytes += CodeBytes;

1374 AddedEpilogs.push_back(EpilogStart);

1375 }

1376 }

1377}

1378

1381 int64_t RawFuncLength) {

1382 if (info->PrologEnd)

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

1385 "prologue");

1386 struct EpilogStartEnd {

1389 int64_t End;

1390 };

1391

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

1395 auto &Instrs = I.second.Instructions;

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

1400 "Epilogs should be monotonically ordered");

1401

1402

1404 }

1405

1406 unsigned E = 0;

1407 int64_t SegLimit = 0xFFFFC;

1408 int64_t SegOffset = 0;

1409

1410 if (RawFuncLength > SegLimit) {

1411

1412 int64_t RemainingLength = RawFuncLength;

1413

1414 while (RemainingLength > SegLimit) {

1415

1416

1417

1418 int64_t SegLength = SegLimit;

1419 int64_t SegEnd = SegOffset + SegLength;

1420

1422

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

1424

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

1426 ++E;

1427 }

1428

1429

1430

1431

1432

1433

1434

1435

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

1437

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

1439

1441 SegOffset, SegLength, !SegOffset);

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

1443 info->Segments.push_back(Seg);

1444

1445 SegOffset += SegLength;

1446 RemainingLength -= SegLength;

1447 }

1448 }

1449

1450

1451

1452 auto LastSeg =

1454 !SegOffset);

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

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

1457 info->Segments.push_back(LastSeg);

1458}

1459

1463 bool TryPacked = true) {

1466

1470

1471 if (Seg.Offset == 0)

1472 info->Symbol = Label;

1473

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

1476

1478 uint32_t PrologCodeBytes = info->PrologCodeBytes;

1479

1480 int PackedEpilogOffset = HasEpilogs ?

1482

1483

1484

1485

1486

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

1488 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&

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

1490

1491

1492

1493

1494

1495

1496

1498 return;

1499 }

1500

1501

1502

1503 if (!HasProlog) {

1504 PrologCodeBytes += 1;

1505 if (PackedEpilogOffset >= 0)

1506 PackedEpilogOffset += 1;

1507

1508

1509

1510

1511

1512 if (!HasEpilogs)

1513

1514 PackedEpilogOffset = 0;

1515 }

1516

1517 uint32_t TotalCodeBytes = PrologCodeBytes;

1518

1519

1522

1523

1525 uint32_t CodeWords = TotalCodeBytes / 4;

1526 uint32_t CodeWordsMod = TotalCodeBytes % 4;

1527 if (CodeWordsMod)

1528 CodeWords++;

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

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

1532 if (!ExtensionWord) {

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

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

1535 }

1536 if (info->HandlesExceptions)

1537 row1 |= 1 << 20;

1538 if (PackedEpilogOffset >= 0)

1539 row1 |= 1 << 21;

1540 row1 |= SegLength & 0x3FFFF;

1542

1543

1544 if (ExtensionWord) {

1545

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

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

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

1550 "later");

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

1553 row2 |= (EpilogCount & 0xFFFF);

1555 }

1556

1557 if (PackedEpilogOffset < 0) {

1558

1559 for (auto &I : EpilogInfo) {

1560 MCSymbol *EpilogStart = I.first;

1561 uint32_t EpilogIndex = I.second;

1562

1564 if (EpilogOffset)

1565 EpilogOffset /= 4;

1566 uint32_t row3 = EpilogOffset;

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

1569 }

1570 }

1571

1572

1573

1574

1575

1576

1577

1578 if (!HasProlog)

1579

1581

1582

1585

1586

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

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

1591 }

1592

1593 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;

1594 assert(BytesMod >= 0);

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

1597

1598 if (info->HandlesExceptions)

1602 4);

1603}

1604

1605

1606

1608 bool TryPacked = true) {

1609

1610 if (info->Symbol)

1611 return;

1612

1613

1614

1615

1616 if (info->empty()) {

1617 info->EmitAttempted = true;

1618 return;

1619 }

1620 if (info->EmitAttempted) {

1621

1622

1623

1624

1625

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

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

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

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

1631 return;

1632 }

1633

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

1637

1638 int64_t RawFuncLength;

1639 if (info->FuncletOrFuncEnd) {

1641 } else {

1642

1643

1644

1645

1646

1647

1648

1649

1650

1651

1652

1653

1654

1655

1656

1657

1658

1659

1660

1661

1662

1663

1664

1665

1666

1667

1668

1669

1670

1672 info->Begin);

1673 }

1674

1676

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

1680

1681

1682 info->Instructions.clear();

1683}

1684

1687 for (const auto &I : Insns) {

1689 default:

1693 break;

1696 break;

1699 break;

1702 break;

1705 break;

1708 break;

1711 break;

1714 break;

1717 break;

1720 break;

1723 break;

1726 break;

1729 break;

1732 break;

1735 break;

1742 break;

1744 int J;

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

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

1747 break;

1749 break;

1750 }

1751 }

1752 }

1754}

1755

1757 bool *HasCustom = nullptr) {

1759 for (const auto &I : Insns) {

1761 default:

1767 break;

1772 break;

1776 break;

1779 break;

1783 break;

1788 break;

1791 break;

1795 break;

1799 break;

1801

1802 break;

1804

1805

1807 if (HasCustom)

1808 *HasCustom = true;

1809 break;

1810 }

1811 }

1813}

1814

1819 if (!End)

1820 return;

1821 std::optional<int64_t> MaybeDistance =

1823 if (!MaybeDistance)

1824 return;

1826 bool HasCustom = false;

1828 if (HasCustom)

1829 return;

1830 if (Distance != InstructionBytes) {

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

1833 Twine(Distance) +

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

1835 "corresponding to " +

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

1837 }

1838}

1839

1845 return true;

1846 default:

1847 return false;

1848 }

1849}

1850

1851

1852

1856 int i;

1858 default:

1864 break;

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

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

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

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

1871 break;

1875 break;

1880 break;

1885 break;

1889 break;

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

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

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

1896 break;

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

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

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

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

1903 break;

1909 break;

1916 break;

1923 break;

1927 w = inst.Offset / 4;

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

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

1931 break;

1935 w = inst.Offset / 4;

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

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

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

1940 break;

1944 w = inst.Offset / 4;

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

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

1948 break;

1952 w = inst.Offset / 4;

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

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

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

1957 break;

1960 break;

1963 break;

1966 break;

1969 break;

1972 break;

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

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

1976 break;

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

1979 break;

1980 }

1981}

1982

1983

1984

1985

1986

1987

1988

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

1991 bool CanTweakProlog) {

1992

1994 return -1;

1995

1996

1997

1998

1999

2000 int EndIdx = CanTweakProlog ? 1 : 0;

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

2002

2003

2005 return -1;

2006 }

2007

2008 if (CanTweakProlog) {

2009

2011 return -1;

2015 return -1;

2016 }

2017

2018

2020 return 0;

2023}

2024

2026 int PrologCodeBytes) {

2027

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

2029 return -1;

2030

2032

2033 if (EpilogInfo.Condition != 0xe)

2034 return -1;

2035

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

2037

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

2039 return -1;

2040

2041

2042

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

2045 if (!MaybeDistance)

2046 return -1;

2049 if (DistanceFromEnd != InstructionBytes)

2050 return -1;

2051

2052 int RetVal = -1;

2053

2054

2055

2056

2057 if (PrologCodeBytes <= 31 &&

2059 RetVal = PrologCodeBytes;

2060

2064 return RetVal;

2065

2066

2067

2068

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

2070 return RetVal;

2071

2072

2073

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

2075

2076

2077

2078 info->EpilogMap.clear();

2080}

2081

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

2083 unsigned &Folded, int &IntRegs) {

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

2085 HasLR = true;

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

2087 }

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

2089 HasR11 = true;

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

2091 }

2092 Folded = 0;

2094 if (!Mask)

2095 return true;

2097

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

2100 Mask >>= 1;

2101 }

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

2103 return false;

2104

2105 int N = 0;

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

2107 N++;

2108 if (First < 4) {

2110 return false;

2111 Folded = 4 - First;

2112 N -= Folded;

2114 }

2116 return false;

2117 if (N >= 1)

2119 return true;

2120}

2121

2124 int Step = 0;

2125 bool Homing = false;

2126 bool HasR11 = false;

2127 bool HasChain = false;

2128 bool HasLR = false;

2129 int IntRegs = -1;

2130 int FloatRegs = -1;

2131 unsigned PF = 0;

2132 unsigned StackAdjust = 0;

2133

2134

2137 default:

2146

2147 return false;

2149

2150

2151 return false;

2153

2154 return false;

2155

2159 if (Step != 0)

2160 return false;

2161 Step = 1;

2162 break;

2163

2166

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

2168 return false;

2173 HasR11 = true;

2175 }

2177 HasLR = true;

2178 Step = 3;

2179 break;

2180

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

2183

2184 Homing = true;

2185 Step = 2;

2186 break;

2187 }

2188 [[fallthrough]];

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

2191 return false;

2192

2193

2194

2196 return false;

2197 Step = 3;

2198 break;

2199

2201

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

2203 return false;

2204 HasChain = true;

2205 Step = 4;

2206 break;

2208

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

2210 return false;

2211 HasChain = true;

2212 Step = 4;

2213 break;

2214

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

2217 return false;

2220 return false;

2222 return false;

2223 FloatRegs = Inst.Register - 8;

2224 Step = 5;

2225 break;

2226

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

2230 return false;

2231 if (PF > 0)

2232 return false;

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

2234 return false;

2235 StackAdjust = Inst.Offset / 4;

2236 Step = 6;

2237 break;

2238 }

2239 }

2240 if (HasR11 && !HasChain) {

2241 if (IntRegs + 4 == 10) {

2242

2243

2245 HasR11 = false;

2246 } else

2247 return false;

2248 }

2249 if (HasChain && !HasLR)

2250 return false;

2251

2252

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

2254 return false;

2255

2256 unsigned EF = 0;

2257 int Ret = 0;

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

2259 Ret = 3;

2260 } else {

2261

2262

2263

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

2266 if (EpilogInfo.Condition != 0xe)

2267 return false;

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

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

2271 if (!MaybeDistance)

2272 return false;

2275 if (DistanceFromEnd != InstructionBytes)

2276 return false;

2277

2278 bool GotStackAdjust = false;

2279 bool GotFloatRegs = false;

2280 bool GotIntRegs = false;

2281 bool GotHomingRestore = false;

2282 bool GotLRRestore = false;

2283 bool NeedsReturn = false;

2284 bool GotReturn = false;

2285

2286 Step = 6;

2289 default:

2301

2302 return false;

2303

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

2307 return false;

2308 if (Step == 6) {

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

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

2311 GotHomingRestore = true;

2312 Step = 10;

2313 } else {

2314 if (StackAdjust > 0) {

2315

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

2317 return false;

2318 GotStackAdjust = true;

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

2320

2321 StackAdjust = Inst.Offset / 4;

2322 GotStackAdjust = true;

2323 } else {

2324

2325 return false;

2326 }

2327 Step = 7;

2328 }

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

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

2331 return false;

2332 GotHomingRestore = true;

2333 Step = 10;

2334 } else

2335 return false;

2336 break;

2337

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

2340 return false;

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

2343 return false;

2344 GotFloatRegs = true;

2345 Step = 8;

2346 break;

2347

2350

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

2352 return false;

2355 if (Homing && HasLR) {

2356

2357

2359 GotLRRestore = true;

2360 NeedsReturn = true;

2361 } else {

2362

2363 }

2364 } else {

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

2366 return false;

2367 }

2368 GotLRRestore = Inst.Offset == 1;

2369 if (IntRegs < 0)

2370 return false;

2372 if (HasChain) {

2373

2375 return false;

2377 }

2379 return false;

2380 GotIntRegs = true;

2381 Step = 9;

2382 break;

2383 }

2384

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

2388 return false;

2389

2390

2391

2392 bool CurHasLR = false, CurHasR11 = false;

2393 int Regs;

2395 return false;

2396 if (EF > 0) {

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

2398 return false;

2399 }

2400 if (Homing && HasLR) {

2401

2402

2403 if (CurHasLR) {

2404 GotLRRestore = true;

2405 NeedsReturn = true;

2406 } else {

2407

2408 }

2409 } else {

2410 if (CurHasLR != HasLR)

2411 return false;

2412 GotLRRestore = CurHasLR;

2413 }

2415 if (HasChain) {

2416

2417 if (!CurHasR11)

2418 return false;

2420

2421

2423 if (!CurHasR11)

2424 return false;

2425 } else {

2426

2427

2428 if (CurHasR11)

2429 return false;

2430 }

2432 return false;

2433 GotIntRegs = true;

2434 Step = 9;

2435 break;

2436 }

2437

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

2440 return false;

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

2442 return false;

2443 GotLRRestore = true;

2444 GotHomingRestore = true;

2445 Step = 10;

2446 break;

2447

2450 GotReturn = true;

2452 [[fallthrough]];

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

2455 return false;

2456 Step = 11;

2457 break;

2458 }

2459 }

2460

2461 if (Step != 11)

2462 return false;

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

2464 return false;

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

2466 return false;

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

2468 return false;

2469 if (Homing && !GotHomingRestore)

2470 return false;

2471 if (HasLR && !GotLRRestore)

2472 return false;

2473 if (NeedsReturn && !GotReturn)

2474 return false;

2475 }

2476

2477 assert(PF == 0 || EF == 0 ||

2478 StackAdjust == 0);

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

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

2481 assert(StackAdjust <= 3);

2482 StackAdjust |= 0x3f0;

2483 if (PF > 0)

2484 StackAdjust |= 1 << 2;

2485 if (EF > 0)

2486 StackAdjust |= 1 << 3;

2487 }

2488

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

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

2491 int H = Homing ? 1 : 0;

2492 int L = HasLR ? 1 : 0;

2493 int C = HasChain ? 1 : 0;

2495 unsigned Reg, R;

2499 R = 0;

2500 } else if (FloatRegs >= 0) {

2501 Reg = FloatRegs;

2503 R = 1;

2504 } else {

2505

2506 Reg = 7;

2507 R = 1;

2508 }

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

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

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

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

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

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

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

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

2517 assert(StackAdjust <= 0x3ff);

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

2519 return true;

2520}

2521

2522

2523

2525 bool TryPacked = true) {

2526

2527 if (info->Symbol)

2528 return;

2529

2530

2531

2532

2533 if (info->empty()) {

2534 info->EmitAttempted = true;

2535 return;

2536 }

2537 if (info->EmitAttempted) {

2538

2539

2540

2541

2542

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

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

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

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

2548 return;

2549 }

2550

2553

2556 info->Symbol = Label;

2557

2558 if (info->PrologEnd)

2560 info->Function->getName() +

2561 " not correctly terminated");

2562

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

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

2566 "prologue");

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

2568 MCSymbol *EpilogStart = I.first;

2569 auto &Epilog = I.second;

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

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

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

2576 " not correctly terminated");

2577 }

2578

2579 std::optional<int64_t> RawFuncLength;

2580 const MCExpr *FuncLengthExpr = nullptr;

2581 if (info->FuncletOrFuncEnd) {

2583 } else {

2584

2585

2586

2587

2588

2589

2590

2591

2592 RawFuncLength =

2594 if (!RawFuncLength)

2595 FuncLengthExpr =

2597 }

2599 if (RawFuncLength)

2600 FuncLength = (uint32_t)*RawFuncLength / 2;

2601 if (FuncLength > 0x3FFFF)

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

2604 uint32_t TotalCodeBytes = PrologCodeBytes;

2605

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

2607 TryPacked) {

2608

2609

2610

2611

2612

2613

2614

2615

2617 return;

2618 }

2619

2620 int PackedEpilogOffset =

2622

2623

2625

2626 std::vector<MCSymbol *> AddedEpilogs;

2627

2628 bool CanTweakProlog = true;

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

2630 MCSymbol *EpilogStart = I.first;

2631 auto &EpilogInstrs = I.second.Instructions;

2633

2636 int PrologOffset;

2637 if (MatchingEpilog) {

2639 "Duplicate epilog not found");

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

2641

2642

2643 EpilogInstrs.clear();

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

2646 if (CanTweakProlog) {

2647

2648

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

2650

2651 CanTweakProlog = false;

2652 }

2653 EpilogInfo[EpilogStart] = PrologOffset;

2654

2655

2656 EpilogInstrs.clear();

2657 } else {

2658 EpilogInfo[EpilogStart] = TotalCodeBytes;

2659 TotalCodeBytes += CodeBytes;

2660 AddedEpilogs.push_back(EpilogStart);

2661 }

2662 }

2663

2664

2666 uint32_t CodeWords = TotalCodeBytes / 4;

2667 uint32_t CodeWordsMod = TotalCodeBytes % 4;

2668 if (CodeWordsMod)

2669 CodeWords++;

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

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

2673 if (!ExtensionWord) {

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

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

2676 }

2677 if (info->HandlesExceptions)

2678 row1 |= 1 << 20;

2679 if (PackedEpilogOffset >= 0)

2680 row1 |= 1 << 21;

2681 if (info->Fragment)

2682 row1 |= 1 << 22;

2683 row1 |= FuncLength & 0x3FFFF;

2684 if (RawFuncLength)

2686 else

2690 4);

2691

2692

2693 if (ExtensionWord) {

2694

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

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

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

2699 row2 |= (EpilogCount & 0xFFFF);

2701 }

2702

2703 if (PackedEpilogOffset < 0) {

2704

2705 for (auto &I : EpilogInfo) {

2706 MCSymbol *EpilogStart = I.first;

2707 uint32_t EpilogIndex = I.second;

2708

2709 std::optional<int64_t> MaybeEpilogOffset =

2711 const MCExpr *OffsetExpr = nullptr;

2713 if (MaybeEpilogOffset)

2714 EpilogOffset = *MaybeEpilogOffset / 2;

2715 else

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

2717

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

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

2720 assert(Condition <= 0xf);

2721

2722 uint32_t row3 = EpilogOffset;

2723 row3 |= Condition << 20;

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

2725 if (MaybeEpilogOffset)

2727 else

2731 4);

2732 }

2733 }

2734

2735

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

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

2739 info->Instructions.pop_back();

2741 }

2742

2743

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

2745 auto &EpilogInstrs = I.second.Instructions;

2748 }

2749

2750 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;

2751 assert(BytesMod >= 0);

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

2754

2755 if (info->HandlesExceptions)

2759 4);

2760}

2761

2765

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

2769 if (info->PackedInfo)

2771 else

2774 context),

2775 4);

2776 }

2777}

2778

2779

2783

2786 if (info->PackedInfo)

2788 else

2791 context),

2792 4);

2793}

2794

2796

2799 if (Info->empty())

2800 continue;

2804 }

2805

2806

2809

2810

2811

2812 if (!Info->Symbol)

2813 continue;

2817 }

2818}

2819

2822 bool HandlerData) const {

2823

2824

2825

2826

2827

2828

2829 if (info->FuncletOrFuncEnd) {

2832 }

2833

2834

2838}

2839

2841

2844 if (Info->empty())

2845 continue;

2849 }

2850

2851

2854

2855

2856

2857 if (!Info->Symbol)

2858 continue;

2862 }

2863}

2864

2867 bool HandlerData) const {

2868

2869

2870

2871

2872

2873

2874 if (info->FuncletOrFuncEnd) {

2877 }

2878

2879

2883}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

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

Definition MCWin64EH.cpp:970

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

Definition MCWin64EH.cpp:1460

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

Definition MCWin64EH.cpp:1685

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

Definition MCWin64EH.cpp:513

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

Definition MCWin64EH.cpp:1815

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

Definition MCWin64EH.cpp:1840

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

Definition MCWin64EH.cpp:623

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

Definition MCWin64EH.cpp:885

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

Definition MCWin64EH.cpp:1853

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

Definition MCWin64EH.cpp:213

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

Definition MCWin64EH.cpp:949

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

Definition MCWin64EH.cpp:2780

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

Definition MCWin64EH.cpp:1013

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

Definition MCWin64EH.cpp:228

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

Definition MCWin64EH.cpp:108

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

Definition MCWin64EH.cpp:1607

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

Definition MCWin64EH.cpp:1989

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

Definition MCWin64EH.cpp:2762

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

Definition MCWin64EH.cpp:176

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

Definition MCWin64EH.cpp:2082

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

Definition MCWin64EH.cpp:2025

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

Definition MCWin64EH.cpp:466

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

Definition MCWin64EH.cpp:1379

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

Definition MCWin64EH.cpp:2122

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

Definition MCWin64EH.cpp:860

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

Definition MCWin64EH.cpp:200

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

Definition MCWin64EH.cpp:475

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

Definition MCWin64EH.cpp:447

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

Definition MCWin64EH.cpp:99

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

Definition MCWin64EH.cpp:2524

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

Definition MCWin64EH.cpp:1756

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

Definition MCWin64EH.cpp:1335

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

Definition MCWin64EH.cpp:71

static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, const MCSpecifierExpr &Expr)

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

static const MCPhysReg IntRegs[32]

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

size_t size() const

size - Get the array size.

Tagged union holding either a T or a Error.

MCContext & getContext() const

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

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

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

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

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

Context object for machine code objects.

LLVM_ABI MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

LLVM_ABI void reportError(SMLoc L, const Twine &Msg)

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

Streaming object file generation interface.

MCAssembler & getAssembler()

void appendContents(ArrayRef< char > Contents)

void addFixup(const MCExpr *Value, MCFixupKind Kind)

void ensureHeadroom(size_t Headroom)

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

Streaming machine code generation interface.

virtual MCSymbol * emitCFILabel()

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

MCSection * getAssociatedPDataSection(const MCSection *TextSec)

Get the .pdata section used for the given section.

MCContext & getContext() const

MCSection * getAssociatedXDataSection(const MCSection *TextSec)

Get the .xdata section used for the given section.

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

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

Emit a label for Symbol into the current section.

virtual void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0)

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

void emitInt16(uint64_t Value)

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

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

void emitInt32(uint64_t Value)

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

void emitInt8(uint64_t Value)

Represent a reference to a symbol from inside an expression.

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

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

LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const

print - Print the value to the stream OS.

MCFragment * getFragment() const

static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)

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

bool contains(const KeyT &Key) const

ValueT lookup(const KeyT &Key) const

Represents a location in source code.

void push_back(const T &Elt)

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

StackOffset holds a fixed and a scalable offset in bytes.

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

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

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

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

Definition MCWin64EH.cpp:2820

void Emit(MCStreamer &Streamer) const override

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

Definition MCWin64EH.cpp:2795

void Emit(MCStreamer &Streamer) const override

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

Definition MCWin64EH.cpp:2840

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

Definition MCWin64EH.cpp:2865

void Emit(MCStreamer &Streamer) const override

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

Definition MCWin64EH.cpp:420

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

Definition MCWin64EH.cpp:436

#define llvm_unreachable(msg)

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

@ C

The default llvm calling convention, compatible with C.

@ UNW_TerminateHandler

UNW_TerminateHandler - Specifies that this function has a termination handler.

@ UNW_ExceptionHandler

UNW_ExceptionHandler - Specifies that this function has an exception handler.

@ UNW_ChainInfo

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

UnwindOpcodes

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

@ UOP_WideSaveRegsR4R11LR

This is an optimization pass for GlobalISel generic memory operations.

auto reverse(ContainerTy &&C)

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

FunctionAddr VTableAddr Count

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

@ FK_Data_2

A two-byte fixup.

DWARFExpression::Operation Op

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

std::vector< Instruction > Instructions

MapVector< MCSymbol *, int64_t > Epilogs