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