CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
llvm_base_model_library_processor.hpp
1 #ifndef CPPAD_CG_LLVM_BASE_MODEL_LIBRARY_PROCESSOR_INCLUDED
2 #define CPPAD_CG_LLVM_BASE_MODEL_LIBRARY_PROCESSOR_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2016 Ciengis
6  * Copyright (C) 2018 Joao Leal
7  *
8  * CppADCodeGen is distributed under multiple licenses:
9  *
10  * - Eclipse Public License Version 1.0 (EPL1), and
11  * - GNU General Public License Version 3 (GPL3).
12  *
13  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
14  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
15  * ----------------------------------------------------------------------------
16  * Author: Joao Leal
17  */
18 
19 namespace CppAD {
20 namespace cg {
21 
27 template<class Base>
29 public:
30 
31  inline explicit LlvmBaseModelLibraryProcessor(ModelLibraryCSourceGen<Base>& modelLibraryHelper) :
32  ModelLibraryProcessor<Base>(modelLibraryHelper) {
33  }
34 
35  inline virtual ~LlvmBaseModelLibraryProcessor() = default;
36 
37 protected:
38 
39  static std::string findInternalClangCHeaders(const std::string& version,
40  const std::string& resourceDir) {
41  // check existing paths
42  for (const std::string& path : explode(resourceDir, " ")) {
43  if (system::isFile(system::createPath(path, system::createPath("include", "stddef.h")))) {
44  return ""; // no need to add anything
45  }
46  }
47 
48 #ifdef CPPAD_CG_SYSTEM_LINUX
49  std::string clangHeaders = "/usr/lib/clang/" + version + "/include";
50  if (system::isDirectory(clangHeaders)) {
51  return clangHeaders; // found them
52  }
53 #endif
54 
55  // failed to locate headers (hope they are not needed...)
56  return "";
57  }
58 
59  const std::set<std::string>& createBitCode(ClangCompiler<Base>& clang,
60  const std::string& version) {
61  // backup output format so that it can be restored
62  OStreamConfigRestore coutb(std::cout);
63 
64  if (clang.getVersion() != version) {
65  auto expected = ClangCompiler<Base>::parseVersion(version);
66  auto execVersion = ClangCompiler<Base>::parseVersion(clang.getVersion());
67  bool error = expected.size() > execVersion.size();
68  if (!error) {
69  for (size_t i = 0; i < expected.size(); ++i) {
70  if (expected[i] != execVersion[i]) {
71  error = true;
72  break;
73  }
74  }
75  }
76  if (error) {
77  throw CGException("Expected a clang with version '", version, "' but found version '", clang.getVersion(), "'");
78  }
79  }
80 
81  const std::map<std::string, ModelCSourceGen<Base>*>& models = this->modelLibraryHelper_->getModels();
82  try {
86  for (const auto& p : models) {
87  const std::map<std::string, std::string>& modelSources = this->getSources(*p.second);
88 
89  this->modelLibraryHelper_->startingJob("", JobTimer::COMPILING_FOR_MODEL);
90  clang.generateLLVMBitCode(modelSources, this->modelLibraryHelper_);
91  this->modelLibraryHelper_->finishedJob();
92  }
93 
94  const std::map<std::string, std::string>& sources = this->getLibrarySources();
95  clang.generateLLVMBitCode(sources, this->modelLibraryHelper_);
96 
97  const std::map<std::string, std::string>& customSource = this->modelLibraryHelper_->getCustomSources();
98  clang.generateLLVMBitCode(customSource, this->modelLibraryHelper_);
99  } catch (...) {
100  clang.cleanup();
101  throw;
102  }
103 
104  return clang.getBitCodeFiles();
105  }
106 
107 };
108 
109 } // END cg namespace
110 } // END CppAD namespace
111 
112 #endif
std::string createPath(const std::string &baseFolder, const std::string &file)
const std::set< std::string > & createBitCode(ClangCompiler< Base > &clang, const std::string &version)
bool isDirectory(const std::string &path)
bool isFile(const std::string &path)