LLVM: lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

14

15#define DEBUG_TYPE "jitlink"

16

17namespace llvm {

18namespace jitlink {

19

21

23

25

26

27 if (auto Err = runPasses(Passes.PrePrunePasses))

28 return Ctx->notifyFailed(std::move(Err));

29

31 dbgs() << "Link graph pre-pruning:\n";

32 G->dump(dbgs());

33 });

34

36

38 dbgs() << "Link graph post-pruning:\n";

39 G->dump(dbgs());

40 });

41

42

43 if (auto Err = runPasses(Passes.PostPrunePasses))

44 return Ctx->notifyFailed(std::move(Err));

45

46

47 if (G->allocActions().empty() && llvm::all_of(G->sections(), [](Section &S) {

48 return S.getMemLifetime() == orc::MemLifetime::NoAlloc;

49 })) {

51 return;

52 }

53

54 Ctx->getMemoryManager().allocate(

55 Ctx->getJITLinkDylib(), *G,

56 [S = std::move(Self)](AllocResult AR) mutable {

57

58

59

60 auto *TmpSelf = S.get();

61 TmpSelf->linkPhase2(std::move(S), std::move(AR));

62 });

63}

64

67

69

70 if (AR)

71 Alloc = std::move(*AR);

72 else

73 return Ctx->notifyFailed(AR.takeError());

74

76 dbgs() << "Link graph before post-allocation passes:\n";

77 G->dump(dbgs());

78 });

79

80

81 if (auto Err = runPasses(Passes.PostAllocationPasses))

82 return abandonAllocAndBailOut(std::move(Self), std::move(Err));

83

84

85 LLVM_DEBUG(dbgs() << "Resolving symbols defined in " << G->getName() << "\n");

86

87 if (auto Err = Ctx->notifyResolved(*G))

88 return abandonAllocAndBailOut(std::move(Self), std::move(Err));

89

90 auto ExternalSymbols = getExternalSymbolNames();

91

92

93 if (ExternalSymbols.empty()) {

95 dbgs() << "No external symbols for " << G->getName()

96 << ". Proceeding immediately with link phase 3.\n";

97 });

98

99

100 auto &TmpSelf = *Self;

102 return;

103 }

104

105

107 dbgs() << "Issuing lookup for external symbols for " << G->getName()

108 << " (may trigger materialization/linking of other graphs)...\n";

109 });

110

111

112

113

114

115

116

117

118

119

120

121 Ctx->lookup(std::move(ExternalSymbols),

123 [S = std::move(Self)](

125 auto &TmpSelf = *S;

126 TmpSelf.linkPhase3(std::move(S), std::move(LookupResult));

127 }));

128}

129

132

134

135

136 if (!LR)

137 return abandonAllocAndBailOut(std::move(Self), LR.takeError());

138

139

140 applyLookupResult(*LR);

141

143 dbgs() << "Link graph before pre-fixup passes:\n";

144 G->dump(dbgs());

145 });

146

147 if (auto Err = runPasses(Passes.PreFixupPasses))

148 return abandonAllocAndBailOut(std::move(Self), std::move(Err));

149

151 dbgs() << "Link graph before copy-and-fixup:\n";

152 G->dump(dbgs());

153 });

154

155

156 if (auto Err = fixUpBlocks(*G))

157 return abandonAllocAndBailOut(std::move(Self), std::move(Err));

158

160 dbgs() << "Link graph after copy-and-fixup:\n";

161 G->dump(dbgs());

162 });

163

164 if (auto Err = runPasses(Passes.PostFixupPasses))

165 return abandonAllocAndBailOut(std::move(Self), std::move(Err));

166

167

168 if (!Alloc) {

170 return;

171 }

172

173 Alloc->finalize([S = std::move(Self)](FinalizeResult FR) mutable {

174

175

176

177 auto *TmpSelf = S.get();

178 TmpSelf->linkPhase4(std::move(S), std::move(FR));

179 });

180}

181

184

186

187 if (!FR)

188 return Ctx->notifyFailed(FR.takeError());

189

190 Ctx->notifyFinalized(std::move(*FR));

191

193}

194

197 if (auto Err = P(*G))

198 return Err;

200}

201

203

205 for (auto *Sym : G->external_symbols()) {

206 assert(!Sym->getAddress() &&

207 "External has already been assigned an address");

208 assert(Sym->hasName() && "Externals must be named");

212 UnresolvedExternals[Sym->getName()] = LookupFlags;

213 }

214 return UnresolvedExternals;

215}

216

218 for (auto *Sym : G->external_symbols()) {

219 assert(Sym->getOffset() == 0 &&

220 "External symbol is not at the start of its addressable block");

221 assert(!Sym->getAddress() && "Symbol already resolved");

222 assert(!Sym->isDefined() && "Symbol being resolved is already defined");

223 auto ResultI = Result.find(Sym->getName());

224 if (ResultI != Result.end()) {

225 Sym->getAddressable().setAddress(ResultI->second.getAddress());

226 Sym->setLinkage(ResultI->second.getFlags().isWeak() ? Linkage::Weak

228 Sym->setScope(ResultI->second.getFlags().isExported() ? Scope::Default

230 } else

231 assert(Sym->isWeaklyReferenced() &&

232 "Failed to resolve non-weak reference");

233 }

234

236 dbgs() << "Externals after applying lookup result:\n";

237 for (auto *Sym : G->external_symbols()) {

238 dbgs() << " " << Sym->getName() << ": "

239 << formatv("{0:x16}", Sym->getAddress().getValue());

240 switch (Sym->getLinkage()) {

242 break;

244 dbgs() << " (weak)";

245 break;

246 }

247 switch (Sym->getScope()) {

251 "side-effects-only linkage");

253 break;

255 dbgs() << " (exported)";

256 break;

257 }

258 dbgs() << "\n";

259 }

260 });

261}

262

263void JITLinkerBase::abandonAllocAndBailOut(std::unique_ptr Self,

265 assert(Err && "Should not be bailing out on success value");

266 assert(Alloc && "can not call abandonAllocAndBailOut before allocation");

267 Alloc->abandon([S = std::move(Self), E1 = std::move(Err)](Error E2) mutable {

268 S->Ctx->notifyFailed(joinErrors(std::move(E1), std::move(E2)));

269 });

270}

271

273 std::vector<Symbol *> Worklist;

275

276

277 for (auto *Sym : G.defined_symbols())

278 if (Sym->isLive())

279 Worklist.push_back(Sym);

280

281

282 while (!Worklist.empty()) {

283 auto *Sym = Worklist.back();

284 Worklist.pop_back();

285

286 auto &B = Sym->getBlock();

287

288

290 continue;

291

293

294 for (auto &E : Sym->getBlock().edges()) {

295

296

297 if (E.getTarget().isDefined() && E.getTarget().isLive())

298 Worklist.push_back(&E.getTarget());

299

300

301 E.getTarget().setLive(true);

302 }

303 }

304

305

306 {

307 LLVM_DEBUG(dbgs() << "Dead-stripping defined symbols:\n");

308 std::vector<Symbol *> SymbolsToRemove;

309 for (auto *Sym : G.defined_symbols())

310 if (!Sym->isLive())

311 SymbolsToRemove.push_back(Sym);

312 for (auto *Sym : SymbolsToRemove) {

314 G.removeDefinedSymbol(*Sym);

315 }

316 }

317

318

319 {

321 std::vector<Block *> BlocksToRemove;

322 for (auto *B : G.blocks())

324 BlocksToRemove.push_back(B);

325 for (auto *B : BlocksToRemove) {

327 G.removeBlock(*B);

328 }

329 }

330

331

332 {

333 LLVM_DEBUG(dbgs() << "Removing unused external symbols:\n");

334 std::vector<Symbol *> SymbolsToRemove;

335 for (auto *Sym : G.external_symbols())

336 if (!Sym->isLive())

337 SymbolsToRemove.push_back(Sym);

338 for (auto *Sym : SymbolsToRemove) {

340 G.removeExternalSymbol(*Sym);

341 }

342 }

343}

344

345}

346}

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

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

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

SmallPtrSet< const BasicBlock *, 8 > VisitedBlocks

Function const char * Passes

Implements a dense probed hash-table based set.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

DenseMap< orc::SymbolStringPtr, SymbolLookupFlags > LookupMap

Represents a finalized allocation.

void linkPhase4(std::unique_ptr< JITLinkerBase > Self, FinalizeResult FR)

Definition JITLinkGeneric.cpp:182

void linkPhase3(std::unique_ptr< JITLinkerBase > Self, Expected< AsyncLookupResult > LookupResult)

Definition JITLinkGeneric.cpp:130

Expected< std::unique_ptr< InFlightAlloc > > AllocResult

void linkPhase1(std::unique_ptr< JITLinkerBase > Self)

Definition JITLinkGeneric.cpp:22

Expected< JITLinkMemoryManager::FinalizedAlloc > FinalizeResult

void linkPhase2(std::unique_ptr< JITLinkerBase > Self, AllocResult AR)

Definition JITLinkGeneric.cpp:65

Represents an object file section.

#define llvm_unreachable(msg)

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

std::unique_ptr< JITLinkAsyncLookupContinuation > createLookupContinuation(Continuation Cont)

Create a lookup continuation from a function object.

SymbolLookupFlags

Flags for symbol lookup.

void prune(LinkGraph &G)

Removes dead symbols/blocks/addressables.

Definition JITLinkGeneric.cpp:272

DenseMap< orc::SymbolStringPtr, orc::ExecutorSymbolDef > AsyncLookupResult

A map of symbol names to resolved addresses.

std::vector< LinkGraphPassFunction > LinkGraphPassList

A list of LinkGraph passes.

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

Error joinErrors(Error E1, Error E2)

Concatenate errors.

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.