|
16 | 16 | #include <libasr/codegen/asr_to_x86.h>
|
17 | 17 | #include <libasr/codegen/asr_to_wasm.h>
|
18 | 18 | #include <libasr/codegen/wasm_to_wat.h>
|
| 19 | +#include <libasr/codegen/wasm_to_x86.h> |
19 | 20 | #include <lpython/python_evaluator.h>
|
20 | 21 | #include <libasr/codegen/evaluator.h>
|
21 | 22 | #include <libasr/pass/pass_manager.h>
|
@@ -49,7 +50,7 @@ using LFortran::CompilerOptions;
|
49 | 50 | using LFortran::parse_python_file;
|
50 | 51 |
|
51 | 52 | enum Backend {
|
52 |
| - llvm, cpp, x86, wasm |
| 53 | + llvm, cpp, x86, wasm, wasm_x86 |
53 | 54 | };
|
54 | 55 |
|
55 | 56 | std::string remove_extension(const std::string& filename) {
|
@@ -720,6 +721,150 @@ int compile_to_binary_wasm(
|
720 | 721 | return 0;
|
721 | 722 | }
|
722 | 723 |
|
| 724 | +int compile_to_binary_x86( |
| 725 | + const std::string &infile, |
| 726 | + const std::string &outfile, |
| 727 | + const std::string &runtime_library_dir, |
| 728 | + CompilerOptions &compiler_options, |
| 729 | + bool time_report) |
| 730 | +{ |
| 731 | + Allocator al(4*1024); |
| 732 | + LFortran::diag::Diagnostics diagnostics; |
| 733 | + LFortran::LocationManager lm; |
| 734 | + lm.in_filename = infile; |
| 735 | + std::vector<std::pair<std::string, double>>times; |
| 736 | + auto file_reading_start = std::chrono::high_resolution_clock::now(); |
| 737 | + std::string input = LFortran::read_file(infile); |
| 738 | + auto file_reading_end = std::chrono::high_resolution_clock::now(); |
| 739 | + times.push_back(std::make_pair("File reading", std::chrono::duration<double, std::milli>(file_reading_end - file_reading_start).count())); |
| 740 | + lm.init_simple(input); |
| 741 | + auto parsing_start = std::chrono::high_resolution_clock::now(); |
| 742 | + LFortran::Result<LFortran::LPython::AST::ast_t*> r = parse_python_file( |
| 743 | + al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); |
| 744 | + auto parsing_end = std::chrono::high_resolution_clock::now(); |
| 745 | + times.push_back(std::make_pair("Parsing", std::chrono::duration<double, std::milli>(parsing_end - parsing_start).count())); |
| 746 | + std::cerr << diagnostics.render(input, lm, compiler_options); |
| 747 | + if (!r.ok) { |
| 748 | + print_time_report(times, time_report); |
| 749 | + return 1; |
| 750 | + } |
| 751 | + |
| 752 | + // Src -> AST -> ASR |
| 753 | + LFortran::LPython::AST::ast_t* ast = r.result; |
| 754 | + diagnostics.diagnostics.clear(); |
| 755 | + auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); |
| 756 | + LFortran::Result<LFortran::ASR::TranslationUnit_t*> |
| 757 | + r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, |
| 758 | + compiler_options.disable_main, compiler_options.symtab_only, infile, compiler_options.import_path); |
| 759 | + auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); |
| 760 | + times.push_back(std::make_pair("AST to ASR", std::chrono::duration<double, std::milli>(ast_to_asr_end - ast_to_asr_start).count())); |
| 761 | + std::cerr << diagnostics.render(input, lm, compiler_options); |
| 762 | + if (!r1.ok) { |
| 763 | + LFORTRAN_ASSERT(diagnostics.has_error()) |
| 764 | + print_time_report(times, time_report); |
| 765 | + return 2; |
| 766 | + } |
| 767 | + LFortran::ASR::TranslationUnit_t* asr = r1.result; |
| 768 | + if( compiler_options.disable_main ) { |
| 769 | + int err = LFortran::LPython::save_pyc_files(*asr, infile); |
| 770 | + if( err ) { |
| 771 | + return err; |
| 772 | + } |
| 773 | + } |
| 774 | + diagnostics.diagnostics.clear(); |
| 775 | + |
| 776 | + // ASR -> X86 |
| 777 | + auto asr_to_x86_start = std::chrono::high_resolution_clock::now(); |
| 778 | + LFortran::Result<int> r3 = LFortran::asr_to_x86(*asr, al, outfile, time_report); |
| 779 | + auto asr_to_x86_end = std::chrono::high_resolution_clock::now(); |
| 780 | + times.push_back(std::make_pair("ASR to X86", std::chrono::duration<double, std::milli>(asr_to_x86_end - asr_to_x86_start).count())); |
| 781 | + std::cerr << diagnostics.render(input, lm, compiler_options); |
| 782 | + print_time_report(times, time_report); |
| 783 | + if (!r3.ok) { |
| 784 | + LFORTRAN_ASSERT(diagnostics.has_error()) |
| 785 | + return 3; |
| 786 | + } |
| 787 | + return 0; |
| 788 | +} |
| 789 | + |
| 790 | +int compile_to_binary_wasm_to_x86( |
| 791 | + const std::string &infile, |
| 792 | + const std::string &outfile, |
| 793 | + const std::string &runtime_library_dir, |
| 794 | + CompilerOptions &compiler_options, |
| 795 | + bool time_report) |
| 796 | +{ |
| 797 | + Allocator al(4*1024); |
| 798 | + LFortran::diag::Diagnostics diagnostics; |
| 799 | + LFortran::LocationManager lm; |
| 800 | + lm.in_filename = infile; |
| 801 | + std::vector<std::pair<std::string, double>>times; |
| 802 | + auto file_reading_start = std::chrono::high_resolution_clock::now(); |
| 803 | + std::string input = LFortran::read_file(infile); |
| 804 | + auto file_reading_end = std::chrono::high_resolution_clock::now(); |
| 805 | + times.push_back(std::make_pair("File reading", std::chrono::duration<double, std::milli>(file_reading_end - file_reading_start).count())); |
| 806 | + lm.init_simple(input); |
| 807 | + auto parsing_start = std::chrono::high_resolution_clock::now(); |
| 808 | + LFortran::Result<LFortran::LPython::AST::ast_t*> r = parse_python_file( |
| 809 | + al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); |
| 810 | + auto parsing_end = std::chrono::high_resolution_clock::now(); |
| 811 | + times.push_back(std::make_pair("Parsing", std::chrono::duration<double, std::milli>(parsing_end - parsing_start).count())); |
| 812 | + std::cerr << diagnostics.render(input, lm, compiler_options); |
| 813 | + if (!r.ok) { |
| 814 | + print_time_report(times, time_report); |
| 815 | + return 1; |
| 816 | + } |
| 817 | + |
| 818 | + // Src -> AST -> ASR |
| 819 | + LFortran::LPython::AST::ast_t* ast = r.result; |
| 820 | + diagnostics.diagnostics.clear(); |
| 821 | + auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); |
| 822 | + LFortran::Result<LFortran::ASR::TranslationUnit_t*> |
| 823 | + r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, |
| 824 | + compiler_options.disable_main, compiler_options.symtab_only, infile, compiler_options.import_path); |
| 825 | + auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); |
| 826 | + times.push_back(std::make_pair("AST to ASR", std::chrono::duration<double, std::milli>(ast_to_asr_end - ast_to_asr_start).count())); |
| 827 | + std::cerr << diagnostics.render(input, lm, compiler_options); |
| 828 | + if (!r1.ok) { |
| 829 | + LFORTRAN_ASSERT(diagnostics.has_error()) |
| 830 | + print_time_report(times, time_report); |
| 831 | + return 2; |
| 832 | + } |
| 833 | + LFortran::ASR::TranslationUnit_t* asr = r1.result; |
| 834 | + if( compiler_options.disable_main ) { |
| 835 | + int err = LFortran::LPython::save_pyc_files(*asr, infile); |
| 836 | + if( err ) { |
| 837 | + return err; |
| 838 | + } |
| 839 | + } |
| 840 | + diagnostics.diagnostics.clear(); |
| 841 | + |
| 842 | + // ASR -> WASM |
| 843 | + auto asr_to_wasm_start = std::chrono::high_resolution_clock::now(); |
| 844 | + LFortran::Result<LFortran::Vec<uint8_t>> r3 = LFortran::asr_to_wasm_bytes_stream(*asr, al, diagnostics); |
| 845 | + auto asr_to_wasm_end = std::chrono::high_resolution_clock::now(); |
| 846 | + times.push_back(std::make_pair("ASR to WASM", std::chrono::duration<double, std::milli>(asr_to_wasm_end - asr_to_wasm_start).count())); |
| 847 | + std::cerr << diagnostics.render(input, lm, compiler_options); |
| 848 | + if (!r3.ok) { |
| 849 | + LFORTRAN_ASSERT(diagnostics.has_error()) |
| 850 | + print_time_report(times, time_report); |
| 851 | + return 3; |
| 852 | + } |
| 853 | + |
| 854 | + // WASM -> X86 |
| 855 | + auto wasm_to_x86_start = std::chrono::high_resolution_clock::now(); |
| 856 | + LFortran::Result<int> res = LFortran::wasm_to_x86(r3.result, al, outfile, time_report, diagnostics); |
| 857 | + auto wasm_to_x86_end = std::chrono::high_resolution_clock::now(); |
| 858 | + times.push_back(std::make_pair("WASM to X86", std::chrono::duration<double, std::milli>(wasm_to_x86_end - wasm_to_x86_start).count())); |
| 859 | + std::cerr << diagnostics.render(input, lm, compiler_options); |
| 860 | + print_time_report(times, time_report); |
| 861 | + if (!res.ok) { |
| 862 | + LFORTRAN_ASSERT(diagnostics.has_error()) |
| 863 | + return 4; |
| 864 | + } |
| 865 | + return 0; |
| 866 | +} |
| 867 | + |
723 | 868 | // infile is an object file
|
724 | 869 | // outfile will become the executable
|
725 | 870 | int link_executable(const std::vector<std::string> &infiles,
|
@@ -1161,7 +1306,7 @@ int main(int argc, char *argv[])
|
1161 | 1306 | app.add_flag("--static", static_link, "Create a static executable");
|
1162 | 1307 | app.add_flag("--no-warnings", compiler_options.no_warnings, "Turn off all warnings");
|
1163 | 1308 | app.add_flag("--no-error-banner", compiler_options.no_error_banner, "Turn off error banner");
|
1164 |
| - app.add_option("--backend", arg_backend, "Select a backend (llvm, cpp, x86)")->capture_default_str(); |
| 1309 | + app.add_option("--backend", arg_backend, "Select a backend (llvm, cpp, x86, wasm, wasm_x86)")->capture_default_str(); |
1165 | 1310 | app.add_flag("--openmp", compiler_options.openmp, "Enable openmp");
|
1166 | 1311 | app.add_flag("--fast", compiler_options.fast, "Best performance (disable strict standard compliance)");
|
1167 | 1312 | app.add_option("--target", compiler_options.target, "Generate code for the given target")->capture_default_str();
|
@@ -1277,8 +1422,10 @@ int main(int argc, char *argv[])
|
1277 | 1422 | backend = Backend::x86;
|
1278 | 1423 | } else if (arg_backend == "wasm") {
|
1279 | 1424 | backend = Backend::wasm;
|
1280 |
| - }else { |
1281 |
| - std::cerr << "The backend must be one of: llvm, cpp, x86, wasm." << std::endl; |
| 1425 | + } else if (arg_backend == "wasm_x86") { |
| 1426 | + backend = Backend::wasm_x86; |
| 1427 | + } else { |
| 1428 | + std::cerr << "The backend must be one of: llvm, cpp, x86, wasm, wasm_x86." << std::endl; |
1282 | 1429 | return 1;
|
1283 | 1430 | }
|
1284 | 1431 |
|
@@ -1397,9 +1544,15 @@ int main(int argc, char *argv[])
|
1397 | 1544 |
|
1398 | 1545 | if (endswith(arg_file, ".py"))
|
1399 | 1546 | {
|
1400 |
| - if (backend == Backend::wasm) { |
| 1547 | + if (backend == Backend::x86) { |
| 1548 | + return compile_to_binary_x86(arg_file, outfile, |
| 1549 | + runtime_library_dir, compiler_options, time_report); |
| 1550 | + } else if (backend == Backend::wasm) { |
1401 | 1551 | return compile_to_binary_wasm(arg_file, outfile,
|
1402 | 1552 | runtime_library_dir, compiler_options, time_report);
|
| 1553 | + } else if (backend == Backend::wasm_x86) { |
| 1554 | + return compile_to_binary_wasm_to_x86(arg_file, outfile, |
| 1555 | + runtime_library_dir, compiler_options, time_report); |
1403 | 1556 | }
|
1404 | 1557 |
|
1405 | 1558 | std::string tmp_o = outfile + ".tmp.o";
|
|
0 commit comments