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() {
71 _linker.reset(
nullptr);
73 this->modelLibraryHelper_->startingJob(
"", JobTimer::JIT_MODEL_LIBRARY);
75 llvm::InitializeAllTargetMCs();
76 llvm::InitializeAllTargets();
77 llvm::InitializeAllAsmPrinters();
79 _context.reset(
new llvm::LLVMContext());
81 const std::map<std::string, ModelCSourceGen<Base>*>& models = this->modelLibraryHelper_->getModels();
82 for (
const auto& p : models) {
83 const std::map<std::string, std::string>& modelSources = this->getSources(*p.second);
84 createLlvmModules(modelSources);
87 const std::map<std::string, std::string>& sources = this->getLibrarySources();
88 createLlvmModules(sources);
90 const std::map<std::string, std::string>& customSource = this->modelLibraryHelper_->getCustomSources();
91 createLlvmModules(customSource);
93 llvm::InitializeNativeTarget();
97 this->modelLibraryHelper_->finishedJob();
110 using namespace llvm;
117 std::unique_ptr<LlvmModelLibrary<Base>> lib;
119 this->modelLibraryHelper_->startingJob(
"", JobTimer::JIT_MODEL_LIBRARY);
125 const std::set<std::string>& bcFiles = this->
createBitCode(clang,
"4.0");
130 llvm::InitializeAllTargets();
131 llvm::InitializeAllAsmPrinters();
133 _context.reset(
new llvm::LLVMContext());
135 std::unique_ptr<Module> linkerModule;
137 for (
const std::string& itbc : bcFiles) {
140 ErrorOr<std::unique_ptr<MemoryBuffer>> buffer = MemoryBuffer::getFile(itbc);
141 if (buffer.get() ==
nullptr) {
146 Expected<std::unique_ptr<Module>> moduleOrError = llvm::parseBitcodeFile(buffer.get()->getMemBufferRef(), *_context.get());
147 if (!moduleOrError) {
148 std::ostringstream error;
150 handleAllErrors(moduleOrError.takeError(), [&](ErrorInfoBase& eib) {
151 if (nError > 0) error <<
"; ";
152 error << eib.message();
159 if (_linker.get() ==
nullptr) {
160 linkerModule = std::move(moduleOrError.get());
161 _linker.reset(
new llvm::Linker(*linkerModule));
163 if (_linker->linkInModule(std::move(moduleOrError.get()))) {
169 llvm::InitializeNativeTarget();
180 this->modelLibraryHelper_->finishedJob();
192 virtual void createLlvmModules(
const std::map<std::string, std::string>& sources) {
193 for (
const auto& p : sources) {
194 createLlvmModule(p.first, p.second);
198 virtual void createLlvmModule(
const std::string& filename,
199 const std::string& source) {
200 using namespace llvm;
201 using namespace clang;
203 ArrayRef<StringRef> paths;
204 llvm::sys::findProgramByName(
"clang", paths);
206 IntrusiveRefCntPtr<DiagnosticOptions> diagOpts =
new DiagnosticOptions();
207 TextDiagnosticPrinter* diagClient =
new TextDiagnosticPrinter(llvm::errs(), &*diagOpts);
208 IntrusiveRefCntPtr<DiagnosticIDs> diagID(
new DiagnosticIDs());
209 IntrusiveRefCntPtr<DiagnosticsEngine> diags(
new DiagnosticsEngine(diagID, &*diagOpts, diagClient));
211 ArrayRef<const char*> args {
"-Wall",
"-x",
"c",
"string-input"};
212 std::shared_ptr<CompilerInvocation> invocation(createInvocationFromCommandLine(args, diags));
213 if (invocation.get() ==
nullptr)
214 throw CGException(
"Failed to create compiler invocation");
218 CompilerInvocation::setLangDefaults(*invocation->getLangOpts(), IK_C,
219 llvm::Triple(invocation->TargetOpts->Triple),
220 invocation->getPreprocessorOpts(),
221 LangStandard::lang_unspecified);
222 invocation->getFrontendOpts().DisableFree =
false;
225 CompilerInstance compiler;
226 compiler.setInvocation(invocation);
230 compiler.createDiagnostics();
231 if (!compiler.hasDiagnostics())
235 std::unique_ptr<llvm::MemoryBuffer> buffer = llvm::MemoryBuffer::getMemBufferCopy(source,
"SIMPLE_BUFFER");
236 if (buffer.get() ==
nullptr)
237 throw CGException(
"Failed to create memory buffer");
240 PreprocessorOptions& po = compiler.getInvocation().getPreprocessorOpts();
241 po.addRemappedFile(
"string-input", buffer.release());
243 HeaderSearchOptions& hso = compiler.getInvocation().getHeaderSearchOpts();
244 std::string iClangHeaders = this->findInternalClangCHeaders(
"4.0", hso.ResourceDir);
245 if(!iClangHeaders.empty()) {
246 hso.AddPath(llvm::StringRef(iClangHeaders), clang::frontend::Angled,
false,
false);
249 for (
size_t s = 0; s < _includePaths.size(); s++)
250 hso.AddPath(llvm::StringRef(_includePaths[s]), clang::frontend::Angled,
false,
false);
253 clang::EmitLLVMOnlyAction action(_context.get());
254 if (!compiler.ExecuteAction(action))
257 std::unique_ptr<llvm::Module> module = action.takeModule();
258 if (module.get() ==
nullptr)
261 if (_linker.get() ==
nullptr) {
262 _module.reset(module.release());
263 _linker.reset(
new llvm::Linker(*_module.get()));
265 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)