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