1 //===-- examples/clang-interpreter/main.cpp - Clang C Interpreter Example -===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "clang/Basic/DiagnosticOptions.h"
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/CompilerInstance.h"
15 #include "clang/Frontend/CompilerInvocation.h"
16 #include "clang/Frontend/FrontendDiagnostic.h"
17 #include "clang/Frontend/TextDiagnosticPrinter.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ExecutionEngine/ExecutionEngine.h"
20 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
21 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
22 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
23 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
24 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
25 #include "llvm/IR/DataLayout.h"
26 #include "llvm/IR/Mangler.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/Support/FileSystem.h"
29 #include "llvm/Support/Host.h"
30 #include "llvm/Support/ManagedStatic.h"
31 #include "llvm/Support/Path.h"
32 #include "llvm/Support/TargetSelect.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include "llvm/Target/TargetMachine.h"
36 using namespace clang
;
37 using namespace clang::driver
;
39 // This function isn't referenced outside its translation unit, but it
40 // can't use the "static" keyword because its address is used for
41 // GetMainExecutable (since some platforms don't support taking the
42 // address of main, and some platforms can't implement GetMainExecutable
43 // without being given the address of a function in the main executable).
44 std::string
GetExecutablePath(const char *Argv0
, void *MainAddr
) {
45 return llvm::sys::fs::getMainExecutable(Argv0
, MainAddr
);
54 std::unique_ptr
<TargetMachine
> TM
;
56 MangleAndInterner Mangle
{ES
, DL
};
57 JITDylib
&MainJD
{ES
.createBareJITDylib("<main>")};
58 RTDyldObjectLinkingLayer ObjectLayer
{ES
, createMemMgr
};
59 IRCompileLayer CompileLayer
{ES
, ObjectLayer
,
60 std::make_unique
<SimpleCompiler
>(*TM
)};
62 static std::unique_ptr
<SectionMemoryManager
> createMemMgr() {
63 return std::make_unique
<SectionMemoryManager
>();
67 std::unique_ptr
<TargetMachine
> TM
, DataLayout DL
,
68 std::unique_ptr
<DynamicLibrarySearchGenerator
> ProcessSymbolsGenerator
)
69 : TM(std::move(TM
)), DL(std::move(DL
)) {
70 llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
71 MainJD
.addGenerator(std::move(ProcessSymbolsGenerator
));
76 if (auto Err
= ES
.endSession())
77 ES
.reportError(std::move(Err
));
80 static Expected
<std::unique_ptr
<SimpleJIT
>> Create() {
81 auto JTMB
= JITTargetMachineBuilder::detectHost();
83 return JTMB
.takeError();
85 auto TM
= JTMB
->createTargetMachine();
87 return TM
.takeError();
89 auto DL
= (*TM
)->createDataLayout();
91 auto ProcessSymbolsGenerator
=
92 DynamicLibrarySearchGenerator::GetForCurrentProcess(
93 DL
.getGlobalPrefix());
95 if (!ProcessSymbolsGenerator
)
96 return ProcessSymbolsGenerator
.takeError();
98 return std::unique_ptr
<SimpleJIT
>(new SimpleJIT(
99 std::move(*TM
), std::move(DL
), std::move(*ProcessSymbolsGenerator
)));
102 const TargetMachine
&getTargetMachine() const { return *TM
; }
104 Error
addModule(ThreadSafeModule M
) {
105 return CompileLayer
.add(MainJD
, std::move(M
));
108 Expected
<JITEvaluatedSymbol
> findSymbol(const StringRef
&Name
) {
109 return ES
.lookup({&MainJD
}, Mangle(Name
));
112 Expected
<JITTargetAddress
> getSymbolAddress(const StringRef
&Name
) {
113 auto Sym
= findSymbol(Name
);
115 return Sym
.takeError();
116 return Sym
->getAddress();
120 } // end namespace orc
121 } // end namespace llvm
123 llvm::ExitOnError ExitOnErr
;
125 int main(int argc
, const char **argv
) {
126 // This just needs to be some symbol in the binary; C++ doesn't
127 // allow taking the address of ::main however.
128 void *MainAddr
= (void*) (intptr_t) GetExecutablePath
;
129 std::string Path
= GetExecutablePath(argv
[0], MainAddr
);
130 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
131 TextDiagnosticPrinter
*DiagClient
=
132 new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts
);
134 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID(new DiagnosticIDs());
135 DiagnosticsEngine
Diags(DiagID
, &*DiagOpts
, DiagClient
);
137 const std::string TripleStr
= llvm::sys::getProcessTriple();
138 llvm::Triple
T(TripleStr
);
140 // Use ELF on Windows-32 and MingW for now.
141 #ifndef CLANG_INTERPRETER_COFF_FORMAT
142 if (T
.isOSBinFormatCOFF())
143 T
.setObjectFormat(llvm::Triple::ELF
);
146 ExitOnErr
.setBanner("clang interpreter");
148 Driver
TheDriver(Path
, T
.str(), Diags
);
149 TheDriver
.setTitle("clang interpreter");
150 TheDriver
.setCheckInputsExist(false);
152 // FIXME: This is a hack to try to force the driver to do something we can
153 // recognize. We need to extend the driver library to support this use model
154 // (basically, exactly one input, and the operation mode is hard wired).
155 SmallVector
<const char *, 16> Args(argv
, argv
+ argc
);
156 Args
.push_back("-fsyntax-only");
157 std::unique_ptr
<Compilation
> C(TheDriver
.BuildCompilation(Args
));
161 // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate.
163 // We expect to get back exactly one command job, if we didn't something
164 // failed. Extract that job from the compilation.
165 const driver::JobList
&Jobs
= C
->getJobs();
166 if (Jobs
.size() != 1 || !isa
<driver::Command
>(*Jobs
.begin())) {
167 SmallString
<256> Msg
;
168 llvm::raw_svector_ostream
OS(Msg
);
169 Jobs
.Print(OS
, "; ", true);
170 Diags
.Report(diag::err_fe_expected_compiler_job
) << OS
.str();
174 const driver::Command
&Cmd
= cast
<driver::Command
>(*Jobs
.begin());
175 if (llvm::StringRef(Cmd
.getCreator().getName()) != "clang") {
176 Diags
.Report(diag::err_fe_expected_clang_command
);
180 // Initialize a compiler invocation object from the clang (-cc1) arguments.
181 const llvm::opt::ArgStringList
&CCArgs
= Cmd
.getArguments();
182 std::unique_ptr
<CompilerInvocation
> CI(new CompilerInvocation
);
183 CompilerInvocation::CreateFromArgs(*CI
, CCArgs
, Diags
);
185 // Show the invocation, with -v.
186 if (CI
->getHeaderSearchOpts().Verbose
) {
187 llvm::errs() << "clang invocation:\n";
188 Jobs
.Print(llvm::errs(), "\n", true);
189 llvm::errs() << "\n";
192 // FIXME: This is copied from cc1_main.cpp; simplify and eliminate.
194 // Create a compiler instance to handle the actual work.
195 CompilerInstance Clang
;
196 Clang
.setInvocation(std::move(CI
));
198 // Create the compilers actual diagnostics engine.
199 Clang
.createDiagnostics();
200 if (!Clang
.hasDiagnostics())
203 // Infer the builtin include path if unspecified.
204 if (Clang
.getHeaderSearchOpts().UseBuiltinIncludes
&&
205 Clang
.getHeaderSearchOpts().ResourceDir
.empty())
206 Clang
.getHeaderSearchOpts().ResourceDir
=
207 CompilerInvocation::GetResourcesPath(argv
[0], MainAddr
);
209 // Create and execute the frontend to generate an LLVM bitcode module.
210 std::unique_ptr
<CodeGenAction
> Act(new EmitLLVMOnlyAction());
211 if (!Clang
.ExecuteAction(*Act
))
214 llvm::InitializeNativeTarget();
215 llvm::InitializeNativeTargetAsmPrinter();
218 std::unique_ptr
<llvm::LLVMContext
> Ctx(Act
->takeLLVMContext());
219 std::unique_ptr
<llvm::Module
> Module
= Act
->takeModule();
222 auto J
= ExitOnErr(llvm::orc::SimpleJIT::Create());
224 ExitOnErr(J
->addModule(
225 llvm::orc::ThreadSafeModule(std::move(Module
), std::move(Ctx
))));
226 auto Main
= (int (*)(...))ExitOnErr(J
->getSymbolAddress("main"));
231 llvm::llvm_shutdown();