Skip to content

Commit

Permalink
Merge pull request #185 from AnyDSL/bugfix/parse_once
Browse files Browse the repository at this point in the history
Bugfix/parse once
  • Loading branch information
leissa authored Mar 27, 2023
2 parents ca844e8 + c255aac commit f84e1df
Show file tree
Hide file tree
Showing 63 changed files with 672 additions and 695 deletions.
49 changes: 22 additions & 27 deletions cli/main.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
#include <cstdlib>
#include <cstring>

#include <filesystem>
#include <fstream>
#include <iostream>
#include <lyra/lyra.hpp>

#include "thorin/config.h"
#include "thorin/dialects.h"
#include "thorin/driver.h"

#include "thorin/be/dot/dot.h"
#include "thorin/be/h/bootstrap.h"
#include "thorin/fe/parser.h"
#include "thorin/pass/optimize.h"
#include "thorin/pass/pass.h"
Expand All @@ -30,10 +29,10 @@ int main(int argc, char** argv) {
Driver driver;
bool show_help = false;
bool show_version = false;
bool list_dialect_paths = false;
bool list_search_paths = false;
std::string input, prefix;
std::string clang = sys::find_cmd("clang");
std::vector<std::string> plugins, dialect_paths;
std::vector<std::string> plugins, search_paths;
std::vector<size_t> breakpoints;
std::array<std::string, Num_Backends> output;
int verbose = 0;
Expand All @@ -45,14 +44,14 @@ int main(int argc, char** argv) {
auto cli = lyra::cli()
| lyra::help(show_help)
| lyra::opt(show_version )["-v"]["--version" ]("Display version info and exit.")
| lyra::opt(list_dialect_paths )["-l"]["--list-dialect-paths"]("List search paths in order and exit.")
| lyra::opt(list_search_paths )["-l"]["--list-search-paths" ]("List search paths in order and exit.")
| lyra::opt(clang, "clang" )["-c"]["--clang" ]("Path to clang executable (default: '" THORIN_WHICH " clang').")
| lyra::opt(plugins, "dialect")["-d"]["--dialect" ]("Dynamically load dialect [WIP].")
| lyra::opt(dialect_paths, "path" )["-D"]["--dialect-path" ]("Path to search dialects in.")
| lyra::opt(plugins, "dialect")["-d"]["--dialect" ]("Dynamically load plugin.")
| lyra::opt(search_paths, "path" )["-D"]["--dialect-path" ]("Path to search for plugins.")
| lyra::opt(inc_verbose )["-V"]["--verbose" ]("Verbose mode. Multiple -V options increase the verbosity. The maximum is 4.").cardinality(0, 4)
| lyra::opt(opt, "level" )["-O"]["--optimize" ]("Optimization level (default: 2).")
| lyra::opt(output[Dot ], "file" ) ["--output-dot" ]("Emits the Thorin program as a graph using Graphviz' DOT language.")
| lyra::opt(output[H ], "file" ) ["--output-h" ]("Emits a header file to be used to interface with a dialect in C++.")
| lyra::opt(output[H ], "file" ) ["--output-h" ]("Emits a header file to be used to interface with a plugin in C++.")
| lyra::opt(output[LL ], "file" ) ["--output-ll" ]("Compiles the Thorin program to LLVM.")
| lyra::opt(output[Md ], "file" ) ["--output-md" ]("Emits the input formatted as Markdown.")
| lyra::opt(output[Thorin], "file" )["-o"]["--output-thorin" ]("Emits the Thorin program again.")
Expand Down Expand Up @@ -80,10 +79,11 @@ int main(int argc, char** argv) {
std::exit(EXIT_SUCCESS);
}

for (auto&& path : dialect_paths) driver.add_search_path(path);
for (auto&& path : search_paths) driver.add_search_path(path);

if (list_dialect_paths) {
for (auto&& path : driver.search_paths()) std::cout << path << std::endl;
if (list_search_paths) {
for (auto&& path : driver.search_paths() | std::views::drop(1)) // skip first empty path
std::cout << path << std::endl;
std::exit(EXIT_SUCCESS);
}

Expand All @@ -107,8 +107,9 @@ int main(int argc, char** argv) {
}
}

// we always need core and mem, as long as we are not in bootstrap mode..
if (!os[H]) plugins.insert(plugins.end(), {"core", "mem", "compile", "opt"});
// we always need core and mem, as long as we are not in bootstrap mode
flags.bootstrap = os[H];
if (!flags.bootstrap) plugins.insert(plugins.end(), {"core", "mem", "compile", "opt"});

if (!plugins.empty())
for (const auto& plugin : plugins) driver.load(plugin);
Expand All @@ -117,22 +118,16 @@ int main(int argc, char** argv) {
if (input[0] == '-' || input.substr(0, 2) == "--")
throw std::invalid_argument("error: unknown option " + input);

std::ifstream ifs(input);
if (!ifs) {
errln("error: cannot read file '{}'", input);
return EXIT_FAILURE;
}

for (const auto& plugin : plugins) fe::Parser::import_module(world, world.sym(plugin));

auto sym = world.sym(std::move(input));
world.set(sym);
fe::Parser parser(world, sym, ifs, os[Md]);
parser.parse_module();
auto path = fs::path(input);
world.set(path.filename().replace_extension().string());
auto parser = fe::Parser(world);
parser.import(input, os[Md]);

if (os[H]) {
parser.bootstrap(*os[H]);
if (auto h = os[H]) {
bootstrap(driver, world.sym(fs::path{path}.filename().replace_extension().string()), *h);
opt = std::min(opt, 1);
} else {
parser.import("opt");
}

// clang-format off
Expand Down
2 changes: 1 addition & 1 deletion cmake/Thorin.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ function(add_thorin_dialect)
OUTPUT ${DIALECT_MD} ${DIALECT_H}
COMMAND $<TARGET_FILE:${THORIN_TARGET_NAMESPACE}thorin> ${THORIN_FILE_LIB_DIR} -D ${THORIN_LIB_DIR} --output-h ${DIALECT_H} --output-md ${DIALECT_MD}
DEPENDS ${THORIN_TARGET_NAMESPACE}thorin internal_thorin_${DIALECT}_thorin ${THORIN_FILE_LIB_DIR}
COMMENT "Bootstrapping Thorin dialect '${DIALECT}' from '${THORIN_FILE}'"
COMMENT "Bootstrapping Thorin plugin '${DIALECT}' from '${THORIN_FILE}'"
)
add_custom_target(${DIALECT} DEPENDS ${DIALECT_H})

Expand Down
2 changes: 1 addition & 1 deletion dialects/affine/affine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

using namespace thorin;

extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"affine", [](Passes& passes) { register_pass<affine::lower_for_pass, affine::LowerFor>(passes); }, nullptr,
nullptr};
}
2 changes: 1 addition & 1 deletion dialects/autodiff/autodiff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

using namespace thorin;

extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"autodiff",
[](Passes& passes) {
register_pass<autodiff::ad_eval_pass, autodiff::AutoDiffEval>(passes);
Expand Down
4 changes: 1 addition & 3 deletions dialects/clos/clos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#include <thorin/pass/pipelinebuilder.h>
#include <thorin/pass/rw/scalarize.h>

#include "thorin/dialects.h"

#include "dialects/clos/pass/fp/lower_typed_clos_prep.h"
#include "dialects/clos/pass/rw/branch_clos_elim.h"
#include "dialects/clos/pass/rw/clos2sjlj.h"
Expand Down Expand Up @@ -137,7 +135,7 @@ Ref ctype(World& w, Defs doms, Ref env_type) {

using namespace thorin;

extern "C" THORIN_EXPORT DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"clos",
[](Passes& passes) {
register_pass<clos::clos_conv_prep_pass, clos::ClosConvPrep>(passes, nullptr);
Expand Down
2 changes: 0 additions & 2 deletions dialects/clos/pass/rw/phase_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
#include <thorin/config.h>
#include <thorin/pass/pass.h>

#include "thorin/dialects.h"

#include "dialects/clos/phase/clos_conv.h"
#include "dialects/clos/phase/lower_typed_clos.h"

Expand Down
23 changes: 11 additions & 12 deletions dialects/compile/compile.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "dialects/compile/compile.h"

#include <thorin/config.h>
#include <thorin/dialects.h>
#include <thorin/pass/pass.h>

#include "thorin/pass/fp/beta_red.h"
Expand Down Expand Up @@ -35,40 +34,40 @@ void add_passes(World& world, PipelineBuilder& builder, Passes& passes, DefVec&
builder.end_pass_phase();
}

extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT thorin::Plugin thorin_get_plugin() {
return {"compile",
[](Passes& passes) {
auto debug_phase_flag = flags_t(Axiom::Base<thorin::compile::debug_phase>);
passes[debug_phase_flag] = [](World& world, PipelineBuilder& builder, const Def* app) {
assert_emplace(passes, debug_phase_flag, [](World& world, PipelineBuilder& builder, const Def* app) {
world.DLOG("Generate debug_phase: {}", app);
int level = (int)(app->as<App>()->arg(0)->as<Lit>()->get<u64>());
world.DLOG(" Level: {}", level);
builder.add_phase<compile::DebugPrint>(level);
};
});

passes[flags_t(Axiom::Base<thorin::compile::passes_to_phase>)] =
assert_emplace(passes, flags_t(Axiom::Base<thorin::compile::passes_to_phase>),
[&](World& world, PipelineBuilder& builder, const Def* app) {
auto pass_array = app->as<App>()->arg()->projs();
DefVec pass_list;
for (auto pass : pass_array) pass_list.push_back(pass);
add_passes(world, builder, passes, pass_list);
};
});

passes[flags_t(Axiom::Base<thorin::compile::phases_to_phase>)] =
assert_emplace(passes, flags_t(Axiom::Base<thorin::compile::phases_to_phase>),
[&](World& world, PipelineBuilder& builder, const Def* app) {
auto phase_array = app->as<App>()->arg()->projs();
DefVec phase_list;
for (auto phase : phase_array) phase_list.push_back(phase);
add_phases(phase_list, world, passes, builder);
};
});

passes[flags_t(Axiom::Base<thorin::compile::pipe>)] = [&](World& world, PipelineBuilder& builder,
assert_emplace(passes, flags_t(Axiom::Base<thorin::compile::pipe>), [&](World& world, PipelineBuilder& builder,
const Def* app) {
auto [ax, phases] = collect_args(app);
add_phases(phases, world, passes, builder);
};
passes[flags_t(Axiom::Base<thorin::compile::nullptr_pass>)] =
[](World&, PipelineBuilder& builder, const Def* def) { builder.def2pass(def, nullptr); };
});
assert_emplace(passes, flags_t(Axiom::Base<thorin::compile::nullptr_pass>),
[](World&, PipelineBuilder& builder, const Def* def) { builder.def2pass(def, nullptr); });

register_pass<compile::partial_eval_pass, PartialEval>(passes);
register_pass<compile::beta_red_pass, BetaRed>(passes);
Expand Down
4 changes: 1 addition & 3 deletions dialects/core/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
#include <thorin/config.h>
#include <thorin/pass/pass.h>

#include "thorin/dialects.h"

#include "dialects/core/be/ll/ll.h"

using namespace thorin;

extern "C" THORIN_EXPORT DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"core", nullptr, [](Backends& backends) { backends["ll"] = &ll::emit; },
[](Normalizers& normalizers) { core::register_normalizers(normalizers); }};
}
Expand Down
5 changes: 2 additions & 3 deletions dialects/demo/demo.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
#include "dialects/demo/demo.h"

#include <thorin/config.h>
#include <thorin/dialects.h>
#include <thorin/plugin.h>
#include <thorin/pass/pass.h>

using namespace thorin;

/// heart of the dialect
/// registers passes in the different optimization phases
/// as well as normalizers for the axioms
extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"demo", nullptr, nullptr, [](Normalizers& normalizers) { demo::register_normalizers(normalizers); }};
}
4 changes: 2 additions & 2 deletions dialects/direct/direct.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#include "dialects/direct/direct.h"

#include <thorin/dialects.h>
#include <thorin/plugin.h>
#include <thorin/pass/pipelinebuilder.h>

#include "dialects/direct/passes/cps2ds.h"
#include "dialects/direct/passes/ds2cps.h"

using namespace thorin;

extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"direct",
[](Passes& passes) {
register_pass<direct::ds2cps_pass, direct::DS2CPS>(passes);
Expand Down
4 changes: 1 addition & 3 deletions dialects/math/math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
#include <thorin/config.h>
#include <thorin/pass/pass.h>

#include "thorin/dialects.h"

using namespace thorin;

extern "C" THORIN_EXPORT DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"math", nullptr, [](Backends&) {},
[](Normalizers& normalizers) { math::register_normalizers(normalizers); }};
}
3 changes: 1 addition & 2 deletions dialects/mem/mem.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "dialects/mem/mem.h"

#include <thorin/config.h>
#include <thorin/dialects.h>
#include <thorin/pass/fp/beta_red.h>
#include <thorin/pass/fp/eta_exp.h>
#include <thorin/pass/fp/eta_red.h>
Expand All @@ -22,7 +21,7 @@

using namespace thorin;

extern "C" THORIN_EXPORT DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"mem",
[](Passes& passes) {
register_pass_with_arg<mem::ssa_pass, mem::SSAConstr, EtaExp>(passes);
Expand Down
14 changes: 6 additions & 8 deletions dialects/opt/opt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

using namespace thorin;

extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"opt",
[](Passes& passes) {
passes[flags_t(Axiom::Base<compile::dialect_select>)] = [&](World& world, PipelineBuilder& builder,
Expand All @@ -20,16 +20,14 @@ extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
auto dialect_axiom = args[1]->as<Axiom>();
auto then_phase = args[2];
auto else_phase = args[3];
world.DLOG("dialect_phase for: {}", dialect_axiom->sym());
auto name = dialect_axiom->sym(); // name has the form %opt.tag
auto [_, tag, __] = Axiom::split(world, name); // where tag = [dialect]_dialect
auto dialect = driver.sym(tag->substr(0, tag->find('_'))); // we want to extract the dialect
bool is_loaded = driver.is_loaded(dialect);

// name has the form %opt.tag where tag = [dialect]_dialect
// we want to extract the dialect part
auto name = dialect_axiom->sym();
auto [_, tag, __] = Axiom::split(world, name);
assert(tag->find('_') != std::string_view::npos && "dialect_phase: invalid dialect name");
auto dialect = driver.sym(tag->substr(0, tag->find('_')));
world.DLOG("dialect_phase for: {}", dialect_axiom->sym());
world.DLOG("dialect: {}", dialect);
bool is_loaded = driver.plugin(dialect);
world.DLOG("contained: {}", is_loaded);

compile::handle_optimization_part(is_loaded ? then_phase : else_phase, world, passes, builder);
Expand Down
3 changes: 1 addition & 2 deletions dialects/refly/refly.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "dialects/refly/refly.h"

#include <thorin/config.h>
#include <thorin/dialects.h>
#include <thorin/pass/pass.h>
#include <thorin/pass/pipelinebuilder.h>

Expand All @@ -12,7 +11,7 @@ using namespace thorin;
/// heart of the dialect
/// registers passes in the different optimization phases
/// as well as normalizers for the axioms
extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
extern "C" THORIN_EXPORT Plugin thorin_get_plugin() {
return {"refly", [](Passes& passes) { register_pass<refly::remove_dbg_perm_pass, refly::RemoveDbgPerm>(passes); },
nullptr, [](Normalizers& normalizers) { refly::register_normalizers(normalizers); }};
}
Expand Down
8 changes: 8 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

\include "cli-help.inc"

In addition, you can specify more search paths using the environment variable `THORIN_PLUGIN_PATH`.
Thorin will look for plugins in this priority:
1. The current working directory.
2. All paths specified via `-D` (in the given order).
3. All paths specified in the environment variable `THORIN_PLUGIN_PATH` (in the given order).
4. `path/to/thorin.exe/../../lib/thorin`
5. `CMAKE_INSTALL_PREFIX/lib/thorin`

## Debugging Features {#clidebug}

* You can increase the log level with `-V`.
Expand Down
Loading

0 comments on commit f84e1df

Please sign in to comment.