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