xref: /openbsd-src/gnu/llvm/clang/lib/Interpreter/Interpreter.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
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