Skip to content

Commit

Permalink
refactor plugin system
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-kenzel committed Jul 27, 2023
1 parent e80b6fe commit 832f74b
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 85 deletions.
2 changes: 2 additions & 0 deletions src/thorin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ set(THORIN_SOURCES
type.h
world.cpp
world.h
plugin.h
plugin_helpers.h
analyses/cfg.cpp
analyses/cfg.h
analyses/domfrontier.cpp
Expand Down
39 changes: 39 additions & 0 deletions src/thorin/plugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef THORIN_PLUGIN_H
#define THORIN_PLUGIN_H

#include <memory>

namespace thorin {
class Def;
class Continuation;
class App;
class World;

struct plugin_intrinsic {
virtual void transform(World* world, const Continuation* cont) = 0;
virtual void destroy() = 0;

protected:
plugin_intrinsic() = default;
plugin_intrinsic(const plugin_intrinsic&) = default;
plugin_intrinsic(plugin_intrinsic&&) = default;
plugin_intrinsic& operator =(const plugin_intrinsic&) = default;
plugin_intrinsic& operator =(plugin_intrinsic&&) = default;
~plugin_intrinsic() = default;
};

struct plugin_deleter {
void operator ()(plugin_intrinsic* ptr) const {
ptr->destroy();
}
};

using unique_plugin_intrinsic = std::unique_ptr<plugin_intrinsic, plugin_deleter>;

extern "C" {
using plugin_init_func_t = void();
using plugin_intrinsic_create_func_t = plugin_intrinsic*();
}
}

#endif
42 changes: 42 additions & 0 deletions src/thorin/plugin_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef THORIN_PLUGIN_HELPERS_H
#define THORIN_PLUGIN_HELPERS_H

#include "plugin.h"
#include "continuation.h"
#include "world.h"

namespace thorin {
template <typename Plugin>
class plugin_intrinsic_app_wrapper : public virtual plugin_intrinsic {
virtual const Def* transform(World* world, const App* app) = 0;

void transform(World* world, const Continuation* cont) final override {
for (auto use : cont->copy_uses()) {
if (!use.def()->isa<App>())
continue;

auto app = use.def()->as<App>();

// transform plugin(mem, args, ret) to ret(mem, func(args))

auto output = static_cast<Plugin*>(this)->transform(world, app);

auto app_rebuild =
output ? app->rebuild(*world, world->bottom_type(), {app->arg(app->num_args() - 1), app->arg(0), output})
: app->rebuild(*world, world->bottom_type(), {app->arg(app->num_args() - 1), app->arg(0)});

app->replace_uses(app_rebuild);
}
}

protected:
plugin_intrinsic_app_wrapper() = default;
plugin_intrinsic_app_wrapper(const plugin_intrinsic_app_wrapper&) = default;
plugin_intrinsic_app_wrapper(plugin_intrinsic_app_wrapper&&) = default;
plugin_intrinsic_app_wrapper& operator =(const plugin_intrinsic_app_wrapper&) = default;
plugin_intrinsic_app_wrapper& operator =(plugin_intrinsic_app_wrapper&&) = default;
~plugin_intrinsic_app_wrapper() = default;
};
}

#endif
5 changes: 5 additions & 0 deletions src/thorin/transform/cleanup_world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ void Cleaner::rebuild() {
importer.import(cont);
}

for (auto&& [cont, func] : world_.data_.plugin_intrinsics_) {
if (cont->num_uses() > 0)
importer.import_plugin_intrinsic(cont, std::move(func));
}

swap(importer.world(), world_);

// verify(world_);
Expand Down
8 changes: 8 additions & 0 deletions src/thorin/transform/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,12 @@ const Def* Importer::import(const Def* odef) {
return ncontinuation;
}

void Importer::import_plugin_intrinsic(const Continuation* cont, unique_plugin_intrinsic func) {
if (auto ncont = def_old2new_.lookup(cont)) {
assert(&(*ncont)->world() == &world_);
assert((*ncont)->isa<Continuation>());
world_.data_.plugin_intrinsics_.push_back({ (*ncont)->as<Continuation>(), std::move(func) });
}
}

}
1 change: 1 addition & 0 deletions src/thorin/transform/importer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Importer {
World& world() { return world_; }
const Type* import(const Type*);
const Def* import(const Def*);
void import_plugin_intrinsic(const Continuation* cont, unique_plugin_intrinsic impl);
bool todo() const { return todo_; }

public:
Expand Down
71 changes: 5 additions & 66 deletions src/thorin/transform/plugin_execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,76 +3,15 @@
#include "thorin/transform/partial_evaluation.h"
#include "thorin/analyses/scope.h"

#include <vector>

namespace thorin {

void plugin_execute(World& world) {
void plugin_execute(World& world, std::vector<World::PluginIntrinsic> intrinsics) {
world.VLOG("start plugin_execute");

std::vector<const Continuation*> plugin_intrinsics;

while (true) {
plugin_intrinsics.clear();

for (auto def : world.defs()) {
auto cont = def->isa_nom<Continuation>();
if (!cont) continue;

if (cont->is_intrinsic() && cont->intrinsic() == Intrinsic::Plugin) {
plugin_intrinsics.push_back(cont);
}
}

if (plugin_intrinsics.empty())
break;

sort(plugin_intrinsics.begin(), plugin_intrinsics.end(), [&](const Continuation* a, const Continuation* b) {
const Continuation* depends = a;
while (depends) {
if (depends == b) return false;
depends = depends->attributes().depends;
}
return true;
});

for (auto cont : plugin_intrinsics) {
auto plugin_function = world.search_plugin_function(cont->name().c_str());
if (!plugin_function) {
world.ELOG("Plugin function not found for: {}", cont->name());
continue;
}

bool evaluated = false;
for (auto use : cont->copy_uses()) {
if (!use.def()->isa<App>()) {
continue;
}

auto app = use.def()->as<App>();

if (app->num_uses() == 0) {
continue;
}

const Def* output = plugin_function(&world, app);
const Def* app_rebuild = nullptr;
if (output) {
app_rebuild = app->rebuild(world, world.bottom_type(), {app->arg(app->num_args() - 1), app->arg(0), output});
} else {
app_rebuild = app->rebuild(world, world.bottom_type(), {app->arg(app->num_args() - 1), app->arg(0)});
}
app->replace_uses(app_rebuild);

//partial_evaluation(world); //TODO: Some form of cleanup would be advisable here.
evaluated = true;
}

if (evaluated)
break;
}

world.cleanup(); //Warning: This must not change the world, there are still references to intrinsics being maintained here.
// assume that dependents precede dependencies
while (!intrinsics.empty()) {
intrinsics.back().impl->transform(&world, intrinsics.back().cont);
intrinsics.pop_back();
}

world.mark_pe_done(false);
Expand Down
4 changes: 3 additions & 1 deletion src/thorin/transform/plugin_execute.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#ifndef THORIN_TRANSFORM_PLUGIN_EXECUTE_H
#define THORIN_TRANSFORM_PLUGIN_EXECUTE_H

#include "thorin/world.h"

namespace thorin {

void plugin_execute(World&);
void plugin_execute(World&, std::vector<World::PluginIntrinsic> intrinsics);

}

Expand Down
41 changes: 30 additions & 11 deletions src/thorin/world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#endif

#include <cmath>
#include <algorithm>
#ifdef _MSC_VER
#include <windows.h>
#else
Expand Down Expand Up @@ -1302,9 +1303,9 @@ void World::opt() {
RUN_PASS(flatten_tuples(*this))
RUN_PASS(clone_bodies(*this))
RUN_PASS(split_slots(*this))
if (plugin_handles.size() > 0) {
RUN_PASS(plugin_execute(*this));
RUN_PASS(cleanup());
if (!data_.plugin_intrinsics_.empty()) {
RUN_PASS(plugin_execute(*this, std::move(data_.plugin_intrinsics_)));
// RUN_PASS(cleanup());
}
RUN_PASS(closure_conversion(*this))
RUN_PASS(lift_builtins(*this))
Expand All @@ -1315,7 +1316,7 @@ void World::opt() {
RUN_PASS(codegen_prepare(*this))
}

bool World::register_plugin(const char* plugin_name) {
bool World::load_plugin(const char* plugin_name) {
#ifdef _MSC_VER
return false;
#else // _MSC_VER
Expand All @@ -1332,23 +1333,41 @@ bool World::register_plugin(const char* plugin_name) {
if ((error = dlerror()) != NULL) {
ILOG("Plugin {} did not supply an init function", plugin_name);
} else {
initfunc(this);
initfunc();
}

plugin_handles.push_back(handle);
data_.plugin_modules_.push_back(handle);
return true;
#endif // _MSC_VER
}

World::plugin_func_t* World::search_plugin_function(const char* function_name) const {
template <typename T>
static T* lookup_plugin_function(void* plugin_module, const char* function_name) {
#ifdef _MSC_VER
#else // _MSC_VER
for (auto plugin : plugin_handles) {
if (void* plugin_function = dlsym(plugin, function_name)) {
return reinterpret_cast<plugin_func_t*>(plugin_function);
}
if (void* func = dlsym(plugin_module, function_name)) {
return reinterpret_cast<T*>(func);
}
#endif // _MSC_VER
return nullptr;
}

unique_plugin_intrinsic World::load_plugin_intrinsic(const char* function_name) const {
for (auto plugin_module : data_.plugin_modules_) {
if (auto create_intrinsic = lookup_plugin_function<plugin_intrinsic_create_func_t>(plugin_module, function_name))
return unique_plugin_intrinsic(create_intrinsic());
}

return nullptr;
}

void World::link_plugin_intrinsic(Continuation* cont) {
auto intrinsic = load_plugin_intrinsic(cont->name().c_str());

if (!intrinsic)
error(cont->loc(), "failed to link plugin intrinsic {}", cont->name());

cont->attributes().intrinsic = Intrinsic::Plugin;
data_.plugin_intrinsics_.push_back({ cont, std::move(intrinsic) });
}
}
19 changes: 12 additions & 7 deletions src/thorin/world.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
#include <functional>
#include <initializer_list>
#include <string>
#include <vector>

#include "thorin/enums.h"
#include "thorin/continuation.h"
#include "thorin/primop.h"
#include "thorin/util/hash.h"
#include "thorin/util/stream.h"
#include "thorin/plugin.h"
#include "thorin/config.h"

namespace thorin {
Expand Down Expand Up @@ -321,11 +323,13 @@ class World : public TypeTable, public Streamable<World> {

// plugins

using plugin_init_func_t = void(World*);
using plugin_func_t = const Def*(World*, const App*);
struct PluginIntrinsic {
const Continuation* cont;
unique_plugin_intrinsic impl;
};

bool register_plugin(const char* plugin_name);
plugin_func_t* search_plugin_function(const char* function_name) const;
bool load_plugin(const char* plugin_name);
void link_plugin_intrinsic(Continuation* cont);

private:
const Param* param(const Type* type, Continuation* continuation, size_t index, Debug dbg);
Expand All @@ -334,9 +338,6 @@ class World : public TypeTable, public Streamable<World> {
template <class F> const Def* transcendental(MathOpTag, const Def*, Debug, F&&);
template <class F> const Def* transcendental(MathOpTag, const Def*, const Def*, Debug, F&&);

std::unique_ptr<World> world_;
std::vector<void*> plugin_handles;

/// @name put into see of nodes
//@{
template <class T> const T* cse(const T* primop) { return cse_base(primop)->template as<T>(); }
Expand Down Expand Up @@ -371,10 +372,14 @@ class World : public TypeTable, public Streamable<World> {
Sea defs_;
Continuation* branch_;
Continuation* end_scope_;
std::vector<void*> plugin_modules_;
std::vector<PluginIntrinsic> plugin_intrinsics_;
} data_;

std::shared_ptr<Stream> stream_;

unique_plugin_intrinsic load_plugin_intrinsic(const char* function_name) const;

friend class Mangler;
friend class Cleaner;
friend class Continuation;
Expand Down

0 comments on commit 832f74b

Please sign in to comment.