Skip to content

Commit

Permalink
Merge pull request #134 from Samy-33/feat/include-and-lib-paths
Browse files Browse the repository at this point in the history
feat(jit-processor): allow adding include, shared libs from cli
  • Loading branch information
jeaye authored Nov 28, 2024
2 parents b9d90a4 + 6b09ba3 commit 418ad11
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 59 deletions.
11 changes: 9 additions & 2 deletions compiler+runtime/include/cpp/jank/jit/processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,24 @@ namespace jank::runtime

namespace jank::jit
{

struct processor
{
processor(native_integer optimization_level);
processor(util::cli::options const &opts);
~processor();

result<option<runtime::object_ptr>, native_persistent_string>
eval(codegen::processor &cg_prc) const;
void eval_string(native_persistent_string const &s) const;
void load_object(native_persistent_string_view const &path) const;
void load_object(native_persistent_string const &path) const;

result<void, native_persistent_string>
load_dynamic_libs(native_vector<native_persistent_string> const &libs) const;

option<native_persistent_string> find_dynamic_lib(native_persistent_string const &lib) const;

std::unique_ptr<clang::Interpreter> interpreter;
native_integer optimization_level{};
native_vector<boost::filesystem::path> library_dirs;
};
}
1 change: 0 additions & 1 deletion compiler+runtime/include/cpp/jank/runtime/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ namespace jank::runtime
{
context();
context(util::cli::options const &opts);
context(context const &);
context(context &&) = delete;
~context();

Expand Down
6 changes: 6 additions & 0 deletions compiler+runtime/include/cpp/jank/util/cli.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ namespace jank::util::cli
native_bool profiler_enabled{};
native_transient_string profiler_file{ "jank.profile" };
native_bool gc_incremental{};

/* Native dependencies */
native_vector<native_persistent_string> include_dirs;
native_vector<native_persistent_string> library_dirs;
native_vector<native_persistent_string> define_macros;
native_vector<native_persistent_string> libs;

/* Compilation. */
native_transient_string compilation_path{ "classes" };
Expand Down
101 changes: 97 additions & 4 deletions compiler+runtime/src/cpp/jank/jit/processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@

namespace jank::jit
{

native_persistent_string default_shared_lib_name(native_persistent_string const &lib)
#if defined(__APPLE__)
{
return fmt::format("{}.dylib", lib);
}
#elif defined(__linux__)
{
return fmt::format("lib{}.so", lib);
}
#endif

static void handle_fatal_llvm_error(void * const user_data,
char const *message,
native_bool const gen_crash_diag)
Expand Down Expand Up @@ -80,9 +92,14 @@ namespace jank::jit
return output_path;
}

processor::processor(native_integer const optimization_level)
: optimization_level{ optimization_level }
processor::processor(util::cli::options const &opts)
: optimization_level{ opts.optimization_level }
{
for(auto const &library_dir : opts.library_dirs)
{
library_dirs.emplace_back(boost::filesystem::absolute(library_dir.c_str()));
}

profile::timer timer{ "jit ctor" };
/* TODO: Pass this into each fn below so we only do this once on startup. */
auto const jank_path(util::process_location().unwrap().parent_path());
Expand All @@ -102,7 +119,7 @@ namespace jank::jit

auto const include_path(jank_path / "../include");

native_persistent_string_view O{ "-O0" };
native_persistent_string O{ "-O0" };
switch(optimization_level)
{
case 0:
Expand Down Expand Up @@ -137,7 +154,22 @@ namespace jank::jit
args.emplace_back("-include-pch");
args.emplace_back(strdup(pch_path_str.c_str()));

//fmt::println("jit flags {}", args);
for(auto const &include_path : opts.include_dirs)
{
args.emplace_back(strdup(fmt::format("-I{}", include_path).c_str()));
}

for(auto const &library_path : opts.library_dirs)
{
args.emplace_back(strdup(fmt::format("-L{}", library_path).c_str()));
}

for(auto const &define_macro : opts.define_macros)
{
args.emplace_back(strdup(fmt::format("-D{}", define_macro).c_str()));
}

// fmt::println("jit flags {}", args);

clang::IncrementalCompilerBuilder compiler_builder;
compiler_builder.SetCompilerArgs(args);
Expand All @@ -148,6 +180,12 @@ namespace jank::jit
compiler_instance->LoadRequestedPlugins();

interpreter = llvm::cantFail(clang::Interpreter::create(std::move(compiler_instance)));

auto const &load_result{ load_dynamic_libs(opts.libs) };
if(load_result.is_err())
{
throw std::runtime_error{ load_result.expect_err().c_str() };
}
}

processor::~processor()
Expand Down Expand Up @@ -199,4 +237,59 @@ namespace jank::jit
auto err(interpreter->ParseAndExecute({ s.data(), s.size() }));
llvm::logAllUnhandledErrors(std::move(err), llvm::errs(), "error: ");
}

option<native_persistent_string>
processor::find_dynamic_lib(native_persistent_string const &lib) const
{
auto const &default_lib_name{ default_shared_lib_name(lib) };
for(auto const &lib_dir : library_dirs)
{
auto const default_lib_abs_path{ fmt::format("{}/{}", lib_dir.string(), default_lib_name) };
if(boost::filesystem::exists(default_lib_abs_path.c_str()))
{
return default_lib_abs_path;
}
else
{
auto const lib_abs_path{ fmt::format("{}/{}", lib_dir.string(), lib) };
if(boost::filesystem::exists(lib_abs_path))
{
return lib_abs_path;
}
}
}

return none;
}

result<void, native_persistent_string>
processor::load_dynamic_libs(native_vector<native_persistent_string> const &libs) const
{
for(auto const &lib : libs)
{
if(boost::filesystem::path{ lib.c_str() }.is_absolute())
{
load_object(lib);
}
else
{
auto const result{ processor::find_dynamic_lib(lib) };
if(result.is_none())
{
return err(fmt::format("Failed to load dynamic library `{}`", lib));
}
else
{
load_object(result.unwrap());
}
}
}

return ok();
}

void processor::load_object(native_persistent_string const &path) const
{
llvm::cantFail(interpreter->LoadDynamicLibrary(path.data()));
}
}
53 changes: 1 addition & 52 deletions compiler+runtime/src/cpp/jank/runtime/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace jank::runtime
}

context::context(util::cli::options const &opts)
: jit_prc{ opts.optimization_level }
: jit_prc{ opts }
, output_dir{ opts.compilation_path }
, module_loader{ *this, opts.class_path }
{
Expand Down Expand Up @@ -68,57 +68,6 @@ namespace jank::runtime
.expect_ok();
}

/* TODO: Remove this. */
context::context(context const &ctx)
: jit_prc{ ctx.jit_prc.optimization_level }
, module_dependencies{ ctx.module_dependencies }
, output_dir{ ctx.output_dir }
, module_loader{ *this, ctx.module_loader.paths }
{
{
auto ns_lock(namespaces.wlock());
for(auto const &ns : *ctx.namespaces.rlock())
{
ns_lock->insert({ ns.first, ns.second->clone(*this) });
}
*keywords.wlock() = *ctx.keywords.rlock();
}

auto &tbfs(thread_binding_frames[this]);
auto const &other_tbfs(thread_binding_frames[&ctx]);
for(auto const &v : other_tbfs)
{
thread_binding_frame frame{ obj::persistent_hash_map::empty() };
for(auto it(v.bindings->fresh_seq()); it != nullptr; it = runtime::next_in_place(it))
{
auto const entry(it->first());
auto const var(expect_object<var>(entry->data[0]));
auto const value(entry->data[1]);
auto const new_var(intern_var(var->n->name->name, var->name->name).expect_ok());
frame.bindings = frame.bindings->assoc(new_var, value);
}

/* We push to the back, since we're looping from the front of the other list. If we
* pushed to the front of this one, we'd reverse the order. */
tbfs.push_back(std::move(frame));
}

auto const core(intern_ns(make_box<obj::symbol>("clojure.core")));
current_ns_var = core->intern_var(make_box<obj::symbol>("clojure.core/*ns*"));

in_ns_var = intern_var(make_box<obj::symbol>("clojure.core/in-ns")).expect_ok();
compile_files_var
= intern_var(make_box<obj::symbol>("clojure.core/*compile-files*")).expect_ok();
assert_var = core->intern_var(make_box<obj::symbol>("clojure.core/*assert*"));

current_module_var
= make_box<runtime::var>(core, make_box<obj::symbol>("*current-module*"))->set_dynamic(true);
no_recur_var
= make_box<runtime::var>(core, make_box<obj::symbol>("*no-recur*"))->set_dynamic(true);
gensym_env_var
= make_box<runtime::var>(core, make_box<obj::symbol>("*gensym-env*"))->set_dynamic(true);
}

context::~context()
{
thread_binding_frames.erase(this);
Expand Down
14 changes: 14 additions & 0 deletions compiler+runtime/src/cpp/jank/util/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ namespace jank::util::cli
cli.add_option("-O,--optimization", opts.optimization_level, "The optimization level to use")
->check(CLI::Range(0, 3));

/* TODO: new category */
cli.add_option("-I,--include-dir",
opts.include_dirs,
"Absolute or relative path to the directory for includes resolution. Accepts multiple values");
cli.add_option("-L,--library-dir",
opts.library_dirs,
"Absolute or relative path to the directory to search dynamic libraries in. Accepts multiple values");
cli.add_option("-D,--define-macro",
opts.define_macros,
"Defines macro value, sets to 1 if omitted. Accepts multiple values");
cli.add_option("-l",
opts.libs,
"Library identifiers, absolute or relative paths eg. -lfoo for libfoo.so or foo.dylib. Accepts multiple values");

/* Run subcommand. */
auto &cli_run(*cli.add_subcommand("run", "Load and run a file"));
cli_run.fallthrough();
Expand Down

0 comments on commit 418ad11

Please sign in to comment.