|
21 | 21 | #include "llvm/CodeGen/TargetInstrInfo.h" |
22 | 22 | #include "llvm/CodeGen/TargetPassConfig.h" |
23 | 23 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
24 | | -#include "llvm/ExecutionEngine/Orc/LLJIT.h" |
| 24 | +#include "llvm/ExecutionEngine/SectionMemoryManager.h" |
25 | 25 | #include "llvm/IR/BasicBlock.h" |
26 | 26 | #include "llvm/IR/Instructions.h" |
27 | 27 | #include "llvm/IR/LegacyPassManager.h" |
28 | 28 | #include "llvm/MC/MCInstrInfo.h" |
29 | | -#include "llvm/Object/SymbolSize.h" |
30 | 29 | #include "llvm/Support/Alignment.h" |
31 | 30 | #include "llvm/Support/MemoryBuffer.h" |
32 | 31 | #include "llvm/Support/raw_ostream.h" |
@@ -106,7 +105,7 @@ MachineFunction &createVoidVoidPtrMachineFunction(StringRef FunctionName, |
106 | 105 | FunctionType *FunctionType = |
107 | 106 | FunctionType::get(ReturnType, {MemParamType}, false); |
108 | 107 | Function *const F = Function::Create( |
109 | | - FunctionType, GlobalValue::ExternalLinkage, FunctionName, Module); |
| 108 | + FunctionType, GlobalValue::InternalLinkage, FunctionName, Module); |
110 | 109 | BasicBlock *BB = BasicBlock::Create(Module->getContext(), "", F); |
111 | 110 | new UnreachableInst(Module->getContext(), BB); |
112 | 111 | return MMI->getOrCreateMachineFunction(*F); |
@@ -325,48 +324,66 @@ object::OwningBinary<object::ObjectFile> getObjectFromFile(StringRef Filename) { |
325 | 324 | return cantFail(object::ObjectFile::createObjectFile(Filename)); |
326 | 325 | } |
327 | 326 |
|
| 327 | +namespace { |
| 328 | + |
| 329 | +// Implementation of this class relies on the fact that a single object with a |
| 330 | +// single function will be loaded into memory. |
| 331 | +class TrackingSectionMemoryManager : public SectionMemoryManager { |
| 332 | +public: |
| 333 | + explicit TrackingSectionMemoryManager(uintptr_t *CodeSize) |
| 334 | + : CodeSize(CodeSize) {} |
| 335 | + |
| 336 | + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, |
| 337 | + unsigned SectionID, |
| 338 | + StringRef SectionName) override { |
| 339 | + *CodeSize = Size; |
| 340 | + return SectionMemoryManager::allocateCodeSection(Size, Alignment, SectionID, |
| 341 | + SectionName); |
| 342 | + } |
| 343 | + |
| 344 | +private: |
| 345 | + uintptr_t *const CodeSize = nullptr; |
| 346 | +}; |
| 347 | + |
| 348 | +} // namespace |
| 349 | + |
328 | 350 | Expected<ExecutableFunction> ExecutableFunction::create( |
329 | 351 | std::unique_ptr<LLVMTargetMachine> TM, |
330 | 352 | object::OwningBinary<object::ObjectFile> &&ObjectFileHolder) { |
331 | 353 | assert(ObjectFileHolder.getBinary() && "cannot create object file"); |
332 | 354 | std::unique_ptr<LLVMContext> Ctx = std::make_unique<LLVMContext>(); |
333 | | - |
334 | | - auto SymbolSizes = object::computeSymbolSizes(*ObjectFileHolder.getBinary()); |
335 | | - // Get the size of the function that we want to call into (with the name of |
336 | | - // FunctionID). This should always be the third symbol returned by |
337 | | - // calculateSymbolSizes. |
338 | | - assert(SymbolSizes.size() == 3); |
339 | | - assert(cantFail(std::get<0>(SymbolSizes[2]).getName()) == FunctionID); |
340 | | - uintptr_t CodeSize = std::get<1>(SymbolSizes[2]); |
341 | | - |
342 | | - auto EJITOrErr = orc::LLJITBuilder().create(); |
343 | | - if (!EJITOrErr) |
344 | | - return EJITOrErr.takeError(); |
345 | | - |
346 | | - auto EJIT = std::move(*EJITOrErr); |
347 | | - |
348 | | - if (auto ObjErr = |
349 | | - EJIT->addObjectFile(std::get<1>(ObjectFileHolder.takeBinary()))) |
350 | | - return std::move(ObjErr); |
351 | | - |
352 | | - auto FunctionAddressOrErr = EJIT->lookup(FunctionID); |
353 | | - if (!FunctionAddressOrErr) |
354 | | - return FunctionAddressOrErr.takeError(); |
355 | | - |
356 | | - const uint64_t FunctionAddress = FunctionAddressOrErr->getValue(); |
357 | | - |
| 355 | + // Initializing the execution engine. |
| 356 | + // We need to use the JIT EngineKind to be able to add an object file. |
| 357 | + LLVMLinkInMCJIT(); |
| 358 | + uintptr_t CodeSize = 0; |
| 359 | + std::string Error; |
| 360 | + std::unique_ptr<ExecutionEngine> EE( |
| 361 | + EngineBuilder(createModule(Ctx, TM->createDataLayout())) |
| 362 | + .setErrorStr(&Error) |
| 363 | + .setMCPU(TM->getTargetCPU()) |
| 364 | + .setEngineKind(EngineKind::JIT) |
| 365 | + .setMCJITMemoryManager( |
| 366 | + std::make_unique<TrackingSectionMemoryManager>(&CodeSize)) |
| 367 | + .create(TM.release())); |
| 368 | + if (!EE) |
| 369 | + return make_error<StringError>(Twine(Error), inconvertibleErrorCode()); |
| 370 | + // Adding the generated object file containing the assembled function. |
| 371 | + // The ExecutionEngine makes sure the object file is copied into an |
| 372 | + // executable page. |
| 373 | + EE->addObjectFile(std::move(ObjectFileHolder)); |
| 374 | + // Fetching function bytes. |
| 375 | + const uint64_t FunctionAddress = EE->getFunctionAddress(FunctionID); |
358 | 376 | assert(isAligned(kFunctionAlignment, FunctionAddress) && |
359 | 377 | "function is not properly aligned"); |
360 | | - |
361 | 378 | StringRef FBytes = |
362 | 379 | StringRef(reinterpret_cast<const char *>(FunctionAddress), CodeSize); |
363 | | - return ExecutableFunction(std::move(Ctx), std::move(EJIT), FBytes); |
| 380 | + return ExecutableFunction(std::move(Ctx), std::move(EE), FBytes); |
364 | 381 | } |
365 | 382 |
|
366 | 383 | ExecutableFunction::ExecutableFunction(std::unique_ptr<LLVMContext> Ctx, |
367 | | - std::unique_ptr<orc::LLJIT> EJIT, |
| 384 | + std::unique_ptr<ExecutionEngine> EE, |
368 | 385 | StringRef FB) |
369 | | - : FunctionBytes(FB), Context(std::move(Ctx)), ExecJIT(std::move(EJIT)) {} |
| 386 | + : FunctionBytes(FB), Context(std::move(Ctx)), ExecEngine(std::move(EE)) {} |
370 | 387 |
|
371 | 388 | Error getBenchmarkFunctionBytes(const StringRef InputData, |
372 | 389 | std::vector<uint8_t> &Bytes) { |
|
0 commit comments