Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 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 | |
Daniel Dunbar | c1b1729 | 2010-06-15 17:48:49 +0000 | [diff] [blame] | 10 | #include "clang/CodeGen/CodeGenAction.h" |
Chandler Carruth | 8675b4a | 2012-12-04 09:37:22 +0000 | [diff] [blame] | 11 | #include "clang/Basic/DiagnosticOptions.h" |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 12 | #include "clang/Driver/Compilation.h" |
| 13 | #include "clang/Driver/Driver.h" |
| 14 | #include "clang/Driver/Tool.h" |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 15 | #include "clang/Frontend/CompilerInstance.h" |
Chandler Carruth | 8675b4a | 2012-12-04 09:37:22 +0000 | [diff] [blame] | 16 | #include "clang/Frontend/CompilerInvocation.h" |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 17 | #include "clang/Frontend/FrontendDiagnostic.h" |
| 18 | #include "clang/Frontend/TextDiagnosticPrinter.h" |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/SmallString.h" |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 20 | #include "llvm/ExecutionEngine/ExecutionEngine.h" |
Rafael Espindola | e89d289 | 2014-07-24 17:13:09 +0000 | [diff] [blame] | 21 | #include "llvm/ExecutionEngine/MCJIT.h" |
Chandler Carruth | ffd5551 | 2013-01-02 11:45:17 +0000 | [diff] [blame] | 22 | #include "llvm/IR/Module.h" |
Rafael Espindola | 9678d27 | 2013-06-26 05:03:40 +0000 | [diff] [blame] | 23 | #include "llvm/Support/FileSystem.h" |
Michael J. Spencer | 8aaf499 | 2010-11-29 18:12:39 +0000 | [diff] [blame] | 24 | #include "llvm/Support/Host.h" |
Chandler Carruth | 8675b4a | 2012-12-04 09:37:22 +0000 | [diff] [blame] | 25 | #include "llvm/Support/ManagedStatic.h" |
Michael J. Spencer | 8aaf499 | 2010-11-29 18:12:39 +0000 | [diff] [blame] | 26 | #include "llvm/Support/Path.h" |
Evan Cheng | 494eb06 | 2011-08-24 18:09:14 +0000 | [diff] [blame] | 27 | #include "llvm/Support/TargetSelect.h" |
Chandler Carruth | 8675b4a | 2012-12-04 09:37:22 +0000 | [diff] [blame] | 28 | #include "llvm/Support/raw_ostream.h" |
Ahmed Charles | dfca6f9 | 2014-03-09 11:36:40 +0000 | [diff] [blame] | 29 | #include <memory> |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 30 | using namespace clang; |
| 31 | using namespace clang::driver; |
| 32 | |
Dan Gohman | ff66a7c | 2010-11-17 17:23:53 +0000 | [diff] [blame] | 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). |
Rafael Espindola | 9678d27 | 2013-06-26 05:03:40 +0000 | [diff] [blame] | 38 | std::string GetExecutablePath(const char *Argv0) { |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 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; |
Rafael Espindola | 9678d27 | 2013-06-26 05:03:40 +0000 | [diff] [blame] | 42 | return llvm::sys::fs::getMainExecutable(Argv0, MainAddr); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 43 | } |
| 44 | |
Rafael Espindola | a296664 | 2014-08-19 04:04:30 +0000 | [diff] [blame^] | 45 | static llvm::ExecutionEngine * |
| 46 | createExecutionEngine(std::unique_ptr<llvm::Module> M, std::string *ErrorStr) { |
| 47 | return llvm::EngineBuilder(std::move(M)) |
| 48 | .setUseMCJIT(true) |
| 49 | .setEngineKind(llvm::EngineKind::Either) |
| 50 | .setErrorStr(ErrorStr) |
| 51 | .create(); |
Rafael Espindola | fb3d5d1 | 2014-07-24 15:54:23 +0000 | [diff] [blame] | 52 | } |
| 53 | |
Rafael Espindola | a296664 | 2014-08-19 04:04:30 +0000 | [diff] [blame^] | 54 | static int Execute(std::unique_ptr<llvm::Module> Mod, char *const *envp) { |
Alp Toker | 60c88cb | 2014-07-01 03:19:50 +0000 | [diff] [blame] | 55 | llvm::InitializeNativeTarget(); |
Rafael Espindola | e89d289 | 2014-07-24 17:13:09 +0000 | [diff] [blame] | 56 | llvm::InitializeNativeTargetAsmPrinter(); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 57 | |
Rafael Espindola | a296664 | 2014-08-19 04:04:30 +0000 | [diff] [blame^] | 58 | llvm::Module &M = *Mod; |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 59 | std::string Error; |
Rafael Espindola | a296664 | 2014-08-19 04:04:30 +0000 | [diff] [blame^] | 60 | std::unique_ptr<llvm::ExecutionEngine> EE( |
| 61 | createExecutionEngine(std::move(Mod), &Error)); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 62 | if (!EE) { |
| 63 | llvm::errs() << "unable to make execution engine: " << Error << "\n"; |
| 64 | return 255; |
| 65 | } |
| 66 | |
Rafael Espindola | a296664 | 2014-08-19 04:04:30 +0000 | [diff] [blame^] | 67 | llvm::Function *EntryFn = M.getFunction("main"); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 68 | if (!EntryFn) { |
| 69 | llvm::errs() << "'main' function not found in module.\n"; |
| 70 | return 255; |
| 71 | } |
| 72 | |
| 73 | // FIXME: Support passing arguments. |
| 74 | std::vector<std::string> Args; |
Rafael Espindola | a296664 | 2014-08-19 04:04:30 +0000 | [diff] [blame^] | 75 | Args.push_back(M.getModuleIdentifier()); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 76 | |
Rafael Espindola | e89d289 | 2014-07-24 17:13:09 +0000 | [diff] [blame] | 77 | EE->finalizeObject(); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 78 | return EE->runFunctionAsMain(EntryFn, Args, envp); |
| 79 | } |
| 80 | |
| 81 | int main(int argc, const char **argv, char * const *envp) { |
| 82 | void *MainAddr = (void*) (intptr_t) GetExecutablePath; |
Rafael Espindola | 9678d27 | 2013-06-26 05:03:40 +0000 | [diff] [blame] | 83 | std::string Path = GetExecutablePath(argv[0]); |
Douglas Gregor | cdb4d69 | 2012-10-23 22:36:49 +0000 | [diff] [blame] | 84 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); |
Benjamin Kramer | 1921fac | 2010-08-26 13:48:56 +0000 | [diff] [blame] | 85 | TextDiagnosticPrinter *DiagClient = |
Douglas Gregor | cdb4d69 | 2012-10-23 22:36:49 +0000 | [diff] [blame] | 86 | new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 87 | |
Dylan Noblesmith | c95d819 | 2012-02-20 14:00:23 +0000 | [diff] [blame] | 88 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
Douglas Gregor | cdb4d69 | 2012-10-23 22:36:49 +0000 | [diff] [blame] | 89 | DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); |
Rafael Espindola | 3175daa | 2014-07-24 20:47:42 +0000 | [diff] [blame] | 90 | |
| 91 | // Use ELF on windows for now. |
| 92 | std::string TripleStr = llvm::sys::getProcessTriple(); |
| 93 | llvm::Triple T(TripleStr); |
| 94 | if (T.isOSBinFormatCOFF()) |
| 95 | T.setObjectFormat(llvm::Triple::ELF); |
| 96 | |
| 97 | Driver TheDriver(Path, T.str(), Diags); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 98 | TheDriver.setTitle("clang interpreter"); |
Alp Toker | ed412da | 2014-07-09 01:37:36 +0000 | [diff] [blame] | 99 | TheDriver.setCheckInputsExist(false); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 100 | |
| 101 | // FIXME: This is a hack to try to force the driver to do something we can |
| 102 | // recognize. We need to extend the driver library to support this use model |
| 103 | // (basically, exactly one input, and the operation mode is hard wired). |
Dmitri Gribenko | f857950 | 2013-01-12 19:30:44 +0000 | [diff] [blame] | 104 | SmallVector<const char *, 16> Args(argv, argv + argc); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 105 | Args.push_back("-fsyntax-only"); |
Ahmed Charles | af94d56 | 2014-03-09 11:34:25 +0000 | [diff] [blame] | 106 | std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args)); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 107 | if (!C) |
| 108 | return 0; |
| 109 | |
| 110 | // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate. |
| 111 | |
| 112 | // We expect to get back exactly one command job, if we didn't something |
| 113 | // failed. Extract that job from the compilation. |
| 114 | const driver::JobList &Jobs = C->getJobs(); |
Manuel Klimek | b66b5ce | 2011-05-23 18:25:41 +0000 | [diff] [blame] | 115 | if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) { |
Dylan Noblesmith | f1a13f2 | 2012-02-13 12:32:26 +0000 | [diff] [blame] | 116 | SmallString<256> Msg; |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 117 | llvm::raw_svector_ostream OS(Msg); |
Hans Wennborg | b212b34 | 2013-09-12 18:23:34 +0000 | [diff] [blame] | 118 | Jobs.Print(OS, "; ", true); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 119 | Diags.Report(diag::err_fe_expected_compiler_job) << OS.str(); |
| 120 | return 1; |
| 121 | } |
| 122 | |
| 123 | const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin()); |
| 124 | if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { |
| 125 | Diags.Report(diag::err_fe_expected_clang_command); |
| 126 | return 1; |
| 127 | } |
| 128 | |
| 129 | // Initialize a compiler invocation object from the clang (-cc1) arguments. |
| 130 | const driver::ArgStringList &CCArgs = Cmd->getArguments(); |
Ahmed Charles | af94d56 | 2014-03-09 11:34:25 +0000 | [diff] [blame] | 131 | std::unique_ptr<CompilerInvocation> CI(new CompilerInvocation); |
Benjamin Kramer | 25d3d78 | 2010-04-20 11:50:39 +0000 | [diff] [blame] | 132 | CompilerInvocation::CreateFromArgs(*CI, |
| 133 | const_cast<const char **>(CCArgs.data()), |
| 134 | const_cast<const char **>(CCArgs.data()) + |
| 135 | CCArgs.size(), |
Benjamin Kramer | 6a2542b | 2010-04-20 11:55:38 +0000 | [diff] [blame] | 136 | Diags); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 137 | |
| 138 | // Show the invocation, with -v. |
| 139 | if (CI->getHeaderSearchOpts().Verbose) { |
| 140 | llvm::errs() << "clang invocation:\n"; |
Hans Wennborg | b212b34 | 2013-09-12 18:23:34 +0000 | [diff] [blame] | 141 | Jobs.Print(llvm::errs(), "\n", true); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 142 | llvm::errs() << "\n"; |
| 143 | } |
| 144 | |
| 145 | // FIXME: This is copied from cc1_main.cpp; simplify and eliminate. |
| 146 | |
| 147 | // Create a compiler instance to handle the actual work. |
| 148 | CompilerInstance Clang; |
Ahmed Charles | a337444 | 2014-03-09 11:46:32 +0000 | [diff] [blame] | 149 | Clang.setInvocation(CI.release()); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 150 | |
| 151 | // Create the compilers actual diagnostics engine. |
Sean Silva | f1b49e2 | 2013-01-20 01:58:28 +0000 | [diff] [blame] | 152 | Clang.createDiagnostics(); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 153 | if (!Clang.hasDiagnostics()) |
| 154 | return 1; |
| 155 | |
| 156 | // Infer the builtin include path if unspecified. |
| 157 | if (Clang.getHeaderSearchOpts().UseBuiltinIncludes && |
| 158 | Clang.getHeaderSearchOpts().ResourceDir.empty()) |
| 159 | Clang.getHeaderSearchOpts().ResourceDir = |
| 160 | CompilerInvocation::GetResourcesPath(argv[0], MainAddr); |
| 161 | |
| 162 | // Create and execute the frontend to generate an LLVM bitcode module. |
Ahmed Charles | af94d56 | 2014-03-09 11:34:25 +0000 | [diff] [blame] | 163 | std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction()); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 164 | if (!Clang.ExecuteAction(*Act)) |
| 165 | return 1; |
| 166 | |
| 167 | int Res = 255; |
Rafael Espindola | a296664 | 2014-08-19 04:04:30 +0000 | [diff] [blame^] | 168 | if (std::unique_ptr<llvm::Module> &Module = Act->getModule()) |
| 169 | Res = Execute(std::move(Module), envp); |
Daniel Dunbar | 0076d94 | 2010-02-25 08:49:05 +0000 | [diff] [blame] | 170 | |
| 171 | // Shutdown. |
| 172 | |
| 173 | llvm::llvm_shutdown(); |
| 174 | |
| 175 | return Res; |
| 176 | } |