26 #include "clang_compiler.hpp"
27 #include "casadi/core/casadi_os.hpp"
28 #include "casadi/core/casadi_misc.hpp"
29 #include "casadi/core/casadi_meta.hpp"
44 int CASADI_IMPORTER_CLANG_EXPORT
47 plugin->name =
"clang";
49 plugin->version = CASADI_VERSION;
79 "Include paths for the JIT compiler. "
80 "The include directory shipped with CasADi will be automatically appended."}},
83 "Compile flags for the JIT compiler. Default: None"}}
92 for (
auto&& op : opts) {
93 if (op.first==
"include_path") {
95 }
else if (op.first==
"flags") {
101 std::vector<const char *> args(1,
name_.c_str());
103 args.push_back(f.c_str());
107 clang::CompilerInstance compInst;
113 std::string jit_include;
115 char buffer[MAX_PATH];
117 if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
118 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
119 (LPCSTR)addr, &hm)) {
120 casadi_error(
"GetModuleHandle failed");
122 GetModuleFileNameA(hm, buffer,
sizeof(buffer));
123 PathRemoveFileSpecA(buffer);
124 jit_include = buffer;
127 if (!dladdr(addr, &dl_info)) {
128 casadi_error(
"dladdr failed");
130 jit_include = dl_info.dli_fname;
131 jit_include = jit_include.substr(0, jit_include.find_last_of(
'/'));
137 auto targetoptions = std::make_shared<clang::Taroptions>();
138 targetoptions->Triple = llvm::sys::getDefaultTargetTriple();
139 clang::TargetInfo *targetInfo =
140 clang::TargetInfo::CreateTargetInfo(compInst.get_diagnostics(), targetoptions);
141 compInst.setTarget(targetInfo);
145 clang::DiagnosticOptions* diagOpts =
new clang::DiagnosticOptions();
147 clang::TextDiagnosticPrinter *diagClient =
new clang::TextDiagnosticPrinter(*
myerr_, diagOpts);
149 clang::DiagnosticIDs* diagID =
new clang::DiagnosticIDs();
151 clang::DiagnosticsEngine diags(diagID, diagOpts, diagClient);
154 #if LLVM_VERSION_MAJOR >= 4
155 std::shared_ptr<clang::CompilerInvocation> compInv(
new clang::CompilerInvocation());
157 clang::CompilerInvocation* compInv =
new clang::CompilerInvocation();
159 #if LLVM_VERSION_MAJOR >= 5
160 clang::CompilerInvocation::CreateFromArgs(*compInv, args, diags);
162 clang::CompilerInvocation::CreateFromArgs(*compInv, &args[0],
163 &args[0] + args.size(), diags);
165 compInst.setInvocation(compInv);
168 compInst.createDiagnostics();
169 if (!compInst.hasDiagnostics())
170 casadi_error(
"Cannot create diagnostics");
173 std::string resourcedir = jit_include +
filesep() +
"clang" +
filesep() + CLANG_VERSION_STRING;
174 compInst.getHeaderSearchOpts().ResourceDir = resourcedir;
177 std::vector<std::pair<std::string, bool> >
178 system_include =
getIncludes(
"system_includes.txt", jit_include);
179 for (
auto i=system_include.begin(); i!=system_include.end(); ++i) {
180 compInst.getHeaderSearchOpts().AddPath(i->first,
181 clang::frontend::System, i->second,
false);
185 system_include =
getIncludes(
"csystem_includes.txt", jit_include);
186 for (
auto i=system_include.begin(); i!=system_include.end(); ++i) {
187 compInst.getHeaderSearchOpts().AddPath(i->first,
188 clang::frontend::CSystem, i->second,
false);
192 system_include =
getIncludes(
"cxxsystem_includes.txt", jit_include);
193 for (
auto i=system_include.begin(); i!=system_include.end(); ++i) {
194 compInst.getHeaderSearchOpts().AddPath(i->first,
195 clang::frontend::CXXSystem, i->second,
false);
199 std::stringstream paths;
203 compInst.getHeaderSearchOpts().AddPath(
path, clang::frontend::System,
false,
false);
211 if (!compInst.ExecuteAction(*
act_))
212 casadi_error(
"Cannot execute action");
215 #if LLVM_VERSION_MAJOR>=4 || (LLVM_VERSION_MAJOR==3 && LLVM_VERSION_MINOR>=5)
216 std::unique_ptr<llvm::Module> module =
act_->takeModule();
219 llvm::Module* module =
act_->takeModule();
223 llvm::InitializeNativeTarget();
224 llvm::InitializeNativeTargetAsmPrinter();
229 llvm::EngineBuilder(std::move(module)).setEngineKind(llvm::EngineKind::JIT)
230 .setErrorStr(&ErrStr).create();
232 casadi_error(
"Could not create ExecutionEngine: " + ErrStr);
239 llvm::Function* f =
module_->getFunction(symname);
251 const char sep =
'\\';
253 const char sep =
'/';
257 std::vector<std::pair<std::string, bool> > ret;
260 std::ifstream setup_file(
path + sep + file);
262 while (std::getline(setup_file, line)) {
264 if (line.empty())
continue;
267 size_t loc = line.find(
" (framework directory)");
268 bool isframework = loc != std::string::npos;
271 line = line.substr(0, loc);
276 bool relative = PathIsRelative(TEXT(line.c_str()));
278 bool relative = line.at(0)!=sep;
283 ret.push_back(std::make_pair(
path + sep + line, isframework));
286 ret.push_back(std::make_pair(line, isframework));
static std::vector< std::pair< std::string, bool > > getIncludes(const std::string &file, const std::string &path)
ClangCompiler(const std::string &name)
Constructor.
void init(const Dict &opts) override
Initialize.
std::string include_path_
clang::EmitLLVMOnlyAction * act_
~ClangCompiler() override
Destructor.
static const Options options_
Options.
static const std::string meta_doc
A documentation string.
llvm::raw_ostream * myerr_
llvm::LLVMContext * context_
std::vector< std::string > flags_
static ImporterInternal * creator(const std::string &name)
Create a new JIT function.
signal_t get_function(const std::string &symname) override
Get a function pointer for numerical evaluation.
llvm::ExecutionEngine * executionEngine_
virtual void init(const Dict &opts)
Initialize.
static const Options options_
Options.
std::string name_
C filename.
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
int CASADI_IMPORTER_CLANG_EXPORT casadi_register_importer_clang(ImporterInternal::Plugin *plugin)
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void CASADI_IMPORTER_CLANG_EXPORT casadi_load_importer_clang()
void(* signal_t)(void)
Function pointer types for the C API.
std::vector< casadi_int > path(const std::vector< casadi_int > &map, casadi_int i_start)
Options metadata for a class.