LLVM: lib/ExecutionEngine/Orc/IndirectionUtils.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

18

19#define DEBUG_TYPE "orc"

20

21using namespace llvm;

23

24namespace {

25

27public:

29

31 CompileFunction Compile)

34 Name(std::move(Name)), Compile(std::move(Compile)) {}

35

36 StringRef getName() const override { return ""; }

37

38private:

39 void materialize(std::unique_ptr R) override {

42

44 cantFail(R->notifyEmitted({}));

45 }

46

49 }

50

52 CompileFunction Compile;

53};

54

55}

56

57namespace llvm {

58namespace orc {

59

61void IndirectStubsManager::anchor() {}

62

63Expected

65 if (auto TrampolineAddr = TP->getTrampoline()) {

66 auto CallbackName =

67 ES.intern(std::string("cc") + std::to_string(++NextCallbackId));

68

69 std::lock_guardstd::mutex Lock(CCMgrMutex);

70 AddrToSymbol[*TrampolineAddr] = CallbackName;

72 CallbacksJD.define(std::make_unique(

73 std::move(CallbackName), std::move(Compile))));

74 return *TrampolineAddr;

75 } else

76 return TrampolineAddr.takeError();

77}

78

82

83 {

84 std::unique_lockstd::mutex Lock(CCMgrMutex);

85 auto I = AddrToSymbol.find(TrampolineAddr);

86

87

88

89

90 if (I == AddrToSymbol.end()) {

91 Lock.unlock();

92 ES.reportError(

94 formatv("{0:x}", TrampolineAddr),

96 return ErrorHandlerAddress;

97 } else

98 Name = I->second;

99 }

100

101 if (auto Sym =

104 Name))

105 return Sym->getAddress();

106 else {

107 llvm::dbgs() << "Didn't find callback.\n";

108

109

110 ES.reportError(Sym.takeError());

111 return ErrorHandlerAddress;

112 }

113}

114

116 for (auto &[Name, Dest] : NewDests)

117 if (auto Err = updatePointer(*Name, Dest.getAddress()))

118 return Err;

120}

121

123 std::unique_ptr MR, SymbolMap InitialDests) {

125 for (auto &[Name, Dest] : InitialDests)

126 StubInits[*Name] = {Dest.getAddress(), Dest.getFlags()};

128 MR->getExecutionSession().reportError(std::move(Err));

129 return MR->failMaterialization();

130 }

132 for (auto &[Name, Dest] : InitialDests) {

133 auto StubSym = findStub(*Name, false);

134 assert(StubSym.getAddress() && "Stub symbol should be present");

135 Stubs[Name] = StubSym;

136 }

137 if (auto Err = MR->notifyResolved(Stubs)) {

138 MR->getExecutionSession().reportError(std::move(Err));

139 return MR->failMaterialization();

140 }

141 if (auto Err = MR->notifyEmitted({})) {

142 MR->getExecutionSession().reportError(std::move(Err));

143 return MR->failMaterialization();

144 }

145}

146

150 switch (T.getArch()) {

151 default:

153 std::string("No callback manager available for ") + T.str(),

158 return CCMgrT::Create(ES, ErrorHandlerAddress);

159 }

160

163 return CCMgrT::Create(ES, ErrorHandlerAddress);

164 }

165

168 return CCMgrT::Create(ES, ErrorHandlerAddress);

169 }

170

173 return CCMgrT::Create(ES, ErrorHandlerAddress);

174 }

177 return CCMgrT::Create(ES, ErrorHandlerAddress);

178 }

179

183 return CCMgrT::Create(ES, ErrorHandlerAddress);

184 }

185

188 return CCMgrT::Create(ES, ErrorHandlerAddress);

189 }

190

194 return CCMgrT::Create(ES, ErrorHandlerAddress);

195 } else {

197 return CCMgrT::Create(ES, ErrorHandlerAddress);

198 }

199 }

200

201 }

202}

203

204std::function<std::unique_ptr()>

206 switch (T.getArch()) {

207 default:

208 return [](){

209 return std::make_unique<

211 };

212

215 return [](){

216 return std::make_unique<

218 };

219

221 return [](){

222 return std::make_unique<

224 };

225

227 return []() {

228 return std::make_unique<

230 };

231

233 return [](){

234 return std::make_unique<

236 };

237

239 return [](){

240 return std::make_unique<

242 };

243

246 return [](){

247 return std::make_unique<

249 };

250

252 return []() {

253 return std::make_unique<

255 };

256

259 return [](){

260 return std::make_unique<

262 };

263 } else {

264 return [](){

265 return std::make_unique<

267 };

268 }

269

270 }

271}

272

278 return AddrPtrVal;

279}

280

284 Initializer, Name, nullptr,

287 return IP;

288}

289

291 assert(F.isDeclaration() && "Can't turn a definition into a stub.");

292 assert(F.getParent() && "Function isn't in a module.");

293 Module &M = *F.getParent();

296 LoadInst *ImplAddr = Builder.CreateLoad(F.getType(), &ImplPointer);

297 std::vector<Value*> CallArgs;

298 for (auto &A : F.args())

299 CallArgs.push_back(&A);

300 CallInst *Call = Builder.CreateCall(F.getFunctionType(), ImplAddr, CallArgs);

301 Call->setTailCall();

302 Call->setAttributes(F.getAttributes());

303 if (F.getReturnType()->isVoidTy())

304 Builder.CreateRetVoid();

305 else

306 Builder.CreateRet(Call);

307}

308

310 std::vector<GlobalValue *> PromotedGlobals;

311

312 for (auto &GV : M.global_values()) {

313 bool Promoted = true;

314

315

316 if (!GV.hasName())

317 GV.setName("__orc_anon." + Twine(NextId++));

318 else if (GV.getName().starts_with("\01L"))

319 GV.setName("__" + GV.getName().substr(1) + "." + Twine(NextId++));

320 else if (GV.hasLocalLinkage())

321 GV.setName("__orc_lcl." + GV.getName() + "." + Twine(NextId++));

322 else

323 Promoted = false;

324

325 if (GV.hasLocalLinkage()) {

328 Promoted = true;

329 }

331

332 if (Promoted)

333 PromotedGlobals.push_back(&GV);

334 }

335

336 return PromotedGlobals;

337}

338

343 F.getLinkage(), F.getName(), &Dst);

345

346 if (VMap) {

347 (*VMap)[&F] = NewF;

348 auto NewArgI = NewF->arg_begin();

349 for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE;

350 ++ArgI, ++NewArgI)

351 (*VMap)[&*ArgI] = &*NewArgI;

352 }

353

354 return NewF;

355}

356

364 if (VMap)

365 (*VMap)[&GV] = NewGV;

366 return NewGV;

367}

368

371 assert(OrigA.getAliasee() && "Original alias doesn't have an aliasee?");

375 NewA->copyAttributesFrom(&OrigA);

376 VMap[&OrigA] = NewA;

377 return NewA;

378}

379

384

385

388

391

392

394 assert(B.isZeroFill() && "expected content block");

396 auto SymStartInBlock =

399 auto Content = ArrayRef(SymStartInBlock, SymSize);

400

402

404 for (auto &E : B.edges()) {

405 if (E.isRelocation())

406 ExistingRelocations.insert(E.getOffset());

407 }

408

409 size_t I = 0;

410 while (I < Content.size()) {

413 uint64_t InstrStart = SymAddress.getValue() + I;

415 Instr, InstrSize, Content.drop_front(I), InstrStart, CommentStream);

417 LLVM_DEBUG(dbgs() << "Aborting due to disassembly failure at address "

418 << InstrStart);

420 formatv("failed to disassemble at address {0:x16}", InstrStart),

422 }

423

424 I += InstrSize;

425

426

427 auto PCRelAddr =

429 if (!PCRelAddr || *PCRelAddr != SymAddress.getValue())

430 continue;

431

432 auto RelocOffInInstr =

434 if (!RelocOffInInstr || InstrSize - *RelocOffInInstr != 4) {

435 LLVM_DEBUG(dbgs() << "Skipping unknown self-relocation at "

436 << InstrStart);

437 continue;

438 }

439

440 auto RelocOffInBlock = orc::ExecutorAddr(InstrStart) + *RelocOffInInstr -

442 if (ExistingRelocations.contains(RelocOffInBlock))

443 continue;

444

445 LLVM_DEBUG(dbgs() << "Adding delta32 self-relocation at " << InstrStart);

447 }

449}

450

451}

452}

MCDisassembler::DecodeStatus DecodeStatus

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

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

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

Module.h This file contains the declarations for the Module class.

static StringRef getName(Value *V)

LLVM Basic Block Representation.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

This class represents a function call, abstracting a target machine's calling convention.

static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)

This is an important base class in LLVM.

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.

Class to represent function types.

static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)

void copyAttributesFrom(const Function *Src)

copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...

const Constant * getAliasee() const

static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)

If a parent module is specified, the alias is automatically inserted into the end of the specified mo...

LinkageTypes getLinkage() const

ThreadLocalMode getThreadLocalMode() const

PointerType * getType() const

Global values are always pointers.

@ HiddenVisibility

The GV is hidden.

@ ExternalLinkage

Externally visible function.

Type * getValueType() const

LLVM_ABI void copyAttributesFrom(const GlobalVariable *Src)

copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...

bool isConstant() const

If the value is a global constant, its value is immutable throughout the runtime execution of the pro...

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

An instruction for reading from memory.

Superclass for all disassemblers.

const MCSubtargetInfo & getSubtargetInfo() const

virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef< uint8_t > Bytes, uint64_t Address, raw_ostream &CStream) const =0

Returns the disassembly of a single instruction.

Instances of this class represent a single low-level machine instruction.

virtual std::optional< uint64_t > getMemoryOperandRelocationOffset(const MCInst &Inst, uint64_t Size) const

Given an instruction with a memory operand that could require relocation, returns the offset within t...

virtual std::optional< uint64_t > evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI, uint64_t Addr, uint64_t Size) const

Given an instruction tries to get the address of a memory operand.

A Module instance is used to store all the information related to an LLVM module.

Class to represent pointers.

unsigned getAddressSpace() const

Return the address space of the Pointer type.

static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)

This constructs a pointer to an object of the specified type in a numbered address space.

Implements a dense probed hash-table based set with some number of buckets stored inline.

StringRef - Represent a constant reference to a string, i.e.

Triple - Helper class for working with autoconf configuration names.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)

LLVM_ABI unsigned getPointerAddressSpace() const

Get the address space of this pointer or pointer vector type.

LLVMContext & getContext() const

Return the LLVMContext in which this type was uniqued.

LLVM Value Representation.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

std::pair< iterator, bool > insert(const ValueT &V)

bool contains(const_arg_type_t< ValueT > V) const

Check if the set contains the given element.

const orc::SymbolStringPtr & getName() const

Returns the name of this symbol (empty if the symbol is anonymous).

orc::ExecutorAddr getAddress() const

Returns the address of this symbol.

Block & getBlock()

Return the Block for this Symbol (Symbol must be defined).

orc::ExecutorAddrDiff getSize() const

Returns the size of this symbol.

orc::ExecutorAddrDiff getOffset() const

Returns the offset for this symbol within the underlying addressable.

An ExecutionSession represents a running JIT program.

Represents an address in the executor process.

uint64_t getValue() const

virtual ExecutorSymbolDef findStub(StringRef Name, bool ExportedStubsOnly)=0

Find the stub with the given name.

StringMap< std::pair< ExecutorAddr, JITSymbolFlags > > StubInitsMap

Map type for initializing the manager. See init.

virtual Error updatePointer(StringRef Name, ExecutorAddr NewAddr)=0

Change the value of the implementation pointer for the stub.

virtual Error createStubs(const StubInitsMap &StubInits)=0

Create StubInits.size() stubs with the given names, target addresses, and flags.

void emitRedirectableSymbols(std::unique_ptr< MaterializationResponsibility > MR, SymbolMap InitialDests) override

Emit redirectable symbol.

Definition IndirectionUtils.cpp:122

Error redirect(JITDylib &JD, const SymbolMap &NewDests) override

— RedirectableSymbolManager implementation —

Definition IndirectionUtils.cpp:115

LLVM_ABI ExecutorAddr executeCompileCallback(ExecutorAddr TrampolineAddr)

Execute the callback for the given trampoline id.

Definition IndirectionUtils.cpp:80

LLVM_ABI Expected< ExecutorAddr > getCompileCallback(CompileFunction Compile)

Reserve a compile callback.

Definition IndirectionUtils.cpp:64

std::function< ExecutorAddr()> CompileFunction

Represents a JIT'd dynamic library.

IndirectStubsManager implementation for the host architecture, e.g.

Manage compile callbacks for in-process JITs.

A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...

Pointer to a pooled string representing a symbol name.

virtual ~TrampolinePool()

A raw_ostream that discards all output.

#define llvm_unreachable(msg)

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

JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)

Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...

LLVM_ABI Constant * createIRTypedAddress(FunctionType &FT, ExecutorAddr Addr)

Build a function pointer of FunctionType with the given constant address.

Definition IndirectionUtils.cpp:273

LLVM_ABI Expected< std::unique_ptr< JITCompileCallbackManager > > createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress)

Create a local compile callback manager.

Definition IndirectionUtils.cpp:148

LLVM_ABI void makeStub(Function &F, Value &ImplPointer)

Turn a function declaration into a stub function that makes an indirect call using the given function...

Definition IndirectionUtils.cpp:290

LLVM_ABI Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym, jitlink::LinkGraph &G, MCDisassembler &Disassembler, MCInstrAnalysis &MIA)

Introduce relocations to Sym in its own definition if there are any pointers formed via PC-relative a...

Definition IndirectionUtils.cpp:380

LLVM_ABI GlobalVariable * cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, ValueToValueMapTy *VMap=nullptr)

Clone a global variable declaration into a new module.

Definition IndirectionUtils.cpp:357

DenseMap< SymbolStringPtr, ExecutorSymbolDef > SymbolMap

A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).

LLVM_ABI Function * cloneFunctionDecl(Module &Dst, const Function &F, ValueToValueMapTy *VMap=nullptr)

Clone a function declaration into a new module.

Definition IndirectionUtils.cpp:339

LLVM_ABI std::function< std::unique_ptr< IndirectStubsManager >()> createLocalIndirectStubsManagerBuilder(const Triple &T)

Create a local indirect stubs manager builder.

Definition IndirectionUtils.cpp:205

LLVM_ABI GlobalAlias * cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA, ValueToValueMapTy &VMap)

Clone a global alias declaration into a new module.

Definition IndirectionUtils.cpp:369

LLVM_ABI GlobalVariable * createImplPointer(PointerType &PT, Module &M, const Twine &Name, Constant *Initializer)

Create a function pointer with the given type, name, and initializer in the given Module.

Definition IndirectionUtils.cpp:281

DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap

A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

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.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

ArrayRef(const T &OneElt) -> ArrayRef< T >

ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.