1a9ac8606Spatrick //===------ Interpreter.cpp - Incremental Compilation and Execution -------===//
2a9ac8606Spatrick //
3a9ac8606Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a9ac8606Spatrick // See https://llvm.org/LICENSE.txt for license information.
5a9ac8606Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9ac8606Spatrick //
7a9ac8606Spatrick //===----------------------------------------------------------------------===//
8a9ac8606Spatrick //
9a9ac8606Spatrick // This file implements the component which performs incremental code
10a9ac8606Spatrick // compilation and execution.
11a9ac8606Spatrick //
12a9ac8606Spatrick //===----------------------------------------------------------------------===//
13a9ac8606Spatrick
14a9ac8606Spatrick #include "clang/Interpreter/Interpreter.h"
15a9ac8606Spatrick
16a9ac8606Spatrick #include "IncrementalExecutor.h"
17a9ac8606Spatrick #include "IncrementalParser.h"
18a9ac8606Spatrick
19a9ac8606Spatrick #include "clang/AST/ASTContext.h"
20a9ac8606Spatrick #include "clang/Basic/TargetInfo.h"
21a9ac8606Spatrick #include "clang/CodeGen/ModuleBuilder.h"
22a9ac8606Spatrick #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
23a9ac8606Spatrick #include "clang/Driver/Compilation.h"
24a9ac8606Spatrick #include "clang/Driver/Driver.h"
25a9ac8606Spatrick #include "clang/Driver/Job.h"
26a9ac8606Spatrick #include "clang/Driver/Options.h"
27a9ac8606Spatrick #include "clang/Driver/Tool.h"
28a9ac8606Spatrick #include "clang/Frontend/CompilerInstance.h"
29a9ac8606Spatrick #include "clang/Frontend/TextDiagnosticBuffer.h"
30a9ac8606Spatrick #include "clang/Lex/PreprocessorOptions.h"
31a9ac8606Spatrick
32a9ac8606Spatrick #include "llvm/IR/Module.h"
33*12c85518Srobert #include "llvm/Support/Errc.h"
34a9ac8606Spatrick #include "llvm/Support/Host.h"
35a9ac8606Spatrick
36a9ac8606Spatrick using namespace clang;
37a9ac8606Spatrick
38a9ac8606Spatrick // FIXME: Figure out how to unify with namespace init_convenience from
39*12c85518Srobert // tools/clang-import-test/clang-import-test.cpp
40a9ac8606Spatrick namespace {
41a9ac8606Spatrick /// Retrieves the clang CC1 specific flags out of the compilation's jobs.
42a9ac8606Spatrick /// \returns NULL on error.
43a9ac8606Spatrick static llvm::Expected<const llvm::opt::ArgStringList *>
GetCC1Arguments(DiagnosticsEngine * Diagnostics,driver::Compilation * Compilation)44a9ac8606Spatrick GetCC1Arguments(DiagnosticsEngine *Diagnostics,
45a9ac8606Spatrick driver::Compilation *Compilation) {
46a9ac8606Spatrick // We expect to get back exactly one Command job, if we didn't something
47a9ac8606Spatrick // failed. Extract that job from the Compilation.
48a9ac8606Spatrick const driver::JobList &Jobs = Compilation->getJobs();
49a9ac8606Spatrick if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin()))
50*12c85518Srobert return llvm::createStringError(llvm::errc::not_supported,
51a9ac8606Spatrick "Driver initialization failed. "
52a9ac8606Spatrick "Unable to create a driver job");
53a9ac8606Spatrick
54a9ac8606Spatrick // The one job we find should be to invoke clang again.
55a9ac8606Spatrick const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin()));
56a9ac8606Spatrick if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
57*12c85518Srobert return llvm::createStringError(llvm::errc::not_supported,
58a9ac8606Spatrick "Driver initialization failed");
59a9ac8606Spatrick
60a9ac8606Spatrick return &Cmd->getArguments();
61a9ac8606Spatrick }
62a9ac8606Spatrick
63a9ac8606Spatrick static llvm::Expected<std::unique_ptr<CompilerInstance>>
CreateCI(const llvm::opt::ArgStringList & Argv)64a9ac8606Spatrick CreateCI(const llvm::opt::ArgStringList &Argv) {
65a9ac8606Spatrick std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
66a9ac8606Spatrick IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
67a9ac8606Spatrick
68a9ac8606Spatrick // Register the support for object-file-wrapped Clang modules.
69a9ac8606Spatrick // FIXME: Clang should register these container operations automatically.
70a9ac8606Spatrick auto PCHOps = Clang->getPCHContainerOperations();
71a9ac8606Spatrick PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
72a9ac8606Spatrick PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
73a9ac8606Spatrick
74a9ac8606Spatrick // Buffer diagnostics from argument parsing so that we can output them using
75a9ac8606Spatrick // a well formed diagnostic object.
76a9ac8606Spatrick IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
77a9ac8606Spatrick TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
78a9ac8606Spatrick DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
79a9ac8606Spatrick bool Success = CompilerInvocation::CreateFromArgs(
80*12c85518Srobert Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
81a9ac8606Spatrick
82a9ac8606Spatrick // Infer the builtin include path if unspecified.
83a9ac8606Spatrick if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
84a9ac8606Spatrick Clang->getHeaderSearchOpts().ResourceDir.empty())
85a9ac8606Spatrick Clang->getHeaderSearchOpts().ResourceDir =
86a9ac8606Spatrick CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
87a9ac8606Spatrick
88a9ac8606Spatrick // Create the actual diagnostics engine.
89a9ac8606Spatrick Clang->createDiagnostics();
90a9ac8606Spatrick if (!Clang->hasDiagnostics())
91*12c85518Srobert return llvm::createStringError(llvm::errc::not_supported,
92a9ac8606Spatrick "Initialization failed. "
93a9ac8606Spatrick "Unable to create diagnostics engine");
94a9ac8606Spatrick
95a9ac8606Spatrick DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
96a9ac8606Spatrick if (!Success)
97*12c85518Srobert return llvm::createStringError(llvm::errc::not_supported,
98a9ac8606Spatrick "Initialization failed. "
99a9ac8606Spatrick "Unable to flush diagnostics");
100a9ac8606Spatrick
101a9ac8606Spatrick // FIXME: Merge with CompilerInstance::ExecuteAction.
102a9ac8606Spatrick llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
103a9ac8606Spatrick Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);
104a9ac8606Spatrick
105a9ac8606Spatrick Clang->setTarget(TargetInfo::CreateTargetInfo(
106a9ac8606Spatrick Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
107a9ac8606Spatrick if (!Clang->hasTarget())
108*12c85518Srobert return llvm::createStringError(llvm::errc::not_supported,
109a9ac8606Spatrick "Initialization failed. "
110a9ac8606Spatrick "Target is missing");
111a9ac8606Spatrick
112a9ac8606Spatrick Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
113a9ac8606Spatrick
114*12c85518Srobert // Don't clear the AST before backend codegen since we do codegen multiple
115*12c85518Srobert // times, reusing the same AST.
116*12c85518Srobert Clang->getCodeGenOpts().ClearASTBeforeBackend = false;
117*12c85518Srobert
118*12c85518Srobert Clang->getFrontendOpts().DisableFree = false;
119*12c85518Srobert Clang->getCodeGenOpts().DisableFree = false;
120*12c85518Srobert
121a9ac8606Spatrick return std::move(Clang);
122a9ac8606Spatrick }
123a9ac8606Spatrick
124a9ac8606Spatrick } // anonymous namespace
125a9ac8606Spatrick
126a9ac8606Spatrick llvm::Expected<std::unique_ptr<CompilerInstance>>
create(std::vector<const char * > & ClangArgv)127a9ac8606Spatrick IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {
128a9ac8606Spatrick
129a9ac8606Spatrick // If we don't know ClangArgv0 or the address of main() at this point, try
130a9ac8606Spatrick // to guess it anyway (it's possible on some platforms).
131a9ac8606Spatrick std::string MainExecutableName =
132a9ac8606Spatrick llvm::sys::fs::getMainExecutable(nullptr, nullptr);
133a9ac8606Spatrick
134a9ac8606Spatrick ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
135a9ac8606Spatrick
136a9ac8606Spatrick // Prepending -c to force the driver to do something if no action was
137a9ac8606Spatrick // specified. By prepending we allow users to override the default
138a9ac8606Spatrick // action and use other actions in incremental mode.
139a9ac8606Spatrick // FIXME: Print proper driver diagnostics if the driver flags are wrong.
140a9ac8606Spatrick // We do C++ by default; append right after argv[0] if no "-x" given
141*12c85518Srobert ClangArgv.insert(ClangArgv.end(), "-xc++");
142*12c85518Srobert ClangArgv.insert(ClangArgv.end(), "-Xclang");
143*12c85518Srobert ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions");
144*12c85518Srobert ClangArgv.insert(ClangArgv.end(), "-c");
145a9ac8606Spatrick
146a9ac8606Spatrick // Put a dummy C++ file on to ensure there's at least one compile job for the
147a9ac8606Spatrick // driver to construct.
148a9ac8606Spatrick ClangArgv.push_back("<<< inputs >>>");
149a9ac8606Spatrick
150a9ac8606Spatrick // Buffer diagnostics from argument parsing so that we can output them using a
151a9ac8606Spatrick // well formed diagnostic object.
152a9ac8606Spatrick IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
153*12c85518Srobert IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
154*12c85518Srobert CreateAndPopulateDiagOpts(ClangArgv);
155a9ac8606Spatrick TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
156a9ac8606Spatrick DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
157a9ac8606Spatrick
158a9ac8606Spatrick driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0],
159a9ac8606Spatrick llvm::sys::getProcessTriple(), Diags);
160a9ac8606Spatrick Driver.setCheckInputsExist(false); // the input comes from mem buffers
161*12c85518Srobert llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv);
162a9ac8606Spatrick std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));
163a9ac8606Spatrick
164a9ac8606Spatrick if (Compilation->getArgs().hasArg(driver::options::OPT_v))
165a9ac8606Spatrick Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
166a9ac8606Spatrick
167a9ac8606Spatrick auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
168a9ac8606Spatrick if (auto Err = ErrOrCC1Args.takeError())
169a9ac8606Spatrick return std::move(Err);
170a9ac8606Spatrick
171a9ac8606Spatrick return CreateCI(**ErrOrCC1Args);
172a9ac8606Spatrick }
173a9ac8606Spatrick
Interpreter(std::unique_ptr<CompilerInstance> CI,llvm::Error & Err)174a9ac8606Spatrick Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
175a9ac8606Spatrick llvm::Error &Err) {
176a9ac8606Spatrick llvm::ErrorAsOutParameter EAO(&Err);
177a9ac8606Spatrick auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
178a9ac8606Spatrick TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
179a9ac8606Spatrick IncrParser = std::make_unique<IncrementalParser>(std::move(CI),
180a9ac8606Spatrick *TSCtx->getContext(), Err);
181a9ac8606Spatrick }
182a9ac8606Spatrick
~Interpreter()183*12c85518Srobert Interpreter::~Interpreter() {
184*12c85518Srobert if (IncrExecutor) {
185*12c85518Srobert if (llvm::Error Err = IncrExecutor->cleanUp())
186*12c85518Srobert llvm::report_fatal_error(
187*12c85518Srobert llvm::Twine("Failed to clean up IncrementalExecutor: ") +
188*12c85518Srobert toString(std::move(Err)));
189*12c85518Srobert }
190*12c85518Srobert }
191a9ac8606Spatrick
192a9ac8606Spatrick llvm::Expected<std::unique_ptr<Interpreter>>
create(std::unique_ptr<CompilerInstance> CI)193a9ac8606Spatrick Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
194a9ac8606Spatrick llvm::Error Err = llvm::Error::success();
195a9ac8606Spatrick auto Interp =
196a9ac8606Spatrick std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
197a9ac8606Spatrick if (Err)
198a9ac8606Spatrick return std::move(Err);
199a9ac8606Spatrick return std::move(Interp);
200a9ac8606Spatrick }
201a9ac8606Spatrick
getCompilerInstance() const202a9ac8606Spatrick const CompilerInstance *Interpreter::getCompilerInstance() const {
203a9ac8606Spatrick return IncrParser->getCI();
204a9ac8606Spatrick }
205a9ac8606Spatrick
getExecutionEngine() const206*12c85518Srobert const llvm::orc::LLJIT *Interpreter::getExecutionEngine() const {
207*12c85518Srobert if (IncrExecutor)
208*12c85518Srobert return IncrExecutor->getExecutionEngine();
209*12c85518Srobert return nullptr;
210*12c85518Srobert }
211*12c85518Srobert
212a9ac8606Spatrick llvm::Expected<PartialTranslationUnit &>
Parse(llvm::StringRef Code)213a9ac8606Spatrick Interpreter::Parse(llvm::StringRef Code) {
214a9ac8606Spatrick return IncrParser->Parse(Code);
215a9ac8606Spatrick }
216a9ac8606Spatrick
Execute(PartialTranslationUnit & T)217a9ac8606Spatrick llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
218a9ac8606Spatrick assert(T.TheModule);
219a9ac8606Spatrick if (!IncrExecutor) {
220*12c85518Srobert const clang::TargetInfo &TI =
221*12c85518Srobert getCompilerInstance()->getASTContext().getTargetInfo();
222a9ac8606Spatrick llvm::Error Err = llvm::Error::success();
223*12c85518Srobert IncrExecutor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI);
224a9ac8606Spatrick
225a9ac8606Spatrick if (Err)
226a9ac8606Spatrick return Err;
227a9ac8606Spatrick }
228a9ac8606Spatrick // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
229*12c85518Srobert if (auto Err = IncrExecutor->addModule(T))
230a9ac8606Spatrick return Err;
231a9ac8606Spatrick
232a9ac8606Spatrick if (auto Err = IncrExecutor->runCtors())
233a9ac8606Spatrick return Err;
234a9ac8606Spatrick
235a9ac8606Spatrick return llvm::Error::success();
236a9ac8606Spatrick }
237*12c85518Srobert
238*12c85518Srobert llvm::Expected<llvm::JITTargetAddress>
getSymbolAddress(GlobalDecl GD) const239*12c85518Srobert Interpreter::getSymbolAddress(GlobalDecl GD) const {
240*12c85518Srobert if (!IncrExecutor)
241*12c85518Srobert return llvm::make_error<llvm::StringError>("Operation failed. "
242*12c85518Srobert "No execution engine",
243*12c85518Srobert std::error_code());
244*12c85518Srobert llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
245*12c85518Srobert return getSymbolAddress(MangledName);
246*12c85518Srobert }
247*12c85518Srobert
248*12c85518Srobert llvm::Expected<llvm::JITTargetAddress>
getSymbolAddress(llvm::StringRef IRName) const249*12c85518Srobert Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
250*12c85518Srobert if (!IncrExecutor)
251*12c85518Srobert return llvm::make_error<llvm::StringError>("Operation failed. "
252*12c85518Srobert "No execution engine",
253*12c85518Srobert std::error_code());
254*12c85518Srobert
255*12c85518Srobert return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
256*12c85518Srobert }
257*12c85518Srobert
258*12c85518Srobert llvm::Expected<llvm::JITTargetAddress>
getSymbolAddressFromLinkerName(llvm::StringRef Name) const259*12c85518Srobert Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
260*12c85518Srobert if (!IncrExecutor)
261*12c85518Srobert return llvm::make_error<llvm::StringError>("Operation failed. "
262*12c85518Srobert "No execution engine",
263*12c85518Srobert std::error_code());
264*12c85518Srobert
265*12c85518Srobert return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
266*12c85518Srobert }
267*12c85518Srobert
Undo(unsigned N)268*12c85518Srobert llvm::Error Interpreter::Undo(unsigned N) {
269*12c85518Srobert
270*12c85518Srobert std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
271*12c85518Srobert if (N > PTUs.size())
272*12c85518Srobert return llvm::make_error<llvm::StringError>("Operation failed. "
273*12c85518Srobert "Too many undos",
274*12c85518Srobert std::error_code());
275*12c85518Srobert for (unsigned I = 0; I < N; I++) {
276*12c85518Srobert if (IncrExecutor) {
277*12c85518Srobert if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
278*12c85518Srobert return Err;
279*12c85518Srobert }
280*12c85518Srobert
281*12c85518Srobert IncrParser->CleanUpPTU(PTUs.back());
282*12c85518Srobert PTUs.pop_back();
283*12c85518Srobert }
284*12c85518Srobert return llvm::Error::success();
285*12c85518Srobert }
286