1 #ifndef CPPAD_CG_LLVM_MODEL_LIBRARY_PROCESSOR_INCLUDED 2 #define CPPAD_CG_LLVM_MODEL_LIBRARY_PROCESSOR_INCLUDED 18 #include <cppad/cg/model/llvm/llvm_base_model_library_processor.hpp> 29 class LlvmModelLibraryProcessor :
public LlvmBaseModelLibraryProcessor<Base> {
31 std::vector<std::string> _includePaths;
32 std::shared_ptr<llvm::LLVMContext> _context;
33 std::unique_ptr<llvm::Linker> _linker;
34 std::unique_ptr<llvm::Module> _module;
53 _includePaths = includePaths;
67 std::unique_ptr<LlvmModelLibrary<Base>>
create() {
69 llvm::sys::Path clangPath = llvm::sys::Program::FindProgramByName(
"clang");
73 args.push_back(clangPath.c_str());
74 args.push_back(inputPath.c_str());
76 args.push_back(
"curl");
80 clang::TextDiagnosticPrinter *DiagClient =
new clang::TextDiagnosticPrinter(llvm::errs(), clang::DiagnosticOptions());
81 clang::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
new clang::DiagnosticIDs());
82 clang::DiagnosticsEngine Diags(DiagID, DiagClient);
85 clang::driver::Driver TheDriver(args[0], llvm::sys::getDefaultTargetTriple(), outputPath,
true, Diags);
90 _linker.reset(
nullptr);
92 this->modelLibraryHelper_->startingJob(
"", JobTimer::JIT_MODEL_LIBRARY);
94 llvm::InitializeAllTargetMCs();
95 llvm::InitializeAllTargets();
96 llvm::InitializeAllAsmPrinters();
98 _context.reset(
new llvm::LLVMContext());
100 const std::map<std::string, ModelCSourceGen<Base>*>& models = this->modelLibraryHelper_->getModels();
101 for (
const auto& p : models) {
102 const std::map<std::string, std::string>& modelSources = this->getSources(*p.second);
103 createLlvmModules(modelSources);
106 const std::map<std::string, std::string>& sources = this->getLibrarySources();
107 createLlvmModules(sources);
109 const std::map<std::string, std::string>& customSource = this->modelLibraryHelper_->getCustomSources();
110 createLlvmModules(customSource);
112 llvm::InitializeNativeTarget();
116 this->modelLibraryHelper_->finishedJob();
127 using namespace llvm;
134 std::unique_ptr<LlvmModelLibrary<Base>> lib;
136 this->modelLibraryHelper_->startingJob(
"", JobTimer::JIT_MODEL_LIBRARY);
142 const std::set<std::string>& bcFiles = this->
createBitCode(clang,
"3.8");
147 llvm::InitializeAllTargets();
148 llvm::InitializeAllAsmPrinters();
150 _context.reset(
new llvm::LLVMContext());
152 std::unique_ptr<Module> linkerModule;
154 for (
const std::string& itbc : bcFiles) {
157 ErrorOr<std::unique_ptr<MemoryBuffer>> buffer = MemoryBuffer::getFile(itbc);
158 if (buffer.get() ==
nullptr) {
163 ErrorOr<std::unique_ptr<Module>> module = llvm::parseBitcodeFile(buffer.get()->getMemBufferRef(), *_context.get());
164 if(module.get() ==
nullptr) {
169 if (_linker.get() ==
nullptr) {
170 linkerModule.reset(module.get().release());
171 _linker.reset(
new llvm::Linker(*linkerModule));
173 if (_linker->linkInModule(std::move(module.get()))) {
179 llvm::InitializeNativeTarget();
190 this->modelLibraryHelper_->finishedJob();
202 virtual void createLlvmModules(
const std::map<std::string, std::string>& sources) {
203 for (
const auto& p : sources) {
204 createLlvmModule(p.first, p.second);
208 virtual void createLlvmModule(
const std::string& filename,
209 const std::string& source) {
210 using namespace llvm;
211 using namespace clang;
213 ArrayRef<StringRef> paths;
214 llvm::sys::findProgramByName(
"clang", paths);
216 static const char* argv [] = {
"program",
"-Wall",
"-x",
"c",
"string-input"};
217 static const int argc =
sizeof (argv) /
sizeof (argv[0]);
219 IntrusiveRefCntPtr<DiagnosticOptions> diagOpts =
new DiagnosticOptions();
220 TextDiagnosticPrinter* diagClient =
new TextDiagnosticPrinter(llvm::errs(), &*diagOpts);
221 IntrusiveRefCntPtr<DiagnosticIDs> diagID(
new DiagnosticIDs());
222 IntrusiveRefCntPtr<DiagnosticsEngine> diags(
new DiagnosticsEngine(diagID, &*diagOpts, diagClient));
224 ArrayRef<const char*> args(argv + 1,
226 std::unique_ptr<CompilerInvocation> invocation(createInvocationFromCommandLine(args, diags));
227 if (invocation.get() ==
nullptr)
228 throw CGException(
"Failed to create compiler invocation");
229 CompilerInvocation::setLangDefaults(*invocation->getLangOpts(), IK_C,
230 LangStandard::lang_unspecified);
231 invocation->getFrontendOpts().DisableFree =
false;
234 CompilerInstance compiler;
235 compiler.setInvocation(invocation.release());
239 compiler.createDiagnostics();
240 if (!compiler.hasDiagnostics())
244 std::unique_ptr<llvm::MemoryBuffer> buffer = llvm::MemoryBuffer::getMemBufferCopy(source,
"SIMPLE_BUFFER");
245 if (buffer.get() ==
nullptr)
246 throw CGException(
"Failed to create memory buffer");
249 PreprocessorOptions& po = compiler.getInvocation().getPreprocessorOpts();
250 po.addRemappedFile(
"string-input", buffer.release());
252 HeaderSearchOptions& hso = compiler.getInvocation().getHeaderSearchOpts();
253 std::string iClangHeaders = this->findInternalClangCHeaders(
"3.8", hso.ResourceDir);
254 if(!iClangHeaders.empty()) {
255 hso.AddPath(llvm::StringRef(iClangHeaders), clang::frontend::Angled,
false,
false);
258 for (
size_t s = 0; s < _includePaths.size(); s++)
259 hso.AddPath(llvm::StringRef(_includePaths[s]), clang::frontend::Angled,
false,
false);
262 clang::EmitLLVMOnlyAction action(_context.get());
263 if (!compiler.ExecuteAction(action))
266 std::unique_ptr<llvm::Module> module = action.takeModule();
267 if (module.get() ==
nullptr)
270 if (_linker.get() ==
nullptr) {
271 _module.reset(module.release());
272 _linker.reset(
new llvm::Linker(*_module.get()));
274 if (_linker->linkInModule(std::move(module))) {
std::unique_ptr< LlvmModelLibrary< Base > > create()
std::unique_ptr< LlvmModelLibrary< Base > > create(ClangCompiler< Base > &clang)
const std::vector< std::string > & getIncludePaths() const
const std::set< std::string > & createBitCode(ClangCompiler< Base > &clang, const std::string &version)
void setIncludePaths(const std::vector< std::string > &includePaths)
LlvmModelLibraryProcessor(ModelLibraryCSourceGen< Base > &librarySourceGen)