diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 423a8b7a83..4379a0fdcc 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -180,6 +180,60 @@ int emit_asr(const std::string &infile, return 0; } +int emit_asr_after_pass(const std::string &infile, + LCompilers::PassManager& pass_manager, + const std::string &runtime_library_dir, + CompilerOptions &compiler_options) +{ + Allocator al(4*1024); + LFortran::diag::Diagnostics diagnostics; + LFortran::LocationManager lm; + lm.in_filename = infile; + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + LFortran::Result r1 = parse_python_file( + al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); + std::cerr << diagnostics.render(input, lm, compiler_options); + if (!r1.ok) { + return 1; + } + LFortran::LPython::AST::ast_t* ast = r1.result; + + diagnostics.diagnostics.clear(); + LFortran::Result + r = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, + compiler_options.disable_main, compiler_options.symtab_only, infile); + std::cerr << diagnostics.render(input, lm, compiler_options); + if (!r.ok) { + LFORTRAN_ASSERT(diagnostics.has_error()) + return 2; + } + LFortran::ASR::TranslationUnit_t* asr = r.result; + LCompilers::PassOptions pass_options; + pass_options.run_fun = "f"; + pass_options.always_run = true; + + std::string cmd = "mkdir asr_pass_log/"; + int err = system(cmd.c_str()); + if (err) { + std::cout << "The command '" + cmd + "' failed." << std::endl; + exit(1); + } + LFortran::write_asr_to_file("./asr_pass_log/0_raw.asr", *asr, false, false); + int index = 0; + std::string pname, asr_file; + while (true) { + pname = pass_manager.apply_one_pass(al, asr, index, pass_options); + if (pname == "") break; + else { + index++; + asr_file = "./asr_pass_log/" + std::to_string(index)+"_"+pname+".asr"; + LFortran::write_asr_to_file(asr_file,*asr, false, false); + } + } + return 0; +} + int emit_cpp(const std::string &infile, const std::string &runtime_library_dir, CompilerOptions &compiler_options) @@ -789,6 +843,7 @@ int main(int argc, char *argv[]) bool static_link = false; std::string arg_backend = "llvm"; std::string arg_kernel_f; + bool print_after_asr_pass = false; bool print_targets = false; bool print_rtlib_header_dir = false; @@ -855,6 +910,7 @@ int main(int argc, char *argv[]) app.add_option("--target", compiler_options.target, "Generate code for the given target")->capture_default_str(); app.add_flag("--print-targets", print_targets, "Print the registered targets"); app.add_flag("--get-rtlib-header-dir", print_rtlib_header_dir, "Print the path to the runtime library header file"); + app.add_flag("--print-after-asr-pass", print_after_asr_pass, "Print ASR output after every pass"); // LSP specific options app.add_flag("--show-errors", show_errors, "Show errors when LSP is running in the background"); @@ -864,6 +920,7 @@ int main(int argc, char *argv[]) lpython_pass_manager.use_optimization_passes(); } + /* * Subcommands: */ @@ -1038,6 +1095,10 @@ int main(int argc, char *argv[]) #endif } lpython_pass_manager.use_default_passes(); + if (print_after_asr_pass) { + return emit_asr_after_pass(arg_file, lpython_pass_manager, runtime_library_dir, + compiler_options); + } if (show_llvm) { #ifdef HAVE_LFORTRAN_LLVM return emit_llvm(arg_file, runtime_library_dir, lpython_pass_manager, compiler_options); diff --git a/src/libasr/pass/pass_manager.h b/src/libasr/pass/pass_manager.h index 5aa72d0c8f..47064c6dab 100644 --- a/src/libasr/pass/pass_manager.h +++ b/src/libasr/pass/pass_manager.h @@ -37,7 +37,6 @@ #include #include #include - #include #include @@ -78,6 +77,14 @@ namespace LCompilers { bool is_fast; bool apply_default_passes; + std::string _apply_one_pass(Allocator& al, LFortran::ASR::TranslationUnit_t* asr, + std::vector& passes, size_t index, PassOptions pass_options) { + if (index >= passes.size()) + return ""; + _passes_db[passes[index]](al, *asr, pass_options); + return passes[index]; + } + void _apply_passes(Allocator& al, LFortran::ASR::TranslationUnit_t* asr, std::vector& passes, PassOptions pass_options) { pass_options.runtime_library_dir = LFortran::get_runtime_library_dir(); @@ -171,6 +178,20 @@ namespace LCompilers { } } + std::string apply_one_pass(Allocator& al, LFortran::ASR::TranslationUnit_t* asr, + size_t index, PassOptions& pass_options) { + if( !_user_defined_passes.empty() ) { + return _apply_one_pass(al, asr, _user_defined_passes, index, pass_options); + } else if( apply_default_passes ) { + if( is_fast ) { + return _apply_one_pass(al, asr, _with_optimization_passes, index, pass_options); + } else { + return _apply_one_pass(al, asr, _passes, index, pass_options); + } + } + return ""; + } + void use_optimization_passes() { is_fast = true; } diff --git a/src/lpython/pickle.cpp b/src/lpython/pickle.cpp index 57b824ab05..54ff43640c 100644 --- a/src/lpython/pickle.cpp +++ b/src/lpython/pickle.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -95,7 +96,7 @@ class ASRTreeVisitor : { public: bool show_intrinsic_modules; - + std::string get_str() { return s; } @@ -114,4 +115,11 @@ std::string pickle_tree(LFortran::ASR::TranslationUnit_t &asr, bool colors, bool return pickle_tree((ASR::asr_t &)asr, colors, show_intrinsic_modules); } +void write_asr_to_file(std::string file, LFortran::ASR::TranslationUnit_t &asr, bool colors, bool show_intrinsic_modules) { + std::ofstream f; + f.open(file); + f << pickle_tree(asr, colors, show_intrinsic_modules); + f.close(); +} + } diff --git a/src/lpython/pickle.h b/src/lpython/pickle.h index 99c062130d..ec8474b7eb 100644 --- a/src/lpython/pickle.h +++ b/src/lpython/pickle.h @@ -14,6 +14,7 @@ namespace LFortran { // Print the tree structure std::string pickle_tree(LFortran::ASR::asr_t &asr, bool colors, bool show_intrinsic_modules); std::string pickle_tree(LFortran::ASR::TranslationUnit_t &asr, bool colors, bool show_intrinsic_modules); + void write_asr_to_file(std::string file, LFortran::ASR::TranslationUnit_t &asr, bool colors, bool show_intrinsic_modules); }