1//===--- IncrementalExecutor.cpp - Incremental Execution --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the class which performs incremental code execution.
10//
11//===----------------------------------------------------------------------===//
12
13#include "IncrementalExecutor.h"
14
15#include "clang/Basic/TargetInfo.h"
16#include "clang/Basic/TargetOptions.h"
17#include "clang/Interpreter/PartialTranslationUnit.h"
18#include "llvm/ExecutionEngine/ExecutionEngine.h"
19#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
20#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
21#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
22#include "llvm/ExecutionEngine/Orc/LLJIT.h"
23#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
24#include "llvm/ExecutionEngine/SectionMemoryManager.h"
25#include "llvm/IR/Module.h"
26#include "llvm/Support/ManagedStatic.h"
27#include "llvm/Support/TargetSelect.h"
28
29namespace clang {
30
31IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
32                                         llvm::Error &Err,
33                                         const clang::TargetInfo &TI)
34    : TSCtx(TSC) {
35  using namespace llvm::orc;
36  llvm::ErrorAsOutParameter EAO(&Err);
37
38  auto JTMB = JITTargetMachineBuilder(TI.getTriple());
39  JTMB.addFeatures(TI.getTargetOpts().Features);
40  if (auto JitOrErr = LLJITBuilder().setJITTargetMachineBuilder(JTMB).create())
41    Jit = std::move(*JitOrErr);
42  else {
43    Err = JitOrErr.takeError();
44    return;
45  }
46
47  const char Pref = Jit->getDataLayout().getGlobalPrefix();
48  // Discover symbols from the process as a fallback.
49  if (auto PSGOrErr = DynamicLibrarySearchGenerator::GetForCurrentProcess(Pref))
50    Jit->getMainJITDylib().addGenerator(std::move(*PSGOrErr));
51  else {
52    Err = PSGOrErr.takeError();
53    return;
54  }
55}
56
57IncrementalExecutor::~IncrementalExecutor() {}
58
59llvm::Error IncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
60  llvm::orc::ResourceTrackerSP RT =
61      Jit->getMainJITDylib().createResourceTracker();
62  ResourceTrackers[&PTU] = RT;
63
64  return Jit->addIRModule(RT, {std::move(PTU.TheModule), TSCtx});
65}
66
67llvm::Error IncrementalExecutor::removeModule(PartialTranslationUnit &PTU) {
68
69  llvm::orc::ResourceTrackerSP RT = std::move(ResourceTrackers[&PTU]);
70  if (!RT)
71    return llvm::Error::success();
72
73  ResourceTrackers.erase(&PTU);
74  if (llvm::Error Err = RT->remove())
75    return Err;
76  return llvm::Error::success();
77}
78
79// Clean up the JIT instance.
80llvm::Error IncrementalExecutor::cleanUp() {
81  // This calls the global dtors of registered modules.
82  return Jit->deinitialize(Jit->getMainJITDylib());
83}
84
85llvm::Error IncrementalExecutor::runCtors() const {
86  return Jit->initialize(Jit->getMainJITDylib());
87}
88
89llvm::Expected<llvm::JITTargetAddress>
90IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
91                                      SymbolNameKind NameKind) const {
92  auto Sym = (NameKind == LinkerName) ? Jit->lookupLinkerMangled(Name)
93                                      : Jit->lookup(Name);
94
95  if (!Sym)
96    return Sym.takeError();
97  return Sym->getValue();
98}
99
100} // end namespace clang
101