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

890

891

892

895

898 Inst.Register = -1;

900 Inst.Register == 29) {

902 Inst.Register = -1;

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

906 Inst.Register = -1;

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

910 Inst.Register == PrevRegister + 2 &&

911 Inst.Offset == PrevOffset + 16) {

913 Inst.Register = -1;

914 Inst.Offset = 0;

915

916

917

918 }

919

920

922 PrevOffset = 0;

923 PrevRegister = 19;

925 PrevOffset = 0;

926 PrevRegister = Inst.Register;

928 PrevOffset = Inst.Offset;

929 PrevRegister = Inst.Register;

931 PrevRegister += 2;

932 PrevOffset += 16;

933 } else {

934 PrevRegister = -1;

935 PrevOffset = -1;

936 }

937 }

938}

939

940

941static int

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

944

946 return -1;

947

948

949

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

952 return -1;

953 }

954

956 return 0;

957

958

961}

962

965 int PrologCodeBytes) {

966

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

968 return -1;

969

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

972 info->EpilogMap[Sym].Instructions;

973

974

975

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

979 return -1;

980

981 int RetVal = -1;

982

983

984

985

986 if (PrologCodeBytes <= 31 &&

988 RetVal = PrologCodeBytes;

989

992 return RetVal;

993

994

995

996

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

998 return RetVal;

999

1000

1001

1002 info->EpilogMap.erase(Sym);

1004}

1005

1007 int PackedEpilogOffset) {

1008 if (PackedEpilogOffset == 0) {

1009

1010

1011

1012

1013

1014 } else if (PackedEpilogOffset == 1) {

1015

1016

1017

1019 return false;

1020 } else {

1021

1022 return false;

1023 }

1024 unsigned RegI = 0, RegF = 0;

1025 int Predecrement = 0;

1026 enum {

1027 Start,

1028 Start2,

1029 Start3,

1031 FloatRegs,

1032 InputArgs,

1033 StackAdjust,

1034 FrameRecord,

1035 End

1036 } Location = Start;

1037 bool StandaloneLR = false, FPLRPair = false;

1038 bool PAC = false;

1040 int Nops = 0;

1041

1042

1043

1044

1045

1046

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

1048 It != EndIt; It++) {

1052 if (Location != Start)

1053 return false;

1054 Location = Start2;

1055 break;

1057 if (Location != Start2)

1058 return false;

1059 PAC = true;

1060 Location = Start3;

1061 break;

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

1064 return false;

1065 Predecrement = Inst.Offset;

1066 RegI = 2;

1068 break;

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

1071 return false;

1072 Predecrement = Inst.Offset;

1074 RegI += 1;

1075 else if (Inst.Register == 30)

1076 StandaloneLR = true;

1077 else

1078 return false;

1079

1080 Location = FloatRegs;

1081 break;

1083

1084

1085

1086

1087

1088

1089

1090

1091

1092

1093

1094 return false;

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

1098 return false;

1099 RegI += 2;

1100 break;

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

1103 return false;

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

1105 RegI += 1;

1106 else if (Inst.Register == 30)

1107 StandaloneLR = true;

1108 else

1109 return false;

1110

1111 Location = FloatRegs;

1112 break;

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

1116 return false;

1117 RegI += 1;

1118 StandaloneLR = true;

1119 Location = FloatRegs;

1120 break;

1122

1123

1124 return false;

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

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

1128 return false;

1129 RegF += 1;

1130 Location = InputArgs;

1131 break;

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

1134 return false;

1135 Predecrement = Inst.Offset;

1136 RegF = 2;

1137 Location = FloatRegs;

1138 break;

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

1141 Inst.Register != 8 + RegF ||

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

1143 return false;

1144 RegF += 2;

1145 Location = FloatRegs;

1146 break;

1148 if (Location == IntRegs)

1149 RegI += 2;

1150 else if (Location == FloatRegs)

1151 RegF += 2;

1152 else

1153 return false;

1154 break;

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

1157 return false;

1158 Location = InputArgs;

1159 Nops++;

1160 break;

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

1164 Location != FloatRegs && Location != InputArgs &&

1165 Location != StackAdjust)

1166 return false;

1167

1168

1169

1170

1171 if (Location == Start2) {

1172 auto NextIt = It + 1;

1173 if (NextIt != EndIt) {

1177 assert(Predecrement == 0);

1179 assert(!StandaloneLR);

1180 Predecrement = Inst.Offset;

1181 RegI = 1;

1182 StandaloneLR = true;

1183 Location = FloatRegs;

1184 It++;

1185 continue;

1186 }

1187 }

1188 }

1189

1190

1194 return false;

1195 else

1197 Location = StackAdjust;

1198 break;

1200

1201

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

1203 Location != FloatRegs && Location != InputArgs)

1204 return false;

1206 Location = FrameRecord;

1207 FPLRPair = true;

1208 break;

1210

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

1212 return false;

1213 Location = FrameRecord;

1214 FPLRPair = true;

1215 break;

1217 if (Location != FrameRecord)

1218 return false;

1219 Location = End;

1220 break;

1233

1234

1235 return false;

1237

1238

1239

1240 return false;

1242

1243

1244 return false;

1248

1249 return false;

1255

1256 return false;

1257 default:

1259 }

1260 }

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

1262 return false;

1263 if (StandaloneLR && FPLRPair)

1264 return false;

1265 if (FPLRPair && Location != End)

1266 return false;

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

1268 return false;

1269 if (PAC && !FPLRPair)

1270 return false;

1271 int H = Nops == 4;

1272

1273

1274

1275

1276

1277

1278

1279

1280

1281

1282

1283

1284

1285

1286

1287 if (H)

1288 return false;

1289

1290

1291

1292

1293

1294

1295

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

1297 return false;

1298 int IntSZ = 8 * RegI;

1299 if (StandaloneLR)

1300 IntSZ += 8;

1301 int FpSZ = 8 * RegF;

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

1303 if (Predecrement != SavSZ)

1304 return false;

1306 return false;

1308 return false;

1310 if (FrameSize > 0x1FF)

1311 return false;

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

1313 if (RegF > 0)

1314 RegF--;

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

1316 int Flag = 0x01;

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

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

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

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

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

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

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

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

1325 return true;

1326}

1327

1332

1333 std::vector<MCSymbol *> EpilogStarts;

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

1335 EpilogStarts.push_back(I.first);

1336

1337

1338 std::vector<MCSymbol *> AddedEpilogs;

1339 for (auto *S : EpilogStarts) {

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

1343

1346 int PrologOffset;

1347 if (MatchingEpilog) {

1349 "Duplicate epilog not found");

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

1351

1352

1353 EpilogInstrs.clear();

1355 EpilogInstrs)) >= 0) {

1356 EpilogInfo[EpilogStart] = PrologOffset;

1357

1358

1360 EpilogInfo[EpilogStart] += 1;

1361

1362

1363 EpilogInstrs.clear();

1364 } else {

1365 EpilogInfo[EpilogStart] = TotalCodeBytes;

1366 TotalCodeBytes += CodeBytes;

1367 AddedEpilogs.push_back(EpilogStart);

1368 }

1369 }

1370}

1371

1374 int64_t RawFuncLength) {

1375 if (info->PrologEnd)

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

1378 "prologue");

1379 struct EpilogStartEnd {

1382 int64_t End;

1383 };

1384

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

1388 auto &Instrs = I.second.Instructions;

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

1393 "Epilogs should be monotonically ordered");

1394

1395

1397 }

1398

1399 unsigned E = 0;

1400 int64_t SegLimit = 0xFFFFC;

1401 int64_t SegOffset = 0;

1402

1403 if (RawFuncLength > SegLimit) {

1404

1405 int64_t RemainingLength = RawFuncLength;

1406

1407 while (RemainingLength > SegLimit) {

1408

1409

1410

1411 int64_t SegLength = SegLimit;

1412 int64_t SegEnd = SegOffset + SegLength;

1413

1415

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

1417

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

1419 ++E;

1420 }

1421

1422

1423

1424

1425

1426

1427

1428

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

1430

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

1432

1434 SegOffset, SegLength, !SegOffset);

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

1436 info->Segments.push_back(Seg);

1437

1438 SegOffset += SegLength;

1439 RemainingLength -= SegLength;

1440 }

1441 }

1442

1443

1444

1445 auto LastSeg =

1447 !SegOffset);

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

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

1450 info->Segments.push_back(LastSeg);

1451}

1452

1456 bool TryPacked = true) {

1459

1463

1464 if (Seg.Offset == 0)

1465 info->Symbol = Label;

1466

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

1469

1471 uint32_t PrologCodeBytes = info->PrologCodeBytes;

1472

1473 int PackedEpilogOffset = HasEpilogs ?

1475

1476

1477

1478

1479

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

1481 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&

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

1483

1484

1485

1486

1487

1488

1489

1491 return;

1492 }

1493

1494

1495

1496 if (!HasProlog) {

1497 PrologCodeBytes += 1;

1498 if (PackedEpilogOffset >= 0)

1499 PackedEpilogOffset += 1;

1500

1501

1502

1503

1504

1505 if (!HasEpilogs)

1506

1507 PackedEpilogOffset = 0;

1508 }

1509

1510 uint32_t TotalCodeBytes = PrologCodeBytes;

1511

1512

1515

1516

1518 uint32_t CodeWords = TotalCodeBytes / 4;

1519 uint32_t CodeWordsMod = TotalCodeBytes % 4;

1520 if (CodeWordsMod)

1521 CodeWords++;

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

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

1525 if (!ExtensionWord) {

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

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

1528 }

1529 if (info->HandlesExceptions)

1530 row1 |= 1 << 20;

1531 if (PackedEpilogOffset >= 0)

1532 row1 |= 1 << 21;

1533 row1 |= SegLength & 0x3FFFF;

1535

1536

1537 if (ExtensionWord) {

1538

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

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

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

1543 "later");

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

1546 row2 |= (EpilogCount & 0xFFFF);

1548 }

1549

1550 if (PackedEpilogOffset < 0) {

1551

1552 for (auto &I : EpilogInfo) {

1553 MCSymbol *EpilogStart = I.first;

1554 uint32_t EpilogIndex = I.second;

1555

1557 if (EpilogOffset)

1558 EpilogOffset /= 4;

1559 uint32_t row3 = EpilogOffset;

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

1562 }

1563 }

1564

1565

1566

1567

1568

1569

1570

1571 if (!HasProlog)

1572

1574

1575

1578

1579

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

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

1584 }

1585

1586 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;

1587 assert(BytesMod >= 0);

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

1590

1591 if (info->HandlesExceptions)

1595 4);

1596}

1597

1598

1599

1601 bool TryPacked = true) {

1602

1603 if (info->Symbol)

1604 return;

1605

1606

1607

1608

1609 if (info->empty()) {

1610 info->EmitAttempted = true;

1611 return;

1612 }

1613 if (info->EmitAttempted) {

1614

1615

1616

1617

1618

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

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

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

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

1624 return;

1625 }

1626

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

1630

1631 int64_t RawFuncLength;

1632 if (info->FuncletOrFuncEnd) {

1634 } else {

1635

1636

1637

1638

1639

1640

1641

1642

1643

1644

1645

1646

1647

1648

1649

1650

1651

1652

1653

1654

1655

1656

1657

1658

1659

1660

1661

1662

1663

1665 info->Begin);

1666 }

1667

1669

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

1673

1674

1675 info->Instructions.clear();

1676}

1677

1680 for (const auto &I : Insns) {

1682 default:

1686 break;

1689 break;

1692 break;

1695 break;

1698 break;

1701 break;

1704 break;

1707 break;

1710 break;

1713 break;

1716 break;

1719 break;

1722 break;

1725 break;

1728 break;

1735 break;

1737 int J;

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

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

1740 break;

1742 break;

1743 }

1744 }

1745 }

1747}

1748

1750 bool *HasCustom = nullptr) {

1752 for (const auto &I : Insns) {

1754 default:

1760 break;

1765 break;

1769 break;

1772 break;

1776 break;

1781 break;

1784 break;

1788 break;

1792 break;

1794

1795 break;

1797

1798

1800 if (HasCustom)

1801 *HasCustom = true;

1802 break;

1803 }

1804 }

1806}

1807

1812 if (!End)

1813 return;

1814 std::optional<int64_t> MaybeDistance =

1816 if (!MaybeDistance)

1817 return;

1819 bool HasCustom = false;

1821 if (HasCustom)

1822 return;

1823 if (Distance != InstructionBytes) {

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

1826 Twine(Distance) +

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

1828 "corresponding to " +

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

1830 }

1831}

1832

1838 return true;

1839 default:

1840 return false;

1841 }

1842}

1843

1844

1845

1849 int i;

1851 default:

1857 break;

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

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

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

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

1864 break;

1868 break;

1873 break;

1878 break;

1882 break;

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

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

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

1889 break;

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

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

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

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

1896 break;

1902 break;

1909 break;

1916 break;

1920 w = inst.Offset / 4;

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

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

1924 break;

1928 w = inst.Offset / 4;

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

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

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

1933 break;

1937 w = inst.Offset / 4;

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

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

1941 break;

1945 w = inst.Offset / 4;

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

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

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

1950 break;

1953 break;

1956 break;

1959 break;

1962 break;

1965 break;

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

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

1969 break;

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

1972 break;

1973 }

1974}

1975

1976

1977

1978

1979

1980

1981

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

1984 bool CanTweakProlog) {

1985

1987 return -1;

1988

1989

1990

1991

1992

1993 int EndIdx = CanTweakProlog ? 1 : 0;

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

1995

1996

1998 return -1;

1999 }

2000

2001 if (CanTweakProlog) {

2002

2004 return -1;

2008 return -1;

2009 }

2010

2011

2013 return 0;

2016}

2017

2019 int PrologCodeBytes) {

2020

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

2022 return -1;

2023

2025

2026 if (EpilogInfo.Condition != 0xe)

2027 return -1;

2028

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

2030

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

2032 return -1;

2033

2034

2035

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

2038 if (!MaybeDistance)

2039 return -1;

2042 if (DistanceFromEnd != InstructionBytes)

2043 return -1;

2044

2045 int RetVal = -1;

2046

2047

2048

2049

2050 if (PrologCodeBytes <= 31 &&

2052 RetVal = PrologCodeBytes;

2053

2057 return RetVal;

2058

2059

2060

2061

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

2063 return RetVal;

2064

2065

2066

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

2068

2069

2070

2071 info->EpilogMap.clear();

2073}

2074

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

2076 unsigned &Folded, int &IntRegs) {

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

2078 HasLR = true;

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

2080 }

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

2082 HasR11 = true;

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

2084 }

2085 Folded = 0;

2087 if (!Mask)

2088 return true;

2090

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

2093 Mask >>= 1;

2094 }

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

2096 return false;

2097

2098 int N = 0;

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

2100 N++;

2101 if (First < 4) {

2103 return false;

2104 Folded = 4 - First;

2105 N -= Folded;

2107 }

2109 return false;

2110 if (N >= 1)

2112 return true;

2113}

2114

2117 int Step = 0;

2118 bool Homing = false;

2119 bool HasR11 = false;

2120 bool HasChain = false;

2121 bool HasLR = false;

2122 int IntRegs = -1;

2123 int FloatRegs = -1;

2124 unsigned PF = 0;

2125 unsigned StackAdjust = 0;

2126

2127

2130 default:

2139

2140 return false;

2142

2143

2144 return false;

2146

2147 return false;

2148

2152 if (Step != 0)

2153 return false;

2154 Step = 1;

2155 break;

2156

2159

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

2161 return false;

2166 HasR11 = true;

2168 }

2170 HasLR = true;

2171 Step = 3;

2172 break;

2173

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

2176

2177 Homing = true;

2178 Step = 2;

2179 break;

2180 }

2181 [[fallthrough]];

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

2184 return false;

2185

2186

2187

2189 return false;

2190 Step = 3;

2191 break;

2192

2194

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

2196 return false;

2197 HasChain = true;

2198 Step = 4;

2199 break;

2201

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

2203 return false;

2204 HasChain = true;

2205 Step = 4;

2206 break;

2207

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

2210 return false;

2213 return false;

2215 return false;

2216 FloatRegs = Inst.Register - 8;

2217 Step = 5;

2218 break;

2219

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

2223 return false;

2224 if (PF > 0)

2225 return false;

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

2227 return false;

2228 StackAdjust = Inst.Offset / 4;

2229 Step = 6;

2230 break;

2231 }

2232 }

2233 if (HasR11 && !HasChain) {

2234 if (IntRegs + 4 == 10) {

2235

2236

2238 HasR11 = false;

2239 } else

2240 return false;

2241 }

2242 if (HasChain && !HasLR)

2243 return false;

2244

2245

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

2247 return false;

2248

2249 unsigned EF = 0;

2250 int Ret = 0;

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

2252 Ret = 3;

2253 } else {

2254

2255

2256

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

2259 if (EpilogInfo.Condition != 0xe)

2260 return false;

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

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

2264 if (!MaybeDistance)

2265 return false;

2268 if (DistanceFromEnd != InstructionBytes)

2269 return false;

2270

2271 bool GotStackAdjust = false;

2272 bool GotFloatRegs = false;

2273 bool GotIntRegs = false;

2274 bool GotHomingRestore = false;

2275 bool GotLRRestore = false;

2276 bool NeedsReturn = false;

2277 bool GotReturn = false;

2278

2279 Step = 6;

2282 default:

2294

2295 return false;

2296

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

2300 return false;

2301 if (Step == 6) {

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

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

2304 GotHomingRestore = true;

2305 Step = 10;

2306 } else {

2307 if (StackAdjust > 0) {

2308

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

2310 return false;

2311 GotStackAdjust = true;

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

2313

2314 StackAdjust = Inst.Offset / 4;

2315 GotStackAdjust = true;

2316 } else {

2317

2318 return false;

2319 }

2320 Step = 7;

2321 }

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

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

2324 return false;

2325 GotHomingRestore = true;

2326 Step = 10;

2327 } else

2328 return false;

2329 break;

2330

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

2333 return false;

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

2336 return false;

2337 GotFloatRegs = true;

2338 Step = 8;

2339 break;

2340

2343

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

2345 return false;

2348 if (Homing && HasLR) {

2349

2350

2352 GotLRRestore = true;

2353 NeedsReturn = true;

2354 } else {

2355

2356 }

2357 } else {

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

2359 return false;

2360 }

2361 GotLRRestore = Inst.Offset == 1;

2362 if (IntRegs < 0)

2363 return false;

2365 if (HasChain) {

2366

2368 return false;

2370 }

2372 return false;

2373 GotIntRegs = true;

2374 Step = 9;

2375 break;

2376 }

2377

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

2381 return false;

2382

2383

2384

2385 bool CurHasLR = false, CurHasR11 = false;

2386 int Regs;

2388 return false;

2389 if (EF > 0) {

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

2391 return false;

2392 }

2393 if (Homing && HasLR) {

2394

2395

2396 if (CurHasLR) {

2397 GotLRRestore = true;

2398 NeedsReturn = true;

2399 } else {

2400

2401 }

2402 } else {

2403 if (CurHasLR != HasLR)

2404 return false;

2405 GotLRRestore = CurHasLR;

2406 }

2408 if (HasChain) {

2409

2410 if (!CurHasR11)

2411 return false;

2413

2414

2416 if (!CurHasR11)

2417 return false;

2418 } else {

2419

2420

2421 if (CurHasR11)

2422 return false;

2423 }

2425 return false;

2426 GotIntRegs = true;

2427 Step = 9;

2428 break;

2429 }

2430

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

2433 return false;

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

2435 return false;

2436 GotLRRestore = true;

2437 GotHomingRestore = true;

2438 Step = 10;

2439 break;

2440

2443 GotReturn = true;

2445 [[fallthrough]];

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

2448 return false;

2449 Step = 11;

2450 break;

2451 }

2452 }

2453

2454 if (Step != 11)

2455 return false;

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

2457 return false;

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

2459 return false;

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

2461 return false;

2462 if (Homing && !GotHomingRestore)

2463 return false;

2464 if (HasLR && !GotLRRestore)

2465 return false;

2466 if (NeedsReturn && !GotReturn)

2467 return false;

2468 }

2469

2470 assert(PF == 0 || EF == 0 ||

2471 StackAdjust == 0);

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

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

2474 assert(StackAdjust <= 3);

2475 StackAdjust |= 0x3f0;

2476 if (PF > 0)

2477 StackAdjust |= 1 << 2;

2478 if (EF > 0)

2479 StackAdjust |= 1 << 3;

2480 }

2481

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

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

2484 int H = Homing ? 1 : 0;

2485 int L = HasLR ? 1 : 0;

2486 int C = HasChain ? 1 : 0;

2488 unsigned Reg, R;

2492 R = 0;

2493 } else if (FloatRegs >= 0) {

2494 Reg = FloatRegs;

2496 R = 1;

2497 } else {

2498

2499 Reg = 7;

2500 R = 1;

2501 }

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

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

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

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

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

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

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

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

2510 assert(StackAdjust <= 0x3ff);

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

2512 return true;

2513}

2514

2515

2516

2518 bool TryPacked = true) {

2519

2520 if (info->Symbol)

2521 return;

2522

2523

2524

2525

2526 if (info->empty()) {

2527 info->EmitAttempted = true;

2528 return;

2529 }

2530 if (info->EmitAttempted) {

2531

2532

2533

2534

2535

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

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

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

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

2541 return;

2542 }

2543

2546

2549 info->Symbol = Label;

2550

2551 if (info->PrologEnd)

2553 info->Function->getName() +

2554 " not correctly terminated");

2555

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

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

2559 "prologue");

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

2561 MCSymbol *EpilogStart = I.first;

2562 auto &Epilog = I.second;

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

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

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

2569 " not correctly terminated");

2570 }

2571

2572 std::optional<int64_t> RawFuncLength;

2573 const MCExpr *FuncLengthExpr = nullptr;

2574 if (info->FuncletOrFuncEnd) {

2576 } else {

2577

2578

2579

2580

2581

2582

2583

2584

2585 RawFuncLength =

2587 if (!RawFuncLength)

2588 FuncLengthExpr =

2590 }

2592 if (RawFuncLength)

2593 FuncLength = (uint32_t)*RawFuncLength / 2;

2594 if (FuncLength > 0x3FFFF)

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

2597 uint32_t TotalCodeBytes = PrologCodeBytes;

2598

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

2600 TryPacked) {

2601

2602

2603

2604

2605

2606

2607

2608

2610 return;

2611 }

2612

2613 int PackedEpilogOffset =

2615

2616

2618

2619 std::vector<MCSymbol *> AddedEpilogs;

2620

2621 bool CanTweakProlog = true;

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

2623 MCSymbol *EpilogStart = I.first;

2624 auto &EpilogInstrs = I.second.Instructions;

2626

2629 int PrologOffset;

2630 if (MatchingEpilog) {

2632 "Duplicate epilog not found");

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

2634

2635

2636 EpilogInstrs.clear();

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

2639 if (CanTweakProlog) {

2640

2641

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

2643

2644 CanTweakProlog = false;

2645 }

2646 EpilogInfo[EpilogStart] = PrologOffset;

2647

2648

2649 EpilogInstrs.clear();

2650 } else {

2651 EpilogInfo[EpilogStart] = TotalCodeBytes;

2652 TotalCodeBytes += CodeBytes;

2653 AddedEpilogs.push_back(EpilogStart);

2654 }

2655 }

2656

2657

2659 uint32_t CodeWords = TotalCodeBytes / 4;

2660 uint32_t CodeWordsMod = TotalCodeBytes % 4;

2661 if (CodeWordsMod)

2662 CodeWords++;

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

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

2666 if (!ExtensionWord) {

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

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

2669 }

2670 if (info->HandlesExceptions)

2671 row1 |= 1 << 20;

2672 if (PackedEpilogOffset >= 0)

2673 row1 |= 1 << 21;

2674 if (info->Fragment)

2675 row1 |= 1 << 22;

2676 row1 |= FuncLength & 0x3FFFF;

2677 if (RawFuncLength)

2679 else

2683 4);

2684

2685

2686 if (ExtensionWord) {

2687

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

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

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

2692 row2 |= (EpilogCount & 0xFFFF);

2694 }

2695

2696 if (PackedEpilogOffset < 0) {

2697

2698 for (auto &I : EpilogInfo) {

2699 MCSymbol *EpilogStart = I.first;

2700 uint32_t EpilogIndex = I.second;

2701

2702 std::optional<int64_t> MaybeEpilogOffset =

2704 const MCExpr *OffsetExpr = nullptr;

2706 if (MaybeEpilogOffset)

2707 EpilogOffset = *MaybeEpilogOffset / 2;

2708 else

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

2710

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

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

2713 assert(Condition <= 0xf);

2714

2715 uint32_t row3 = EpilogOffset;

2716 row3 |= Condition << 20;

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

2718 if (MaybeEpilogOffset)

2720 else

2724 4);

2725 }

2726 }

2727

2728

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

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

2732 info->Instructions.pop_back();

2734 }

2735

2736

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

2738 auto &EpilogInstrs = I.second.Instructions;

2741 }

2742

2743 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;

2744 assert(BytesMod >= 0);

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

2747

2748 if (info->HandlesExceptions)

2752 4);

2753}

2754

2758

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

2762 if (info->PackedInfo)

2764 else

2767 context),

2768 4);

2769 }

2770}

2771

2772

2776

2779 if (info->PackedInfo)

2781 else

2784 context),

2785 4);

2786}

2787

2789

2792 if (Info->empty())

2793 continue;

2797 }

2798

2799

2802

2803

2804

2805 if (!Info->Symbol)

2806 continue;

2810 }

2811}

2812

2815 bool HandlerData) const {

2816

2817

2818

2819

2820

2821

2822 if (info->FuncletOrFuncEnd) {

2825 }

2826

2827

2831}

2832

2834

2837 if (Info->empty())

2838 continue;

2842 }

2843

2844

2847

2848

2849

2850 if (!Info->Symbol)

2851 continue;

2855 }

2856}

2857

2860 bool HandlerData) const {

2861

2862

2863

2864

2865

2866

2867 if (info->FuncletOrFuncEnd) {

2870 }

2871

2872

2876}

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

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

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

Definition MCWin64EH.cpp:963

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

Definition MCWin64EH.cpp:1453

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

Definition MCWin64EH.cpp:1678

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

Definition MCWin64EH.cpp:513

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

Definition MCWin64EH.cpp:1808

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

Definition MCWin64EH.cpp:1833

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

Definition MCWin64EH.cpp:623

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

Definition MCWin64EH.cpp:885

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

Definition MCWin64EH.cpp:1846

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

Definition MCWin64EH.cpp:213

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

Definition MCWin64EH.cpp:942

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

Definition MCWin64EH.cpp:2773

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

Definition MCWin64EH.cpp:1006

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

Definition MCWin64EH.cpp:228

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

Definition MCWin64EH.cpp:108

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

Definition MCWin64EH.cpp:1600

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

Definition MCWin64EH.cpp:1982

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

Definition MCWin64EH.cpp:2755

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

Definition MCWin64EH.cpp:176

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

Definition MCWin64EH.cpp:2075

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

Definition MCWin64EH.cpp:2018

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

Definition MCWin64EH.cpp:466

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

Definition MCWin64EH.cpp:1372

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

Definition MCWin64EH.cpp:2115

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

Definition MCWin64EH.cpp:860

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

Definition MCWin64EH.cpp:200

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

Definition MCWin64EH.cpp:475

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

Definition MCWin64EH.cpp:447

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

Definition MCWin64EH.cpp:99

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

Definition MCWin64EH.cpp:2517

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

Definition MCWin64EH.cpp:1749

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

Definition MCWin64EH.cpp:1328

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

Definition MCWin64EH.cpp:71

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

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

static const MCPhysReg IntRegs[32]

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

size_t size() const

size - Get the array size.

Tagged union holding either a T or a Error.

MCContext & getContext() const

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

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

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

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

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

Context object for machine code objects.

LLVM_ABI MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

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

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

Streaming object file generation interface.

MCAssembler & getAssembler()

void appendContents(ArrayRef< char > Contents)

void addFixup(const MCExpr *Value, MCFixupKind Kind)

void ensureHeadroom(size_t Headroom)

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

Streaming machine code generation interface.

virtual MCSymbol * emitCFILabel()

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

MCSection * getAssociatedPDataSection(const MCSection *TextSec)

Get the .pdata section used for the given section.

MCContext & getContext() const

MCSection * getAssociatedXDataSection(const MCSection *TextSec)

Get the .xdata section used for the given section.

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

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

Emit a label for Symbol into the current section.

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

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

void emitInt16(uint64_t Value)

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

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

void emitInt32(uint64_t Value)

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

void emitInt8(uint64_t Value)

Represent a reference to a symbol from inside an expression.

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

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

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

print - Print the value to the stream OS.

MCFragment * getFragment() const

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

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

bool contains(const KeyT &Key) const

ValueT lookup(const KeyT &Key) const

Represents a location in source code.

void push_back(const T &Elt)

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

StackOffset holds a fixed and a scalable offset in bytes.

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

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

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

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

Definition MCWin64EH.cpp:2813

void Emit(MCStreamer &Streamer) const override

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

Definition MCWin64EH.cpp:2788

void Emit(MCStreamer &Streamer) const override

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

Definition MCWin64EH.cpp:2833

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

Definition MCWin64EH.cpp:2858

void Emit(MCStreamer &Streamer) const override

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

Definition MCWin64EH.cpp:420

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

Definition MCWin64EH.cpp:436

#define llvm_unreachable(msg)

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

@ C

The default llvm calling convention, compatible with C.

@ UNW_TerminateHandler

UNW_TerminateHandler - Specifies that this function has a termination handler.

@ UNW_ExceptionHandler

UNW_ExceptionHandler - Specifies that this function has an exception handler.

@ UNW_ChainInfo

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

UnwindOpcodes

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

@ UOP_WideSaveRegsR4R11LR

This is an optimization pass for GlobalISel generic memory operations.

auto reverse(ContainerTy &&C)

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

FunctionAddr VTableAddr Count

auto reverse_conditionally(ContainerTy &&C, bool ShouldReverse)

Return a range that conditionally reverses C.

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

@ FK_Data_2

A two-byte fixup.

DWARFExpression::Operation Op

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

std::vector< Instruction > Instructions

MapVector< MCSymbol *, int64_t > Epilogs