Skip to content

Commit 37f6b2c

Browse files
authored
Merge pull request #1223 from Shaikh-Ubaid/wasm_to_x86_backend
Wasm to x86 backend
2 parents 27dd868 + 16b6436 commit 37f6b2c

File tree

8 files changed

+809
-331
lines changed

8 files changed

+809
-331
lines changed

src/bin/lpython.cpp

Lines changed: 158 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <libasr/codegen/asr_to_x86.h>
1717
#include <libasr/codegen/asr_to_wasm.h>
1818
#include <libasr/codegen/wasm_to_wat.h>
19+
#include <libasr/codegen/wasm_to_x86.h>
1920
#include <lpython/python_evaluator.h>
2021
#include <libasr/codegen/evaluator.h>
2122
#include <libasr/pass/pass_manager.h>
@@ -49,7 +50,7 @@ using LFortran::CompilerOptions;
4950
using LFortran::parse_python_file;
5051

5152
enum Backend {
52-
llvm, cpp, x86, wasm
53+
llvm, cpp, x86, wasm, wasm_x86
5354
};
5455

5556
std::string remove_extension(const std::string& filename) {
@@ -720,6 +721,150 @@ int compile_to_binary_wasm(
720721
return 0;
721722
}
722723

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+
723868
// infile is an object file
724869
// outfile will become the executable
725870
int link_executable(const std::vector<std::string> &infiles,
@@ -1161,7 +1306,7 @@ int main(int argc, char *argv[])
11611306
app.add_flag("--static", static_link, "Create a static executable");
11621307
app.add_flag("--no-warnings", compiler_options.no_warnings, "Turn off all warnings");
11631308
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();
11651310
app.add_flag("--openmp", compiler_options.openmp, "Enable openmp");
11661311
app.add_flag("--fast", compiler_options.fast, "Best performance (disable strict standard compliance)");
11671312
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[])
12771422
backend = Backend::x86;
12781423
} else if (arg_backend == "wasm") {
12791424
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;
12821429
return 1;
12831430
}
12841431

@@ -1397,9 +1544,15 @@ int main(int argc, char *argv[])
13971544

13981545
if (endswith(arg_file, ".py"))
13991546
{
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) {
14011551
return compile_to_binary_wasm(arg_file, outfile,
14021552
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);
14031556
}
14041557

14051558
std::string tmp_o = outfile + ".tmp.o";

src/libasr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ set(SRC
2323
codegen/asr_to_x86.cpp
2424
codegen/asr_to_wasm.cpp
2525
codegen/wasm_to_wat.cpp
26+
codegen/wasm_to_x86.cpp
2627
codegen/wasm_utils.cpp
2728

2829
pass/param_to_const.cpp

src/libasr/codegen/asr_to_x86.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,24 @@ class ASRToX86Visitor : public ASR::BaseVisitor<ASRToX86Visitor>
6060
// must be empty:
6161
LFORTRAN_ASSERT(x.n_items == 0);
6262

63+
emit_elf32_header(m_a);
64+
65+
// Add runtime library functions
66+
emit_print_int(m_a, "print_int");
67+
emit_exit(m_a, "exit", 0);
68+
emit_exit(m_a, "exit_error_stop", 1);
6369
for (auto &item : x.m_global_scope->get_scope()) {
6470
if (!is_a<ASR::Variable_t>(*item.second)) {
6571
visit_symbol(*item.second);
6672
}
6773
}
74+
75+
emit_elf32_footer(m_a);
6876
}
6977

7078
void visit_Program(const ASR::Program_t &x) {
7179

72-
emit_elf32_header(m_a);
7380

74-
// Add runtime library functions
75-
emit_print_int(m_a, "print_int");
76-
emit_exit(m_a, "exit", 0);
77-
emit_exit(m_a, "exit_error_stop", 1);
7881

7982
// Generate code for nested subroutines and functions first:
8083
for (auto &item : x.m_symtab->get_scope()) {
@@ -126,7 +129,6 @@ class ASRToX86Visitor : public ASR::BaseVisitor<ASRToX86Visitor>
126129
emit_data_string(m_a, s.first, s.second);
127130
}
128131

129-
emit_elf32_footer(m_a);
130132
}
131133

132134
void visit_Function(const ASR::Function_t &x) {
@@ -186,7 +188,7 @@ class ASRToX86Visitor : public ASR::BaseVisitor<ASRToX86Visitor>
186188
}
187189

188190
// Leave return value in eax
189-
{
191+
if (x.m_return_var) {
190192
ASR::Variable_t *retv = LFortran::ASRUtils::EXPR2VAR(x.m_return_var);
191193

192194
uint32_t h = get_hash((ASR::asr_t*)retv);
@@ -204,6 +206,8 @@ class ASRToX86Visitor : public ASR::BaseVisitor<ASRToX86Visitor>
204206
m_a.asm_ret();
205207
}
206208

209+
void visit_Return(const ASR::Return_t &/*x*/) { }
210+
207211
// Expressions leave integer values in eax
208212

209213
void visit_IntegerConstant(const ASR::IntegerConstant_t &x) {

0 commit comments

Comments
 (0)