1e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar//===-- examples/clang-interpreter/main.cpp - Clang C Interpreter Example -===// 2e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar// 3e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar// The LLVM Compiler Infrastructure 4e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar// 5e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar// This file is distributed under the University of Illinois Open Source 6e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar// License. See LICENSE.TXT for details. 7e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar// 8e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar//===----------------------------------------------------------------------===// 9e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 109b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/CodeGen/CodeGenAction.h" 11e0c6e93dddf4503d9b12ce09d7ab6ea5d523499fChandler Carruth#include "clang/Basic/DiagnosticOptions.h" 12e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar#include "clang/Driver/Compilation.h" 13e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar#include "clang/Driver/Driver.h" 14e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar#include "clang/Driver/Tool.h" 15e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar#include "clang/Frontend/CompilerInstance.h" 16e0c6e93dddf4503d9b12ce09d7ab6ea5d523499fChandler Carruth#include "clang/Frontend/CompilerInvocation.h" 17e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar#include "clang/Frontend/FrontendDiagnostic.h" 18e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar#include "clang/Frontend/TextDiagnosticPrinter.h" 19e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar#include "llvm/ADT/SmallString.h" 20e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar#include "llvm/ExecutionEngine/ExecutionEngine.h" 21e0c6e93dddf4503d9b12ce09d7ab6ea5d523499fChandler Carruth#include "llvm/ExecutionEngine/JIT.h" 223b844ba7d5be205a9b4f5f0b0d1b7978977f4b8cChandler Carruth#include "llvm/IR/Module.h" 23ac1db6b2bde50e9a0f3846243f654f6c13682725Rafael Espindola#include "llvm/Support/FileSystem.h" 2403013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Host.h" 25e0c6e93dddf4503d9b12ce09d7ab6ea5d523499fChandler Carruth#include "llvm/Support/ManagedStatic.h" 2603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 27a6b4045dc462c03cd1e7cb9c3ec9dbfdb9c6ad62Evan Cheng#include "llvm/Support/TargetSelect.h" 28e0c6e93dddf4503d9b12ce09d7ab6ea5d523499fChandler Carruth#include "llvm/Support/raw_ostream.h" 29651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <memory> 30e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbarusing namespace clang; 31e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbarusing namespace clang::driver; 32e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 33ea1924e62162b299d797d23992a466142b3c6c68Dan Gohman// This function isn't referenced outside its translation unit, but it 34ea1924e62162b299d797d23992a466142b3c6c68Dan Gohman// can't use the "static" keyword because its address is used for 35ea1924e62162b299d797d23992a466142b3c6c68Dan Gohman// GetMainExecutable (since some platforms don't support taking the 36ea1924e62162b299d797d23992a466142b3c6c68Dan Gohman// address of main, and some platforms can't implement GetMainExecutable 37ea1924e62162b299d797d23992a466142b3c6c68Dan Gohman// without being given the address of a function in the main executable). 38ac1db6b2bde50e9a0f3846243f654f6c13682725Rafael Espindolastd::string GetExecutablePath(const char *Argv0) { 39e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // This just needs to be some symbol in the binary; C++ doesn't 40e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // allow taking the address of ::main however. 41e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar void *MainAddr = (void*) (intptr_t) GetExecutablePath; 42ac1db6b2bde50e9a0f3846243f654f6c13682725Rafael Espindola return llvm::sys::fs::getMainExecutable(Argv0, MainAddr); 43e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar} 44e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 45f129562b4397be749148f5fe543c81f90fdfb6fcDan Gohmanstatic int Execute(llvm::Module *Mod, char * const *envp) { 46e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar llvm::InitializeNativeTarget(); 47e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 48e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar std::string Error; 49651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<llvm::ExecutionEngine> EE( 50ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::ExecutionEngine::create(Mod, /*ForceInterpreter*/ false, &Error)); 51e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (!EE) { 52e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar llvm::errs() << "unable to make execution engine: " << Error << "\n"; 53e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return 255; 54e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar } 55e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 56e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar llvm::Function *EntryFn = Mod->getFunction("main"); 57e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (!EntryFn) { 58e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar llvm::errs() << "'main' function not found in module.\n"; 59e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return 255; 60e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar } 61e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 62e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // FIXME: Support passing arguments. 63e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar std::vector<std::string> Args; 64e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar Args.push_back(Mod->getModuleIdentifier()); 65e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 66e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return EE->runFunctionAsMain(EntryFn, Args, envp); 67e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar} 68e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 69e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbarint main(int argc, const char **argv, char * const *envp) { 70e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar void *MainAddr = (void*) (intptr_t) GetExecutablePath; 71ac1db6b2bde50e9a0f3846243f654f6c13682725Rafael Espindola std::string Path = GetExecutablePath(argv[0]); 7235d516cf1aa88a1af7b25c869984758750af3c1bDouglas Gregor IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 7306b901be05f92417af25de10c55b9e850e5e5c16Benjamin Kramer TextDiagnosticPrinter *DiagClient = 7435d516cf1aa88a1af7b25c869984758750af3c1bDouglas Gregor new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); 75e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 76c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 7735d516cf1aa88a1af7b25c869984758750af3c1bDouglas Gregor DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); 786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Driver TheDriver(Path, llvm::sys::getProcessTriple(), Diags); 79e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar TheDriver.setTitle("clang interpreter"); 80ef8225444452a1486bd721f3285301fe84643b00Stephen Hines TheDriver.setCheckInputsExist(false); 81e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 82e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // FIXME: This is a hack to try to force the driver to do something we can 83e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // recognize. We need to extend the driver library to support this use model 84e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // (basically, exactly one input, and the operation mode is hard wired). 85cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVector<const char *, 16> Args(argv, argv + argc); 86e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar Args.push_back("-fsyntax-only"); 87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args)); 88e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (!C) 89e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return 0; 90e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 91e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate. 92e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 93e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // We expect to get back exactly one command job, if we didn't something 94e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // failed. Extract that job from the compilation. 95e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar const driver::JobList &Jobs = C->getJobs(); 96c8b3e6302f75c4fd44866ecfca9a7063d176c30cManuel Klimek if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) { 9736d592718ff342f762e32cbde73d1113f88cb275Dylan Noblesmith SmallString<256> Msg; 98e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar llvm::raw_svector_ostream OS(Msg); 99fc3389701ead32709ba84825e4c06651065da2c0Hans Wennborg Jobs.Print(OS, "; ", true); 100e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar Diags.Report(diag::err_fe_expected_compiler_job) << OS.str(); 101e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return 1; 102e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar } 103e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 104e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin()); 105e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { 106e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar Diags.Report(diag::err_fe_expected_clang_command); 107e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return 1; 108e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar } 109e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 110e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // Initialize a compiler invocation object from the clang (-cc1) arguments. 111e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar const driver::ArgStringList &CCArgs = Cmd->getArguments(); 112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<CompilerInvocation> CI(new CompilerInvocation); 1139e8635a86db25415ed0b6b64b10984943b3bad65Benjamin Kramer CompilerInvocation::CreateFromArgs(*CI, 1149e8635a86db25415ed0b6b64b10984943b3bad65Benjamin Kramer const_cast<const char **>(CCArgs.data()), 1159e8635a86db25415ed0b6b64b10984943b3bad65Benjamin Kramer const_cast<const char **>(CCArgs.data()) + 1169e8635a86db25415ed0b6b64b10984943b3bad65Benjamin Kramer CCArgs.size(), 117a4f0a80e7367bad218ffe1f8ab1b380f690276ceBenjamin Kramer Diags); 118e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 119e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // Show the invocation, with -v. 120e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (CI->getHeaderSearchOpts().Verbose) { 121e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar llvm::errs() << "clang invocation:\n"; 122fc3389701ead32709ba84825e4c06651065da2c0Hans Wennborg Jobs.Print(llvm::errs(), "\n", true); 123e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar llvm::errs() << "\n"; 124e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar } 125e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 126e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // FIXME: This is copied from cc1_main.cpp; simplify and eliminate. 127e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 128e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // Create a compiler instance to handle the actual work. 129e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar CompilerInstance Clang; 130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Clang.setInvocation(CI.release()); 131e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 132e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // Create the compilers actual diagnostics engine. 133d47afb96a3f988e6d21a92fe4dfe875ab227c7c0Sean Silva Clang.createDiagnostics(); 134e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (!Clang.hasDiagnostics()) 135e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return 1; 136e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 137e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // Infer the builtin include path if unspecified. 138e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (Clang.getHeaderSearchOpts().UseBuiltinIncludes && 139e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar Clang.getHeaderSearchOpts().ResourceDir.empty()) 140e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar Clang.getHeaderSearchOpts().ResourceDir = 141e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar CompilerInvocation::GetResourcesPath(argv[0], MainAddr); 142e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 143e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // Create and execute the frontend to generate an LLVM bitcode module. 144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction()); 145e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (!Clang.ExecuteAction(*Act)) 146e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return 1; 147e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 148e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar int Res = 255; 149e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar if (llvm::Module *Module = Act->takeModule()) 150e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar Res = Execute(Module, envp); 151e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 152e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar // Shutdown. 153e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 154e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar llvm::llvm_shutdown(); 155e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar 156e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar return Res; 157e22462867ca63e41eabe92b12d6182a62bd829a6Daniel Dunbar} 158