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