|
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