1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
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/IRCompileLayer.h" |
22 | #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" |
23 | #include "llvm/ExecutionEngine/SectionMemoryManager.h" |
24 | #include "llvm/IR/DataLayout.h" |
25 | #include "llvm/IR/Mangler.h" |
26 | #include "llvm/IR/Module.h" |
27 | #include "llvm/Support/FileSystem.h" |
28 | #include "llvm/Support/Host.h" |
29 | #include "llvm/Support/ManagedStatic.h" |
30 | #include "llvm/Support/Path.h" |
31 | #include "llvm/Support/TargetSelect.h" |
32 | #include "llvm/Support/raw_ostream.h" |
33 | #include "llvm/Target/TargetMachine.h" |
34 | |
35 | using namespace clang; |
36 | using namespace clang::driver; |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | std::string GetExecutablePath(const char *Argv0, void *MainAddr) { |
44 | return llvm::sys::fs::getMainExecutable(Argv0, MainAddr); |
45 | } |
46 | |
47 | namespace llvm { |
48 | namespace orc { |
49 | |
50 | class SimpleJIT { |
51 | private: |
52 | ExecutionSession ES; |
53 | std::shared_ptr<SymbolResolver> Resolver; |
54 | std::unique_ptr<TargetMachine> TM; |
55 | const DataLayout DL; |
56 | LegacyRTDyldObjectLinkingLayer ObjectLayer; |
57 | LegacyIRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer; |
58 | |
59 | public: |
60 | SimpleJIT() |
61 | : Resolver(createLegacyLookupResolver( |
62 | ES, |
63 | [this](const std::string &Name) -> JITSymbol { |
64 | if (auto Sym = CompileLayer.findSymbol(Name, false)) |
65 | return Sym; |
66 | else if (auto Err = Sym.takeError()) |
67 | return std::move(Err); |
68 | if (auto SymAddr = |
69 | RTDyldMemoryManager::getSymbolAddressInProcess(Name)) |
70 | return JITSymbol(SymAddr, JITSymbolFlags::Exported); |
71 | return nullptr; |
72 | }, |
73 | [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), |
74 | TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), |
75 | ObjectLayer(ES, |
76 | [this](VModuleKey) { |
77 | return LegacyRTDyldObjectLinkingLayer::Resources{ |
78 | std::make_shared<SectionMemoryManager>(), Resolver}; |
79 | }), |
80 | CompileLayer(ObjectLayer, SimpleCompiler(*TM)) { |
81 | llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); |
82 | } |
83 | |
84 | const TargetMachine &getTargetMachine() const { return *TM; } |
85 | |
86 | VModuleKey addModule(std::unique_ptr<Module> M) { |
87 | |
88 | auto K = ES.allocateVModule(); |
89 | cantFail(CompileLayer.addModule(K, std::move(M))); |
90 | return K; |
91 | } |
92 | |
93 | JITSymbol findSymbol(const StringRef &Name) { |
94 | std::string MangledName; |
95 | raw_string_ostream MangledNameStream(MangledName); |
96 | Mangler::getNameWithPrefix(MangledNameStream, Name, DL); |
97 | return CompileLayer.findSymbol(MangledNameStream.str(), true); |
98 | } |
99 | |
100 | JITTargetAddress getSymbolAddress(const StringRef &Name) { |
101 | return cantFail(findSymbol(Name).getAddress()); |
102 | } |
103 | |
104 | void removeModule(VModuleKey K) { |
105 | cantFail(CompileLayer.removeModule(K)); |
106 | } |
107 | }; |
108 | |
109 | } |
110 | } |
111 | |
112 | int main(int argc, const char **argv) { |
113 | |
114 | |
115 | void *MainAddr = (void*) (intptr_t) GetExecutablePath; |
116 | std::string Path = GetExecutablePath(argv[0], MainAddr); |
117 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); |
118 | TextDiagnosticPrinter *DiagClient = |
119 | new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); |
120 | |
121 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
122 | DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); |
123 | |
124 | const std::string TripleStr = llvm::sys::getProcessTriple(); |
125 | llvm::Triple T(TripleStr); |
126 | |
127 | |
128 | #ifndef CLANG_INTERPRETER_COFF_FORMAT |
129 | if (T.isOSBinFormatCOFF()) |
130 | T.setObjectFormat(llvm::Triple::ELF); |
131 | #endif |
132 | |
133 | Driver TheDriver(Path, T.str(), Diags); |
134 | TheDriver.setTitle("clang interpreter"); |
135 | TheDriver.setCheckInputsExist(false); |
136 | |
137 | |
138 | |
139 | |
140 | SmallVector<const char *, 16> Args(argv, argv + argc); |
141 | Args.push_back("-fsyntax-only"); |
142 | std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args)); |
143 | if (!C) |
144 | return 0; |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | const driver::JobList &Jobs = C->getJobs(); |
151 | if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) { |
152 | SmallString<256> Msg; |
153 | llvm::raw_svector_ostream OS(Msg); |
154 | Jobs.Print(OS, "; ", true); |
155 | Diags.Report(diag::err_fe_expected_compiler_job) << OS.str(); |
156 | return 1; |
157 | } |
158 | |
159 | const driver::Command &Cmd = cast<driver::Command>(*Jobs.begin()); |
160 | if (llvm::StringRef(Cmd.getCreator().getName()) != "clang") { |
161 | Diags.Report(diag::err_fe_expected_clang_command); |
162 | return 1; |
163 | } |
164 | |
165 | |
166 | const llvm::opt::ArgStringList &CCArgs = Cmd.getArguments(); |
167 | std::unique_ptr<CompilerInvocation> CI(new CompilerInvocation); |
168 | CompilerInvocation::CreateFromArgs(*CI, |
169 | const_cast<const char **>(CCArgs.data()), |
170 | const_cast<const char **>(CCArgs.data()) + |
171 | CCArgs.size(), |
172 | Diags); |
173 | |
174 | |
175 | if (CI->getHeaderSearchOpts().Verbose) { |
176 | llvm::errs() << "clang invocation:\n"; |
177 | Jobs.Print(llvm::errs(), "\n", true); |
178 | llvm::errs() << "\n"; |
179 | } |
180 | |
181 | |
182 | |
183 | |
184 | CompilerInstance Clang; |
185 | Clang.setInvocation(std::move(CI)); |
186 | |
187 | |
188 | Clang.createDiagnostics(); |
189 | if (!Clang.hasDiagnostics()) |
190 | return 1; |
191 | |
192 | |
193 | if (Clang.getHeaderSearchOpts().UseBuiltinIncludes && |
194 | Clang.getHeaderSearchOpts().ResourceDir.empty()) |
195 | Clang.getHeaderSearchOpts().ResourceDir = |
196 | CompilerInvocation::GetResourcesPath(argv[0], MainAddr); |
197 | |
198 | |
199 | std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction()); |
200 | if (!Clang.ExecuteAction(*Act)) |
201 | return 1; |
202 | |
203 | llvm::InitializeNativeTarget(); |
204 | llvm::InitializeNativeTargetAsmPrinter(); |
205 | |
206 | int Res = 255; |
207 | std::unique_ptr<llvm::Module> Module = Act->takeModule(); |
208 | |
209 | if (Module) { |
210 | llvm::orc::SimpleJIT J; |
211 | auto H = J.addModule(std::move(Module)); |
212 | auto Main = (int(*)(...))J.getSymbolAddress("main"); |
213 | Res = Main(); |
214 | J.removeModule(H); |
215 | } |
216 | |
217 | |
218 | llvm::llvm_shutdown(); |
219 | |
220 | return Res; |
221 | } |
222 | |