CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
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 * Copyright (C) 2019 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#include <cppad/cg/model/llvm/llvm_base_model_library_processor.hpp>
20
21namespace CppAD {
22namespace cg {
23
29template<class Base>
30class LlvmModelLibraryProcessor : public LlvmBaseModelLibraryProcessor<Base> {
31protected:
32 const std::string _version;
33 std::vector<std::string> _includePaths;
34 std::unique_ptr<llvm::Linker> _linker;
35 std::unique_ptr<llvm::LLVMContext> _context;
36public:
37
43 LlvmBaseModelLibraryProcessor<Base>(modelLibraryHelper),
44 _version("3.4") {
45 }
46
47 virtual ~LlvmModelLibraryProcessor() = default;
48
52 inline const std::string& getVersion() const {
53 return _version;
54 }
55
56 inline void setIncludePaths(const std::vector<std::string>& includePaths) {
57 _includePaths = includePaths;
58 }
59
60 inline const std::vector<std::string>& getIncludePaths() const {
61 return _includePaths;
62 }
63
64 std::unique_ptr<LlvmModelLibrary<Base>> create() {
65 ClangCompiler<Base> clang;
66 return create(clang);
67 }
68
69 std::unique_ptr<LlvmModelLibrary<Base>> create(ClangCompiler<Base>& clang) {
70 using namespace llvm;
71
72 // backup output format so that it can be restored
73 OStreamConfigRestore coutb(std::cout);
74
75 _linker.release();
76
77 std::unique_ptr<LlvmModelLibrary<Base>> lib;
78
79 this->modelLibraryHelper_->startingJob("", JobTimer::JIT_MODEL_LIBRARY);
80
81 try {
85 const std::set<std::string>& bcFiles = this->createBitCode(clang, "3.4");
86
90 llvm::InitializeAllTargets();
91 llvm::InitializeAllAsmPrinters();
92
93 _context.reset(new llvm::LLVMContext());
94
95 for (const std::string& itbc : bcFiles) {
96 // load bitcode file
97 OwningPtr<MemoryBuffer> buffer;
98
99 error_code ec = MemoryBuffer::getFile(itbc, buffer);
100 if (buffer.get() == nullptr)
101 throw CGException(ec.message());
102
103 // create the module
104 std::string errMsg;
105 Module* module = llvm::ParseBitcodeFile(buffer.get(), *_context.get(), &errMsg);
106 if(module == nullptr)
107 throw CGException("Failed to create LLVM bitcode: ", errMsg);
108
109 // link modules together
110 if (_linker.get() == nullptr) {
111 _linker.reset(new llvm::Linker(module)); // module not destroyed
112 } else {
113 if (_linker->linkInModule(module, &errMsg)) { // module destroyed
114 throw CGException(errMsg);
115 }
116 }
117 }
118
119 llvm::InitializeNativeTarget();
120
121 // voila
122 lib.reset(new LlvmModelLibrary3_4<Base>(_linker->getModule(), _context.release()));
123
124 } catch (...) {
125 clang.cleanup();
126 throw;
127 }
128 clang.cleanup();
129
130 this->modelLibraryHelper_->finishedJob();
131
132 return lib;
133 }
134
135 static inline std::unique_ptr<LlvmModelLibrary<Base>> create(ModelLibraryCSourceGen<Base>& modelLibraryHelper) {
136 LlvmModelLibraryProcessor<Base> p(modelLibraryHelper);
137 return p.create();
138 }
139
140protected:
141#if 0
142
146 static void createnPrintModule() {
147 using namespace llvm;
148 using namespace clang;
149
153 std::string source;
154 std::cin >> source;
155
156 static const char* argv [] = {"program", "-Wall", "-x", "c", "string-input"};
157 static const int argc = sizeof (argv) / sizeof (argv[0]);
158
159 IntrusiveRefCntPtr<DiagnosticOptions> diagOpts = new DiagnosticOptions();
160 TextDiagnosticPrinter *diagClient = new TextDiagnosticPrinter(llvm::errs(), &*diagOpts); // will be owned by diags
161 IntrusiveRefCntPtr<DiagnosticIDs> diagID(new DiagnosticIDs());
162 IntrusiveRefCntPtr<DiagnosticsEngine> diags(new DiagnosticsEngine(diagID, &*diagOpts, diagClient));
163
164 ArrayRef<const char *> args(argv + 1, // skip program name
165 argc - 1);
166 std::unique_ptr<CompilerInvocation> invocation(createInvocationFromCommandLine(args, diags));
167 if (invocation.get() == nullptr)
168 throw CGException("Failed to create compiler invocation");
169 CompilerInvocation::setLangDefaults(*invocation->getLangOpts(), IK_C,
170 LangStandard::lang_unspecified);
171 invocation->getFrontendOpts().DisableFree = false; // make sure we free memory (by default it does not)
172
173 // Create a compiler instance to handle the actual work.
174 CompilerInstance compiler;
175 compiler.setInvocation(invocation.release());
176
177 // Create the compilers actual diagnostics engine.
178 compiler.createDiagnostics();
179 if (!compiler.hasDiagnostics())
180 throw CGException("No diagnostics");
181
182 // Create memory buffer with source text
183 llvm::MemoryBuffer * buffer = llvm::MemoryBuffer::getMemBufferCopy(source, "SIMPLE_BUFFER");
184 if (buffer == nullptr)
185 throw CGException("Failed to create memory buffer");
186
187 // Remap auxiliary name "string-input" to memory buffer
188 PreprocessorOptions& po = compiler.getInvocation().getPreprocessorOpts();
189 po.addRemappedFile("string-input", buffer);
190
191 HeaderSearchOptions& hso = compiler.getInvocation().getHeaderSearchOpts();
192 for (size_t s = 0; s < _includePaths.size(); s++)
193 hso.AddPath(llvm::StringRef(_includePaths[s]), clang::frontend::Angled, true, false);
194
195 // Create and execute the frontend to generate an LLVM bitcode module.
196 OwningPtr<CodeGenAction> action(new clang::EmitLLVMOnlyAction(_context.get()));
197
198 if (!compiler.ExecuteAction(*action))
199 throw CGException("Failed to emit LLVM bitcode");
200
201 llvm::Module* module = action->takeModule();
202 if (module == nullptr)
203 throw CGException("No module");
204
208 //std::cout << *module;
209 raw_fd_ostream os(STDOUT_FILENO, true);
210 module->print(os);
211 delete module;
212 }
213#endif
214};
215
216} // END cg namespace
217} // END CppAD namespace
218
219#endif
const std::set< std::string > & createBitCode(ClangCompiler< Base > &clang, const std::string &version)
std::unique_ptr< LlvmModelLibrary< Base > > create(ClangCompiler< Base > &clang)
LlvmModelLibraryProcessor(ModelLibraryCSourceGen< Base > &modelLibraryHelper)