From 0baea9533f5d6782a8a9ddd9d644cd53ef81824b Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Wed, 15 Mar 2023 20:45:17 +0530 Subject: [PATCH 1/4] Initial support for global Lists --- src/libasr/codegen/asr_to_llvm.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 26f8181e31..4d39bb4e57 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -2296,6 +2296,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } llvm_symtab[h] = ptr; + } else if (x.m_type->type == ASR::ttypeType::List) { + llvm::StructType* list_type = static_cast( + get_type_from_ttype_t_util(x.m_type)); + llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, list_type); + module->getNamedGlobal(x.m_name)->setInitializer( + llvm::ConstantStruct::get(list_type, + llvm::Constant::getNullValue(list_type))); + llvm_symtab[h] = ptr; } else if (x.m_type->type == ASR::ttypeType::TypeParameter) { // Ignore type variables } else { @@ -7015,7 +7023,7 @@ Result> asr_to_llvm(ASR::TranslationUnit_t &asr, pass_manager.apply_passes(al, &asr, pass_options, diagnostics); // Uncomment for debugging the ASR after the transformation - // std::cout << pickle(asr, true, true, true) << std::endl; + // std::cout << LPython::pickle(asr, true, true, true) << std::endl; v.nested_func_types = pass_find_nested_vars(asr, context, v.nested_globals, v.nested_call_out, v.nesting_map); From bd48497516c741645dabc8524c8eb5fc11373299 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Wed, 15 Mar 2023 20:45:35 +0530 Subject: [PATCH 2/4] Allow assert statement in global scope --- src/lpython/semantics/python_ast_to_asr.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 85166ab499..480c57043e 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -3800,6 +3800,10 @@ class SymbolTableVisitor : public CommonVisitor { void visit_For(const AST::For_t &/*x*/) { // We skip this in the SymbolTable visitor, but visit it in the BodyVisitor } + + void visit_Assert(const AST::Assert_t &/*x*/) { + // We skip this in the SymbolTable visitor, but visit it in the BodyVisitor + } }; Result symbol_table_visitor(Allocator &al, LocationManager &lm, const AST::Module_t &ast, From 4a91d332d89a359ab849e8007c456a5b1604b1ff Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Wed, 15 Mar 2023 20:46:20 +0530 Subject: [PATCH 3/4] Support Annotated assignment in the global_scope --- src/libasr/asr_scopes.cpp | 18 +++++++++++++++++- src/libasr/asr_scopes.h | 3 ++- src/libasr/pass/global_symbols.cpp | 17 +++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/libasr/asr_scopes.cpp b/src/libasr/asr_scopes.cpp index 7169e68afe..2c0a7f2ea1 100644 --- a/src/libasr/asr_scopes.cpp +++ b/src/libasr/asr_scopes.cpp @@ -137,10 +137,11 @@ std::string SymbolTable::get_unique_name(const std::string &name) { void SymbolTable::move_symbols_from_global_scope(Allocator &al, SymbolTable *module_scope, Vec &syms, - Vec &mod_dependencies) { + Vec &mod_dependencies, Vec &var_init) { // TODO: This isn't scalable. We have write a visitor in asdl_cpp.py syms.reserve(al, 4); mod_dependencies.reserve(al, 4); + var_init.reserve(al, 4); for (auto &a : scope) { switch (a.second->type) { case (ASR::symbolType::Module): { @@ -225,6 +226,21 @@ void SymbolTable::move_symbols_from_global_scope(Allocator &al, } case (ASR::symbolType::Variable) : { ASR::Variable_t *v = ASR::down_cast(a.second); v->m_parent_symtab = module_scope; + if (v->m_symbolic_value && !ASR::is_a(*v->m_type)) { + ASR::expr_t* v_expr = ASRUtils::EXPR(ASR::make_Var_t( + al, v->base.base.loc, (ASR::symbol_t *) v)); + ASR::asr_t* assign = ASR::make_Assignment_t(al, + v->base.base.loc, v_expr, v->m_symbolic_value, nullptr); + var_init.push_back(al, ASRUtils::STMT(assign)); + v->m_symbolic_value = nullptr; + v->m_value = nullptr; + Vec v_dependencies; + v_dependencies.reserve(al, 1); + ASRUtils::collect_variable_dependencies(al, + v_dependencies, v->m_type); + v->m_dependencies = v_dependencies.p; + v->n_dependencies = v_dependencies.size(); + } module_scope->add_symbol(a.first, (ASR::symbol_t *) v); syms.push_back(al, s2c(al, a.first)); break; diff --git a/src/libasr/asr_scopes.h b/src/libasr/asr_scopes.h index c8805c1147..5576f63ad2 100644 --- a/src/libasr/asr_scopes.h +++ b/src/libasr/asr_scopes.h @@ -10,6 +10,7 @@ namespace LCompilers { namespace ASR { struct asr_t; + struct stmt_t; struct symbol_t; } @@ -84,7 +85,7 @@ struct SymbolTable { void move_symbols_from_global_scope(Allocator &al, SymbolTable *module_scope, Vec &syms, - Vec &mod_dependencies); + Vec &mod_dependencies, Vec &var_init); }; } // namespace LCompilers diff --git a/src/libasr/pass/global_symbols.cpp b/src/libasr/pass/global_symbols.cpp index 1684b02f4a..e9c3293035 100644 --- a/src/libasr/pass/global_symbols.cpp +++ b/src/libasr/pass/global_symbols.cpp @@ -16,22 +16,35 @@ namespace LCompilers { void pass_wrap_global_syms_into_module(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& /*pass_options*/) { + const LCompilers::PassOptions& pass_options) { Location loc = unit.base.base.loc; char *module_name = s2c(al, "_global_symbols"); SymbolTable *module_scope = al.make_new(unit.m_global_scope); Vec moved_symbols; Vec mod_dependencies; + Vec var_init; // Move all the symbols from global into the module scope unit.m_global_scope->move_symbols_from_global_scope(al, module_scope, - moved_symbols, mod_dependencies); + moved_symbols, mod_dependencies, var_init); // Erase the symbols that are moved into the module for (auto &sym: moved_symbols) { unit.m_global_scope->erase_symbol(sym); } + if (module_scope->get_symbol(pass_options.run_fun) && var_init.n > 0) { + ASR::Function_t *f = ASR::down_cast( + module_scope->get_symbol(pass_options.run_fun)); + for (size_t i = 0; i < f->n_body; i++) { + var_init.push_back(al, f->m_body[i]); + } + f->m_body = var_init.p; + f->n_body = var_init.n; + // Overwrites the function: `_lpython_main_program` + module_scope->add_symbol(f->m_name, (ASR::symbol_t *) f); + } + Vec m_dependencies; m_dependencies.reserve(al, mod_dependencies.size()); for( auto &dep: mod_dependencies) { From f86901dbc30f5dddb4430557856006da8469ef17 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Wed, 15 Mar 2023 20:46:37 +0530 Subject: [PATCH 4/4] Add a test and register in CMakeLists --- integration_tests/CMakeLists.txt | 3 ++- integration_tests/global_syms_02.py | 23 ++++++++++++++++++++ tests/reference/asr-expr_07-7742668.json | 2 +- tests/reference/asr-expr_07-7742668.stdout | 2 +- tests/reference/llvm-print_04-443a8d8.json | 2 +- tests/reference/llvm-print_04-443a8d8.stdout | 12 ++++++---- 6 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 integration_tests/global_syms_02.py diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 77534822a1..94b3ccb7ac 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -432,4 +432,5 @@ RUN(NAME bit_operations_i32 LABELS cpython llvm wasm wasm_x64) RUN(NAME bit_operations_i64 LABELS cpython llvm wasm) RUN(NAME test_argv_01 LABELS llvm) # TODO: Test using CPython -RUN(NAME global_syms_01 LABELS cpython) +RUN(NAME global_syms_01 LABELS cpython llvm) +RUN(NAME global_syms_02 LABELS cpython llvm) diff --git a/integration_tests/global_syms_02.py b/integration_tests/global_syms_02.py new file mode 100644 index 0000000000..d6ed192bac --- /dev/null +++ b/integration_tests/global_syms_02.py @@ -0,0 +1,23 @@ +from ltypes import i32 + +x: list[i32] +x = [0, 1] +x.append(3) + +def test_global_symbols(): + assert len(x) == 3 + x.insert(2, 2) + +test_global_symbols() + +i: i32 +for i in range(len(x)): + assert i == x[i] + +tmp: list[i32] +tmp = x + +tmp.remove(0) +assert len(tmp) == 3 +tmp.clear() +assert len(tmp) == 0 diff --git a/tests/reference/asr-expr_07-7742668.json b/tests/reference/asr-expr_07-7742668.json index 6dbe0f9b84..7c0662de44 100644 --- a/tests/reference/asr-expr_07-7742668.json +++ b/tests/reference/asr-expr_07-7742668.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-expr_07-7742668.stdout", - "stdout_hash": "36af7cdd0a8bed977355197e5fb0512e1b23f1b36966eef5e83ef244", + "stdout_hash": "e419602ad57368da314d299a740459bc2fd912e9302ef68207e70105", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-expr_07-7742668.stdout b/tests/reference/asr-expr_07-7742668.stdout index 4d4a392f80..ac77a53a98 100644 --- a/tests/reference/asr-expr_07-7742668.stdout +++ b/tests/reference/asr-expr_07-7742668.stdout @@ -1 +1 @@ -(TranslationUnit (SymbolTable 1 {_global_symbols: (Module (SymbolTable 7 {_lpython_main_program: (Function (SymbolTable 6 {}) _lpython_main_program (FunctionType [] () Source Implementation () .false. .false. .false. .false. .false. [] [] .false.) [f bool_to_str] [] [(SubroutineCall 7 f () [] ()) (SubroutineCall 7 bool_to_str () [] ())] () Public .false. .false.), bool_to_str: (Function (SymbolTable 4 {var: (Variable 4 var [] Local () () Default (Logical 4 []) Source Public Required .false.)}) bool_to_str (FunctionType [] () Source Implementation () .false. .false. .false. .false. .false. [] [] .false.) [] [] [(= (Var 4 var) (LogicalConstant .true. (Logical 4 [])) ()) (Print () [(Cast (LogicalConstant .true. (Logical 4 [])) LogicalToCharacter (Character 1 -2 () []) (StringConstant "True" (Character 1 4 () [])))] () ()) (Assert (StringCompare (Cast (Var 4 var) LogicalToCharacter (Character 1 -2 () []) ()) Eq (StringConstant "True" (Character 1 4 () [])) (Logical 4 []) ()) ()) (= (Var 4 var) (LogicalConstant .false. (Logical 4 [])) ()) (Assert (StringCompare (Cast (Var 4 var) LogicalToCharacter (Character 1 -2 () []) ()) Eq (StringConstant "False" (Character 1 5 () [])) (Logical 4 []) ()) ()) (Assert (StringCompare (Cast (LogicalConstant .true. (Logical 4 [])) LogicalToCharacter (Character 1 -2 () []) (StringConstant "True" (Character 1 4 () []))) Eq (StringConstant "True" (Character 1 4 () [])) (Logical 4 []) (LogicalConstant .true. (Logical 4 []))) ())] () Public .false. .false.), f: (Function (SymbolTable 3 {a: (Variable 3 a [] Local (IntegerConstant 5 (Integer 4 [])) () Default (Integer 4 []) Source Public Required .false.), b: (Variable 3 b [x] Local (IntegerBinOp (Var 3 x) Add (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) ()) () Default (Integer 4 []) Source Public Required .false.), x: (Variable 3 x [] Local (IntegerConstant 3 (Integer 4 [])) () Default (Integer 4 []) Source Public Required .false.)}) f (FunctionType [] () Source Implementation () .false. .false. .false. .false. .false. [] [] .false.) [g] [] [(= (Var 3 a) (IntegerConstant 5 (Integer 4 [])) ()) (= (Var 3 x) (IntegerConstant 3 (Integer 4 [])) ()) (= (Var 3 x) (IntegerConstant 5 (Integer 4 [])) ()) (= (Var 3 b) (IntegerBinOp (Var 3 x) Add (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) ()) ()) (Print () [(Var 3 a) (Var 3 b)] () ()) (Assert (IntegerCompare (Var 3 b) Eq (IntegerConstant 6 (Integer 4 [])) (Logical 4 []) ()) ()) (SubroutineCall 7 g () [((IntegerBinOp (IntegerBinOp (Var 3 a) Mul (Var 3 b) (Integer 4 []) ()) Add (IntegerConstant 3 (Integer 4 [])) (Integer 4 []) ()))] ())] () Public .false. .false.), g: (Function (SymbolTable 2 {x: (Variable 2 x [] In () () Default (Integer 4 []) Source Public Required .false.)}) g (FunctionType [(Integer 4 [])] () Source Implementation () .false. .false. .false. .false. .false. [] [] .false.) [] [(Var 2 x)] [(Print () [(Var 2 x)] () ())] () Public .false. .false.), x: (Variable 7 x [] Local (IntegerConstant 7 (Integer 4 [])) () Default (Integer 4 []) Source Public Required .false.)}) _global_symbols [] .false. .false.), main_program: (Program (SymbolTable 5 {_lpython_main_program: (ExternalSymbol 5 _lpython_main_program 7 _lpython_main_program _global_symbols [] _lpython_main_program Public)}) main_program [_global_symbols] [(SubroutineCall 5 _lpython_main_program () [] ())])}) []) +(TranslationUnit (SymbolTable 1 {_global_symbols: (Module (SymbolTable 7 {_lpython_main_program: (Function (SymbolTable 6 {}) _lpython_main_program (FunctionType [] () Source Implementation () .false. .false. .false. .false. .false. [] [] .false.) [f bool_to_str] [] [(= (Var 7 x) (IntegerConstant 7 (Integer 4 [])) ()) (SubroutineCall 7 f () [] ()) (SubroutineCall 7 bool_to_str () [] ())] () Public .false. .false.), bool_to_str: (Function (SymbolTable 4 {var: (Variable 4 var [] Local () () Default (Logical 4 []) Source Public Required .false.)}) bool_to_str (FunctionType [] () Source Implementation () .false. .false. .false. .false. .false. [] [] .false.) [] [] [(= (Var 4 var) (LogicalConstant .true. (Logical 4 [])) ()) (Print () [(Cast (LogicalConstant .true. (Logical 4 [])) LogicalToCharacter (Character 1 -2 () []) (StringConstant "True" (Character 1 4 () [])))] () ()) (Assert (StringCompare (Cast (Var 4 var) LogicalToCharacter (Character 1 -2 () []) ()) Eq (StringConstant "True" (Character 1 4 () [])) (Logical 4 []) ()) ()) (= (Var 4 var) (LogicalConstant .false. (Logical 4 [])) ()) (Assert (StringCompare (Cast (Var 4 var) LogicalToCharacter (Character 1 -2 () []) ()) Eq (StringConstant "False" (Character 1 5 () [])) (Logical 4 []) ()) ()) (Assert (StringCompare (Cast (LogicalConstant .true. (Logical 4 [])) LogicalToCharacter (Character 1 -2 () []) (StringConstant "True" (Character 1 4 () []))) Eq (StringConstant "True" (Character 1 4 () [])) (Logical 4 []) (LogicalConstant .true. (Logical 4 []))) ())] () Public .false. .false.), f: (Function (SymbolTable 3 {a: (Variable 3 a [] Local (IntegerConstant 5 (Integer 4 [])) () Default (Integer 4 []) Source Public Required .false.), b: (Variable 3 b [x] Local (IntegerBinOp (Var 3 x) Add (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) ()) () Default (Integer 4 []) Source Public Required .false.), x: (Variable 3 x [] Local (IntegerConstant 3 (Integer 4 [])) () Default (Integer 4 []) Source Public Required .false.)}) f (FunctionType [] () Source Implementation () .false. .false. .false. .false. .false. [] [] .false.) [g] [] [(= (Var 3 a) (IntegerConstant 5 (Integer 4 [])) ()) (= (Var 3 x) (IntegerConstant 3 (Integer 4 [])) ()) (= (Var 3 x) (IntegerConstant 5 (Integer 4 [])) ()) (= (Var 3 b) (IntegerBinOp (Var 3 x) Add (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) ()) ()) (Print () [(Var 3 a) (Var 3 b)] () ()) (Assert (IntegerCompare (Var 3 b) Eq (IntegerConstant 6 (Integer 4 [])) (Logical 4 []) ()) ()) (SubroutineCall 7 g () [((IntegerBinOp (IntegerBinOp (Var 3 a) Mul (Var 3 b) (Integer 4 []) ()) Add (IntegerConstant 3 (Integer 4 [])) (Integer 4 []) ()))] ())] () Public .false. .false.), g: (Function (SymbolTable 2 {x: (Variable 2 x [] In () () Default (Integer 4 []) Source Public Required .false.)}) g (FunctionType [(Integer 4 [])] () Source Implementation () .false. .false. .false. .false. .false. [] [] .false.) [] [(Var 2 x)] [(Print () [(Var 2 x)] () ())] () Public .false. .false.), x: (Variable 7 x [] Local () () Default (Integer 4 []) Source Public Required .false.)}) _global_symbols [] .false. .false.), main_program: (Program (SymbolTable 5 {_lpython_main_program: (ExternalSymbol 5 _lpython_main_program 7 _lpython_main_program _global_symbols [] _lpython_main_program Public)}) main_program [_global_symbols] [(SubroutineCall 5 _lpython_main_program () [] ())])}) []) diff --git a/tests/reference/llvm-print_04-443a8d8.json b/tests/reference/llvm-print_04-443a8d8.json index ebe61b4517..229674e449 100644 --- a/tests/reference/llvm-print_04-443a8d8.json +++ b/tests/reference/llvm-print_04-443a8d8.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "llvm-print_04-443a8d8.stdout", - "stdout_hash": "82ed5155deef7a5b597b62a427ca9c33a1dd6650f757223c5c604889", + "stdout_hash": "740498e6d0b9c0a6ffc7f6711e1f8c5bae27b834b726d108fb0e0c18", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/llvm-print_04-443a8d8.stdout b/tests/reference/llvm-print_04-443a8d8.stdout index 864734a85e..b0f1a8f7de 100644 --- a/tests/reference/llvm-print_04-443a8d8.stdout +++ b/tests/reference/llvm-print_04-443a8d8.stdout @@ -1,10 +1,10 @@ ; ModuleID = 'LFortran' source_filename = "LFortran" -@u = global i64 -922337203685477580 -@x = global i32 -2147483648 -@y = global i16 -32768 -@z = global i8 -128 +@u = global i64 0 +@x = global i32 0 +@y = global i16 0 +@z = global i8 0 @0 = private unnamed_addr constant [2 x i8] c" \00", align 1 @1 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 @2 = private unnamed_addr constant [7 x i8] c"%lld%s\00", align 1 @@ -20,6 +20,10 @@ source_filename = "LFortran" define void @__module__global_symbols__lpython_main_program() { .entry: + store i64 -922337203685477580, i64* @u, align 4 + store i32 -2147483648, i32* @x, align 4 + store i16 -32768, i16* @y, align 2 + store i8 -128, i8* @z, align 1 %0 = load i64, i64* @u, align 4 call void (i8*, ...) @_lfortran_printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @2, i32 0, i32 0), i64 %0, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @1, i32 0, i32 0)) %1 = load i32, i32* @x, align 4