main.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. //===-- examples/clang-interpreter/main.cpp - Clang C Interpreter Example -===//
  2. //
  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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "clang/Basic/DiagnosticOptions.h"
  9. #include "clang/CodeGen/CodeGenAction.h"
  10. #include "clang/Driver/Compilation.h"
  11. #include "clang/Driver/Driver.h"
  12. #include "clang/Driver/Tool.h"
  13. #include "clang/Frontend/CompilerInstance.h"
  14. #include "clang/Frontend/CompilerInvocation.h"
  15. #include "clang/Frontend/FrontendDiagnostic.h"
  16. #include "clang/Frontend/TextDiagnosticPrinter.h"
  17. #include "llvm/ADT/SmallString.h"
  18. #include "llvm/ExecutionEngine/ExecutionEngine.h"
  19. #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
  20. #include "llvm/ExecutionEngine/Orc/ExecutionUtils.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. using namespace clang;
  35. using namespace clang::driver;
  36. // This function isn't referenced outside its translation unit, but it
  37. // can't use the "static" keyword because its address is used for
  38. // GetMainExecutable (since some platforms don't support taking the
  39. // address of main, and some platforms can't implement GetMainExecutable
  40. // without being given the address of a function in the main executable).
  41. std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
  42. return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
  43. }
  44. namespace llvm {
  45. namespace orc {
  46. class SimpleJIT {
  47. private:
  48. ExecutionSession ES;
  49. std::unique_ptr<TargetMachine> TM;
  50. const DataLayout DL;
  51. MangleAndInterner Mangle{ES, DL};
  52. RTDyldObjectLinkingLayer ObjectLayer{ES, createMemMgr};
  53. IRCompileLayer CompileLayer{ES, ObjectLayer, SimpleCompiler(*TM)};
  54. static std::unique_ptr<SectionMemoryManager> createMemMgr() {
  55. return llvm::make_unique<SectionMemoryManager>();
  56. }
  57. SimpleJIT(
  58. std::unique_ptr<TargetMachine> TM, DataLayout DL,
  59. std::unique_ptr<DynamicLibrarySearchGenerator> ProcessSymbolsGenerator)
  60. : TM(std::move(TM)), DL(std::move(DL)) {
  61. llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
  62. ES.getMainJITDylib().addGenerator(std::move(ProcessSymbolsGenerator));
  63. }
  64. public:
  65. static Expected<std::unique_ptr<SimpleJIT>> Create() {
  66. auto JTMB = JITTargetMachineBuilder::detectHost();
  67. if (!JTMB)
  68. return JTMB.takeError();
  69. auto TM = JTMB->createTargetMachine();
  70. if (!TM)
  71. return TM.takeError();
  72. auto DL = (*TM)->createDataLayout();
  73. auto ProcessSymbolsGenerator =
  74. DynamicLibrarySearchGenerator::GetForCurrentProcess(
  75. DL.getGlobalPrefix());
  76. if (!ProcessSymbolsGenerator)
  77. return ProcessSymbolsGenerator.takeError();
  78. return std::unique_ptr<SimpleJIT>(new SimpleJIT(
  79. std::move(*TM), std::move(DL), std::move(*ProcessSymbolsGenerator)));
  80. }
  81. const TargetMachine &getTargetMachine() const { return *TM; }
  82. Error addModule(ThreadSafeModule M) {
  83. return CompileLayer.add(ES.getMainJITDylib(), std::move(M));
  84. }
  85. Expected<JITEvaluatedSymbol> findSymbol(const StringRef &Name) {
  86. return ES.lookup({&ES.getMainJITDylib()}, Mangle(Name));
  87. }
  88. Expected<JITTargetAddress> getSymbolAddress(const StringRef &Name) {
  89. auto Sym = findSymbol(Name);
  90. if (!Sym)
  91. return Sym.takeError();
  92. return Sym->getAddress();
  93. }
  94. };
  95. } // end namespace orc
  96. } // end namespace llvm
  97. llvm::ExitOnError ExitOnErr;
  98. int main(int argc, const char **argv) {
  99. // This just needs to be some symbol in the binary; C++ doesn't
  100. // allow taking the address of ::main however.
  101. void *MainAddr = (void*) (intptr_t) GetExecutablePath;
  102. std::string Path = GetExecutablePath(argv[0], MainAddr);
  103. IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  104. TextDiagnosticPrinter *DiagClient =
  105. new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
  106. IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  107. DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
  108. const std::string TripleStr = llvm::sys::getProcessTriple();
  109. llvm::Triple T(TripleStr);
  110. // Use ELF on Windows-32 and MingW for now.
  111. #ifndef CLANG_INTERPRETER_COFF_FORMAT
  112. if (T.isOSBinFormatCOFF())
  113. T.setObjectFormat(llvm::Triple::ELF);
  114. #endif
  115. ExitOnErr.setBanner("clang interpreter");
  116. Driver TheDriver(Path, T.str(), Diags);
  117. TheDriver.setTitle("clang interpreter");
  118. TheDriver.setCheckInputsExist(false);
  119. // FIXME: This is a hack to try to force the driver to do something we can
  120. // recognize. We need to extend the driver library to support this use model
  121. // (basically, exactly one input, and the operation mode is hard wired).
  122. SmallVector<const char *, 16> Args(argv, argv + argc);
  123. Args.push_back("-fsyntax-only");
  124. std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args));
  125. if (!C)
  126. return 0;
  127. // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate.
  128. // We expect to get back exactly one command job, if we didn't something
  129. // failed. Extract that job from the compilation.
  130. const driver::JobList &Jobs = C->getJobs();
  131. if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
  132. SmallString<256> Msg;
  133. llvm::raw_svector_ostream OS(Msg);
  134. Jobs.Print(OS, "; ", true);
  135. Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
  136. return 1;
  137. }
  138. const driver::Command &Cmd = cast<driver::Command>(*Jobs.begin());
  139. if (llvm::StringRef(Cmd.getCreator().getName()) != "clang") {
  140. Diags.Report(diag::err_fe_expected_clang_command);
  141. return 1;
  142. }
  143. // Initialize a compiler invocation object from the clang (-cc1) arguments.
  144. const llvm::opt::ArgStringList &CCArgs = Cmd.getArguments();
  145. std::unique_ptr<CompilerInvocation> CI(new CompilerInvocation);
  146. CompilerInvocation::CreateFromArgs(*CI,
  147. const_cast<const char **>(CCArgs.data()),
  148. const_cast<const char **>(CCArgs.data()) +
  149. CCArgs.size(),
  150. Diags);
  151. // Show the invocation, with -v.
  152. if (CI->getHeaderSearchOpts().Verbose) {
  153. llvm::errs() << "clang invocation:\n";
  154. Jobs.Print(llvm::errs(), "\n", true);
  155. llvm::errs() << "\n";
  156. }
  157. // FIXME: This is copied from cc1_main.cpp; simplify and eliminate.
  158. // Create a compiler instance to handle the actual work.
  159. CompilerInstance Clang;
  160. Clang.setInvocation(std::move(CI));
  161. // Create the compilers actual diagnostics engine.
  162. Clang.createDiagnostics();
  163. if (!Clang.hasDiagnostics())
  164. return 1;
  165. // Infer the builtin include path if unspecified.
  166. if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
  167. Clang.getHeaderSearchOpts().ResourceDir.empty())
  168. Clang.getHeaderSearchOpts().ResourceDir =
  169. CompilerInvocation::GetResourcesPath(argv[0], MainAddr);
  170. // Create and execute the frontend to generate an LLVM bitcode module.
  171. std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction());
  172. if (!Clang.ExecuteAction(*Act))
  173. return 1;
  174. llvm::InitializeNativeTarget();
  175. llvm::InitializeNativeTargetAsmPrinter();
  176. int Res = 255;
  177. std::unique_ptr<llvm::LLVMContext> Ctx(Act->takeLLVMContext());
  178. std::unique_ptr<llvm::Module> Module = Act->takeModule();
  179. if (Module) {
  180. auto J = ExitOnErr(llvm::orc::SimpleJIT::Create());
  181. ExitOnErr(J->addModule(
  182. llvm::orc::ThreadSafeModule(std::move(Module), std::move(Ctx))));
  183. auto Main = (int (*)(...))ExitOnErr(J->getSymbolAddress("main"));
  184. Res = Main();
  185. }
  186. // Shutdown.
  187. llvm::llvm_shutdown();
  188. return Res;
  189. }