17#define DEBUG_TYPE "jitlink" 
   25  std::vector<Block *> OriginalBlocks(CompactUnwindSection.
blocks().
begin(),
 
   28    dbgs() << 
"In " << 
G.getName() << 
" splitting compact unwind section " 
   29           << CompactUnwindSection.
getName() << 
" containing " 
   30           << OriginalBlocks.size() << 
" initial blocks...\n";
 
   33  while (!OriginalBlocks.empty()) {
 
   34    auto *
B = OriginalBlocks.back();
 
   35    OriginalBlocks.pop_back();
 
   37    if (
B->getSize() == 0) {
 
   39        dbgs() << 
"  Skipping empty block at " 
   40               << 
formatv(
"{0:x16}", 
B->getAddress()) << 
"\n";
 
   45    unsigned NumBlocks = 
B->getSize() / RecordSize;
 
   48      dbgs() << 
"  Splitting block at " << 
formatv(
"{0:x16}", 
B->getAddress())
 
   49             << 
" into " << NumBlocks << 
" compact unwind record(s)\n";
 
   52    if (
B->getSize() % RecordSize)
 
   54          "Error splitting compact unwind record in " + 
G.getName() +
 
   55          ": block at " + 
formatv(
"{0:x}", 
B->getAddress()) + 
" has size " +
 
   57          " (not a multiple of CU record size of " +
 
   58          formatv(
"{0:x}", RecordSize) + 
")");
 
   61        G.splitBlock(*
B, 
map_range(
seq(1U, NumBlocks), [=](Edge::OffsetT Idx) {
 
   62          return Idx * RecordSize;
 
   65    for (
auto *CURec : Blocks) {
 
   66      bool AddedKeepAlive = 
false;
 
   68      for (
auto &
E : CURec->edges()) {
 
   69        if (
E.getOffset() == 0) {
 
   71            dbgs() << 
"    Updating compact unwind record at " 
   72                   << CURec->getAddress() << 
" to point to " 
   73                   << (
E.getTarget().hasName() ? *
E.getTarget().getName()
 
   75                   << 
" (at " << 
E.getTarget().getAddress() << 
")\n";
 
   78          if (
E.getTarget().isExternal())
 
   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();
 
   85              G.addAnonymousSymbol(*CURec, 0, RecordSize, 
false, 
false);
 
   86          TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);
 
   87          AddedKeepAlive = 
true;
 
   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");
 
 
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
 
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
 
Provides some synthesis utilities to produce sequences of values.
 
Lightweight error class with error context and mandatory checking.
 
static ErrorSuccess success()
Create a success value.
 
StringRef - Represent a constant reference to a string, i.e.
 
Represents an object file section.
 
StringRef getName() const
Returns the name of this section.
 
iterator_range< block_iterator > blocks()
Returns an iterator over the blocks defined in this section.
 
Error splitCompactUnwindBlocks(LinkGraph &G, Section &CompactUnwindSection, size_t RecordSize)
Split blocks in an __LD,__compact_unwind section on record boundaries.
 
This is an optimization pass for GlobalISel generic memory operations.
 
auto map_range(ContainerTy &&C, FuncTy F)
 
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
 
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
 
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
 
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.