80      : CompactUnwindSectionName(CompactUnwindSectionName),
 
   81        UnwindInfoSectionName(UnwindInfoSectionName),
 
   82        EHFrameSectionName(EHFrameSectionName) {}
 
 
   92    Section *CUSec = 
G.findSectionByName(CompactUnwindSectionName);
 
   93    if (!CUSec || CUSec->
empty()) {
 
   95        dbgs() << 
"Compact unwind: No compact unwind info for " << 
G.getName()
 
  102      dbgs() << 
"Compact unwind: preparing " << 
G.getName() << 
" for prune\n";
 
  105    Section *EHFrameSec = 
G.findSectionByName(EHFrameSectionName);
 
  112             << CompactUnwindSectionName << 
"\n";
 
  115    for (
auto *
B : CUSec->
blocks()) {
 
  118      Edge *PCBeginEdge = 
nullptr;
 
  119      for (
auto &
E : 
B->edges_at(CURecTraits::FnFieldOffset)) {
 
  126            "In " + 
G.getName() + 
", compact unwind record at " +
 
  127            formatv(
"{0:x}", 
B->getAddress()) + 
" has no pc-begin edge");
 
  131            "In " + 
G.getName() + 
", compact unwind record at " +
 
  132            formatv(
"{0:x}", 
B->getAddress()) + 
" points at external symbol " +
 
  137      if (!Fn.isDefined()) {
 
  139          dbgs() << 
"In " << CompactUnwindSectionName << 
" for " << 
G.getName()
 
  140                 << 
" encountered unexpected pc-edge to undefined symbol " 
  141                 << Fn.getName() << 
"\n";
 
  146      uint32_t Encoding = CURecTraits::readEncoding(
B->getContent());
 
  147      bool NeedsDWARF = CURecTraits::encodingSpecifiesDWARF(Encoding);
 
  150        dbgs() << 
"    Found record for function ";
 
  152          dbgs() << Fn.getName();
 
  154          dbgs() << 
"<anon @ " << Fn.getAddress() << 
'>';
 
  155        dbgs() << 
": encoding = " << 
formatv(
"{0:x}", Encoding);
 
  157          dbgs() << 
" (needs DWARF)";
 
  162          G.addAnonymousSymbol(*
B, 0, CURecTraits::Size, 
false, 
false);
 
  164      bool KeepAliveAlreadyPresent = 
false;
 
  166        Edge *KeepAliveEdge = 
nullptr;
 
  167        for (
auto &
E : Fn.getBlock().edges_at(0)) {
 
  168          if (
E.getKind() == Edge::KeepAlive && 
E.getTarget().isDefined() &&
 
  169              &
E.getTarget().getSection() == EHFrameSec) {
 
  181          KeepAliveAlreadyPresent = 
true;
 
  184              dbgs() << 
"      Adding keep-alive edge to FDE at " 
  185                     << FDE.getAddress() << 
"\n";
 
  187            B->addEdge(Edge::KeepAlive, 0, FDE, 0);
 
  192                "In " + 
G.getName() + 
", compact unwind recard ot " +
 
  194                " needs DWARF, but no FDE was found");
 
  199              "In " + 
G.getName() + 
", compact unwind recard ot " +
 
  200              formatv(
"{0:x}", 
B->getAddress()) + 
" needs DWARF, but no " +
 
  201              EHFrameSectionName + 
" section exists");
 
  204      if (!KeepAliveAlreadyPresent) {
 
  207        Fn.getBlock().addEdge(Edge::KeepAlive, 0, CURecSym, 0);
 
 
  217    Section *CUSec = 
G.findSectionByName(CompactUnwindSectionName);
 
  227    if (
auto Err = getOrCreateCompactUnwindBase(
G))
 
  232    if (
G.findSectionByName(UnwindInfoSectionName))
 
  234                                      UnwindInfoSectionName +
 
  239    if (
auto Err = processCompactUnwind(
G, *CUSec))
 
  243    size_t UnwindInfoSectionSize =
 
  244        UnwindInfoSectionHeaderSize +
 
  245        Personalities.size() * PersonalityEntrySize +
 
  246        (NumSecondLevelPages + 1) * IndexEntrySize + NumLSDAs * LSDAEntrySize +
 
  247        NumSecondLevelPages * SecondLevelPageHeaderSize +
 
  248        Records.size() * SecondLevelPageEntrySize;
 
  251      dbgs() << 
"In " << 
G.getName() << 
", reserving " 
  252             << 
formatv(
"{0:x}", UnwindInfoSectionSize) << 
" bytes for " 
  253             << UnwindInfoSectionName << 
"\n";
 
  260    auto UnwindInfoSectionContent = 
G.allocateBuffer(UnwindInfoSectionSize);
 
  261    memset(UnwindInfoSectionContent.data(), 0, UnwindInfoSectionContent.size());
 
  262    auto &
B = 
G.createMutableContentBlock(
 
  267    for (
auto &R : Records)
 
  268      B.addEdge(Edge::KeepAlive, 0, *R.Fn, 0);
 
 
  274    Section *CUSec = 
G.findSectionByName(CompactUnwindSectionName);
 
  275    if (!CUSec || CUSec->
empty())
 
  278    Section *UnwindInfoSec = 
G.findSectionByName(UnwindInfoSectionName);
 
  281                                      UnwindInfoSectionName +
 
  282                                      " missing after allocation");
 
  286          "In " + 
G.getName() + 
", " + UnwindInfoSectionName +
 
  287          " contains more than one block post-allocation");
 
  290        { 
dbgs() << 
"Writing unwind info for " << 
G.getName() << 
"...\n"; });
 
  294    auto &UnwindInfoBlock = **UnwindInfoSec->
blocks().
begin();
 
  295    auto Content = UnwindInfoBlock.getMutableContent(
G);
 
  297        {
reinterpret_cast<uint8_t *
>(Content.data()), Content.size()},
 
  298        CURecTraits::Endianness);
 
  318    if (
auto Err = writeHeader(
G, Writer))
 
  323    if (
auto Err = writePersonalities(
G, Writer))
 
  327    size_t SectionOffsetToLSDAs =
 
  328        Writer.
getOffset() + (NumSecondLevelPages + 1) * IndexEntrySize;
 
  331    size_t SectionOffsetToSecondLevelPages =
 
  332        SectionOffsetToLSDAs + NumLSDAs * LSDAEntrySize;
 
  334    if (
auto Err = writeIndexes(
G, Writer, SectionOffsetToLSDAs,
 
  335                                SectionOffsetToSecondLevelPages))
 
  338    if (
auto Err = writeLSDAs(
G, Writer))
 
  341    if (
auto Err = writeSecondLevelPages(
G, Writer))
 
  345      dbgs() << 
"    Wrote " << 
formatv(
"{0:x}", Writer.getOffset())
 
  346             << 
" bytes of unwind info.\n";
 
 
  354  static constexpr size_t MaxPersonalities = 4;
 
  355  static constexpr size_t PersonalityShift = 28;
 
  357  static constexpr size_t UnwindInfoSectionHeaderSize = 4 * 7;
 
  358  static constexpr size_t PersonalityEntrySize = 4;
 
  359  static constexpr size_t IndexEntrySize = 3 * 4;
 
  360  static constexpr size_t LSDAEntrySize = 2 * 4;
 
  361  static constexpr size_t SecondLevelPageSize = 4096;
 
  362  static constexpr size_t SecondLevelPageHeaderSize = 8;
 
  363  static constexpr size_t SecondLevelPageEntrySize = 8;
 
  364  static constexpr size_t NumRecordsPerSecondLevelPage =
 
  365      (SecondLevelPageSize - SecondLevelPageHeaderSize) /
 
  366      SecondLevelPageEntrySize;
 
  368  struct CompactUnwindRecord {
 
  376  Error processCompactUnwind(LinkGraph &
G, Section &CUSec) {
 
  379    assert(NumLSDAs == 0 && 
"NumLSDAs should be zero");
 
  380    assert(Records.
empty() && 
"CompactUnwindRecords vector should be empty.");
 
  381    assert(Personalities.empty() && 
"Personalities vector should be empty.");
 
  384    NonUniquedRecords.
reserve(CUSec.blocks_size());
 
  387    for (
auto *
B : CUSec.blocks()) {
 
  388      CompactUnwindRecord R;
 
  389      R.Encoding = CURecTraits::readEncoding(
B->getContent());
 
  390      for (
auto &
E : 
B->edges()) {
 
  391        switch (
E.getOffset()) {
 
  392        case CURecTraits::FnFieldOffset:
 
  395          if (
E.getKind() == Edge::KeepAlive)
 
  396            R.FDE = &
E.getTarget();
 
  398            R.Fn = &
E.getTarget();
 
  400        case CURecTraits::PersonalityFieldOffset: {
 
  403          size_t PersonalityIdx = 0;
 
  404          for (; PersonalityIdx != Personalities.size(); ++PersonalityIdx)
 
  405            if (Personalities[PersonalityIdx] == &
E.getTarget())
 
  407          if (PersonalityIdx == MaxPersonalities)
 
  409                "In " + 
G.getName() +
 
  410                ", __compact_unwind contains too many personalities (max " +
 
  411                formatv(
"{}", MaxPersonalities) + 
")");
 
  412          if (PersonalityIdx == Personalities.size())
 
  413            Personalities.push_back(&
E.getTarget());
 
  415          R.Encoding |= (PersonalityIdx + 1) << PersonalityShift;
 
  418        case CURecTraits::LSDAFieldOffset:
 
  420          R.LSDA = &
E.getTarget();
 
  424                                          ", compact unwind record at " +
 
  426                                          " has unrecognized edge at offset " +
 
  430      Records.push_back(R);
 
  435                           const CompactUnwindRecord &
RHS) {
 
  436      return LHS.Fn->getAddress() < 
RHS.Fn->getAddress();
 
  440    NumSecondLevelPages = (Records.size() + NumRecordsPerSecondLevelPage - 1) /
 
  441                          NumRecordsPerSecondLevelPage;
 
  444    typename CURecTraits::GOTManager 
GOT(
G);
 
  445    for (
auto &Personality : Personalities)
 
  446      Personality = &
GOT.getEntryForTarget(
G, *Personality);
 
  449      dbgs() << 
"  In " << 
G.getName() << 
", " << CompactUnwindSectionName
 
  450             << 
": raw records = " << Records.size()
 
  451             << 
", personalities = " << Personalities.size()
 
  452             << 
", lsdas = " << NumLSDAs << 
"\n";
 
  458  void mergeRecords() {
 
  459    SmallVector<CompactUnwindRecord> NonUniqued = std::move(Records);
 
  460    Records.reserve(NonUniqued.size());
 
  462    Records.push_back(NonUniqued.front());
 
  463    for (
size_t I = 1; 
I != NonUniqued.size(); ++
I) {
 
  464      auto &
Next = NonUniqued[
I];
 
  465      auto &
Last = Records.back();
 
  467      bool NextNeedsDWARF = CURecTraits::encodingSpecifiesDWARF(
Next.Encoding);
 
  468      bool CannotBeMerged = CURecTraits::encodingCannotBeMerged(
Next.Encoding);
 
  469      if (NextNeedsDWARF || (
Next.Encoding != 
Last.Encoding) ||
 
  470          CannotBeMerged || 
Next.LSDA || 
Last.LSDA)
 
  471        Records.push_back(
Next);
 
  475    NumSecondLevelPages = (Records.size() + NumRecordsPerSecondLevelPage - 1) /
 
  476                          NumRecordsPerSecondLevelPage;
 
  479  Error writeHeader(LinkGraph &
G, BinaryStreamWriter &W) {
 
  482                                      UnwindInfoSectionName +
 
  483                                      "second-level pages required");
 
  486    size_t IndexArrayOffset = UnwindInfoSectionHeaderSize +
 
  487                              Personalities.size() * PersonalityEntrySize;
 
  490    cantFail(
W.writeInteger<uint32_t>(UnwindInfoSectionHeaderSize));
 
  492    cantFail(
W.writeInteger<uint32_t>(UnwindInfoSectionHeaderSize));
 
  493    cantFail(
W.writeInteger<uint32_t>(Personalities.size()));
 
  494    cantFail(
W.writeInteger<uint32_t>(IndexArrayOffset));
 
  495    cantFail(
W.writeInteger<uint32_t>(NumSecondLevelPages + 1));
 
  500  Error writePersonalities(LinkGraph &
G, BinaryStreamWriter &W) {
 
  502    for (
auto *PSym : Personalities) {
 
  503      auto Delta = PSym->getAddress() - CompactUnwindBase->getAddress();
 
  505        return makePersonalityRangeError(
G, *PSym);
 
  506      cantFail(
W.writeInteger<uint32_t>(Delta));
 
  511  Error writeIndexes(LinkGraph &
G, BinaryStreamWriter &W,
 
  512                     size_t SectionOffsetToLSDAs,
 
  513                     size_t SectionOffsetToSecondLevelPages) {
 
  518    size_t RecordIdx = 0;
 
  519    size_t NumPreviousLSDAs = 0;
 
  520    for (
auto &R : Records) {
 
  522      if (RecordIdx % NumRecordsPerSecondLevelPage == 0) {
 
  523        auto FnDelta = 
R.Fn->getAddress() - CompactUnwindBase->getAddress();
 
  524        auto SecondLevelPageOffset =
 
  525            SectionOffsetToSecondLevelPages +
 
  526            SecondLevelPageSize * (RecordIdx / NumRecordsPerSecondLevelPage);
 
  528            SectionOffsetToLSDAs + NumPreviousLSDAs * LSDAEntrySize;
 
  530        cantFail(
W.writeInteger<uint32_t>(FnDelta));
 
  531        cantFail(
W.writeInteger<uint32_t>(SecondLevelPageOffset));
 
  532        cantFail(
W.writeInteger<uint32_t>(LSDAOffset));
 
  542          Records.back().Fn->getRange().End - CompactUnwindBase->getAddress();
 
  546            "In " + 
G.getName() + 
" " + UnwindInfoSectionName +
 
  547            ", delta to end of functions  " +
 
  548            formatv(
"{0:x}", Records.back().Fn->getRange().End) +
 
  551      cantFail(
W.writeInteger<uint32_t>(FnEndDelta));
 
  553      cantFail(
W.writeInteger<uint32_t>(SectionOffsetToSecondLevelPages));
 
  559  Error writeLSDAs(LinkGraph &
G, BinaryStreamWriter &W) {
 
  561    for (
auto &R : Records) {
 
  563        auto FnDelta = 
R.Fn->getAddress() - CompactUnwindBase->getAddress();
 
  564        auto LSDADelta = 
R.LSDA->getAddress() - CompactUnwindBase->getAddress();
 
  568              "In " + 
G.getName() + 
" " + UnwindInfoSectionName +
 
  569              ", delta to lsda at " + 
formatv(
"{0:x}", 
R.LSDA->getAddress()) +
 
  572        cantFail(
W.writeInteger<uint32_t>(FnDelta));
 
  573        cantFail(
W.writeInteger<uint32_t>(LSDADelta));
 
  580  Error writeSecondLevelPages(LinkGraph &
G, BinaryStreamWriter &W) {
 
  581    size_t RecordIdx = 0;
 
  583    for (
auto &R : Records) {
 
  589      if (RecordIdx % NumRecordsPerSecondLevelPage == 0) {
 
  590        constexpr uint32_t SecondLevelPageHeaderKind = 2;
 
  591        constexpr uint16_t SecondLevelPageHeaderSize = 8;
 
  592        uint16_t SecondLevelPageNumEntries =
 
  593            std::min(Records.size() - RecordIdx, NumRecordsPerSecondLevelPage);
 
  595        cantFail(
W.writeInteger<uint32_t>(SecondLevelPageHeaderKind));
 
  596        cantFail(
W.writeInteger<uint16_t>(SecondLevelPageHeaderSize));
 
  597        cantFail(
W.writeInteger<uint16_t>(SecondLevelPageNumEntries));
 
  601      auto FnDelta = 
R.Fn->getAddress() - CompactUnwindBase->getAddress();
 
  605            "In " + 
G.getName() + 
" " + UnwindInfoSectionName +
 
  606            ", delta to function at " + 
formatv(
"{0:x}", 
R.Fn->getAddress()) +
 
  609      auto Encoding = 
R.Encoding;
 
  611      if (
LLVM_UNLIKELY(CURecTraits::encodingSpecifiesDWARF(
R.Encoding))) {
 
  613          EHFrameBase = SectionRange(
R.FDE->getSection()).getStart();
 
  614        auto FDEDelta = 
R.FDE->getAddress() - EHFrameBase;
 
  616        if (
auto EncodedFDEDelta = CURecTraits::encodeDWARFOffset(FDEDelta))
 
  617          Encoding |= *EncodedFDEDelta;
 
  620              "In " + 
G.getName() + 
" " + UnwindInfoSectionName +
 
  621              ", cannot encode delta " + 
formatv(
"{0:x}", FDEDelta) +
 
  622              " to FDE at " + 
formatv(
"{0:x}", 
R.FDE->getAddress()));
 
  625      cantFail(
W.writeInteger<uint32_t>(FnDelta));
 
  626      cantFail(
W.writeInteger<uint32_t>(Encoding));
 
  634  Error getOrCreateCompactUnwindBase(LinkGraph &
G) {
 
  635    auto Name = 
G.intern(
"__jitlink$libunwind_dso_base");
 
  636    CompactUnwindBase = 
G.findAbsoluteSymbolByName(Name);
 
  637    if (!CompactUnwindBase) {
 
  639        CompactUnwindBase = &*LocalCUBase;
 
  640        auto &
B = LocalCUBase->getBlock();
 
  644        return LocalCUBase.takeError();
 
  646    CompactUnwindBase->setLive(
true);
 
  650  Error makePersonalityRangeError(LinkGraph &
G, Symbol &PSym) {
 
  653      raw_string_ostream ErrStream(ErrMsg);
 
  654      ErrStream << 
"In " << 
G.getName() << 
" " << UnwindInfoSectionName
 
  657        ErrStream << PSym.getName() << 
" ";
 
  658      ErrStream << 
"at " << PSym.getAddress()
 
  659                << 
" is out of 32-bit delta range of compact-unwind base at " 
  660                << CompactUnwindBase->getAddress();
 
  665  StringRef CompactUnwindSectionName;
 
  666  StringRef UnwindInfoSectionName;
 
  667  StringRef EHFrameSectionName;
 
  668  Symbol *CompactUnwindBase = 
nullptr;
 
  669  orc::ExecutorAddr EHFrameBase;
 
  672  size_t NumSecondLevelPages = 0;
 
  674  SmallVector<CompactUnwindRecord> Records;