diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 913eadcccb..91db0e112d 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -262,6 +262,7 @@ int emit_cpp(const std::string &infile, int emit_c(const std::string &infile, const std::string &runtime_library_dir, + LCompilers::PassManager& pass_manager, CompilerOptions &compiler_options) { Allocator al(4*1024); @@ -293,6 +294,13 @@ int emit_c(const std::string &infile, } LCompilers::ASR::TranslationUnit_t* asr = r1.result; + // Apply ASR passes + LCompilers::PassOptions pass_options; + pass_manager.use_default_passes(true); + pass_options.run_fun = "f"; + pass_options.always_run = true; + pass_manager.apply_passes(al, asr, pass_options, diagnostics); + diagnostics.diagnostics.clear(); auto res = LCompilers::asr_to_c(al, *asr, diagnostics, compiler_options, 0); std::cerr << diagnostics.render(lm, compiler_options); @@ -305,7 +313,7 @@ int emit_c(const std::string &infile, } int emit_c_to_file(const std::string &infile, const std::string &outfile, - const std::string &runtime_library_dir, + const std::string &runtime_library_dir, LCompilers::PassManager& pass_manager, CompilerOptions &compiler_options) { Allocator al(4*1024); @@ -337,6 +345,13 @@ int emit_c_to_file(const std::string &infile, const std::string &outfile, } LCompilers::ASR::TranslationUnit_t* asr = r1.result; + // Apply ASR passes + LCompilers::PassOptions pass_options; + pass_manager.use_default_passes(true); + pass_options.run_fun = "f"; + pass_options.always_run = true; + pass_manager.apply_passes(al, asr, pass_options, diagnostics); + diagnostics.diagnostics.clear(); auto res = LCompilers::asr_to_c(al, *asr, diagnostics, compiler_options, 0); std::cerr << diagnostics.render(lm, compiler_options); @@ -1666,7 +1681,8 @@ int main(int argc, char *argv[]) return emit_cpp(arg_file, runtime_library_dir, compiler_options); } if (show_c) { - return emit_c(arg_file, runtime_library_dir, compiler_options); + return emit_c(arg_file, runtime_library_dir, lpython_pass_manager, + compiler_options); } if (show_wat) { return emit_wat(arg_file, runtime_library_dir, compiler_options); @@ -1741,7 +1757,8 @@ int main(int argc, char *argv[]) runtime_library_dir, compiler_options, time_report, backend); } else if (backend == Backend::c) { std::string emit_file_name = basename + "__tmp__generated__.c"; - err = emit_c_to_file(arg_file, emit_file_name, runtime_library_dir, compiler_options); + err = emit_c_to_file(arg_file, emit_file_name, runtime_library_dir, + lpython_pass_manager, compiler_options); err = link_executable({emit_file_name}, outfile, runtime_library_dir, backend, static_link, true, compiler_options, rtlib_header_dir); } else if (backend == Backend::llvm) { diff --git a/src/libasr/codegen/asr_to_c.cpp b/src/libasr/codegen/asr_to_c.cpp index ce82cb86e6..bfad7791f8 100644 --- a/src/libasr/codegen/asr_to_c.cpp +++ b/src/libasr/codegen/asr_to_c.cpp @@ -1280,27 +1280,12 @@ R"( src = "strlen(" + src + ")"; } - void visit_GoTo(const ASR::GoTo_t &x) { - std::string indent(indentation_level*indentation_spaces, ' '); - src = indent + "goto " + std::string(x.m_name) + ";\n"; - } - - void visit_GoToTarget(const ASR::GoToTarget_t &x) { - src = std::string(x.m_name) + ":\n"; - } }; -Result asr_to_c(Allocator &al, ASR::TranslationUnit_t &asr, +Result asr_to_c(Allocator & /*al*/, ASR::TranslationUnit_t &asr, diag::Diagnostics &diagnostics, CompilerOptions &co, int64_t default_lower_bound) { - - LCompilers::PassOptions pass_options; - pass_options.always_run = true; - pass_create_subroutine_from_function(al, asr, pass_options); - pass_replace_array_op(al, asr, pass_options); - pass_unused_functions(al, asr, pass_options); - pass_replace_class_constructor(al, asr, pass_options); ASRToCVisitor v(diagnostics, co, default_lower_bound); try { v.visit_asr((ASR::asr_t &)asr); diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index fb69904bcb..aa3cbfbfb2 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -102,6 +102,7 @@ class BaseCCPPVisitor : public ASR::BaseVisitor const ASR::Function_t *current_function = nullptr; std::map sym_info; std::map const_var_names; + std::map gotoid2name; // Output configuration: // Use std::string or char* @@ -331,6 +332,15 @@ R"(#include std::string indent(indentation_level*indentation_spaces, ' '); std::string open_paranthesis = indent + "{\n"; std::string close_paranthesis = indent + "}\n"; + if (x.m_label != -1) { + std::string b_name; + if (gotoid2name.find(x.m_label) != gotoid2name.end()) { + b_name = gotoid2name[x.m_label]; + } else { + b_name = "__" +std::to_string(x.m_label); + } + open_paranthesis = indent + b_name + ": {\n"; + } indent += std::string(indentation_spaces, ' '); indentation_level += 1; SymbolTable* current_scope_copy = current_scope; @@ -1911,9 +1921,14 @@ R"(#include } } - void visit_GoToTarget(const ASR::GoToTarget_t & /* x */) { - // Ignore for now - src = ""; + void visit_GoTo(const ASR::GoTo_t &x) { + std::string indent(indentation_level*indentation_spaces, ' '); + src = indent + "goto " + std::string(x.m_name) + ";\n"; + gotoid2name[x.m_target_id] = std::string(x.m_name); + } + + void visit_GoToTarget(const ASR::GoToTarget_t &x) { + src = std::string(x.m_name) + ":\n"; } void visit_Stop(const ASR::Stop_t &x) { diff --git a/src/libasr/pass/pass_list_expr.cpp b/src/libasr/pass/pass_list_expr.cpp index efabbd28ab..a0cf68740c 100644 --- a/src/libasr/pass/pass_list_expr.cpp +++ b/src/libasr/pass/pass_list_expr.cpp @@ -152,7 +152,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer */ SymbolTable* list_section_symtab = al.make_new(global_scope); - std::string list_type_name = ASRUtils::type_to_str_python(list_type); + std::string list_type_name = ASRUtils::get_type_code(list_type, true); std::string fn_name = global_scope->get_unique_name("_lcompilers_list_section_" + list_type_name); ASR::ttype_t* item_type = ASR::down_cast(list_type)->m_type; ASR::ttype_t* int_type = ASRUtils::TYPE(ASR::make_Integer_t( @@ -409,7 +409,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer call_arg.m_value = is_end_present; args.push_back(al, call_arg); - std::string list_type_name = ASRUtils::type_to_str_python(x->m_type); + std::string list_type_name = ASRUtils::get_type_code(x->m_type, true); if (list_section_func_map.find(list_type_name) == list_section_func_map.end()) { create_list_section_func(unit.base.base.loc, unit.m_global_scope, x->m_type); @@ -437,7 +437,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer return result_list */ SymbolTable* list_concat_symtab = al.make_new(global_scope); - std::string list_type_name = ASRUtils::type_to_str_python(list_type); + std::string list_type_name = ASRUtils::get_type_code(list_type, true); std::string fn_name = global_scope->get_unique_name("_lcompilers_list_concat_" + list_type_name); Vec arg_exprs; @@ -535,7 +535,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer right_list.loc = x->m_right->base.loc; right_list.m_value = x->m_right; args.push_back(al, right_list); - std::string list_type_name = ASRUtils::type_to_str_python(x->m_type); + std::string list_type_name = ASRUtils::get_type_code(x->m_type, true); if (list_concat_func_map.find(list_type_name) == list_concat_func_map.end()) { create_concat_function(unit.base.base.loc, unit.m_global_scope, x->m_type); diff --git a/src/libasr/pass/pass_manager.h b/src/libasr/pass/pass_manager.h index 3f3bcddb66..8dfb256c7c 100644 --- a/src/libasr/pass/pass_manager.h +++ b/src/libasr/pass/pass_manager.h @@ -59,7 +59,7 @@ namespace LCompilers { std::vector _passes; std::vector _with_optimization_passes; std::vector _user_defined_passes; - std::vector _skip_passes; + std::vector _skip_passes, _c_skip_passes; std::map _passes_db = { {"do_loops", &pass_replace_do_loops}, {"global_stmts", &pass_wrap_global_stmts_into_function}, @@ -90,6 +90,7 @@ namespace LCompilers { bool is_fast; bool apply_default_passes; + bool c_skip_pass; // This will contain the passes that are to be skipped in C void _apply_passes(Allocator& al, ASR::TranslationUnit_t* asr, std::vector& passes, PassOptions &pass_options, @@ -103,6 +104,9 @@ namespace LCompilers { if (rtlib && passes[i] == "unused_functions") continue; if( std::find(_skip_passes.begin(), _skip_passes.end(), passes[i]) != _skip_passes.end()) continue; + if (c_skip_pass && std::find(_c_skip_passes.begin(), + _c_skip_passes.end(), passes[i]) != _c_skip_passes.end()) + continue; _passes_db[passes[i]](al, *asr, pass_options); #if defined(WITH_LFORTRAN_ASSERT) if (!asr_verify(*asr, true, diagnostics)) { @@ -142,7 +146,8 @@ namespace LCompilers { } } - PassManager(): is_fast{false}, apply_default_passes{false} { + PassManager(): is_fast{false}, apply_default_passes{false}, + c_skip_pass{false} { _passes = { "global_stmts", "init_expr", @@ -191,6 +196,14 @@ namespace LCompilers { "inline_function_calls" }; + // These are re-write passes which are already handled + // appropriately in C backend. + _c_skip_passes = { + "pass_list_expr", + "print_list_tuple", + "do_loops", + "inline_function_calls" + }; _user_defined_passes.clear(); } @@ -227,8 +240,9 @@ namespace LCompilers { is_fast = false; } - void use_default_passes() { + void use_default_passes(bool _c_skip_pass=false) { apply_default_passes = true; + c_skip_pass = _c_skip_pass; } void do_not_use_default_passes() {