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