CppADCodeGen  2.3.0
A C++ Algorithmic Differentiation Package with Source Code Generation
llvm_model_library_processor.hpp
1 #ifndef CPPAD_CG_LLVM_MODEL_LIBRARY_PROCESSOR_INCLUDED
2 #define CPPAD_CG_LLVM_MODEL_LIBRARY_PROCESSOR_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2014 Ciengis
6  *
7  * CppADCodeGen is distributed under multiple licenses:
8  *
9  * - Eclipse Public License Version 1.0 (EPL1), and
10  * - GNU General Public License Version 3 (GPL3).
11  *
12  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14  * ----------------------------------------------------------------------------
15  * Author: Joao Leal
16  */
17 
18 #include <cppad/cg/model/llvm/llvm_base_model_library_processor.hpp>
19 
20 namespace CppAD {
21 namespace cg {
22 
28 template<class Base>
29 class LlvmModelLibraryProcessor : public LlvmBaseModelLibraryProcessor<Base> {
30 protected:
31  std::vector<std::string> _includePaths;
32  std::unique_ptr<llvm::Linker> _linker;
33  std::unique_ptr<llvm::LLVMContext> _context;
34 public:
35 
41  LlvmBaseModelLibraryProcessor<Base>(modelLibraryHelper) {
42  }
43 
44  virtual ~LlvmModelLibraryProcessor() {
45  }
46 
47  inline void setIncludePaths(const std::vector<std::string>& includePaths) {
48  _includePaths = includePaths;
49  }
50 
51  inline const std::vector<std::string>& getIncludePaths() const {
52  return _includePaths;
53  }
54 
55  std::unique_ptr<LlvmModelLibrary<Base>> create() {
56  ClangCompiler<Base> clang;
57  return create(clang);
58  }
59 
60  std::unique_ptr<LlvmModelLibrary<Base>> create(ClangCompiler<Base>& clang) {
61  using namespace llvm;
62 
63  // backup output format so that it can be restored
64  OStreamConfigRestore coutb(std::cout);
65 
66  _linker.release();
67 
68  std::unique_ptr<LlvmModelLibrary<Base>> lib;
69 
70  this->modelLibraryHelper_->startingJob("", JobTimer::JIT_MODEL_LIBRARY);
71 
72  try {
76  const std::set<std::string>& bcFiles = this->createBitCode(clang, "3.4");
77 
81  llvm::InitializeAllTargets();
82  llvm::InitializeAllAsmPrinters();
83 
84  _context.reset(new llvm::LLVMContext());
85 
86  for (const std::string& itbc : bcFiles) {
87  // load bitcode file
88  OwningPtr<MemoryBuffer> buffer;
89 
90  error_code ec = MemoryBuffer::getFile(itbc, buffer);
91  if (buffer.get() == nullptr)
92  throw CGException(ec.message());
93 
94  // create the module
95  std::string errMsg;
96  Module* module = llvm::ParseBitcodeFile(buffer.get(), *_context.get(), &errMsg);
97  if(module == nullptr)
98  throw CGException("Failed to create LLVM bitcode: ", errMsg);
99 
100  // link modules together
101  if (_linker.get() == nullptr) {
102  _linker.reset(new llvm::Linker(module)); // module not destroyed
103  } else {
104  if (_linker->linkInModule(module, &errMsg)) { // module destroyed
105  throw CGException(errMsg);
106  }
107  }
108  }
109 
110  llvm::InitializeNativeTarget();
111 
112  // voila
113  lib.reset(new LlvmModelLibrary3_4<Base>(_linker->getModule(), _context.release()));
114 
115  } catch (...) {
116  clang.cleanup();
117  throw;
118  }
119  clang.cleanup();
120 
121  this->modelLibraryHelper_->finishedJob();
122 
123  return lib;
124  }
125 
126  static inline std::unique_ptr<LlvmModelLibrary<Base>> create(ModelLibraryCSourceGen<Base>& modelLibraryHelper) {
127  LlvmModelLibraryProcessor<Base> p(modelLibraryHelper);
128  return p.create();
129  }
130 
131 protected:
132 #if 0
133 
137  static void createnPrintModule() {
138  using namespace llvm;
139  using namespace clang;
140 
144  std::string source;
145  std::cin >> source;
146 
147  static const char* argv [] = {"program", "-Wall", "-x", "c", "string-input"};
148  static const int argc = sizeof (argv) / sizeof (argv[0]);
149 
150  IntrusiveRefCntPtr<DiagnosticOptions> diagOpts = new DiagnosticOptions();
151  TextDiagnosticPrinter *diagClient = new TextDiagnosticPrinter(llvm::errs(), &*diagOpts); // will be owned by diags
152  IntrusiveRefCntPtr<DiagnosticIDs> diagID(new DiagnosticIDs());
153  IntrusiveRefCntPtr<DiagnosticsEngine> diags(new DiagnosticsEngine(diagID, &*diagOpts, diagClient));
154 
155  ArrayRef<const char *> args(argv + 1, // skip program name
156  argc - 1);
157  std::unique_ptr<CompilerInvocation> invocation(createInvocationFromCommandLine(args, diags));
158  if (invocation.get() == nullptr)
159  throw CGException("Failed to create compiler invocation");
160  CompilerInvocation::setLangDefaults(*invocation->getLangOpts(), IK_C,
161  LangStandard::lang_unspecified);
162  invocation->getFrontendOpts().DisableFree = false; // make sure we free memory (by default it does not)
163 
164  // Create a compiler instance to handle the actual work.
165  CompilerInstance compiler;
166  compiler.setInvocation(invocation.release());
167 
168  // Create the compilers actual diagnostics engine.
169  compiler.createDiagnostics();
170  if (!compiler.hasDiagnostics())
171  throw CGException("No diagnostics");
172 
173  // Create memory buffer with source text
174  llvm::MemoryBuffer * buffer = llvm::MemoryBuffer::getMemBufferCopy(source, "SIMPLE_BUFFER");
175  if (buffer == nullptr)
176  throw CGException("Failed to create memory buffer");
177 
178  // Remap auxiliary name "string-input" to memory buffer
179  PreprocessorOptions& po = compiler.getInvocation().getPreprocessorOpts();
180  po.addRemappedFile("string-input", buffer);
181 
182  HeaderSearchOptions& hso = compiler.getInvocation().getHeaderSearchOpts();
183  for (size_t s = 0; s < _includePaths.size(); s++)
184  hso.AddPath(llvm::StringRef(_includePaths[s]), clang::frontend::Angled, true, false);
185 
186  // Create and execute the frontend to generate an LLVM bitcode module.
187  OwningPtr<CodeGenAction> action(new clang::EmitLLVMOnlyAction(_context.get()));
188 
189  if (!compiler.ExecuteAction(*action))
190  throw CGException("Failed to emit LLVM bitcode");
191 
192  llvm::Module* module = action->takeModule();
193  if (module == nullptr)
194  throw CGException("No module");
195 
199  //std::cout << *module;
200  raw_fd_ostream os(STDOUT_FILENO, true);
201  module->print(os);
202  delete module;
203  }
204 #endif
205 };
206 
207 } // END cg namespace
208 } // END CppAD namespace
209 
210 #endif
std::unique_ptr< LlvmModelLibrary< Base > > create(ClangCompiler< Base > &clang)
const std::set< std::string > & createBitCode(ClangCompiler< Base > &clang, const std::string &version)
LlvmModelLibraryProcessor(ModelLibraryCSourceGen< Base > &modelLibraryHelper)