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