brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.5 KiB · 51e3d26 Raw
104 lines · cpp
1//=------- CompactUnwindSupport.cpp - Compact Unwind format support -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Compact Unwind support.10//11//===----------------------------------------------------------------------===//12 13#include "CompactUnwindSupport.h"14 15#include "llvm/ADT/Sequence.h"16 17#define DEBUG_TYPE "jitlink"18 19namespace llvm {20namespace jitlink {21 22Error splitCompactUnwindBlocks(LinkGraph &G, Section &CompactUnwindSection,23                               size_t RecordSize) {24 25  std::vector<Block *> OriginalBlocks(CompactUnwindSection.blocks().begin(),26                                      CompactUnwindSection.blocks().end());27  LLVM_DEBUG({28    dbgs() << "In " << G.getName() << " splitting compact unwind section "29           << CompactUnwindSection.getName() << " containing "30           << OriginalBlocks.size() << " initial blocks...\n";31  });32 33  while (!OriginalBlocks.empty()) {34    auto *B = OriginalBlocks.back();35    OriginalBlocks.pop_back();36 37    if (B->getSize() == 0) {38      LLVM_DEBUG({39        dbgs() << "  Skipping empty block at "40               << formatv("{0:x16}", B->getAddress()) << "\n";41      });42      continue;43    }44 45    unsigned NumBlocks = B->getSize() / RecordSize;46 47    LLVM_DEBUG({48      dbgs() << "  Splitting block at " << formatv("{0:x16}", B->getAddress())49             << " into " << NumBlocks << " compact unwind record(s)\n";50    });51 52    if (B->getSize() % RecordSize)53      return make_error<JITLinkError>(54          "Error splitting compact unwind record in " + G.getName() +55          ": block at " + formatv("{0:x}", B->getAddress()) + " has size " +56          formatv("{0:x}", B->getSize()) +57          " (not a multiple of CU record size of " +58          formatv("{0:x}", RecordSize) + ")");59 60    auto Blocks =61        G.splitBlock(*B, map_range(seq(1U, NumBlocks), [=](Edge::OffsetT Idx) {62          return Idx * RecordSize;63        }));64 65    for (auto *CURec : Blocks) {66      bool AddedKeepAlive = false;67 68      for (auto &E : CURec->edges()) {69        if (E.getOffset() == 0) {70          LLVM_DEBUG({71            dbgs() << "    Updating compact unwind record at "72                   << CURec->getAddress() << " to point to "73                   << (E.getTarget().hasName() ? *E.getTarget().getName()74                                               : StringRef())75                   << " (at " << E.getTarget().getAddress() << ")\n";76          });77 78          if (E.getTarget().isExternal())79            return make_error<JITLinkError>(80                "Error adding keep-alive edge for compact unwind record at " +81                formatv("{0:x}", CURec->getAddress()) + ": target " +82                *E.getTarget().getName() + " is an external symbol");83          auto &TgtBlock = E.getTarget().getBlock();84          auto &CURecSym =85              G.addAnonymousSymbol(*CURec, 0, RecordSize, false, false);86          TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);87          AddedKeepAlive = true;88        }89      }90 91      if (!AddedKeepAlive)92        return make_error<JITLinkError>(93            "Error adding keep-alive edge for compact unwind record at " +94            formatv("{0:x}", CURec->getAddress()) +95            ": no outgoing target edge at offset 0");96    }97  }98 99  return Error::success();100}101 102} // end namespace jitlink103} // end namespace llvm104