17#define DEBUG_TYPE "jitlink"
25 std::vector<Block *> OriginalBlocks(CompactUnwindSection.
blocks().begin(),
26 CompactUnwindSection.
blocks().end());
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)
53 return make_error<JITLinkError>(
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) +
")");
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())
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();
85 G.addAnonymousSymbol(*CURec, 0, RecordSize,
false,
false);
86 TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);
87 AddedKeepAlive =
true;
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");
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
DenseMap< Block *, BlockRelaxAux > Blocks
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.
constexpr size_t size() const
size - Get the string size.
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.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.