Skip to content

Commit 0f92df6

Browse files
committed
WASM: Support emitting functions based on requirement
1 parent d22dc94 commit 0f92df6

File tree

1 file changed

+107
-48
lines changed

1 file changed

+107
-48
lines changed

src/libasr/codegen/asr_to_wasm.cpp

Lines changed: 107 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
7373
uint32_t nesting_level;
7474
uint32_t cur_loop_nesting_level;
7575
bool is_prototype_only;
76+
ASR::Function_t* main_func;
7677

7778
Vec<uint8_t> m_type_section;
7879
Vec<uint8_t> m_import_section;
@@ -103,11 +104,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
103104
std::map<std::string, uint32_t> m_self_func_name_idx_map;
104105
std::map<std::string, uint32_t> m_string_to_iov_loc_map;
105106

107+
std::map<std::string,void (LCompilers::ASRToWASMVisitor::*)(int)> m_self_funcs_map;
108+
106109
public:
107110
ASRToWASMVisitor(Allocator &al, diag::Diagnostics &diagnostics)
108111
: m_al(al), diag(diagnostics) {
109112
intrinsic_module = false;
110113
is_prototype_only = false;
114+
main_func = nullptr;
111115
nesting_level = 0;
112116
cur_loop_nesting_level = 0;
113117
no_of_types = 0;
@@ -357,9 +361,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
357361
std::vector<wasm::type> results,
358362
std::vector<wasm::type> locals,
359363
std::string func_name,
360-
std::function<void()> func_body) {
364+
std::function<void()> func_body,
365+
int func_idx = -1
366+
) {
367+
368+
if (func_idx == -1) {
369+
func_idx = no_of_types++;
370+
}
361371

362-
uint32_t func_idx = no_of_types;
363372
{ // type declaration
364373
wasm::emit_b8(m_type_section, m_al, 0x60);
365374
wasm::emit_u32(m_type_section, m_al, params.size()); // no of params
@@ -370,7 +379,6 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
370379
for (auto result:results) {
371380
wasm::emit_b8(m_type_section, m_al, result);
372381
}
373-
no_of_types++;
374382
}
375383

376384
/*** Reference Function Prototype ***/
@@ -394,12 +402,11 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
394402

395403
/*** Export the function ***/
396404
wasm::emit_export_fn(m_export_section, m_al, func_name, func_idx); // add function to export
397-
m_self_func_name_idx_map[func_name] = func_idx;
398405
no_of_functions++;
399406
no_of_exports++;
400407
}
401408

402-
void emit_print_int() {
409+
void emit_print_int(int fn_idx = -1) {
403410
using namespace wasm;
404411
define_emit_func({i64}, {}, {i64, i64, i64, i64}, "print_i64", [&](){
405412
// locals 0 is given parameter
@@ -509,10 +516,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
509516
}
510517

511518
});
512-
});
519+
}, fn_idx);
513520
}
514521

515-
void emit_print_float() {
522+
void emit_print_float(int fn_idx = -1) {
516523
using namespace wasm;
517524
define_emit_func({f64}, {}, {i64, i64, i64}, "print_f64", [&](){
518525
emit_if_else([&](){
@@ -581,10 +588,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
581588

582589
wasm::emit_get_local(m_code_section, m_al, 3);
583590
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["print_i64"]);
584-
});
591+
}, fn_idx);
585592
}
586593

587-
void emit_complex_add_32() {
594+
void emit_complex_add_32(int fn_idx = -1) {
588595
using namespace wasm;
589596
define_emit_func({f32, f32, f32, f32}, {f32, f32}, {}, "add_c32", [&](){
590597
wasm::emit_get_local(m_code_section, m_al, 0);
@@ -594,10 +601,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
594601
wasm::emit_get_local(m_code_section, m_al, 1);
595602
wasm::emit_get_local(m_code_section, m_al, 3);
596603
wasm::emit_f32_add(m_code_section, m_al);
597-
});
604+
}, fn_idx);
598605
}
599606

600-
void emit_complex_add_64() {
607+
void emit_complex_add_64(int fn_idx = -1) {
601608
using namespace wasm;
602609
define_emit_func({f64, f64, f64, f64}, {f64, f64}, {}, "add_c64", [&](){
603610
wasm::emit_get_local(m_code_section, m_al, 0);
@@ -607,10 +614,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
607614
wasm::emit_get_local(m_code_section, m_al, 1);
608615
wasm::emit_get_local(m_code_section, m_al, 3);
609616
wasm::emit_f64_add(m_code_section, m_al);
610-
});
617+
}, fn_idx);
611618
}
612619

613-
void emit_complex_sub_32() {
620+
void emit_complex_sub_32(int fn_idx = -1) {
614621
using namespace wasm;
615622
define_emit_func({f32, f32, f32, f32}, {f32, f32}, {}, "sub_c32", [&](){
616623
wasm::emit_get_local(m_code_section, m_al, 0);
@@ -620,10 +627,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
620627
wasm::emit_get_local(m_code_section, m_al, 1);
621628
wasm::emit_get_local(m_code_section, m_al, 3);
622629
wasm::emit_f32_sub(m_code_section, m_al);
623-
});
630+
}, fn_idx);
624631
}
625632

626-
void emit_complex_sub_64() {
633+
void emit_complex_sub_64(int fn_idx = -1) {
627634
using namespace wasm;
628635
define_emit_func({f64, f64, f64, f64}, {f64, f64}, {}, "sub_c64", [&](){
629636
wasm::emit_get_local(m_code_section, m_al, 0);
@@ -633,10 +640,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
633640
wasm::emit_get_local(m_code_section, m_al, 1);
634641
wasm::emit_get_local(m_code_section, m_al, 3);
635642
wasm::emit_f64_sub(m_code_section, m_al);
636-
});
643+
}, fn_idx);
637644
}
638645

639-
void emit_complex_mul_32() {
646+
void emit_complex_mul_32(int fn_idx = -1) {
640647
using namespace wasm;
641648
define_emit_func({f32, f32, f32, f32}, {f32, f32}, {}, "mul_c32", [&](){
642649
wasm::emit_get_local(m_code_section, m_al, 0);
@@ -658,10 +665,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
658665
wasm::emit_f32_mul(m_code_section, m_al);
659666

660667
wasm::emit_f32_add(m_code_section, m_al);
661-
});
668+
}, fn_idx);
662669
}
663670

664-
void emit_complex_mul_64() {
671+
void emit_complex_mul_64(int fn_idx = -1) {
665672
using namespace wasm;
666673
define_emit_func({f64, f64, f64, f64}, {f64, f64}, {}, "mul_c64", [&](){
667674
wasm::emit_get_local(m_code_section, m_al, 0);
@@ -683,10 +690,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
683690
wasm::emit_f64_mul(m_code_section, m_al);
684691

685692
wasm::emit_f64_add(m_code_section, m_al);
686-
});
693+
}, fn_idx);
687694
}
688695

689-
void emit_complex_abs_32() {
696+
void emit_complex_abs_32(int fn_idx = -1) {
690697
using namespace wasm;
691698
define_emit_func({f32, f32}, {f32}, {}, "abs_c32", [&](){
692699
wasm::emit_get_local(m_code_section, m_al, 0);
@@ -699,10 +706,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
699706

700707
wasm::emit_f32_add(m_code_section, m_al);
701708
wasm::emit_f32_sqrt(m_code_section, m_al);
702-
});
709+
}, fn_idx);
703710
}
704711

705-
void emit_complex_abs_64() {
712+
void emit_complex_abs_64(int fn_idx = -1) {
706713
using namespace wasm;
707714
define_emit_func({f64, f64}, {f64}, {}, "abs_c64", [&](){
708715
wasm::emit_get_local(m_code_section, m_al, 0);
@@ -715,7 +722,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
715722

716723
wasm::emit_f64_add(m_code_section, m_al);
717724
wasm::emit_f64_sqrt(m_code_section, m_al);
718-
});
725+
}, fn_idx);
719726
}
720727

721728
template <typename T>
@@ -766,16 +773,17 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
766773
for (int i = 0; i < 10; i++) {
767774
emit_string(std::to_string(i));
768775
}
769-
emit_print_int();
770-
emit_print_float();
771-
emit_complex_add_32();
772-
emit_complex_add_64();
773-
emit_complex_sub_32();
774-
emit_complex_sub_64();
775-
emit_complex_mul_32();
776-
emit_complex_mul_64();
777-
emit_complex_abs_32();
778-
emit_complex_abs_64();
776+
777+
m_self_funcs_map["print_i64"] = &ASRToWASMVisitor::emit_print_int;
778+
m_self_funcs_map["print_f64"] = &ASRToWASMVisitor::emit_print_float;
779+
m_self_funcs_map["add_c32"] = &ASRToWASMVisitor::emit_complex_add_32;
780+
m_self_funcs_map["add_c64"] = &ASRToWASMVisitor::emit_complex_add_64;
781+
m_self_funcs_map["sub_c32"] = &ASRToWASMVisitor::emit_complex_sub_32;
782+
m_self_funcs_map["sub_c64"] = &ASRToWASMVisitor::emit_complex_sub_64;
783+
m_self_funcs_map["mul_c32"] = &ASRToWASMVisitor::emit_complex_mul_32;
784+
m_self_funcs_map["mul_c64"] = &ASRToWASMVisitor::emit_complex_mul_64;
785+
m_self_funcs_map["abs_c32"] = &ASRToWASMVisitor::emit_complex_abs_32;
786+
m_self_funcs_map["abs_c64"] = &ASRToWASMVisitor::emit_complex_abs_64;
779787

780788
{
781789
// Pre-declare all functions first, then generate code
@@ -790,9 +798,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
790798
x.m_global_scope->get_scope().end());
791799
ASR::symbol_t *mod = x.m_global_scope->get_symbol(item);
792800
if (ASR::is_a<ASR::Module_t>(*mod)) {
793-
ASR::Module_t *m =
794-
ASR::down_cast<ASR::Module_t>(mod);
795-
declare_all_functions(*(m->m_symtab));
801+
visit_symbol(*mod);
796802
}
797803
}
798804

@@ -802,9 +808,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
802808
// then the main program:
803809
for (auto &item : x.m_global_scope->get_scope()) {
804810
if (ASR::is_a<ASR::Program_t>(*item.second)) {
805-
ASR::Program_t *p =
806-
ASR::down_cast<ASR::Program_t>(item.second);
807-
declare_all_functions(*(p->m_symtab));
811+
visit_symbol(*item.second);
808812
}
809813
}
810814
}
@@ -845,6 +849,21 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
845849
visit_symbol(*item.second);
846850
}
847851
}
852+
853+
std::vector<std::pair<std::string, uint32_t>> ordered_self_funcs_name_idx;
854+
for (auto self_func:m_self_func_name_idx_map) {
855+
ordered_self_funcs_name_idx.push_back(self_func);
856+
}
857+
858+
sort(ordered_self_funcs_name_idx.begin(),
859+
ordered_self_funcs_name_idx.end(),
860+
[](std::pair<std::string, uint32_t> &a, std::pair<std::string, uint32_t> &b){
861+
return a.second < b.second;
862+
});
863+
864+
for (auto self_func:ordered_self_funcs_name_idx) {
865+
(this->*m_self_funcs_map[self_func.first])(self_func.second);
866+
}
848867
}
849868

850869
void declare_all_functions(const SymbolTable &symtab) {
@@ -876,14 +895,15 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
876895
declare_all_functions(*x.m_symtab);
877896

878897
// Generate main program code
879-
auto main_func = ASRUtils::make_Function_t_util(
880-
m_al, x.base.base.loc, x.m_symtab, s2c(m_al, "_start"),
881-
nullptr, 0, nullptr, 0, x.m_body, x.n_body, nullptr,
882-
ASR::abiType::Source, ASR::accessType::Public,
883-
ASR::deftypeType::Implementation, nullptr, false, false, false, false, false,
884-
nullptr, 0, nullptr, 0, false, false, false);
885-
emit_function_prototype(*((ASR::Function_t *)main_func));
886-
emit_function_body(*((ASR::Function_t *)main_func));
898+
if (main_func == nullptr) {
899+
main_func = (ASR::Function_t *)ASRUtils::make_Function_t_util(
900+
m_al, x.base.base.loc, x.m_symtab, s2c(m_al, "_start"),
901+
nullptr, 0, nullptr, 0, x.m_body, x.n_body, nullptr,
902+
ASR::abiType::Source, ASR::accessType::Public,
903+
ASR::deftypeType::Implementation, nullptr, false, false, false, false, false,
904+
nullptr, 0, nullptr, 0, false, false, false);
905+
}
906+
this->visit_Function(*main_func);
887907
}
888908

889909
void emit_var_type(Vec<uint8_t> &code, ASR::Variable_t *v) {
@@ -1685,24 +1705,42 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
16851705
switch (x.m_op) {
16861706
case ASR::binopType::Add: {
16871707
if (a_kind == 4) {
1708+
if (m_self_func_name_idx_map.find("add_c32") == m_self_func_name_idx_map.end()) {
1709+
m_self_func_name_idx_map["add_c32"] = no_of_types++;
1710+
}
16881711
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["add_c32"]);
16891712
} else {
1713+
if (m_self_func_name_idx_map.find("add_c64") == m_self_func_name_idx_map.end()) {
1714+
m_self_func_name_idx_map["add_c64"] = no_of_types++;
1715+
}
16901716
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["add_c64"]);
16911717
}
16921718
break;
16931719
};
16941720
case ASR::binopType::Sub: {
16951721
if (a_kind == 4) {
1722+
if (m_self_func_name_idx_map.find("sub_c32") == m_self_func_name_idx_map.end()) {
1723+
m_self_func_name_idx_map["sub_c32"] = no_of_types++;
1724+
}
16961725
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["sub_c32"]);
16971726
} else {
1727+
if (m_self_func_name_idx_map.find("sub_c64") == m_self_func_name_idx_map.end()) {
1728+
m_self_func_name_idx_map["sub_c64"] = no_of_types++;
1729+
}
16981730
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["sub_c64"]);
16991731
}
17001732
break;
17011733
};
17021734
case ASR::binopType::Mul: {
17031735
if (a_kind == 4) {
1736+
if (m_self_func_name_idx_map.find("mul_c32") == m_self_func_name_idx_map.end()) {
1737+
m_self_func_name_idx_map["mul_c32"] = no_of_types++;
1738+
}
17041739
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["mul_c32"]);
17051740
} else {
1741+
if (m_self_func_name_idx_map.find("mul_c64") == m_self_func_name_idx_map.end()) {
1742+
m_self_func_name_idx_map["mul_c64"] = no_of_types++;
1743+
}
17061744
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["mul_c64"]);
17071745
}
17081746
break;
@@ -2629,10 +2667,16 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
26292667
int arg_kind = -1, dest_kind = -1;
26302668
extract_kinds(x, arg_kind, dest_kind);
26312669
if (arg_kind == 4) {
2670+
if (m_self_func_name_idx_map.find("abs_c32") == m_self_func_name_idx_map.end()) {
2671+
m_self_func_name_idx_map["abs_c32"] = no_of_types++;
2672+
}
26322673
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["abs_c32"]);
26332674
wasm::emit_f32_const(m_code_section, m_al, 0.0);
26342675
wasm::emit_f32_gt(m_code_section, m_al);
26352676
} else if (arg_kind == 8) {
2677+
if (m_self_func_name_idx_map.find("abs_c64") == m_self_func_name_idx_map.end()) {
2678+
m_self_func_name_idx_map["abs_c64"] = no_of_types++;
2679+
}
26362680
wasm::emit_call(m_code_section, m_al, m_self_func_name_idx_map["abs_c64"]);
26372681
wasm::emit_f64_const(m_code_section, m_al, 0.0);
26382682
wasm::emit_f64_gt(m_code_section, m_al);
@@ -2773,6 +2817,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
27732817
int a_kind = ASRUtils::extract_kind_from_ttype_t(t);
27742818

27752819
if (ASRUtils::is_integer(*t) || ASRUtils::is_logical(*t)) {
2820+
if (m_self_func_name_idx_map.find("print_i64") == m_self_func_name_idx_map.end()) {
2821+
m_self_func_name_idx_map["print_i64"] = no_of_types++;
2822+
}
27762823
this->visit_expr(*x.m_values[i]);
27772824
switch (a_kind) {
27782825
case 4: {
@@ -2791,6 +2838,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
27912838
}
27922839
}
27932840
} else if (ASRUtils::is_real(*t)) {
2841+
if (m_self_func_name_idx_map.find("print_i64") == m_self_func_name_idx_map.end()) {
2842+
m_self_func_name_idx_map["print_i64"] = no_of_types++;
2843+
}
2844+
if (m_self_func_name_idx_map.find("print_f64") == m_self_func_name_idx_map.end()) {
2845+
m_self_func_name_idx_map["print_f64"] = no_of_types++;
2846+
}
27942847
this->visit_expr(*x.m_values[i]);
27952848
switch (a_kind) {
27962849
case 4: {
@@ -2822,6 +2875,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
28222875
->index);
28232876
wasm::emit_drop(m_code_section, m_al);
28242877
} else if (t->type == ASR::ttypeType::Complex) {
2878+
if (m_self_func_name_idx_map.find("print_i64") == m_self_func_name_idx_map.end()) {
2879+
m_self_func_name_idx_map["print_i64"] = no_of_types++;
2880+
}
2881+
if (m_self_func_name_idx_map.find("print_f64") == m_self_func_name_idx_map.end()) {
2882+
m_self_func_name_idx_map["print_f64"] = no_of_types++;
2883+
}
28252884
emit_call_fd_write(1, "(", 1, 0);
28262885
this->visit_expr(*x.m_values[i]);
28272886
if (a_kind == 4) {

0 commit comments

Comments
 (0)