Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/parse once #185

Merged
merged 57 commits into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
de079ec
clean up that we actually parse everything only once
leissa Mar 8, 2023
4b22d89
clang-format
leissa Mar 8, 2023
09e20ae
Merge branch 'master' into bugfix/parse_once
leissa Mar 9, 2023
93996cd
using stack of lexers for imports
leissa Mar 9, 2023
e4a9560
clang-format
leissa Mar 9, 2023
4650e83
only output in Bootstrapper if from main input
leissa Mar 9, 2023
e35e4b0
bug fixes
leissa Mar 9, 2023
f308a33
clang-format
leissa Mar 9, 2023
2ca5d63
doxygen fix
leissa Mar 9, 2023
2bb57a8
polish
leissa Mar 10, 2023
88983bc
clang-format
leissa Mar 10, 2023
8ece6c9
Merge branch 'refactor/driver' into bugfix/parse_once
leissa Mar 10, 2023
dd97647
Merge branch 'refactor/driver' into bugfix/parse_once
leissa Mar 13, 2023
8bbee84
Merge branch 'refactor/driver' into bugfix/parse_once
leissa Mar 15, 2023
215e809
Merge branch 'master' into bugfix/parse_once
leissa Mar 16, 2023
9f1fc61
consitently use fs::path when sth is a file
leissa Mar 16, 2023
3371ac2
Merge branch 'refactor/fs' into bugfix/parse_once
leissa Mar 16, 2023
952e484
cleanup
leissa Mar 16, 2023
9cf2229
wip: sort Bootstrapper::axioms by dialect
leissa Mar 17, 2023
7474024
first working version
leissa Mar 18, 2023
f9a250d
clang-format
leissa Mar 18, 2023
f22f8e7
fixed test cases
leissa Mar 20, 2023
aabc163
clang-format
leissa Mar 20, 2023
8d4bbe9
simplified bootstrap
leissa Mar 20, 2023
570af99
fixed various issues regarging search paths
leissa Mar 20, 2023
32180f6
print: check if operator<<(std::ostream&, T) is available
leissa Mar 20, 2023
5600ac4
clang-format
leissa Mar 20, 2023
aef7304
hopefully these compile fixes make CI happy
leissa Mar 20, 2023
fd8fd24
fighting path madness
leissa Mar 20, 2023
5b11281
clang-format
leissa Mar 20, 2023
ced5820
cli/main: only import opt if not bootstrapping
leissa Mar 20, 2023
805c8df
make use of assert_emplace
leissa Mar 20, 2023
4a71829
clang-format
leissa Mar 20, 2023
71af3c9
make use of lookup
leissa Mar 20, 2023
b5b0a15
clang-format
leissa Mar 20, 2023
066d274
fighting path madness
leissa Mar 21, 2023
c37f836
refactoring:
leissa Mar 22, 2023
66a91fd
compile fix
leissa Mar 22, 2023
4672633
compile fix
leissa Mar 22, 2023
e864999
docs + small refactoring
leissa Mar 22, 2023
236515c
directly load plugin from thorin file
leissa Mar 22, 2023
152f3fb
fix test case for now
leissa Mar 22, 2023
e322a15
clang-format
leissa Mar 22, 2023
0b7b0f8
better infer that can cope with test case
leissa Mar 22, 2023
dad2b9d
clang-format
leissa Mar 22, 2023
1fc2cb6
make msvc happy
leissa Mar 22, 2023
a8ecf39
clang-format
leissa Mar 22, 2023
69a498f
docs
leissa Mar 23, 2023
9bf6ee2
clang-format
leissa Mar 23, 2023
9b8595b
better capsulation
leissa Mar 23, 2023
577a1d8
compile fix
leissa Mar 23, 2023
8b3b4ca
only load `.plugin XXX` if not in bootstrap mode
leissa Mar 23, 2023
f4ae20d
docs
leissa Mar 23, 2023
6e9a6f3
renaming
leissa Mar 23, 2023
0e82b48
cleanup
leissa Mar 23, 2023
8f3d0c4
cleanup
leissa Mar 23, 2023
c255aac
distinguish between plugin/import in output
leissa Mar 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.")
NeuralCoder3 marked this conversation as resolved.
Show resolved Hide resolved
| 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}
NeuralCoder3 marked this conversation as resolved.
Show resolved Hide resolved
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