Skip to content

Commit 12d9574

Browse files
Merge pull request #1491 from Thirumalai-Shaktivel/global_symbols
2 parents 05b4864 + 092a46e commit 12d9574

File tree

179 files changed

+731
-383
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

179 files changed

+731
-383
lines changed

integration_tests/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,4 +429,5 @@ RUN(NAME comp_01 LABELS cpython llvm wasm wasm_x64)
429429
RUN(NAME bit_operations_i32 LABELS cpython llvm wasm wasm_x64)
430430
RUN(NAME bit_operations_i64 LABELS cpython llvm wasm)
431431

432-
RUN(NAME test_argv_01 LABELS llvm) # TODO: Test using CPython
432+
RUN(NAME test_argv_01 LABELS llvm) # TODO: Test using CPython
433+
RUN(NAME global_syms_01 LABELS cpython)

integration_tests/global_syms_01.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from ltypes import i32
2+
3+
x: list[i32]
4+
x = [1, 2]
5+
i: i32
6+
i = x[0]
7+
8+
def test_global_symbols():
9+
assert i == 1
10+
assert x[1] == 2
11+
12+
test_global_symbols()

src/libasr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ set(SRC
3232
pass/for_all.cpp
3333
pass/global_stmts.cpp
3434
pass/global_stmts_program.cpp
35+
pass/global_symbols.cpp
3536
pass/select_case.cpp
3637
pass/implied_do_loops.cpp
3738
pass/array_op.cpp

src/libasr/asr_scopes.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,105 @@ std::string SymbolTable::get_unique_name(const std::string &name) {
135135
return unique_name;
136136
}
137137

138+
void SymbolTable::move_symbols_from_global_scope(Allocator &al,
139+
SymbolTable *module_scope, Vec<char *> &syms,
140+
Vec<char *> &mod_dependencies) {
141+
// TODO: This isn't scalable. We have write a visitor in asdl_cpp.py
142+
syms.reserve(al, 4);
143+
mod_dependencies.reserve(al, 4);
144+
for (auto &a : scope) {
145+
switch (a.second->type) {
146+
case (ASR::symbolType::Module): {
147+
// Pass
148+
break;
149+
} case (ASR::symbolType::Function) : {
150+
ASR::Function_t *fn = ASR::down_cast<ASR::Function_t>(a.second);
151+
for (size_t i = 0; i < fn->n_dependencies; i++ ) {
152+
ASR::symbol_t *s = fn->m_symtab->get_symbol(
153+
fn->m_dependencies[i]);
154+
if (s == nullptr) {
155+
std::string block_name = "block";
156+
ASR::symbol_t *block_s = fn->m_symtab->get_symbol(block_name);
157+
int32_t j = 1;
158+
while(block_s != nullptr) {
159+
while(block_s != nullptr) {
160+
ASR::Block_t *b = ASR::down_cast<ASR::Block_t>(block_s);
161+
s = b->m_symtab->get_symbol(fn->m_dependencies[i]);
162+
if (s == nullptr) {
163+
block_s = b->m_symtab->get_symbol("block");
164+
} else {
165+
break;
166+
}
167+
}
168+
if (s == nullptr) {
169+
block_s = fn->m_symtab->get_symbol(block_name +
170+
std::to_string(j));
171+
j++;
172+
} else {
173+
break;
174+
}
175+
}
176+
}
177+
if (s == nullptr) {
178+
s = fn->m_symtab->parent->get_symbol(fn->m_dependencies[i]);
179+
}
180+
if (s != nullptr && ASR::is_a<ASR::ExternalSymbol_t>(*s)) {
181+
char *es_name = ASR::down_cast<
182+
ASR::ExternalSymbol_t>(s)->m_module_name;
183+
if (!present(mod_dependencies, es_name)) {
184+
mod_dependencies.push_back(al, es_name);
185+
}
186+
}
187+
}
188+
fn->m_symtab->parent = module_scope;
189+
module_scope->add_symbol(a.first, (ASR::symbol_t *) fn);
190+
syms.push_back(al, s2c(al, a.first));
191+
break;
192+
} case (ASR::symbolType::GenericProcedure) : {
193+
ASR::GenericProcedure_t *es = ASR::down_cast<ASR::GenericProcedure_t>(a.second);
194+
es->m_parent_symtab = module_scope;
195+
module_scope->add_symbol(a.first, (ASR::symbol_t *) es);
196+
syms.push_back(al, s2c(al, a.first));
197+
break;
198+
} case (ASR::symbolType::ExternalSymbol) : {
199+
ASR::ExternalSymbol_t *es = ASR::down_cast<ASR::ExternalSymbol_t>(a.second);
200+
if (!present(mod_dependencies, es->m_module_name)) {
201+
mod_dependencies.push_back(al, es->m_module_name);
202+
}
203+
es->m_parent_symtab = module_scope;
204+
module_scope->add_symbol(a.first, (ASR::symbol_t *) es);
205+
syms.push_back(al, s2c(al, a.first));
206+
break;
207+
} case (ASR::symbolType::StructType) : {
208+
ASR::StructType_t *st = ASR::down_cast<ASR::StructType_t>(a.second);
209+
st->m_symtab->parent = module_scope;
210+
module_scope->add_symbol(a.first, (ASR::symbol_t *) st);
211+
syms.push_back(al, s2c(al, a.first));
212+
break;
213+
} case (ASR::symbolType::EnumType) : {
214+
ASR::EnumType_t *et = ASR::down_cast<ASR::EnumType_t>(a.second);
215+
et->m_symtab->parent = module_scope;
216+
module_scope->add_symbol(a.first, (ASR::symbol_t *) et);
217+
syms.push_back(al, s2c(al, a.first));
218+
break;
219+
} case (ASR::symbolType::UnionType) : {
220+
ASR::UnionType_t *ut = ASR::down_cast<ASR::UnionType_t>(a.second);
221+
ut->m_symtab->parent = module_scope;
222+
module_scope->add_symbol(a.first, (ASR::symbol_t *) ut);
223+
syms.push_back(al, s2c(al, a.first));
224+
break;
225+
} case (ASR::symbolType::Variable) : {
226+
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(a.second);
227+
v->m_parent_symtab = module_scope;
228+
module_scope->add_symbol(a.first, (ASR::symbol_t *) v);
229+
syms.push_back(al, s2c(al, a.first));
230+
break;
231+
} default : {
232+
throw LCompilersException("Moving the symbol:`" + a.first +
233+
"` from global scope is not implemented yet");
234+
};
235+
}
236+
}
237+
}
238+
138239
} // namespace LCompilers

src/libasr/asr_scopes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <map>
55

66
#include <libasr/alloc.h>
7+
#include <libasr/containers.h>
78

89
namespace LCompilers {
910

@@ -80,6 +81,10 @@ struct SymbolTable {
8081
size_t n_scope_names, char **m_scope_names);
8182

8283
std::string get_unique_name(const std::string &name);
84+
85+
void move_symbols_from_global_scope(Allocator &al,
86+
SymbolTable *module_scope, Vec<char *> &syms,
87+
Vec<char *> &mod_dependencies);
8388
};
8489

8590
} // namespace LCompilers

src/libasr/codegen/asr_to_c.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,54 @@ R"(
726726
ds_funcs_defined + util_funcs_defined;
727727
}
728728

729+
void visit_Module(const ASR::Module_t &x) {
730+
std::string unit_src = "";
731+
for (auto &item : x.m_symtab->get_scope()) {
732+
if (ASR::is_a<ASR::Variable_t>(*item.second)) {
733+
std::string unit_src_tmp;
734+
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(
735+
item.second);
736+
unit_src_tmp = convert_variable_decl(*v);
737+
unit_src += unit_src_tmp;
738+
if(unit_src_tmp.size() > 0 &&
739+
(!ASR::is_a<ASR::Const_t>(*v->m_type) ||
740+
v->m_intent == ASRUtils::intent_return_var )) {
741+
unit_src += ";\n";
742+
}
743+
}
744+
}
745+
std::map<std::string, std::vector<std::string>> struct_dep_graph;
746+
for (auto &item : x.m_symtab->get_scope()) {
747+
if (ASR::is_a<ASR::StructType_t>(*item.second) ||
748+
ASR::is_a<ASR::EnumType_t>(*item.second) ||
749+
ASR::is_a<ASR::UnionType_t>(*item.second)) {
750+
std::vector<std::string> struct_deps_vec;
751+
std::pair<char**, size_t> struct_deps_ptr = ASRUtils::symbol_dependencies(item.second);
752+
for( size_t i = 0; i < struct_deps_ptr.second; i++ ) {
753+
struct_deps_vec.push_back(std::string(struct_deps_ptr.first[i]));
754+
}
755+
struct_dep_graph[item.first] = struct_deps_vec;
756+
}
757+
}
758+
759+
std::vector<std::string> struct_deps = ASRUtils::order_deps(struct_dep_graph);
760+
for (auto &item : struct_deps) {
761+
ASR::symbol_t* struct_sym = x.m_symtab->get_symbol(item);
762+
visit_symbol(*struct_sym);
763+
}
764+
765+
// Topologically sort all module functions
766+
// and then define them in the right order
767+
std::vector<std::string> func_order = ASRUtils::determine_function_definition_order(x.m_symtab);
768+
for (auto &item : func_order) {
769+
ASR::symbol_t* sym = x.m_symtab->get_symbol(item);
770+
ASR::Function_t *s = ASR::down_cast<ASR::Function_t>(sym);
771+
visit_Function(*s);
772+
unit_src += src;
773+
}
774+
src = unit_src;
775+
}
776+
729777
void visit_Program(const ASR::Program_t &x) {
730778
// Topologically sort all program functions
731779
// and then define them in the right order

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2446,14 +2446,16 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
24462446
ASR::Variable_t *v = down_cast<ASR::Variable_t>(
24472447
item.second);
24482448
visit_Variable(*v);
2449-
}
2450-
if (is_a<ASR::Function_t>(*item.second)) {
2449+
} else if (is_a<ASR::Function_t>(*item.second)) {
24512450
ASR::Function_t *v = down_cast<ASR::Function_t>(
24522451
item.second);
24532452
if (ASRUtils::get_FunctionType(v)->n_type_params == 0) {
24542453
instantiate_function(*v);
24552454
declare_needed_global_types(*v);
24562455
}
2456+
} else if (is_a<ASR::EnumType_t>(*item.second)) {
2457+
ASR::EnumType_t *et = down_cast<ASR::EnumType_t>(item.second);
2458+
visit_EnumType(*et);
24572459
}
24582460
}
24592461
finish_module_init_function_prototype(x);

src/libasr/codegen/asr_to_x86.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ class ASRToX86Visitor : public ASR::BaseVisitor<ASRToX86Visitor>
7979
visit_symbol(*sym);
8080
}
8181

82+
std::vector<std::string> build_order = ASRUtils::determine_module_dependencies(x);
83+
for (auto &item : build_order) {
84+
ASR::symbol_t *mod = x.m_global_scope->get_symbol(item);
85+
visit_symbol(*mod);
86+
}
87+
8288
// Then the main program:
8389
for (auto &item : x.m_global_scope->get_scope()) {
8490
if (ASR::is_a<ASR::Program_t>(*item.second)) {
@@ -89,6 +95,19 @@ class ASRToX86Visitor : public ASR::BaseVisitor<ASRToX86Visitor>
8995
emit_elf32_footer(m_a);
9096
}
9197

98+
void visit_Module(const ASR::Module_t &x) {
99+
std::vector<std::string> func_order
100+
= ASRUtils::determine_function_definition_order(x.m_symtab);
101+
for (size_t i = 0; i < func_order.size(); i++) {
102+
ASR::symbol_t* sym = x.m_symtab->get_symbol(func_order[i]);
103+
// Ignore external symbols because they are already defined by the loop above.
104+
if( !sym || ASR::is_a<ASR::ExternalSymbol_t>(*sym) ) {
105+
continue;
106+
}
107+
visit_symbol(*sym);
108+
}
109+
}
110+
92111
void visit_Program(const ASR::Program_t &x) {
93112

94113

@@ -504,7 +523,8 @@ class ASRToX86Visitor : public ASR::BaseVisitor<ASRToX86Visitor>
504523
}
505524

506525
void visit_SubroutineCall(const ASR::SubroutineCall_t &x) {
507-
ASR::Function_t *s = ASR::down_cast<ASR::Function_t>(x.m_name);
526+
ASR::Function_t *s = ASR::down_cast<ASR::Function_t>(
527+
ASRUtils::symbol_get_past_external(x.m_name));
508528

509529
uint32_t h = get_hash((ASR::asr_t*)s);
510530
if (x86_symtab.find(h) == x86_symtab.end()) {

src/libasr/pass/array_op.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,36 @@ class ArrayOpVisitor : public ASR::CallReplacerOnExpressionsVisitor<ArrayOpVisit
831831
current_scope = current_scope_copy;
832832
}
833833

834+
void visit_Module(const ASR::Module_t &x) {
835+
// FIXME: this is a hack, we need to pass in a non-const `x`,
836+
// which requires to generate a TransformVisitor.
837+
ASR::Module_t &xx = const_cast<ASR::Module_t&>(x);
838+
current_scope = xx.m_symtab;
839+
for (auto &item : x.m_symtab->get_scope()) {
840+
if (is_a<ASR::Function_t>(*item.second)) {
841+
ASR::Function_t *s = ASR::down_cast<ASR::Function_t>(item.second);
842+
if (s->m_return_var) {
843+
/*
844+
* A function which returns an array will be converted
845+
* to a subroutine with the destination array as the last
846+
* argument. This helps in avoiding deep copies and the
847+
* destination memory directly gets filled inside the subroutine.
848+
*/
849+
if( PassUtils::is_array(s->m_return_var) ) {
850+
ASR::symbol_t* s_sub = create_subroutine_from_function(s);
851+
// Update the symtab with this function changes
852+
xx.m_symtab->add_symbol(item.first, s_sub);
853+
}
854+
}
855+
}
856+
}
857+
858+
// Now visit everything else
859+
for (auto &item : x.m_symtab->get_scope()) {
860+
this->visit_symbol(*item.second);
861+
}
862+
}
863+
834864
void visit_Program(const ASR::Program_t &x) {
835865
// FIXME: this is a hack, we need to pass in a non-const `x`,
836866
// which requires to generate a TransformVisitor.

src/libasr/pass/global_stmts_program.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <libasr/asr_utils.h>
55
#include <libasr/asr_verify.h>
66
#include <libasr/pass/global_stmts.h>
7+
#include <libasr/pass/global_symbols.h>
78

89

910
namespace LCompilers {
@@ -24,17 +25,30 @@ void pass_wrap_global_stmts_into_program(Allocator &al,
2425
std::string prog_name = "main_program";
2526
Vec<ASR::stmt_t*> prog_body;
2627
prog_body.reserve(al, 1);
28+
Vec<char *> prog_dep;
29+
prog_dep.reserve(al, 1);
2730
if (unit.n_items > 0) {
2831
pass_wrap_global_stmts_into_function(al, unit, pass_options);
29-
ASR::symbol_t *fn = unit.m_global_scope->get_symbol(program_fn_name);
30-
if (ASR::is_a<ASR::Function_t>(*fn)
31-
&& ASR::down_cast<ASR::Function_t>(fn)->m_return_var == nullptr) {
32+
pass_wrap_global_syms_into_module(al, unit, pass_options);
33+
ASR::Module_t *mod = ASR::down_cast<ASR::Module_t>(
34+
unit.m_global_scope->get_symbol("_global_symbols"));
35+
// Call `_lpython_main_program` function
36+
ASR::symbol_t *fn_s = mod->m_symtab->get_symbol(program_fn_name);
37+
if (ASR::is_a<ASR::Function_t>(*fn_s)
38+
&& ASR::down_cast<ASR::Function_t>(fn_s)->m_return_var == nullptr) {
39+
ASR::Function_t *fn = ASR::down_cast<ASR::Function_t>(fn_s);
40+
fn_s = ASR::down_cast<ASR::symbol_t>(ASR::make_ExternalSymbol_t(
41+
al, fn->base.base.loc, current_scope, s2c(al, program_fn_name),
42+
fn_s, mod->m_name, nullptr, 0, s2c(al, program_fn_name),
43+
ASR::accessType::Public));
44+
current_scope->add_symbol(program_fn_name, fn_s);
3245
ASR::asr_t *stmt = ASR::make_SubroutineCall_t(
3346
al, unit.base.base.loc,
34-
fn, nullptr,
47+
fn_s, nullptr,
3548
nullptr, 0,
3649
nullptr);
3750
prog_body.push_back(al, ASR::down_cast<ASR::stmt_t>(stmt));
51+
prog_dep.push_back(al, s2c(al, "_global_symbols"));
3852
} else {
3953
throw LCompilersException("Return type not supported yet");
4054
}
@@ -43,8 +57,8 @@ void pass_wrap_global_stmts_into_program(Allocator &al,
4357
al, unit.base.base.loc,
4458
/* a_symtab */ current_scope,
4559
/* a_name */ s2c(al, prog_name),
46-
nullptr,
47-
0,
60+
prog_dep.p,
61+
prog_dep.n,
4862
/* a_body */ prog_body.p,
4963
/* n_body */ prog_body.n);
5064
unit.m_global_scope->add_symbol(prog_name, ASR::down_cast<ASR::symbol_t>(prog));

0 commit comments

Comments
 (0)